2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
8 #include <proto/exec.h>
10 #include <proto/utility.h>
12 #include <hidd/graphics.h>
13 #include <aros/atomic.h>
14 #include <proto/arossupport.h>
16 #include "graphics_intern.h"
17 #include "fakegfxhidd.h"
23 * DISABLE_ARGB_POINTER actually makes the software mouse pointer code to always
24 * behave like if a LUT framebuffer is used.
25 * Useful for debugging if you have only truecolor display modes.
26 * If you define this, make sure that ALWAYS_ALLOCATE_SPRITE_COLORS in
27 * intuition/intuition_intern.h is also defined.
29 #define DISABLE_ARGB_POINTER */
31 #include <aros/debug.h>
33 /******************************************************************************/
35 #define SPECIAL_LOCKING 1 /* When activated mouse cursor relevant locks are
36 treated in some kind of privileged way, by
37 inserting wait-for-sem-requests at head of
38 wait queue, instead of at tail */
40 /******************************************************************************/
42 static OOP_Class
*init_fakefbclass(struct GfxBase
*GfxBase
);
43 static OOP_Class
*init_fakegfxhiddclass (struct GfxBase
*GfxBase
);
45 /******************************************************************************/
50 OOP_Object
*framebuffer
;
59 OOP_Object
*curs_backup
;
61 HIDDT_StdPixFmt curs_pixfmt
;
72 struct SignalSemaphore fbsema
;
76 /******************************************************************************/
78 static void gfx_setFrameBuffer(struct GfxBase
*GfxBase
, struct gfx_data
*data
, OOP_Object
*fb
);
79 static VOID
draw_cursor(struct gfx_data
*data
, BOOL draw
, BOOL updaterect
, struct GfxBase
*GfxBase
);
80 static BOOL
rethink_cursor(struct gfx_data
*data
, struct GfxBase
*GfxBase
);
81 static OOP_Object
*create_fake_fb(OOP_Object
*framebuffer
, struct gfx_data
*data
, struct GfxBase
*GfxBase
);
83 /******************************************************************************/
87 static void FakeGfxHidd_ObtainSemaphore(struct SignalSemaphore
*sigSem
, BOOL urgent
,
88 struct GfxBase
*GfxBase
)
92 /* Get pointer to current task */
95 /* Arbitrate for the semaphore structure */
99 ss_QueueCount == -1 indicates that the semaphore is
100 free, so we increment this straight away. If it then
101 equals 0, then we are the first to allocate this semaphore.
103 Note: This will need protection for SMP machines.
105 sigSem
->ss_QueueCount
++;
106 if( sigSem
->ss_QueueCount
== 0 )
108 /* We now own the semaphore. This is quick. */
109 sigSem
->ss_Owner
= me
;
110 sigSem
->ss_NestCount
++;
113 /* The semaphore was in use, but was it by us? */
114 else if( sigSem
->ss_Owner
== me
)
116 /* Yes, just increase the nesting count */
117 sigSem
->ss_NestCount
++;
121 Else, some other task must own it. We have
122 to set a waiting request here.
127 We need a node to mark our semaphore request. Lets use some
130 struct SemaphoreRequest sr
;
134 Have to clear the signal to make sure that we don't
135 return immediately. We then add the SemReq to the
136 waiters list of the semaphore. We were the last to
137 request, so we must be the last to get the semaphore.
140 AROS_ATOMIC_AND(me
->tc_SigRecvd
, ~SIGF_SINGLE
);
144 AddHead((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
148 AddTail((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
152 Finally, we simply wait, ReleaseSemaphore() will fill in
153 who owns the semaphore.
163 /******************************************************************************/
165 static void FakeGfxHidd_ReleaseSemaphore(struct SignalSemaphore
*sigSem
,
166 struct GfxBase
*GfxBase
)
168 /* Protect the semaphore structure from multiple access. */
171 /* Release one on the nest count */
172 sigSem
->ss_NestCount
--;
173 sigSem
->ss_QueueCount
--;
175 if(sigSem
->ss_NestCount
== 0)
178 There are two cases here. Either we are a shared
179 semaphore, or not. If we are not, make sure that the
180 correct Task is calling ReleaseSemaphore()
184 Do not try and wake anything unless there are a number
185 of tasks waiting. We do both the tests, this is another
186 opportunity to throw an alert if there is an error.
189 sigSem
->ss_QueueCount
>= 0
190 && sigSem
->ss_WaitQueue
.mlh_Head
->mln_Succ
!= NULL
193 struct SemaphoreRequest
*sr
, *srn
;
196 Look at the first node, but only to see whether it
199 sr
= (struct SemaphoreRequest
*)sigSem
->ss_WaitQueue
.mlh_Head
;
202 A node is shared if the ln_Name/sr_Waiter field is
203 odd (ie it has bit 1 set).
205 If the sr_Waiter field is != NULL, then this is a
206 task waiting, otherwise it is a message.
208 if( ((IPTR
)sr
->sr_Waiter
& SM_SHARED
) == SM_SHARED
)
210 /* This is a shared lock, so ss_Owner == NULL */
211 sigSem
->ss_Owner
= NULL
;
213 /* Go through all the nodes to find the shared ones */
214 ForeachNodeSafe(&sigSem
->ss_WaitQueue
, sr
, srn
)
216 srn
= (struct SemaphoreRequest
*)sr
->sr_Link
.mln_Succ
;
218 if( ((IPTR
)sr
->sr_Waiter
& SM_SHARED
) == SM_SHARED
)
220 Remove((struct Node
*)sr
);
222 /* Clear the bit, and update the owner count */
223 sr
->sr_Waiter
= (APTR
)((IPTR
)sr
->sr_Waiter
& ~1);
224 sigSem
->ss_NestCount
++;
226 /* This is a task, signal it */
227 Signal(sr
->sr_Waiter
, SIGF_SINGLE
);
232 /* This is an exclusive lock - awaken first node */
235 /* Only awaken the first of the nodes */
236 Remove((struct Node
*)sr
);
237 sigSem
->ss_NestCount
++;
239 sigSem
->ss_Owner
= sr
->sr_Waiter
;
240 Signal(sr
->sr_Waiter
, SIGF_SINGLE
);
243 } /* there are waiters */
244 /* Otherwise, there are not tasks waiting. */
247 sigSem
->ss_Owner
= NULL
;
248 sigSem
->ss_QueueCount
= -1;
251 else if(sigSem
->ss_NestCount
< 0)
254 This can't happen. It means that somebody has released
255 more times than they have obtained.
257 Alert( AN_SemCorrupt
);
265 /******************************************************************************/
267 #define LFB(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, FALSE, GfxBase)
268 #define UFB(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, GfxBase)
269 #define LFB_QUICK(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, TRUE, GfxBase)
270 #define UFB_QUICK(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, GfxBase)
272 #else /* !SPECIAL_LOCKING */
274 #define LFB(data) ObtainSemaphore(&(data)->fbsema)
275 #define UFB(data) ReleaseSemaphore(&(data)->fbsema)
276 #define LFB_QUICK(data) ObtainSemaphore(&(data)->fbsema)
277 #define UFB_QUICK(data) ReleaseSemaphore(&(data)->fbsema)
279 #endif /* SPECIAL_LOCKING */
281 /******************************************************************************/
283 #define GfxBase ((struct GfxBase *)cl->UserData)
285 static OOP_Object
*gfx_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
287 /* Create a new gfxhid object */
288 OOP_Object
*realgfxhidd
;
289 struct gfx_data
*data
;
292 realgfxhidd
= (OOP_Object
*)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd
, (IPTR
)NULL
, msg
->attrList
);
293 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
297 data
= OOP_INST_DATA(cl
, o
);
298 memset(data
, 0, sizeof (*data
));
299 InitSemaphore(&data
->fbsema
);
302 * If this is direct framebuffer driver, we draw our
303 * cursor on framebuffer bitmap.
304 * Otherwise we draw cursor on displayable bitmaps.
305 * TODO: Implement separate handling for mirrored framebuffers.
306 * In this case we actually don't need to backup pixels
307 * behind the sprite, because we can use mirror for this.
309 data
->fakefb_attr
= (OOP_GET(realgfxhidd
, aHidd_Gfx_FrameBufferType
) == vHidd_FrameBuffer_Direct
) ?
310 aHidd_BitMap_FrameBuffer
: aHidd_BitMap_Displayable
;
312 data
->gfxhidd
= realgfxhidd
;
314 if (NULL
!= data
->gfxhidd
)
316 struct TagItem gctags
[] =
321 data
->gc
= HIDD_Gfx_NewGC(data
->gfxhidd
, gctags
);
322 if (NULL
!= data
->gc
)
332 mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
333 OOP_CoerceMethod(cl
, o
, (OOP_Msg
)&mid
);
339 static VOID
gfx_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
341 struct gfx_data
*data
;
343 data
= OOP_INST_DATA(cl
, o
);
344 if (NULL
!= data
->curs_backup
)
346 OOP_DisposeObject(data
->curs_backup
);
347 data
->curs_backup
= NULL
;
350 if (data
->curs_pixels
)
351 FreeMem(data
->curs_pixels
, data
->curs_width
* data
->curs_height
* 4);
353 if (NULL
!= data
->gc
)
355 OOP_DisposeObject(data
->gc
);
360 static void gfx_get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
362 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
364 if (msg
->attrID
== aHidd_Gfx_HWSpriteTypes
) {
365 *msg
->storage
= vHidd_SpriteType_3Plus1
|vHidd_SpriteType_DirectColor
;
369 OOP_DoMethod(data
->gfxhidd
, (OOP_Msg
)msg
);
372 static OOP_Object
*gfx_newbitmap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
)
374 /* Is the user about to create a framebuffer ? */
376 struct gfx_data
*data
;
378 OOP_Object
*ret
= NULL
;
380 data
= OOP_INST_DATA(cl
, o
);
381 create_fb
= (BOOL
)GetTagData(data
->fakefb_attr
, FALSE
, msg
->attrList
);
383 realfb
= HIDD_Gfx_NewBitMap(data
->gfxhidd
, msg
->attrList
);
385 if (realfb
&& create_fb
)
387 ret
= create_fake_fb(realfb
, data
, GfxBase
);
389 OOP_DisposeObject(realfb
);
397 static BOOL
gfx_setcursorshape(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorShape
*msg
)
399 struct gfx_data
*data
;
403 data
= OOP_INST_DATA(cl
, o
);
405 D(bug("[FakeGfx] SetCursorShape(0x%p)\n", shape
));
410 /* Erase the old cursor */
411 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
412 data
->curs_on
= FALSE
;
413 data
->curs_bm
= NULL
;
414 data
->curs_x
= data
->curs_y
= 0;
415 data
->curs_maxx
= data
->curs_maxy
= 0;
416 data
->curs_width
= data
->curs_height
= 0;
417 data
->curs_xoffset
= 0;
418 data
->curs_yoffset
= 0;
420 if (NULL
!= data
->curs_backup
)
422 OOP_DisposeObject(data
->curs_backup
);
423 data
->curs_backup
= NULL
;
425 if (data
->curs_pixels
) {
426 FreeMem(data
->curs_pixels
, data
->curs_width
* data
->curs_height
* 4);
427 data
->curs_pixels
= NULL
;
432 IPTR curs_width
, curs_height
;
433 APTR new_curs_pixels
;
434 ULONG curs_pixels_len
;
436 OOP_GetAttr(shape
, aHidd_BitMap_Width
, &curs_width
);
437 OOP_GetAttr(shape
, aHidd_BitMap_Height
, &curs_height
);
439 DCURS(bug("[FakeGfx] New cursor size: %lu x %lu, framebuffer 0x%p\n", curs_width
, curs_height
, data
->framebuffer
));
441 /* Create new cursor pixelbuffer. We multiply size by 4 because we want ARGB data
443 curs_pixels_len
= curs_width
* curs_height
* 4;
444 new_curs_pixels
= AllocMem(curs_pixels_len
, MEMF_ANY
|MEMF_CLEAR
);
445 if (!new_curs_pixels
)
450 /* Erase the old cursor */
451 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
453 /* Now that we have disposed the old image using the old
454 backup bm, we can install the new image and backup bm before
455 rendering the new cursor.
456 Backup bitmap is recreated in rethink_cursor()
459 if (data
->curs_pixels
)
460 FreeMem(data
->curs_pixels
, data
->curs_width
* data
->curs_height
* 4);
462 data
->curs_bm
= shape
;
463 data
->curs_width
= curs_width
;
464 data
->curs_height
= curs_height
;
465 data
->curs_maxx
= data
->curs_x
+ curs_width
- 1;
466 data
->curs_maxy
= data
->curs_y
+ curs_height
- 1;
467 data
->curs_pixels
= new_curs_pixels
;
468 data
->curs_xoffset
= msg
->xoffset
;
469 data
->curs_yoffset
= msg
->yoffset
;
471 ok
= rethink_cursor(data
, GfxBase
);
474 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
480 static BOOL
gfx_setcursorpos(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorPos
*msg
)
482 struct gfx_data
*data
;
486 data
= OOP_INST_DATA(cl
, o
);
487 DPOS(bug("[FakeGfx] SetCursorPos(%d, %d)\n", msg
->x
, msg
->y
));
489 if (!data
->framebuffer
)
492 /* We draw our cursor on the bitmap, so we have to convert back
493 from physical to logical coordinates */
494 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_LeftEdge
, &xoffset
);
495 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_TopEdge
, &yoffset
);
498 /* erase the old cursor */
499 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
501 data
->curs_x
= msg
->x
- xoffset
;
502 data
->curs_y
= msg
->y
- yoffset
;
503 /* Shift to the hotspot location */
504 data
->curs_x
+= data
->curs_xoffset
;
505 data
->curs_y
+= data
->curs_yoffset
;
506 data
->curs_maxx
= data
->curs_x
+ data
->curs_width
- 1;
507 data
->curs_maxy
= data
->curs_y
+ data
->curs_height
- 1;
509 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
514 static VOID
gfx_setcursorvisible(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorVisible
*msg
)
516 struct gfx_data
*data
;
518 data
= OOP_INST_DATA(cl
, o
);
526 data
->curs_on
= TRUE
;
527 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
534 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
535 data
->curs_on
= FALSE
;
543 #define PIXEL_INSIDE(fgh, x, y) \
544 ( ( (x) >= (fgh)->curs_x ) \
545 && ( (y) >= (fgh)->curs_y ) \
546 && ( (x) <= (fgh)->curs_maxx ) \
547 && ( (y) <= (fgh)->curs_maxy ) )
549 /* NOTE: x1, y1, x2, y2 MUST be sorted */
550 #define RECT_INSIDE(fgh, x1, y1, x2, y2) \
551 ( ( (x1) <= fgh->curs_maxx ) \
552 && ( (x2) >= fgh->curs_x ) \
553 && ( (y1) <= fgh->curs_maxy ) \
554 && ( (y2) >= fgh->curs_y ) )
556 #define WRECT_INSIDE(fgh, x1, y1, width, height) \
557 RECT_INSIDE(fgh, x1, y1, (x1) + (width) - 1, (y1) + (height) - 1)
559 static void gfx_copybox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
561 struct gfx_data
*data
;
562 OOP_Object
*src
= NULL
;
563 OOP_Object
*dest
= NULL
;
566 data
= OOP_INST_DATA(cl
, o
);
569 /* De-masquerade bitmap objects, every of which can be fakefb object */
570 OOP_GetAttr(msg
->src
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&src
);
571 OOP_GetAttr(msg
->dest
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&dest
);
577 /* FIXME: other bitmap may belong to another instance of fakegfx which can be on
578 display on another monitor. In this case mouse cursor should be handled also
579 there. Needs further reengineering. */
580 if ((msg
->src
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->srcX
, msg
->srcY
, msg
->width
, msg
->height
))
583 if ((msg
->dest
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
587 draw_cursor(data
, FALSE
, FALSE
, GfxBase
);
589 HIDD_Gfx_CopyBox(data
->gfxhidd
, src
, msg
->srcX
, msg
->srcY
,
590 dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
, msg
->gc
);
593 draw_cursor(data
, TRUE
, FALSE
, GfxBase
);
598 static IPTR
gfx_copyboxmasked(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBoxMasked
*msg
)
600 struct gfx_data
*data
;
601 OOP_Object
*src
= NULL
;
602 OOP_Object
*dest
= NULL
;
606 data
= OOP_INST_DATA(cl
, o
);
609 /* De-masquerade bitmap objects, every of which can be fakefb object */
610 OOP_GetAttr(msg
->src
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&src
);
611 OOP_GetAttr(msg
->dest
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&dest
);
618 * FIXME: other bitmap may belong to another instance of fakegfx which can be on
619 * display on another monitor. In this case mouse cursor should be handled also
620 * there. Needs further reengineering.
622 if ((msg
->src
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->srcX
, msg
->srcY
, msg
->width
, msg
->height
))
625 if ((msg
->dest
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
629 draw_cursor(data
, FALSE
, FALSE
, GfxBase
);
631 ret
= HIDD_Gfx_CopyBoxMasked(data
->gfxhidd
, src
, msg
->srcX
, msg
->srcY
,
632 dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
, msg
->mask
, msg
->gc
);
635 draw_cursor(data
, TRUE
, FALSE
, GfxBase
);
642 static OOP_Object
*gfx_show(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_Show
*msg
)
645 struct gfx_data
*data
;
647 data
= OOP_INST_DATA(cl
, o
);
650 D(bug("[FakeGfx] Show(0x%p)\n", ret
));
653 * If we are attempting to show a fake bitmap, we are working
654 * in NoFrameBuffer mode where each displayable bitmap is
657 if (ret
&& (OOP_OCLASS(ret
) == CDD(GfxBase
)->fakefbclass
))
660 OOP_GetAttr(msg
->bitMap
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&ret
);
661 D(bug("[FakeGfx] Bitmap is a fakefb object, real bitmap is 0x%p\n", ret
));
665 draw_cursor(data
, FALSE
, FALSE
, GfxBase
);
667 ret
= HIDD_Gfx_Show(data
->gfxhidd
, ret
, msg
->flags
);
668 D(bug("[FakeGfx] Real framebuffer object 0x%p\n", ret
));
669 gfx_setFrameBuffer(GfxBase
, data
, ret
);
672 /* FIXME: temporary workaround: at this point Intuition has already destroyed
673 the sprite image (since the last screen was closed) but we have no information
674 about it. Perhaps FreeSpriteData() should track this down somehow and inform
675 drivers about destroyed sprites.
677 data->curs_bm = NULL;*/
678 rethink_cursor(data
, GfxBase
);
679 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
683 D(bug("[FakeGfx] Returning 0x%p\n", ret
));
687 static BOOL
gfx_getmaxspritesize(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_GetMaxSpriteSize
*msg
)
689 if (msg
->Type
& (vHidd_SpriteType_3Plus1
|vHidd_SpriteType_DirectColor
)) {
690 /* I hope these values are enough for everyone :) */
692 *msg
->Height
= 65535;
699 static IPTR
gfx_fwd(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
701 struct gfx_data
*data
;
703 data
= OOP_INST_DATA(cl
, o
);
705 return OOP_DoMethod(data
->gfxhidd
, msg
);
708 /* Private non-virtual method */
709 static BOOL
FakeGfx_UpdateFrameBuffer(OOP_Object
*o
)
711 OOP_Class
*cl
= OOP_OCLASS(o
);
712 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
717 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_Width
, &data
->fb_width
);
718 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_Height
, &data
->fb_height
);
720 DCURS(bug("[FakeGfx] Changed framebuffer size: %u x %u\n", data
->fb_width
, data
->fb_height
));
722 ok
= rethink_cursor(data
, GfxBase
);
725 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
731 OOP_Object
*framebuffer
;
732 OOP_Object
*fakegfxhidd
;
735 #define FGH(data) ((struct gfx_data *)data->fakegfxhidd)
736 #define REMOVE_CURSOR(data) \
737 draw_cursor(FGH(data), FALSE, FALSE, GfxBase)
739 #define RENDER_CURSOR(data) \
740 draw_cursor(FGH(data), TRUE, FALSE, GfxBase)
743 #define BITMAP_METHOD_INIT \
744 struct fakefb_data *data; \
745 BOOL inside = FALSE; \
747 struct gfx_data *fgh; \
748 data = OOP_INST_DATA(cl, o); \
752 #define FORWARD_METHOD \
753 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
755 #define BITMAP_METHOD_EXIT \
757 RENDER_CURSOR(data); \
762 static OOP_Object
*fakefb_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
764 OOP_Object
*framebuffer
;
765 OOP_Object
*fakegfxhidd
;
767 framebuffer
= (OOP_Object
*)GetTagData(aHidd_FakeFB_RealBitMap
, 0, msg
->attrList
);
768 fakegfxhidd
= (OOP_Object
*)GetTagData(aHidd_FakeFB_FakeGfxHidd
, 0, msg
->attrList
);
770 if (NULL
== framebuffer
|| NULL
== fakegfxhidd
)
772 D(bug("!!! FakeBM::New(): MISSING FRAMEBUFFER OR FAKE GFX HIDD !!!\n"));
776 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
779 struct fakefb_data
*data
;
780 data
= OOP_INST_DATA(cl
, o
);
781 data
->framebuffer
= framebuffer
;
782 data
->fakegfxhidd
= fakegfxhidd
;
787 static VOID
fakefb_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
789 struct fakefb_data
*data
;
790 data
= OOP_INST_DATA(cl
, o
);
791 if (NULL
!= data
->framebuffer
)
793 OOP_DisposeObject(data
->framebuffer
);
794 data
->framebuffer
= NULL
;
798 static void fakefb_get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
800 struct fakefb_data
*data
= OOP_INST_DATA(cl
, o
);
802 if (msg
->attrID
== aHidd_FakeFB_RealBitMap
)
804 *msg
->storage
= (IPTR
)data
->framebuffer
;
807 else if (msg
->attrID
== aHidd_BitMap_GfxHidd
)
809 *msg
->storage
= (IPTR
)data
->fakegfxhidd
;
813 OOP_DoMethod(data
->framebuffer
, (OOP_Msg
)msg
);
816 /* Intercept framebuffer mode change */
817 static IPTR
fakefb_set(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Set
*msg
)
819 struct fakefb_data
*data
= OOP_INST_DATA(cl
, o
);
820 IPTR ret
= OOP_DoMethod(data
->framebuffer
, &msg
->mID
);
821 struct TagItem
*modeid
= FindTagItem(aHidd_BitMap_ModeID
, msg
->attrList
);
825 /* Framebuffer mode change succeeded. Update fakegfx' information */
826 ret
= FakeGfx_UpdateFrameBuffer(data
->fakegfxhidd
);
832 static IPTR
fakefb_getpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetPixel
*msg
)
836 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
847 static IPTR
fakefb_putpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPixel
*msg
)
851 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
862 static IPTR
fakefb_drawpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPixel
*msg
)
866 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
877 static IPTR
fakefb_drawline(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawLine
*msg
)
879 register LONG x1
, y1
, x2
, y2
;
882 if (msg
->x1
< msg
->x2
)
884 x1
= msg
->x1
; x2
= msg
->x2
;
888 x2
= msg
->x1
; x1
= msg
->x2
;
891 if (msg
->y1
< msg
->y2
)
893 y1
= msg
->y1
; y2
= msg
->y2
;
897 y2
= msg
->y1
; y1
= msg
->y2
;
900 /* FIXME: Maybe do some more intelligent checking for DrawLine */
901 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
912 static IPTR
fakefb_getimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetImage
*msg
)
916 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
927 static IPTR
fakefb_putimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutImage
*msg
)
931 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
942 static IPTR
fakefb_putalphaimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutAlphaImage
*msg
)
946 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
957 static IPTR
fakefb_puttemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTemplate
*msg
)
961 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
972 static IPTR
fakefb_putalphatemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutAlphaTemplate
*msg
)
976 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
987 static IPTR
fakefb_putpattern(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPattern
*msg
)
991 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1002 static IPTR
fakefb_getimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetImageLUT
*msg
)
1006 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1008 REMOVE_CURSOR(data
);
1017 static IPTR
fakefb_putimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutImageLUT
*msg
)
1021 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1023 REMOVE_CURSOR(data
);
1032 static IPTR
fakefb_puttranspimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTranspImageLUT
*msg
)
1036 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1038 REMOVE_CURSOR(data
);
1047 static IPTR
fakefb_drawrect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
1051 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1052 if (RECT_INSIDE(fgh
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
))
1054 REMOVE_CURSOR(data
);
1063 static IPTR
fakefb_fillrect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
1067 /* bug("BITMAP FILLRECT(%d, %d, %d, %d), (%d, %d, %d, %d, %d, %d)\n"
1068 , msg->minX, msg->minY, msg->maxX, msg->maxY
1069 , fgh->curs_x, fgh->curs_y, fgh->curs_maxx, fgh->curs_maxy
1070 , fgh->curs_width, fgh->curs_height);
1072 if (RECT_INSIDE(fgh
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
))
1074 /* bug("FILLRECT: REMOVING CURSOR\n");
1076 REMOVE_CURSOR(data
);
1086 static IPTR
fakefb_drawellipse(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawEllipse
*msg
)
1088 register LONG x1
, y1
, x2
, y2
;
1091 x1
= msg
->x
- msg
->rx
;
1092 y1
= msg
->y
- msg
->ry
;
1093 x2
= msg
->x
+ msg
->rx
;
1094 y2
= msg
->y
+ msg
->ry
;
1095 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1097 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
1099 REMOVE_CURSOR(data
);
1108 static IPTR
fakefb_fillellipse(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawEllipse
*msg
)
1110 register LONG x1
, y1
, x2
, y2
;
1113 x1
= msg
->x
- msg
->rx
;
1114 y1
= msg
->y
- msg
->ry
;
1115 x2
= msg
->x
+ msg
->rx
;
1116 y2
= msg
->y
+ msg
->ry
;
1118 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
1120 REMOVE_CURSOR(data
);
1129 static IPTR
fakefb_drawpolygon(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPolygon
*msg
)
1132 /* FIXME: Maybe do checking here, but it probably is not worth it */
1133 REMOVE_CURSOR(data
);
1141 static IPTR
fakefb_fillpolygon(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPolygon
*msg
)
1144 /* FIXME: Maybe do checking here, but it probably is not worth it */
1145 REMOVE_CURSOR(data
);
1154 static IPTR
fakefb_drawtext(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawText
*msg
)
1158 /* FIXME: Maybe do testing here, but probably not wirth it */
1159 REMOVE_CURSOR(data
);
1166 static IPTR
fakefb_drawfilltext(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawText
*msg
)
1170 /* FIXME: Maybe do testing here, but probably not worth it */
1171 REMOVE_CURSOR(data
);
1178 static IPTR
fakefb_blitcolexp(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_BlitColorExpansion
*msg
)
1182 if (WRECT_INSIDE(fgh
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
1184 REMOVE_CURSOR(data
);
1193 static IPTR
fakefb_clear(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_Clear
*msg
)
1205 static IPTR
fakefb_fillspan(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
1209 REMOVE_CURSOR(data
);
1217 static IPTR
fakefb_scale(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_BitMapScale
*msg
)
1219 /* FIXME: should check both source and destination, similar to gfx_copybox() */
1222 if (WRECT_INSIDE(fgh
, msg
->bsa
->bsa_SrcX
, msg
->bsa
->bsa_SrcY
, msg
->bsa
->bsa_SrcWidth
, msg
->bsa
->bsa_SrcHeight
))
1224 REMOVE_CURSOR(data
);
1233 static IPTR
fakefb_fwd(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
1235 struct fakefb_data
*data
;
1236 data
= OOP_INST_DATA(cl
, o
);
1237 // kill(getpid(), 19);
1238 // bug("BITMAP_FWD\n");
1239 return OOP_DoMethod(data
->framebuffer
, msg
);
1244 static BOOL
rethink_cursor(struct gfx_data
*data
, struct GfxBase
*GfxBase
)
1246 OOP_Object
*pf
, *cmap
;
1247 IPTR fbdepth
, curdepth
, i
;
1248 UWORD curs_base
= 16;
1250 struct TagItem bmtags
[] = {
1251 { aHidd_BitMap_Width
, data
->curs_width
},
1252 { aHidd_BitMap_Height
, data
->curs_height
},
1253 { aHidd_BitMap_Friend
, (IPTR
)data
->framebuffer
},
1257 D(bug("rethink_cursor(), curs_bm is 0x%p, framebuffer is 0x%p\n", data
->curs_bm
, data
->framebuffer
));
1259 /* The first thing we do is recreating a backup bitmap. We do it every time when either
1260 cursor shape changes (because new shape may have different size) or shown bitmap
1261 changes (because new bitmap may have different depth). Note that even real framebuffer
1262 object may dynamically change its characteristics.
1264 Delete the old backup bitmap first */
1265 if (NULL
!= data
->curs_backup
) {
1266 OOP_DisposeObject(data
->curs_backup
);
1267 D(bug("[FakeGfx] Disposed old backup bitmap\n"));
1268 data
->curs_backup
= NULL
;
1271 /* If we have no cursor, we have nothing more to do.
1272 We also don't need new backup bitmap */
1276 /* We may also have no framebuffer (empty display on
1277 non-framebuffer driver). Also NOP in this case */
1278 if (!data
->framebuffer
)
1281 /* Create new backup bitmap */
1282 data
->curs_backup
= HIDD_Gfx_NewBitMap(data
->gfxhidd
, bmtags
);
1283 D(bug("[FakeGfx] New backup bitmap is 0x%p\n", data
->curs_backup
));
1284 if (!data
->curs_backup
)
1287 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
1288 D(bug("[FakeGfx] Framebuffer pixelformat 0x%p\n", pf
));
1289 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &fbdepth
);
1290 D(bug("[FakeGfx] Framebuffer depth %u\n", fbdepth
));
1291 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_ColorMap
, (IPTR
*)&cmap
);
1292 D(bug("[FakeGfx] Cursor colormap 0x%p\n", cmap
));
1293 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
1294 D(bug("[FakeGfx] Cursor pixelformat 0x%p\n", pf
));
1295 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &curdepth
);
1296 D(bug("[FakeGfx] Cursor depth %u\n", curdepth
));
1298 #ifndef DISABLE_ARGB_POINTER
1299 /* We can get ARGB data from the pointer bitmap only
1300 on one of two cases:
1301 1) Pointer bitmap has more than 256 colors, in this case it
1302 stores ARGB data in itself.
1303 2) Pointer bitmap is a LUT bitmap with a colormap attached.
1304 In this case colormap should contain ARGB values for actual
1306 Of course having ARGB data makes sense only on truecolor screens. */
1307 if ((fbdepth
> 8) && ((curdepth
> 8) || cmap
)) {
1308 data
->curs_pixfmt
= vHidd_StdPixFmt_ARGB32
;
1313 data
->curs_pixfmt
= vHidd_StdPixFmt_LUT8
;
1315 /* TODO: curs_base should be somehow synchronised with SpriteBase field of ColorMap */
1316 curs_base
= (fbdepth
> 4) ? 16 : (1 << fbdepth
) - 8;
1318 /* If we have some good bitmap->bitmap blitting function with alpha channel support,
1319 we would not need this extra buffer and conversion for truecolor screens. */
1320 HIDD_BM_GetImage(data
->curs_bm
, data
->curs_pixels
, data
->curs_width
* data
->curs_bpp
, 0, 0, data
->curs_width
, data
->curs_height
, data
->curs_pixfmt
);
1321 D(bug("[FakeGfx] Obtained cursor sprite data @ 0x%p\n", data
->curs_pixels
));
1323 if (data
->curs_pixfmt
== vHidd_StdPixFmt_LUT8
)
1325 for (i
= 0; i
< data
->curs_width
* data
->curs_height
; i
++)
1327 if (data
->curs_pixels
[i
])
1328 data
->curs_pixels
[i
] += curs_base
;
1334 static VOID
draw_cursor(struct gfx_data
*data
, BOOL draw
, BOOL updaterect
, struct GfxBase
*GfxBase
)
1337 LONG fbwidth
, fbheight
;
1343 struct TagItem gctags
[] =
1345 { aHidd_GC_DrawMode
, vHidd_GC_DrawMode_Copy
},
1352 if (NULL
== data
->curs_bm
|| NULL
== data
->framebuffer
)
1354 DB2(bug("!!! draw_cursor: FAKE GFX HIDD NOT PROPERLY INITIALIZED !!!\n"));
1355 DB2(bug("CURS BM: 0x%p, FB: 0x%p\n", data
->curs_bm
, data
->framebuffer
));
1359 fbwidth
= data
->fb_width
;
1360 fbheight
= data
->fb_height
;
1361 width
= data
->curs_width
;
1362 height
= data
->curs_height
;
1366 /* Do nothing if sprite went outside of bitmap */
1367 if ((x
< -width
) || (y
< -height
)) {
1368 DCURS(bug("[FakeGfx] Cursor is beyond left or top edge\n"));
1371 if ((x
>= fbwidth
) || (y
>= fbheight
)) {
1372 DCURS(bug("[FakeGfx] Cursor is beyond right or bottom edge\n"));
1376 /* Do some clipping */
1389 w2end
= data
->fb_width
- width
;
1390 h2end
= data
->fb_height
- height
;
1394 width
-= (x
- w2end
);
1395 DCLIP(bug("[FakeGfx] Clipped sprite width to %d\n", width
));
1400 height
-= (y
- h2end
);
1401 DCLIP(bug("[FakeGfx] Clipped sprite height to %d\n", height
));
1404 /* FIXME: clip negative coordinates */
1406 OOP_SetAttrs(data
->gc
, gctags
);
1410 /* Calculate origin of sprite image according to offsets */
1411 ULONG modulo
= data
->curs_width
* data
->curs_bpp
;
1412 UBYTE
*pixels
= data
->curs_pixels
+ yoffset
* modulo
+ xoffset
* data
->curs_bpp
;
1414 /* Backup under the new cursor image */
1415 // bug("BACKING UP RENDERED AREA\n");
1416 HIDD_Gfx_CopyBox(data
->gfxhidd
1425 data
->backup_done
= TRUE
;
1427 DB2(bug("[FakeGfx] Rendering cursor, framebuffer 0x%p\n", data
->framebuffer
));
1428 /* Render the cursor image */
1429 if (data
->curs_pixfmt
== vHidd_StdPixFmt_ARGB32
)
1430 HIDD_BM_PutAlphaImage(data
->framebuffer
, data
->gc
, pixels
, modulo
, x
, y
, width
, height
);
1432 /* data->curs_bpp is always 1 here so we safely ignore it */
1433 HIDD_BM_PutTranspImageLUT(data
->framebuffer
, data
->gc
, pixels
, modulo
, x
, y
, width
, height
, NULL
, 0);
1436 HIDD_BM_UpdateRect(data
->framebuffer
, x
, y
, width
, height
);
1441 /* Erase the old cursor image */
1442 if (data
->backup_done
)
1444 DB2(bug("[FakeGfx] Restoring cursor area, framebuffer 0x%p\n", data
->framebuffer
));
1445 HIDD_Gfx_CopyBox(data
->gfxhidd
1455 HIDD_BM_UpdateRect(data
->framebuffer
, x
, y
, width
, height
);
1461 static void gfx_setFrameBuffer(struct GfxBase
*GfxBase
, struct gfx_data
*data
, OOP_Object
*fb
)
1463 data
->framebuffer
= fb
;
1467 /* Cache framebuffer size, needed by sprite rendering routine */
1468 OOP_GetAttr(fb
, aHidd_BitMap_Width
, &data
->fb_width
);
1469 OOP_GetAttr(fb
, aHidd_BitMap_Height
, &data
->fb_height
);
1471 DCURS(bug("[FakeGfx] Framebuffer size: %u x %u\n", data
->fb_width
, data
->fb_height
));
1475 static OOP_Object
*create_fake_fb(OOP_Object
*framebuffer
, struct gfx_data
*data
, struct GfxBase
*GfxBase
)
1478 struct TagItem fakebmtags
[] =
1480 { aHidd_FakeFB_RealBitMap
, (IPTR
)framebuffer
},
1481 { aHidd_FakeFB_FakeGfxHidd
, (IPTR
)data
},
1485 /* If we work with framebuffer-based driver, Show() will never be called on
1486 a fakefb object so we remember it right now */
1487 fakebm
= OOP_NewObject(CDD(GfxBase
)->fakefbclass
, NULL
, fakebmtags
);
1489 if (data
->fakefb_attr
== aHidd_BitMap_FrameBuffer
)
1491 data
->fakefb
= fakebm
;
1492 gfx_setFrameBuffer(GfxBase
, data
, framebuffer
);
1498 static OOP_Class
*init_fakegfxhiddclass (struct GfxBase
*GfxBase
)
1500 OOP_Class
*cl
= NULL
;
1502 struct OOP_MethodDescr root_descr
[num_Root_Methods
+ 1] =
1504 {(IPTR (*)())gfx_new
, moRoot_New
},
1505 {(IPTR (*)())gfx_dispose
, moRoot_Dispose
},
1506 {(IPTR (*)())gfx_get
, moRoot_Get
},
1507 {(IPTR (*)())gfx_fwd
, moRoot_Set
},
1511 struct OOP_MethodDescr gfxhidd_descr
[num_Hidd_Gfx_Methods
+ 1] =
1513 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NewGC
},
1514 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_DisposeGC
},
1515 {(IPTR (*)())gfx_newbitmap
, moHidd_Gfx_NewBitMap
},
1516 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_DisposeBitMap
},
1517 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_QueryModeIDs
},
1518 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ReleaseModeIDs
},
1519 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_CheckMode
},
1520 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NextModeID
},
1521 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetMode
},
1522 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetPixFmt
},
1523 {(IPTR (*)())gfx_setcursorshape
, moHidd_Gfx_SetCursorShape
},
1524 {(IPTR (*)())gfx_setcursorpos
, moHidd_Gfx_SetCursorPos
},
1525 {(IPTR (*)())gfx_setcursorvisible
, moHidd_Gfx_SetCursorVisible
},
1526 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_SetMode
},
1527 {(IPTR (*)())gfx_show
, moHidd_Gfx_Show
},
1528 {(IPTR (*)())gfx_copybox
, moHidd_Gfx_CopyBox
},
1529 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ModeProperties
},
1530 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ShowViewPorts
},
1531 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetSync
},
1532 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetGamma
},
1533 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_SetGamma
},
1534 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_QueryHardware3D
},
1535 {(IPTR (*)())gfx_getmaxspritesize
, moHidd_Gfx_GetMaxSpriteSize
},
1536 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NewOverlay
},
1537 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_DisposeOverlay
},
1538 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_MakeViewPort
},
1539 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_CleanViewPort
},
1540 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_PrepareViewPorts
},
1541 {(IPTR (*)())gfx_copyboxmasked
, moHidd_Gfx_CopyBoxMasked
},
1545 struct OOP_InterfaceDescr ifdescr
[] =
1547 {root_descr
, IID_Root
, num_Root_Methods
},
1548 {gfxhidd_descr
, IID_Hidd_Gfx
, num_Hidd_Gfx_Methods
},
1552 OOP_AttrBase MetaAttrBase
= OOP_GetAttrBase(IID_Meta
);
1554 struct TagItem tags
[] =
1556 { aMeta_SuperID
, (IPTR
)CLID_Root
},
1557 { aMeta_InterfaceDescr
, (IPTR
)ifdescr
},
1558 { aMeta_InstSize
, (IPTR
)sizeof (struct gfx_data
) },
1563 D(bug("INIT FAKEGFXCLASS\n"));
1565 if ((__IHidd_FakeFB
= OOP_ObtainAttrBase(IID_Hidd_FakeFB
)))
1567 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
1570 D(bug("FAKE GFX CLASS INITED\n"));
1571 cl
->UserData
= GfxBase
;
1576 OOP_ReleaseAttrBase(IID_Hidd_FakeFB
);
1582 static OOP_Class
*init_fakefbclass(struct GfxBase
*GfxBase
)
1584 struct OOP_MethodDescr root_descr
[num_Root_Methods
+ 1] =
1586 {(IPTR (*)())fakefb_new
, moRoot_New
},
1587 {(IPTR (*)())fakefb_dispose
, moRoot_Dispose
},
1588 {(IPTR (*)())fakefb_get
, moRoot_Get
},
1589 {(IPTR (*)())fakefb_set
, moRoot_Set
},
1593 struct OOP_MethodDescr bitmap_descr
[num_Hidd_BitMap_Methods
+ 1] =
1595 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetColors
},
1596 {(IPTR (*)())fakefb_putpixel
, moHidd_BitMap_PutPixel
},
1597 {(IPTR (*)())fakefb_drawpixel
, moHidd_BitMap_DrawPixel
},
1598 {(IPTR (*)())fakefb_putimage
, moHidd_BitMap_PutImage
},
1599 {(IPTR (*)())fakefb_putalphaimage
, moHidd_BitMap_PutAlphaImage
},
1600 {(IPTR (*)())fakefb_puttemplate
, moHidd_BitMap_PutTemplate
},
1601 {(IPTR (*)())fakefb_putalphatemplate
, moHidd_BitMap_PutAlphaTemplate
},
1602 {(IPTR (*)())fakefb_putpattern
, moHidd_BitMap_PutPattern
},
1603 {(IPTR (*)())fakefb_getimage
, moHidd_BitMap_GetImage
},
1604 {(IPTR (*)())fakefb_getpixel
, moHidd_BitMap_GetPixel
},
1605 {(IPTR (*)())fakefb_drawline
, moHidd_BitMap_DrawLine
},
1606 {(IPTR (*)())fakefb_drawrect
, moHidd_BitMap_DrawRect
},
1607 {(IPTR (*)())fakefb_fillrect
, moHidd_BitMap_FillRect
},
1608 {(IPTR (*)())fakefb_drawellipse
, moHidd_BitMap_DrawEllipse
},
1609 {(IPTR (*)())fakefb_fillellipse
, moHidd_BitMap_FillEllipse
},
1610 {(IPTR (*)())fakefb_drawpolygon
, moHidd_BitMap_DrawPolygon
},
1611 {(IPTR (*)())fakefb_fillpolygon
, moHidd_BitMap_FillPolygon
},
1612 {(IPTR (*)())fakefb_drawtext
, moHidd_BitMap_DrawText
},
1613 {(IPTR (*)())fakefb_drawfilltext
, moHidd_BitMap_FillText
},
1614 {(IPTR (*)())fakefb_fillspan
, moHidd_BitMap_FillSpan
},
1615 {(IPTR (*)())fakefb_clear
, moHidd_BitMap_Clear
},
1616 {(IPTR (*)())fakefb_blitcolexp
, moHidd_BitMap_BlitColorExpansion
},
1617 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_MapColor
},
1618 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_UnmapPixel
},
1619 {(IPTR (*)())fakefb_putimagelut
, moHidd_BitMap_PutImageLUT
},
1620 {(IPTR (*)())fakefb_puttranspimagelut
, moHidd_BitMap_PutTranspImageLUT
},
1621 {(IPTR (*)())fakefb_getimagelut
, moHidd_BitMap_GetImageLUT
},
1622 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_BytesPerLine
},
1623 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ConvertPixels
},
1624 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect8
},
1625 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect16
},
1626 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect24
},
1627 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect32
},
1628 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_InvertMemRect
},
1629 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox8
},
1630 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox16
},
1631 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox24
},
1632 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox32
},
1633 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyLUTMemBox16
},
1634 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyLUTMemBox24
},
1635 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyLUTMemBox32
},
1636 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMem32Image8
},
1637 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMem32Image16
},
1638 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMem32Image24
},
1639 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_GetMem32Image8
},
1640 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_GetMem32Image16
},
1641 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_GetMem32Image24
},
1642 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate8
},
1643 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate16
},
1644 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate24
},
1645 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate32
},
1646 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern8
},
1647 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern16
},
1648 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern24
},
1649 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern32
},
1650 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetColorMap
},
1651 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ObtainDirectAccess
},
1652 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ReleaseDirectAccess
},
1653 {(IPTR (*)())fakefb_scale
, moHidd_BitMap_BitMapScale
},
1654 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PrivateSet
},
1655 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetRGBConversionFunction
},
1656 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_UpdateRect
},
1660 struct OOP_InterfaceDescr ifdescr
[] =
1662 {root_descr
, IID_Root
, num_Root_Methods
},
1663 {bitmap_descr
, IID_Hidd_BitMap
, num_Hidd_BitMap_Methods
},
1667 OOP_AttrBase MetaAttrBase
= OOP_GetAttrBase(IID_Meta
);
1669 struct TagItem tags
[] =
1671 {aMeta_SuperID
, (IPTR
) CLID_Root
},
1672 {aMeta_InterfaceDescr
, (IPTR
) ifdescr
},
1673 {aMeta_InstSize
, (IPTR
) sizeof(struct fakefb_data
) },
1677 OOP_Class
*cl
= NULL
;
1681 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
1683 cl
->UserData
= GfxBase
;
1684 } /* if(MetaAttrBase) */
1689 OOP_Object
*init_fakegfxhidd(OOP_Object
*gfxhidd
, struct GfxBase
*GfxBase
)
1691 struct common_driverdata
*csd
= CDD(GfxBase
);
1693 if (!csd
->fakegfxclass
)
1695 /* Lazy class initialization */
1696 csd
->fakegfxclass
= init_fakegfxhiddclass(GfxBase
);
1697 csd
->fakefbclass
= init_fakefbclass(GfxBase
);
1699 if (!csd
->fakegfxclass
|| !csd
->fakefbclass
)
1701 cleanup_fakegfxhidd(GfxBase
);
1707 return OOP_NewObjectTags(csd
->fakegfxclass
, NULL
, aHidd_FakeGfxHidd_RealGfxHidd
, gfxhidd
, TAG_DONE
);
1710 VOID
cleanup_fakegfxhidd(struct GfxBase
*GfxBase
)
1712 struct common_driverdata
*csd
= CDD(GfxBase
);
1714 if (NULL
!= csd
->fakefbclass
)
1716 OOP_DisposeObject((OOP_Object
*)csd
->fakefbclass
);
1717 csd
->fakefbclass
= NULL
;
1720 if (NULL
!= csd
->fakegfxclass
)
1722 OOP_DisposeObject((OOP_Object
*)csd
->fakegfxclass
);
1723 OOP_ReleaseAttrBase(IID_Hidd_FakeFB
);
1724 csd
->fakegfxclass
= NULL
;