2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
5 Desc: Create a new BitMap
8 #include <aros/debug.h>
10 #include <exec/memory.h>
11 #include <proto/exec.h>
12 #include <proto/oop.h>
13 #include <cybergraphx/cybergraphics.h>
14 #include "graphics_intern.h"
15 #include "gfxfuncsupport.h"
17 #define SET_TAG(tags, idx, tag, val) \
18 tags[idx].ti_Tag = tag ; tags[idx].ti_Data = (IPTR)val;
20 #define SET_BM_TAG(tags, idx, tag, val) \
21 SET_TAG(tags, idx, aHidd_BitMap_ ## tag, val)
23 /*****************************************************************************
26 #include <graphics/gfx.h>
27 #include <proto/graphics.h>
29 AROS_LH5(struct BitMap
*, AllocBitMap
,
32 AROS_LHA(ULONG
, sizex
, D0
),
33 AROS_LHA(ULONG
, sizey
, D1
),
34 AROS_LHA(ULONG
, depth
, D2
),
35 AROS_LHA(ULONG
, flags
, D3
),
36 AROS_LHA(struct BitMap
*, friend_bitmap
, A0
),
39 struct GfxBase
*, GfxBase
, 153, Graphics
)
42 Allocates and initializes a bitmap structure. Allocates and
43 initializes bitplane data, and sets the bitmap's planes to point to
47 sizex, sizey - The width and height in pixels
49 depth - The depth of the bitmap. A depth of 1 will allocate a
50 bitmap for two colors, a depth of 24 will allocate a bitmap for
51 16 million colors. Pixels with AT LEAST this many bits will be
54 flags - One of these flags:
56 BMF_CLEAR: Fill the bitmap with color 0.
58 BMF_DISPLAYABLE: to specify that this bitmap data should
59 be allocated in such a manner that it can be displayed.
60 Displayable data has more severe alignment restrictions
61 than non-displayable data in some systems.
63 BMF_INTERLEAVED: tells graphics that you would like your
64 bitmap to be allocated with one large chunk of display
65 memory for all bitplanes. This minimizes color flashing on
66 deep displays. If there is not enough contiguous RAM for an
67 interleaved bitmap, graphics.library will fall back to a
70 BMF_MINPLANES: causes graphics to only allocate enough
71 space in the bitmap structure for "depth" plane pointers.
72 This is for system use and should not be used by
73 applications use as it is inefficient, and may waste
76 BMF_SPECIALFMT: causes graphics to allocate a bitmap
77 of a standard CyberGraphX format. The format
78 (PIXFMT_????) must be stored in the 8 most significant bits.
80 friend_bitmap - pointer to another bitmap, or NULL. If this pointer
81 is passed, then the bitmap data will be allocated in
82 the most efficient form for blitting to friend_bitmap.
85 A pointer to the new bitmap.
88 When allocating using a friend_bitmap bitmap, it is not safe to assume
89 anything about the structure of the bitmap data if that friend_bitmap
90 BitMap might not be a standard Amiga bitmap (for instance, if the
91 workbench is running on a non-Amiga display device, its
92 Screen->RastPort->BitMap won't be in standard Amiga format. The
93 only safe operations to perform on a non-standard BitMap are:
95 blitting it to another bitmap, which must be either a
96 standard Amiga bitmap, or a friend_bitmap of this bitmap.
98 blitting from this bitmap to a friend_bitmap bitmap or to a
99 standard Amiga bitmap.
101 attaching it to a rastport and making rendering calls.
103 Good arguments to pass for the friend_bitmap are your window's
104 RPort->BitMap, and your screen's RastPort->BitMap. Do NOT pass
105 &(screenptr->BitMap)!
107 BitMaps not allocated with BMF_DISPLAYABLE may not be used as
108 Intuition Custom BitMaps or as RasInfo->BitMaps. They may be
109 blitted to a BMF_DISPLAYABLE BitMap, using one of the BltBitMap()
123 *****************************************************************************/
129 HIDDT_ModeID hiddmode
= vHidd_ModeID_Invalid
;
132 If the depth is too large or the bitmap should be displayable or
133 there is a friend_bitmap bitmap and that's not a normal bitmap, then
137 /* Hack: see AllocScreenBitMap */
141 depth
= (ULONG
)(-((LONG
)depth
));
142 hiddmode
= (HIDDT_ModeID
)friend_bitmap
;
143 friend_bitmap
= NULL
;
145 else if (flags
& HIDD_BMF_SCREEN_BITMAP
) // (flags & BMF_DISPLAYABLE)
147 /* Make real BMF_DISPLAYABLE bitmap only, if a friend bitmap was
148 specified which is displayable (ie. a screen bitmap). Because
149 as the gfxhidd stuff is now, displayable bitmap needs to have
150 a Display ModeID "known" to them. */
152 if (friend_bitmap
&& IS_HIDD_BM(friend_bitmap
) && (HIDD_BM_FLAGS(friend_bitmap
) & HIDD_BMF_SCREEN_BITMAP
)) // (friend_bitmap->Flags & BMF_DISPLAYABLE))
154 hiddmode
= HIDD_BM_HIDDMODE(friend_bitmap
);
158 flags
&= ~HIDD_BMF_SCREEN_BITMAP
; //flags &= ~BMF_DISPLAYABLE;
162 ASSERT_VALID_PTR_OR_NULL(friend_bitmap
);
166 || (flags
& HIDD_BMF_SCREEN_BITMAP
) // (flags & BMF_DISPLAYABLE)
167 /* || (friend_bitmap && friend_bitmap->pad != 0) */
168 || (friend_bitmap
&& friend_bitmap
->Flags
& BMF_AROS_HIDD
)
169 #warning Should we also check for BMF_MINPLANES ?
170 || (flags
& BMF_SPECIALFMT
) /* Cybergfx bitmap */
174 struct TagItem bm_tags
[8]; /* Tags for offscreen bitmaps */
177 bug("driver_AllocBitMap(sizex=%d, sizey=%d, depth=%d, flags=%d, friend_bitmap=%p)\n",
178 sizex, sizey, depth, flags, friend_bitmap);
182 SET_BM_TAG( bm_tags
, 0, Width
, sizex
);
183 SET_BM_TAG( bm_tags
, 1, Height
, sizey
);
185 if (flags
& HIDD_BMF_SCREEN_BITMAP
) // (flags & BMF_DISPLAYABLE)
187 /* Use the hiddmode instead of depth/friend_bitmap */
188 if (vHidd_ModeID_Invalid
== hiddmode
)
189 ReturnPtr("driver_AllocBitMap(Invalid modeID)", struct BitMap
*, NULL
);
191 SET_BM_TAG(bm_tags
, 2, ModeID
, hiddmode
);
192 SET_BM_TAG(bm_tags
, 3, Displayable
, TRUE
);
193 SET_TAG(bm_tags
, 4, TAG_DONE
, 0);
197 SET_TAG(bm_tags
, 2, TAG_IGNORE
, 0);
199 if (NULL
!= friend_bitmap
)
201 if (IS_HIDD_BM(friend_bitmap
))
202 SET_BM_TAG(bm_tags
, 2, Friend
, HIDD_BM_OBJ(friend_bitmap
));
205 if (flags
& BMF_SPECIALFMT
)
207 HIDDT_StdPixFmt stdpf
;
209 stdpf
= cyber2hidd_pixfmt(DOWNSHIFT_PIXFMT(flags
), GfxBase
);
210 SET_BM_TAG(bm_tags
, 3, StdPixFmt
, stdpf
);
214 SET_TAG(bm_tags
, 3, TAG_IGNORE
, 0);
217 SET_TAG(bm_tags
, 4, TAG_DONE
, 0);
220 nbm
= AllocMem (sizeof (struct BitMap
), MEMF_ANY
|MEMF_CLEAR
);
227 gfxhidd
= SDD(GfxBase
)->gfxhidd
;
229 /* Create HIDD bitmap object */
232 bm_obj
= HIDD_Gfx_NewBitMap(gfxhidd
, bm_tags
);
237 OOP_Object
*colmap
= 0;
238 HIDDT_ColorModel colmod
;
240 IPTR width
, height
, val
;
243 /* It is possible that the HIDD had to allocate
244 a larger depth than that supplied, so
245 we should get back the correct depth.
246 This is because layers.library might
247 want to allocate offscreen bitmaps to
248 store obscured areas, and then those
249 offscreen bitmaps should be of the same depth as
253 OOP_GetAttr(bm_obj
, aHidd_BitMap_Width
, &width
);
254 OOP_GetAttr(bm_obj
, aHidd_BitMap_Height
, &height
);
255 OOP_GetAttr(bm_obj
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
257 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &val
);
260 OOP_GetAttr(pf
, aHidd_PixFmt_ColorModel
, &val
);
263 OOP_GetAttr(bm_obj
, aHidd_BitMap_ColorMap
, (IPTR
*)&colmap
);
265 /* Store it in plane array */
266 HIDD_BM_OBJ(nbm
) = bm_obj
;
267 HIDD_BM_COLMOD(nbm
) = colmod
;
268 HIDD_BM_COLMAP(nbm
) = colmap
;
269 HIDD_BM_REALDEPTH(nbm
) = depth
;
270 HIDD_BM_HIDDMODE(nbm
) = hiddmode
;
273 nbm
->BytesPerRow
= WIDTH_TO_BYTES(width
);
274 #if BMDEPTH_COMPATIBILITY
275 nbm
->Depth
= (depth
> 8) ? 8 : depth
;
279 nbm
->Flags
= flags
| BMF_AROS_HIDD
;
281 /* If this is a displayable bitmap, create a color table for it */
283 if (flags
& HIDD_BMF_SCREEN_BITMAP
) // (flags & BMF_DISPLAYABLE)
285 HIDD_BM_FLAGS(nbm
) |= HIDD_BMF_SCREEN_BITMAP
;
289 OOP_Object
*oldcolmap
;
291 oldcolmap
= HIDD_BM_SetColorMap(HIDD_BM_OBJ(nbm
), HIDD_BM_COLMAP(friend_bitmap
));
292 if (oldcolmap
) OOP_DisposeObject(oldcolmap
);
294 HIDD_BM_COLMAP(nbm
) = HIDD_BM_COLMAP(friend_bitmap
);
295 HIDD_BM_PIXTAB(nbm
) = HIDD_BM_PIXTAB(friend_bitmap
);
296 HIDD_BM_COLMOD(nbm
) = HIDD_BM_COLMOD(friend_bitmap
);
297 HIDD_BM_REALDEPTH(nbm
) = HIDD_BM_REALDEPTH(friend_bitmap
);
299 HIDD_BM_FLAGS(nbm
) |= HIDD_BMF_SHARED_PIXTAB
;
305 /* Allcoate a pixtab */
306 HIDD_BM_PIXTAB(nbm
) = AllocVec(sizeof (HIDDT_Pixel
) * AROS_PALETTE_SIZE
, MEMF_ANY
);
308 if (NULL
!= HIDD_BM_PIXTAB(nbm
))
310 /* Set this palette to all black by default */
320 if (vHidd_ColorModel_Palette
== colmod
||
321 vHidd_ColorModel_TrueColor
== colmod
)
325 numcolors
= 1L << ((depth
<= 8) ? depth
: 8);
327 /* Set palette to all black */
328 for (i
= 0; i
< numcolors
; i
++)
330 HIDD_BM_SetColors(HIDD_BM_OBJ(nbm
), &col
, i
, 1);
331 HIDD_BM_PIXTAB(nbm
)[i
] = col
.pixval
;
337 } /* if (pixtab successfully allocated) */
341 } /* if (flags & HIDD_BMF_SCREEN_BITMAP) ... (flags & BMF_DISPLAYABLE) */
346 /* We got a friend_bitmap bitmap. We inherit its colormap
347 !!! NOTE !!! If this is used after the friend_bitmap bitmap is freed
348 it means trouble, as the colortab mem
349 will no longer be valid
354 HIDD_BM_COLMAP(nbm
) = HIDD_BM_COLMAP(friend_bitmap
);
355 HIDD_BM_COLMOD(nbm
) = HIDD_BM_COLMOD(friend_bitmap
);
356 HIDD_BM_PIXTAB(nbm
) = HIDD_BM_PIXTAB(friend_bitmap
);
357 HIDD_BM_REALDEPTH(nbm
) = HIDD_BM_REALDEPTH(friend_bitmap
);
365 HIDD_BM_REALDEPTH(nbm
) = depth
;
372 if (flags
& BMF_CLEAR
)
384 ReturnPtr("driver_AllocBitMap", struct BitMap
*, nbm
);
387 OOP_DisposeObject(bm_obj
);
389 } /* if (bitmap object allocated) */
392 FreeMem(nbm
, sizeof (struct BitMap
));
398 else /* Otherwise init a plain Amiga bitmap */
400 nbm
= AllocMem (sizeof(struct BitMap
) + ((depth
> 8) ? (depth
- 8) * sizeof(PLANEPTR
) : 0),
401 MEMF_ANY
| MEMF_CLEAR
);
407 nbm
->BytesPerRow
= ((sizex
+ 15) >> 4) * 2;
413 for (plane
=0; plane
<depth
; plane
++)
415 nbm
->Planes
[plane
] = AllocRaster (sizex
, sizey
);
417 if (!nbm
->Planes
[plane
])
420 if (flags
& BMF_CLEAR
)
421 memset (nbm
->Planes
[plane
], 0, RASSIZE(sizex
,sizey
));
426 for (plane
=0; plane
<depth
; plane
++)
427 if (nbm
->Planes
[plane
])
428 FreeRaster (nbm
->Planes
[plane
], sizex
, sizey
);
430 FreeMem (nbm
, sizeof (struct BitMap
));