2 Copyright 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: Bitmap class for native Amiga chipset.
10 /****************************************************************************************/
16 #include <proto/oop.h>
17 #include <proto/utility.h>
18 #include <exec/alerts.h>
19 #include <aros/macros.h>
20 #include <exec/memory.h>
21 #include <exec/lists.h>
22 #include <graphics/rastport.h>
23 #include <graphics/gfx.h>
25 #include <hidd/graphics.h>
26 #include <aros/symbolsets.h>
28 #define CMDDEBUGUNIMP(x) ;
29 #define CMDDEBUGPIXEL(x) ;
33 #include <aros/debug.h>
35 #include LC_LIBDEFS_FILE
37 #include "amigavideogfx.h"
38 #include "amigavideobitmap.h"
43 /****************************************************************************************/
45 #define AO(x) (aoHidd_BitMap_ ## x)
46 #define GOT_BM_ATTR(code) GOT_ATTR(code, aoHidd_BitMap, bitmap)
48 /****************************************************************************************/
50 static void setrtg(struct amigavideo_staticdata
*csd
, BOOL showrtg
)
54 OOP_Object
*AmigaVideoBM__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
56 struct amigavideo_staticdata
*csd
= CSD(cl
);
57 IPTR width
, height
, depth
, disp
;
59 struct amigabm_data
*data
;
61 DB2(bug("AmigaVideoBM__Root__New\n"));
63 o
=(OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
67 data
= OOP_INST_DATA(cl
, o
);
68 memset(data
, 0, sizeof (*data
));
70 data
->align
= csd
->aga
? 64 : 16; // AGA 64-bit fetchmode needs 8-byte alignment
72 /* Get some data about the dimensions of the bitmap */
73 OOP_GetAttr(o
, aHidd_BitMap_Width
, &width
);
74 OOP_GetAttr(o
, aHidd_BitMap_Height
, &height
);
75 OOP_GetAttr(o
, aHidd_BitMap_Depth
, &depth
);
76 OOP_GetAttr(o
, aoHidd_BitMap_Displayable
, &disp
);
78 DB2(bug("%dx%dx%d\n", width
, height
, depth
));
80 /* We cache some info */
82 data
->bytesperrow
= ((width
+ data
->align
- 1) & ~(data
->align
- 1)) / 8;
83 data
->height
= height
;
85 data
->pixelcacheoffset
= -1;
88 /* Allocate memory for plane array */
89 data
->planes
= AllocVec(sizeof(UBYTE
*) * depth
, MEMF_PUBLIC
| MEMF_CLEAR
);
90 if (NULL
== data
->planes
) {
94 /* Allocate all the planes */
95 for (i
= 0; i
< depth
&& ok
; i
++) {
96 data
->planes
[i
] = AllocMem(data
->bytesperrow
* data
->height
, MEMF_CHIP
| MEMF_CLEAR
);
97 if (NULL
== data
->planes
[i
])
104 OOP_MethodID dispose_mid
;
106 dispose_mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
107 OOP_CoerceMethod(cl
, o
, (OOP_Msg
)&dispose_mid
);
112 DB2(bug("ret=%x bm=%x\n", o
, data
));
117 VOID
AmigaVideoBM__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
119 struct amigabm_data
*data
;
122 data
= OOP_INST_DATA(cl
, o
);
124 DB2(bug("AmigaVideoBM__Root__Dispose %x bm=%x\n", o
, data
));
126 DB2(bug("removing displayed bitmap?!\n"));
128 if (NULL
!= data
->planes
)
130 for (i
= 0; i
< data
->depth
; i
++)
132 if (NULL
!= data
->planes
[i
])
134 FreeMem(data
->planes
[i
], data
->bytesperrow
* data
->height
);
137 FreeVec(data
->planes
);
140 OOP_DoSuperMethod(cl
, o
, msg
);
146 VOID
AmigaVideoBM__Root__Set(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Set
*msg
)
148 struct amigavideo_staticdata
*csd
= CSD(cl
);
149 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
150 struct TagItem
*tag
, *tstate
;
154 DB2(bug("AmigaVideoBM__Root__Set\n"));
155 tstate
= msg
->attrList
;
156 while((tag
= NextTagItem((const struct TagItem
**)&tstate
)))
158 DB2(bug("%d/%d\n", tag
->ti_Tag
, tag
->ti_Data
));
159 if(IS_BITMAP_ATTR(tag
->ti_Tag
, idx
))
161 DB2(bug("->%d\n", idx
));
164 case aoHidd_BitMap_Visible
:
165 data
->disp
= tag
->ti_Data
;
174 case aoHidd_BitMap_LeftEdge
:
175 if (data
->leftedge
!= tag
->ti_Data
) {
176 data
->leftedge
= tag
->ti_Data
;
180 case aoHidd_BitMap_TopEdge
:
181 if (data
->topedge
!= tag
->ti_Data
) {
182 data
->topedge
= tag
->ti_Data
;
183 if (data
->topedge
< 0)
185 if (data
->topedge
>= data
->height
)
186 data
->topedge
= data
->height
- 1;
193 DB2(bug("AmigaVideoBM__Root__Set Exit\n"));
194 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
195 if (moved
&& csd
->disp
== data
)
196 setscroll(csd
, data
);
199 VOID
AmigaVideoBM__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
201 struct amigavideo_staticdata
*csd
= CSD(cl
);
202 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
205 DB2(bug("AmigaVideoBM__Root__Get %d, Attr=%d AmigaVideoBitmap=%d\n", msg
->attrID
, __IHidd_Attr
, __IHidd_AmigaVideoBitmap
));
206 if (IS_AmigaVideoBM_ATTR(msg
->attrID
, idx
)) {
207 DB2(bug("AVBM=%d\n", idx
));
210 case aoHidd_AmigaVideoBitMap_Drawable
:
211 *msg
->storage
= TRUE
;
214 } else if (IS_BITMAP_ATTR(msg
->attrID
, idx
)) {
215 DB2(bug("BM=%d\n", idx
));
218 case aoHidd_BitMap_LeftEdge
:
219 *msg
->storage
= data
->leftedge
;
221 case aoHidd_BitMap_TopEdge
:
222 *msg
->storage
= data
->topedge
;
224 case aoHidd_BitMap_Visible
:
225 *msg
->storage
= data
->disp
;
227 case aoHidd_BitMap_Align
:
228 *msg
->storage
= csd
->aga
? 64 : 16;
230 case aoHidd_BitMap_BytesPerRow
:
231 if (data
->bytesperrow
== 0) {
233 IPTR align
= csd
->aga
? 64 : 16;
234 OOP_GetAttr(o
, aHidd_BitMap_Width
, &width
);
235 *msg
->storage
= ((width
+ align
- 1) & ~(align
- 1)) / 8;
237 *msg
->storage
= data
->bytesperrow
;
242 DB2(bug("AmigaVideoBM__Root__Get Exit\n"));
243 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
246 /****************************************************************************************/
248 static int AmigaVideoBM_Init(LIBBASETYPEPTR LIBBASE
)
250 D(bug("AmigaVideoBM_Init\n"));
251 return TRUE
; //return OOP_ObtainAttrBases(attrbases);
254 /****************************************************************************************/
256 static int AmigaVideoBM_Expunge(LIBBASETYPEPTR LIBBASE
)
258 D(bug("AmigaVideoBM_Expunge\n"));
259 //OOP_ReleaseAttrBases(attrbases);
263 /****************************************************************************************/
265 ADD2INITLIB(AmigaVideoBM_Init
, 0);
266 ADD2EXPUNGELIB(AmigaVideoBM_Expunge
, 0);
268 /****************************************************************************************/
270 BOOL
AmigaVideoBM__Hidd_BitMap__SetColors(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_SetColors
*msg
)
272 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
273 struct amigavideo_staticdata
*csd
= CSD(cl
);
275 if (!OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
))
277 return setcolors(csd
, msg
, data
->disp
);
280 /****************************************************************************************/
282 #define CLEARCACHE flushpixelcache(data)
283 /* Better than nothing but m68k assembly C2P still needed for best performance */
284 static void flushpixelcache(struct amigabm_data
*data
)
287 ULONG offset
= data
->pixelcacheoffset
;
288 UBYTE
**plane
= data
->planes
;
290 if (data
->writemask
) {
292 ULONG pixel
, notpixel
, wmask
;
293 if (~data
->writemask
) {
294 for (i
= 0; i
< data
->depth
; i
++) {
295 if (plane
[i
] == (UBYTE
*)-1)
296 tmpplanes
[i
] = 0xffffffff;
297 else if (plane
[i
] == NULL
)
298 tmpplanes
[i
] = 0x00000000;
300 tmpplanes
[i
] = *((ULONG
*)(plane
[i
] + offset
));
305 for (x
= 0; pixel
; x
++, pixel
>>= 1, wmask
<<= 1) {
306 if (data
->writemask
& wmask
) {
307 UBYTE c
= data
->pixelcache
[x
];
310 for (i
= 0; i
< data
->depth
; i
++, mask
<<= 1) {
311 if (plane
[i
] != NULL
&& plane
[i
] != (UBYTE
*)-1) {
313 tmpplanes
[i
] |= pixel
;
315 tmpplanes
[i
] &= notpixel
;
320 for (i
= 0; i
< data
->depth
; i
++) {
321 if (plane
[i
] != NULL
&& plane
[i
] != (UBYTE
*)-1)
322 *((ULONG
*)(plane
[i
] + offset
)) = tmpplanes
[i
];
325 data
->pixelcacheoffset
= -1;
329 VOID
AmigaVideoBM__Hidd_BitMap__PutPixel(OOP_Class
*cl
, OOP_Object
*o
,
330 struct pHidd_BitMap_PutPixel
*msg
)
332 struct amigabm_data
*data
;
336 data
= OOP_INST_DATA(cl
, o
);
338 offset
= msg
->x
/ 8 + msg
->y
* data
->bytesperrow
;
339 if ((offset
& ~3) != data
->pixelcacheoffset
) {
341 data
->pixelcacheoffset
= offset
& ~3;
343 bit
= (offset
- data
->pixelcacheoffset
) * 8 + (msg
->x
& 7);
344 data
->pixelcache
[bit
] = msg
->pixel
;
345 data
->writemask
|= 1 << bit
;
347 CMDDEBUGPIXEL(bug("PutPixel: %dx%d %x\n", msg
->x
, msg
->y
, msg
->pixel
));
350 /****************************************************************************************/
352 ULONG
AmigaVideoBM__Hidd_BitMap__GetPixel(OOP_Class
*cl
, OOP_Object
*o
,
353 struct pHidd_BitMap_GetPixel
*msg
)
355 struct amigabm_data
*data
;
359 data
= OOP_INST_DATA(cl
, o
);
360 offset
= msg
->x
/ 8 + msg
->y
* data
->bytesperrow
;
362 if ((offset
& ~3) != data
->pixelcacheoffset
) {
363 ULONG tmpplanes
[8], mask
;
365 UBYTE
**plane
= data
->planes
;
368 data
->pixelcacheoffset
= offset
& ~3;
369 for (i
= 0; i
< data
->depth
; i
++) {
370 if (plane
[i
] == (UBYTE
*)-1)
371 tmpplanes
[i
] = 0xffffffff;
372 else if (plane
[i
] == NULL
)
373 tmpplanes
[i
] = 0x00000000;
375 tmpplanes
[i
] = *((ULONG
*)(plane
[i
] + data
->pixelcacheoffset
));
378 for (x
= 0; mask
; x
++, mask
>>= 1) {
379 UBYTE c
= 0, pixel
= 1;
380 for(i
= 0; i
< data
->depth
; i
++, pixel
<<= 1) {
381 if (tmpplanes
[i
] & mask
)
384 data
->pixelcache
[x
] = c
;
387 bit
= (offset
- data
->pixelcacheoffset
) * 8 + (msg
->x
& 7);
388 c
= data
->pixelcache
[bit
];
389 CMDDEBUGPIXEL(bug("GetPixel: %dx%d %x\n", msg
->x
, msg
->y
, c
));
393 /****************************************************************************************/
395 VOID
AmigaVideoBM__Hidd_BitMap__DrawLine(OOP_Class
*cl
, OOP_Object
*o
,
396 struct pHidd_BitMap_DrawLine
*msg
)
398 HIDDT_Pixel fg
= GC_FG(msg
->gc
);
399 HIDDT_DrawMode mode
= GC_DRMD(msg
->gc
);
400 struct amigavideo_staticdata
*csd
= CSD(cl
);
401 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
404 if (msg
->x1
== msg
->x2
|| msg
->y1
== msg
->y2
) {
405 WORD x1
= msg
->x1
, x2
= msg
->x2
;
406 WORD y1
= msg
->y1
, y2
= msg
->y2
;
421 if (x1
>= data
->width
)
423 if (y1
>= data
->height
)
429 if (x2
>= data
->width
)
430 x2
= data
->width
- 1;
431 if (y2
>= data
->height
)
432 y2
= data
->height
- 1;
433 if (!blit_fillrect(csd
, data
, x1
, y1
, x2
, y2
, fg
, mode
))
434 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
436 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
437 CMDDEBUGUNIMP(bug("DrawLine\n"));
441 /****************************************************************************************/
443 VOID
AmigaVideoBM__Hidd_BitMap__PutPattern(OOP_Class
*cl
, OOP_Object
*o
,
444 struct pHidd_BitMap_PutPattern
*msg
)
446 struct amigavideo_staticdata
*csd
= CSD(cl
);
447 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
450 D(bug("PutPattern(%dx%d,%dx%d,mask=%x,mod=%d,masksrcx=%d)\n(%x,%dx%d,h=%d,d=%d,lut=%x,inv=%d)(fg=%d,bg=%d,colexp=%d,drmd=%d)\n",
451 msg
->x
, msg
->y
, msg
->width
, msg
->height
,
452 msg
->mask
, msg
->maskmodulo
, msg
->masksrcx
,
453 msg
->pattern
, msg
->patternsrcx
, msg
->patternsrcy
, msg
->patternheight
, msg
->patterndepth
, msg
->patternlut
, msg
->invertpattern
,
454 GC_FG(msg
->gc
), GC_BG(msg
->gc
), GC_COLEXP(msg
->gc
), GC_DRMD(msg
->gc
)));
456 if (!blit_putpattern(csd
, data
, msg
))
457 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
461 /****************************************************************************************/
463 VOID
AmigaVideoBM__Hidd_BitMap__PutImageLUT(OOP_Class
*cl
, OOP_Object
*o
,
464 struct pHidd_BitMap_PutImageLUT
*msg
)
467 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
470 struct amigabm_data
*data
;
472 CMDDEBUGUNIMP(bug("PutImageLUT\n"));
474 data
= OOP_INST_DATA(cl
, o
);
477 planeoffset
= msg
->y
* data
->bytesperrow
+ msg
->x
/ 8;
479 for(y
= 0; y
< msg
->height
; y
++)
481 UBYTE
*src
= pixarray
;
483 plane
= data
->planes
;
485 for(d
= 0; d
< data
->depth
; d
++)
487 ULONG dmask
= 1L << d
;
488 ULONG pmask
= 0x80 >> (msg
->x
& 7);
491 if (pl
== (UBYTE
*)-1) continue;
492 if (pl
== NULL
) continue;
496 for(x
= 0; x
< msg
->width
; x
++)
517 } /* for(x = 0; x < msg->width; x++) */
521 } /* for(d = 0; d < data->depth; d++) */
523 pixarray
+= msg
->modulo
;
524 planeoffset
+= data
->bytesperrow
;
526 } /* for(y = 0; y < msg->height; y++) */
529 /****************************************************************************************/
531 VOID
AmigaVideoBM__Hidd_BitMap__GetImageLUT(OOP_Class
*cl
, OOP_Object
*o
,
532 struct pHidd_BitMap_GetImageLUT
*msg
)
535 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
538 struct amigabm_data
*data
;
541 data
= OOP_INST_DATA(cl
, o
);
543 D(bug("[%s] Get %dx%d to %dx%d from %d planes to buffer at %p\n", __func__
, msg
->x
, msg
->y
, msg
->x
+ msg
->width
- 1, msg
->y
+ msg
->height
- 1, data
->depth
, msg
->pixels
));
545 planeoffset
= msg
->y
* data
->bytesperrow
+ msg
->x
/ 8;
548 for (d
= 0; d
< data
->depth
; d
++)
550 if (data
->planes
[d
] == (UBYTE
*)-1)
552 prefill
|= (1L << d
);
556 for (y
= 0; y
< msg
->height
; y
++)
558 UBYTE
*dest
= pixarray
;
560 plane
= data
->planes
;
561 for(x
= 0; x
< msg
->width
; x
++)
566 for (d
= 0; d
< data
->depth
; d
++)
568 ULONG dmask
= 1L << d
;
569 ULONG pmask
= 0x80 >> (msg
->x
& 7);
572 if (pl
== (UBYTE
*)-1) continue;
573 if (pl
== NULL
) continue;
577 for (x
= 0; x
< msg
->width
; x
++)
598 } /* for(x = 0; x < msg->width; x++) */
602 } /* for(d = 0; d < data->depth; d++) */
604 pixarray
+= msg
->modulo
;
605 planeoffset
+= data
->bytesperrow
;
607 } /* for(y = 0; y < msg->height; y++) */
609 D(bug("[%s] Got %d\n", __func__
, *(UBYTE
*)msg
->pixels
));
613 /****************************************************************************************/
615 VOID
AmigaVideoBM__Hidd_BitMap__PutImage(OOP_Class
*cl
, OOP_Object
*o
,
616 struct pHidd_BitMap_PutImage
*msg
)
619 UBYTE
*pixarray
= (UBYTE
*)msg
->pixels
;
622 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
626 if ((msg
->pixFmt
!= vHidd_StdPixFmt_Native
) &&
627 (msg
->pixFmt
!= vHidd_StdPixFmt_Native32
))
629 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
632 CMDDEBUGUNIMP(bug("PutImage\n"));
634 planeoffset
= msg
->y
* data
->bytesperrow
+ msg
->x
/ 8;
636 for(y
= 0; y
< msg
->height
; y
++)
640 case vHidd_StdPixFmt_Native
:
642 UBYTE
*src
= pixarray
;
644 plane
= data
->planes
;
646 for(d
= 0; d
< data
->depth
; d
++)
648 ULONG dmask
= 1L << d
;
649 ULONG pmask
= 0x80 >> (msg
->x
& 7);
652 if (pl
== (UBYTE
*)-1) continue;
653 if (pl
== NULL
) continue;
657 for(x
= 0; x
< msg
->width
; x
++)
678 } /* for(x = 0; x < msg->width; x++) */
682 } /* for(d = 0; d < data->depth; d++) */
684 pixarray
+= msg
->modulo
;
685 planeoffset
+= data
->bytesperrow
;
689 case vHidd_StdPixFmt_Native32
:
691 HIDDT_Pixel
*src
= (HIDDT_Pixel
*)pixarray
;
693 plane
= data
->planes
;
695 for(d
= 0; d
< data
->depth
; d
++)
697 ULONG dmask
= 1L << d
;
698 ULONG pmask
= 0x80 >> (msg
->x
& 7);
701 if (pl
== (UBYTE
*)-1) continue;
702 if (pl
== NULL
) continue;
706 for(x
= 0; x
< msg
->width
; x
++)
727 } /* for(x = 0; x < msg->width; x++) */
731 } /* for(d = 0; d < data->depth; d++) */
733 pixarray
+= msg
->modulo
;
734 planeoffset
+= data
->bytesperrow
;
739 } /* switch(msg->pixFmt) */
741 } /* for(y = 0; y < msg->height; y++) */
744 /****************************************************************************************/
746 VOID
AmigaVideoBM__Hidd_BitMap__FillRect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
748 HIDDT_Pixel fg
= GC_FG(msg
->gc
);
749 HIDDT_DrawMode mode
= GC_DRMD(msg
->gc
);
750 struct amigavideo_staticdata
*csd
= CSD(cl
);
751 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
754 if (!blit_fillrect(csd
, data
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
, fg
, mode
)) {
755 CMDDEBUGUNIMP(bug("FillRect\n"));
756 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
760 /****************************************************************************************/
762 VOID
AmigaVideoBM__Hidd_BitMap__PutTemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTemplate
*msg
)
764 struct amigavideo_staticdata
*csd
= CSD(cl
);
765 struct amigabm_data
*data
= OOP_INST_DATA(cl
, o
);
768 if (!blit_puttemplate(csd
, data
, msg
)) {
769 CMDDEBUGUNIMP(bug("PutTemplate: %x x=%d y=%d w=%d h=%d srcx=%d modulo=%d invert=%d\n",
770 msg
->Template
, msg
->x
, msg
->y
, msg
->width
, msg
->height
, msg
->srcx
, msg
->inverttemplate
));
771 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
776 /****************************************************************************************/
778 VOID
AmigaVideoBM__Hidd_BitMap__UpdateRect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_UpdateRect
*msg
)
782 /****************************************************************************************/
784 BOOL
AmigaVideoBM__Hidd_PlanarBM__SetBitMap(OOP_Class
*cl
, OOP_Object
*o
,
785 struct pHidd_PlanarBM_SetBitMap
*msg
)
787 CMDDEBUGUNIMP(bug("SetBitMap\n"));
788 return OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
791 /****************************************************************************************/
793 BOOL
AmigaVideoBM__Hidd_PlanarBM__GetBitMap(OOP_Class
*cl
, OOP_Object
*o
,
794 struct pHidd_PlanarBM_GetBitMap
*msg
)
796 CMDDEBUGUNIMP(bug("GetBitMap\n"));
797 return OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);