wip prep commit in lieu of gfx subsystem update changes.
[AROS.git] / rom / hidds / graphics / gfx_planarbitmapclass.c
blob2c6bab0ed81751e96b4c0d3dace20db4313331e4
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Gfx Hidd planar bitmap class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #include "gfx_debug.h"
13 #include <proto/exec.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
17 #include <exec/memory.h>
18 #include <utility/tagitem.h>
19 #include <graphics/gfx.h>
20 #include <oop/oop.h>
22 #include <hidd/gfx.h>
24 #include <string.h>
26 #include "gfx_intern.h"
28 /*****************************************************************************************
30 NAME
31 --background_planarbm--
33 LOCATION
34 hidd.gfx.bitmap.planarbm
36 NOTES
37 This is a class representing a planar Amiga(tm) bitmap in AROS graphics subsystem.
39 When you create an object of this class, an associated planar bitmap will be created.
40 However, it's possible to use this class with pre-existing bitmaps, making them
41 available to the graphics HIDD subsystem.
43 *****************************************************************************************/
45 /*****************************************************************************************
47 NAME
48 aoHidd_PlanarBM_AllocPlanes
50 SYNOPSIS
51 [I..], BOOL
53 LOCATION
54 hidd.gfx.bitmap.planarbm
56 FUNCTION
57 Set this attribute to FALSE if you want to create an empty bitmap object containing
58 no bitmap data. Useful if you want to create an empty object to be associated with
59 existing bitmap later.
61 NOTES
62 This attribute is obsolete. It's equal to supplying aoHidd_PlanarBM_BitMap attribute
63 with a NULL value.
65 EXAMPLE
67 BUGS
69 SEE ALSO
70 aoHidd_PlanarBM_BitMap
72 INTERNALS
74 *****************************************************************************************/
76 /*****************************************************************************************
78 NAME
79 aoHidd_PlanarBM_BitMap
81 SYNOPSIS
82 [ISG], struct BitMap *
84 LOCATION
85 hidd.gfx.bitmap.planarbm
87 FUNCTION
88 Allows to specify or retrieve a raw planar bitmap structure associated with the object.
89 Useful for direct access to the bitmap within subclasses, as well as for associating
90 an object with already existing BitMap structure.
92 It is valid to pass this attribute with a NULL value. In this case the object becomes
93 empty and contains no actual bitmap.
95 NOTES
96 If the object was created with own bitmap data (with no aoHidd_PlanarBM_BitMap specified
97 during creation), this data will be deallocated when you set this attribute.
99 It's up to you to deallocate own bitmaps, set using this attribute. Even if the object
100 is disposed, it won't deallocate user-supplied bitmap.
102 EXAMPLE
104 BUGS
106 SEE ALSO
108 INTERNALS
110 *****************************************************************************************/
112 OOP_Object *PBM__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
114 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
115 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
116 IPTR height, bytesperrow;
117 UBYTE depth;
118 IPTR displayable = FALSE;
119 BOOL ok = FALSE;
120 struct planarbm_data *data;
121 struct TagItem *tag;
123 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, &msg->mID);
124 if (NULL == o)
125 return NULL;
127 data = OOP_INST_DATA(cl, o);
129 /* Check if we want to use existing bitmap */
131 tag = FindTagItem(aHidd_PlanarBM_BitMap, msg->attrList);
132 if (tag)
134 /* It's not our own bitmap */
135 data->planes_alloced = FALSE;
136 /* Remember the bitmap. It can be NULL here. */
137 data->bitmap = (struct BitMap *)tag->ti_Data;
139 /* That's all, we are attached to an existing BitMap */
140 return o;
142 else
144 /* Check obsolete attribute now */
145 data->planes_alloced = GetTagData(aHidd_PlanarBM_AllocPlanes, TRUE, msg->attrList);
147 if (!data->planes_alloced)
148 return o; /* Late initialization */
151 /* By default we create 1-plane bitmap */
152 depth = GetTagData(aHidd_BitMap_Depth, 1, msg->attrList);
154 /* Not late initialization. Get some info on the bitmap */
155 OOP_GetAttr(o, aHidd_BitMap_Height, &height);
156 OOP_GetAttr(o, aHidd_BitMap_BytesPerRow, &bytesperrow);
157 OOP_GetAttr(o, aHidd_BitMap_Displayable, &displayable);
159 data->bitmap = AllocMem(sizeof(struct BitMap), MEMF_CLEAR);
160 if (data->bitmap)
162 UBYTE i;
164 ok = TRUE;
166 /* We cache some info */
167 data->bitmap->Rows = height;
168 data->bitmap->BytesPerRow = bytesperrow;
169 data->bitmap->Depth = depth;
170 data->bitmap->Flags = BMF_STANDARD|BMF_MINPLANES; /* CHECKME */
171 if (displayable)
172 data->bitmap->Flags |= BMF_DISPLAYABLE;
174 /* Allocate memory for all the planes. Use chip memory. */
175 for (i = 0; i < depth; i++)
177 data->bitmap->Planes[i] = AllocMem(height * bytesperrow, MEMF_CHIP | MEMF_CLEAR);
179 if (NULL == data->bitmap->Planes[i])
181 ok = FALSE;
182 break;
187 if (!ok)
189 OOP_MethodID dispose_mid;
191 dispose_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
192 OOP_CoerceMethod(cl, o, (OOP_Msg)&dispose_mid);
194 o = NULL;
197 return o;
200 /****************************************************************************************/
202 static void PBM_FreeBitMap(struct planarbm_data *data)
204 if (data->planes_alloced)
206 if (NULL != data->bitmap)
208 UBYTE i;
210 for (i = 0; i < data->bitmap->Depth; i++)
212 if (data->bitmap->Planes[i])
214 FreeMem(data->bitmap->Planes[i], data->bitmap->Rows * data->bitmap->BytesPerRow);
217 FreeMem(data->bitmap, sizeof(struct BitMap));
222 VOID PBM__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
224 struct planarbm_data *data = OOP_INST_DATA(cl, o);
226 PBM_FreeBitMap(data);
227 OOP_DoSuperMethod(cl, o, msg);
230 /****************************************************************************************/
232 VOID PBM__Root__Get(OOP_Class *cl, OOP_Object *obj, struct pRoot_Get *msg)
234 struct planarbm_data *data = OOP_INST_DATA(cl, obj);
236 if (msg->attrID == aHidd_BitMap_Depth)
238 /* Planar bitmaps may have a variable depth. */
239 *msg->storage = data->bitmap ? data->bitmap->Depth : 0;
240 return;
242 else if (msg->attrID == aHidd_PlanarBM_BitMap)
244 *msg->storage = (IPTR)data->bitmap;
245 return;
248 OOP_DoSuperMethod(cl, obj, &msg->mID);
251 /****************************************************************************************/
253 static BOOL PBM_SetBitMap(OOP_Class *cl, OOP_Object *o, struct BitMap *bm)
255 struct TagItem pftags[] =
257 { aHidd_PixFmt_Depth , 0UL }, /* 0 */
258 { aHidd_PixFmt_BitsPerPixel , 0UL }, /* 1 */
259 { aHidd_PixFmt_BytesPerPixel, 1UL }, /* 2 */
260 { aHidd_PixFmt_ColorModel , vHidd_ColorModel_Palette }, /* 3 */
261 { aHidd_PixFmt_BitMapType , vHidd_BitMapType_Planar }, /* 4 */
262 { aHidd_PixFmt_CLUTShift , 0UL }, /* 5 */
263 { aHidd_PixFmt_CLUTMask , 0x000000FF }, /* 6 */
264 { aHidd_PixFmt_RedMask , 0x00FF0000 }, /* 7 */
265 { aHidd_PixFmt_GreenMask , 0x0000FF00 }, /* 8 */
266 { aHidd_PixFmt_BlueMask , 0x000000FF }, /* 9 */
267 { aHidd_PixFmt_StdPixFmt , vHidd_StdPixFmt_Plane },
268 { TAG_DONE , 0UL }
270 struct TagItem bmtags[] =
272 { aHidd_BitMap_Width , 0 }, /* 0 */
273 { aHidd_BitMap_Height , 0 }, /* 1 */
274 { aHidd_BitMap_BytesPerRow , 0 }, /* 2 */
275 { TAG_DONE , 0 }
277 struct planarbm_data *data = OOP_INST_DATA(cl, o);
278 OOP_Object *pf;
280 /* First we attempt to register a pixelformat */
281 pftags[0].ti_Data = bm->Depth; /* PixFmt_Depth */
282 pftags[1].ti_Data = bm->Depth; /* PixFmt_BitsPerPixel */
284 pf = GFXHIDD__Hidd_Gfx__RegisterPixFmt(CSD(cl)->gfxhiddclass, pftags);
286 if (!pf)
288 /* Fail is pixelformat registration failed */
289 return FALSE;
292 /* Free old bitmap, if it was ours. */
293 PBM_FreeBitMap(data);
295 /* Set the new bitmap. It's not ours. */
296 data->bitmap = bm;
297 data->planes_alloced = FALSE;
299 /* Call private bitmap method to update superclass */
300 bmtags[0].ti_Data = bm->BytesPerRow * 8;
301 bmtags[1].ti_Data = bm->Rows;
302 bmtags[2].ti_Data = bm->BytesPerRow;
304 BM__Hidd_BitMap__SetBitMapTags(CSD(cl)->bitmapclass, o, bmtags);
305 BM__Hidd_BitMap__SetPixFmt(CSD(cl)->bitmapclass, o, pf);
307 return TRUE;
310 VOID PBM__Root__Set(OOP_Class *cl, OOP_Object *obj, struct pRoot_Set *msg)
312 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
313 struct TagItem *tag = FindTagItem(aHidd_PlanarBM_BitMap, msg->attrList);
315 if (tag)
318 * TODO: We can't check for failure here. However, since we already
319 * have Depth attribute for the bitmap, may be we shouldn't register
320 * 8 pixelformats? In this case we are unable to fail.
322 PBM_SetBitMap(cl, obj, (struct BitMap *)tag->ti_Data);
325 OOP_DoSuperMethod(cl, obj, &msg->mID);
328 /****************************************************************************************/
330 VOID PBM__Hidd_BitMap__PutPixel(OOP_Class *cl, OOP_Object *o,
331 struct pHidd_BitMap_PutPixel *msg)
333 UBYTE **plane;
334 struct planarbm_data *data;
335 ULONG offset;
336 UWORD mask;
337 UBYTE pixel, notpixel;
338 UBYTE i;
340 data = OOP_INST_DATA(cl, o);
342 if (!data->bitmap)
343 return;
345 /* bitmap in plane-mode */
346 plane = data->bitmap->Planes;
347 offset = msg->x / 8 + msg->y * data->bitmap->BytesPerRow;
348 pixel = 128 >> (msg->x % 8);
349 notpixel = ~pixel;
350 mask = 1;
352 for (i = 0; i < data->bitmap->Depth; i++, mask <<=1, plane ++)
354 if ((*plane != NULL) && (*plane != (UBYTE *)-1))
356 if(msg->pixel & mask)
358 *(*plane + offset) = *(*plane + offset) | pixel;
360 else
362 *(*plane + offset) = *(*plane + offset) & notpixel;
368 /****************************************************************************************/
370 ULONG PBM__Hidd_BitMap__GetPixel(OOP_Class *cl, OOP_Object *o,
371 struct pHidd_BitMap_GetPixel *msg)
373 struct planarbm_data *data;
374 UBYTE **plane;
375 ULONG offset;
376 UWORD i;
377 UBYTE pixel;
378 ULONG retval;
380 data = OOP_INST_DATA(cl, o);
382 if (!data->bitmap)
383 return 0;
385 plane = data->bitmap->Planes;
386 offset = msg->x / 8 + msg->y * data->bitmap->BytesPerRow;
387 pixel = 128 >> (msg->x % 8);
388 retval = 0;
390 for (i = 0; i < data->bitmap->Depth; i++, plane ++)
392 if (*plane == (UBYTE *)-1)
394 retval = retval | (1 << i);
396 else if (*plane != NULL)
398 if(*(*plane + offset) & pixel)
400 retval = retval | (1 << i);
405 return retval;
408 /****************************************************************************************/
411 * In fact these two routines are implementations of C2P algorighm. The first one takes chunky
412 * array of 8-bit values, the second one - 32-bit one.
414 static void PBM_PutImage_Native(UBYTE *src, ULONG modulo, struct BitMap *data, UWORD startx, UWORD starty, UWORD width, UWORD height)
416 ULONG planeoffset = starty * data->BytesPerRow + startx / 8;
417 UWORD x, y, d;
419 startx &= 7;
421 for (y = 0; y < height; y++)
423 UBYTE **plane = data->Planes;
425 for (d = 0; d < data->Depth; d++)
427 UWORD dmask = 1L << d;
428 UWORD pmask = 0x80 >> startx;
429 UBYTE *pl = *plane;
431 if (pl == (UBYTE *)-1) continue;
432 if (pl == NULL) continue;
434 pl += planeoffset;
436 for (x = 0; x < width; x++)
438 if (src[x] & dmask)
440 *pl |= pmask;
442 else
444 *pl &= ~pmask;
447 if (pmask == 0x1)
449 pmask = 0x80;
450 pl++;
452 else
454 pmask >>= 1;
456 } /* for (x = 0; x < msg->width; x++) */
458 plane++;
460 } /* for (d = 0; d < data->depth; d++) */
462 src += modulo;
463 planeoffset += data->BytesPerRow;
464 } /* for (y = 0; y < msg->height; y++) */
467 static void PBM_PutImage_Native32(HIDDT_Pixel *src, ULONG modulo, struct BitMap *data, UWORD startx, UWORD starty, UWORD width, UWORD height)
469 ULONG planeoffset = starty * data->BytesPerRow + startx / 8;
470 UWORD x, y, d;
472 startx &= 7;
474 for (y = 0; y < height; y++)
476 UBYTE **plane = data->Planes;
478 for (d = 0; d < data->Depth; d++)
480 UWORD dmask = 1L << d;
481 UWORD pmask = 0x80 >> startx;
482 UBYTE *pl = *plane;
484 if (pl == (UBYTE *)-1) continue;
485 if (pl == NULL) continue;
487 pl += planeoffset;
489 for (x = 0; x < width; x++)
491 if (src[x] & dmask)
493 *pl |= pmask;
495 else
497 *pl &= ~pmask;
500 if (pmask == 0x1)
502 pmask = 0x80;
503 pl++;
505 else
507 pmask >>= 1;
509 } /* for (x = 0; x < msg->width; x++) */
511 plane++;
513 } /* for (d = 0; d < data->depth; d++) */
515 src = ((APTR)src + modulo);
516 planeoffset += data->BytesPerRow;
517 } /* for (y = 0; y < msg->height; y++) */
520 VOID PBM__Hidd_BitMap__PutImage(OOP_Class *cl, OOP_Object *o,
521 struct pHidd_BitMap_PutImage *msg)
523 struct planarbm_data *data = OOP_INST_DATA(cl, o);
525 if (!data->bitmap)
526 return;
528 if ((msg->pixFmt != vHidd_StdPixFmt_Native) &&
529 (msg->pixFmt != vHidd_StdPixFmt_Native32))
531 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
532 return;
535 switch(msg->pixFmt)
537 case vHidd_StdPixFmt_Native:
538 PBM_PutImage_Native(msg->pixels, msg->modulo, data->bitmap, msg->x, msg->y, msg->width, msg->height);
539 break;
541 case vHidd_StdPixFmt_Native32:
542 PBM_PutImage_Native32((HIDDT_Pixel *)msg->pixels, msg->modulo, data->bitmap, msg->x, msg->y, msg->width, msg->height);
543 break;
548 /****************************************************************************************/
550 VOID PBM__Hidd_BitMap__PutImageLUT(OOP_Class *cl, OOP_Object *o,
551 struct pHidd_BitMap_PutImageLUT *msg)
553 struct planarbm_data *data = OOP_INST_DATA(cl, o);
555 if (!data->bitmap)
556 return;
558 /* This is the same as PutImage() with vHidd_StdPixFmt_Native format */
559 PBM_PutImage_Native(msg->pixels, msg->modulo, data->bitmap, msg->x, msg->y, msg->width, msg->height);
562 /****************************************************************************************/
564 VOID PBM__Hidd_BitMap__GetImageLUT(OOP_Class *cl, OOP_Object *o,
565 struct pHidd_BitMap_GetImageLUT *msg)
567 WORD x, y, d;
568 UBYTE *pixarray = (UBYTE *)msg->pixels;
569 UBYTE **plane;
570 ULONG planeoffset;
571 struct planarbm_data *data;
572 UBYTE prefill;
574 data = OOP_INST_DATA(cl, o);
576 if (!data->bitmap)
577 return;
579 planeoffset = msg->y * data->bitmap->BytesPerRow + msg->x / 8;
581 prefill = 0;
582 for (d = 0; d < data->bitmap->Depth; d++)
584 if (data->bitmap->Planes[d] == (UBYTE *)-1)
586 prefill |= (1L << d);
590 for (y = 0; y < msg->height; y++)
592 UBYTE *dest = pixarray;
594 plane = data->bitmap->Planes;
595 for(x = 0; x < msg->width; x++)
597 dest[x] = prefill;
600 for (d = 0; d < data->bitmap->Depth; d++)
602 UWORD dmask = 1L << d;
603 UWORD pmask = 0x80 >> (msg->x & 7);
604 UBYTE *pl = *plane;
606 if (pl == (UBYTE *)-1) continue;
607 if (pl == NULL) continue;
609 pl += planeoffset;
611 for (x = 0; x < msg->width; x++)
613 if (*pl & pmask)
615 dest[x] |= dmask;
617 else
619 dest[x] &= ~dmask;
622 if (pmask == 0x1)
624 pmask = 0x80;
625 pl++;
627 else
629 pmask >>= 1;
632 } /* for(x = 0; x < msg->width; x++) */
634 plane++;
636 } /* for(d = 0; d < data->depth; d++) */
638 pixarray += msg->modulo;
639 planeoffset += data->bitmap->BytesPerRow;
641 } /* for(y = 0; y < msg->height; y++) */
645 /****************************************************************************************/
647 BOOL PBM__Hidd_PlanarBM__SetBitMap(OOP_Class *cl, OOP_Object *o,
648 struct pHidd_PlanarBM_SetBitMap *msg)
650 return PBM_SetBitMap(cl, o, msg->bitMap);
653 /****************************************************************************************/
655 BOOL PBM__Hidd_PlanarBM__GetBitMap(OOP_Class *cl, OOP_Object *o,
656 struct pHidd_PlanarBM_GetBitMap *msg)
658 struct planarbm_data *data = OOP_INST_DATA(cl, o);
660 if (!data->bitmap)
661 return FALSE;
664 * Totally obsolete and deprecated.
665 * Just get aoHidd_PlanarBM_BitMap value instead.
667 CopyMem(data->bitmap, msg->bitMap, sizeof(struct BitMap));
668 return TRUE;