New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / rom / graphics / fakegfxhidd.c
blobb48d54589cd19fa105b5d477dff92488906de496
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <string.h>
8 #include <proto/exec.h>
9 #include <proto/oop.h>
10 #include <proto/utility.h>
11 #include <oop/oop.h>
12 #include <hidd/graphics.h>
13 #include <aros/atomic.h>
14 #include <proto/arossupport.h>
16 #include "graphics_intern.h"
17 #include "graphics_internal.h"
18 #include "fakegfxhidd.h"
20 #define DEBUG 0
21 #include <aros/debug.h>
23 /******************************************************************************/
25 #define SPECIAL_LOCKING 1 /* When activated mouse cursor relevant locks are
26 treated in some kind of privileged way, by
27 inserting wait-for-sem-requests at head of
28 wait queue, instead of at tail */
30 /******************************************************************************/
32 static OOP_Class *init_fakefbclass(struct class_static_data *csd);
33 static VOID free_fakefbclass(OOP_Class *cl, struct class_static_data *csd);
35 static OOP_Class *init_fakegfxhiddclass (struct class_static_data *csd);
36 static VOID free_fakegfxhiddclass(OOP_Class *cl, struct class_static_data *csd);
38 /******************************************************************************/
40 struct gfx_data
42 OOP_Object *gfxhidd;
43 OOP_Object *framebuffer;
44 OOP_Object *fakefb;
45 OOP_Object *gc;
47 OOP_Object *curs_bm;
48 OOP_Object *curs_backup;
49 HIDDT_Pixel curs_pixels[256];
50 BOOL curs_on;
51 LONG curs_x;
52 LONG curs_y;
53 ULONG curs_width;
54 ULONG curs_height;
55 LONG curs_maxx;
56 LONG curs_maxy;
57 struct SignalSemaphore fbsema;
58 BOOL backup_done;
61 /******************************************************************************/
63 static VOID draw_cursor(struct gfx_data *data, BOOL draw, struct class_static_data *csd);
64 static VOID rethink_cursor(struct gfx_data *data, struct class_static_data *csd);
65 static OOP_Object *create_fake_fb(OOP_Object *framebuffer, struct gfx_data *data, struct class_static_data *csd);
67 /******************************************************************************/
69 #define LFB(data) ObtainSemaphore(&(data)->fbsema)
70 #define UFB(data) ReleaseSemaphore(&(data)->fbsema)
71 #define LFB_QUICK(data) ObtainSemaphore(&(data)->fbsema)
72 #define UFB_QUICK(data) ReleaseSemaphore(&(data)->fbsema)
74 #define CSD(cl) ((struct class_static_data *)cl->UserData)
76 #define __IHidd_FakeFB (CSD(cl)->hiddFakeFBAttrBase)
78 /******************************************************************************/
80 #if SPECIAL_LOCKING
82 /******************************************************************************/
84 #undef SysBase
86 static void FakeGfxHidd_ObtainSemaphore(struct SignalSemaphore *sigSem, BOOL urgent,
87 struct ExecBase *SysBase)
89 struct Task *me;
91 /* Get pointer to current task */
92 me=SysBase->ThisTask;
94 /* Arbitrate for the semaphore structure */
95 Forbid();
98 ss_QueueCount == -1 indicates that the semaphore is
99 free, so we increment this straight away. If it then
100 equals 0, then we are the first to allocate this semaphore.
102 Note: This will need protection for SMP machines.
104 sigSem->ss_QueueCount++;
105 if( sigSem->ss_QueueCount == 0 )
107 /* We now own the semaphore. This is quick. */
108 sigSem->ss_Owner = me;
109 sigSem->ss_NestCount++;
112 /* The semaphore was in use, but was it by us? */
113 else if( sigSem->ss_Owner == me )
115 /* Yes, just increase the nesting count */
116 sigSem->ss_NestCount++;
120 Else, some other task must own it. We have
121 to set a waiting request here.
123 else
126 We need a node to mark our semaphore request. Lets use some
127 stack memory.
129 struct SemaphoreRequest sr;
130 sr.sr_Waiter = me;
133 Have to clear the signal to make sure that we don't
134 return immediately. We then add the SemReq to the
135 waiters list of the semaphore. We were the last to
136 request, so we must be the last to get the semaphore.
139 #warning This must be atomic!
140 AROS_ATOMIC_AND(me->tc_SigRecvd, ~SIGF_SINGLE);
142 if (urgent)
144 AddHead((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
146 else
148 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
152 Finally, we simply wait, ReleaseSemaphore() will fill in
153 who owns the semaphore.
155 Wait(SIGF_SINGLE);
158 /* All Done! */
159 Permit();
163 /******************************************************************************/
165 static void FakeGfxHidd_ReleaseSemaphore(struct SignalSemaphore *sigSem,
166 struct ExecBase *SysBase)
168 /* Protect the semaphore structure from multiple access. */
169 Forbid();
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
197 is shared or not.
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 */
233 else
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. */
245 else
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 );
260 /* All done. */
261 Permit();
265 /******************************************************************************/
267 #undef LFB
268 #undef UFB
269 #undef LFB_QUICK
270 #undef UFB_QUICK
272 #define LFB(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, FALSE, SysBase)
273 #define UFB(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, SysBase)
275 #define LFB_QUICK(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, TRUE, SysBase)
276 #define UFB_QUICK(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, SysBase)
279 /******************************************************************************/
281 #endif /* SPECIAL_LOCKING */
283 /******************************************************************************/
285 #undef GfxBase
286 #define GfxBase (CSD(cl)->gfxbase)
288 static OOP_Object *gfx_new(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
290 /* Create a new gfxhid object */
291 OOP_Object *realgfxhidd;
292 struct gfx_data *data;
293 BOOL ok = FALSE;
295 realgfxhidd = (OOP_Object *)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd, (IPTR)NULL, msg->attrList);
296 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
297 if (NULL == o)
298 return NULL;
300 data = OOP_INST_DATA(cl, o);
301 memset(data, 0, sizeof (*data));
302 InitSemaphore(&data->fbsema);
304 data->gfxhidd = realgfxhidd;
306 if (NULL != data->gfxhidd)
308 struct TagItem gctags[] =
310 { TAG_DONE, 0UL }
313 data->gc = HIDD_Gfx_NewGC(data->gfxhidd, gctags);
314 if (NULL != data->gc)
316 ok = TRUE;
320 if (!ok)
322 OOP_MethodID mid;
324 mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
325 OOP_CoerceMethod(cl, o, (OOP_Msg)&mid);
328 return o;
331 static VOID gfx_dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
333 struct gfx_data *data;
335 data = OOP_INST_DATA(cl, o);
336 if (NULL != data->curs_backup)
338 OOP_DisposeObject(data->curs_backup);
339 data->curs_backup = NULL;
342 if (NULL != data->gc)
344 OOP_DisposeObject(data->gc);
345 data->gc = NULL;
348 #if 0
349 if (NULL != data->gfxhidd)
351 OOP_DisposeObject(data->gfxhidd);
352 data->gfxhidd = NULL;
354 #endif
357 static OOP_Object *gfx_newbitmap(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewBitMap *msg)
359 /* Is the user about to create a framebuffer ? */
360 BOOL create_fb;
361 struct gfx_data *data;
362 OOP_Object *realfb;
363 OOP_Object *ret = NULL;
364 BOOL ok = TRUE;
366 data = OOP_INST_DATA(cl, o);
367 create_fb = (BOOL)GetTagData(aHidd_BitMap_FrameBuffer, FALSE, msg->attrList);
369 realfb = HIDD_Gfx_NewBitMap(data->gfxhidd, msg->attrList);
371 if (NULL != realfb && create_fb)
373 OOP_Object *fakefb;
374 fakefb = create_fake_fb(realfb, data, CSD(cl));
375 if (NULL != fakefb)
377 ret = fakefb;
378 data->framebuffer = realfb;
380 else
382 ok = FALSE;
385 else
387 ret = realfb;
390 if (!ok)
392 OOP_DisposeObject(realfb);
393 ret = NULL;
396 return ret;
399 static BOOL gfx_setcursorshape(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorShape *msg)
401 struct gfx_data *data;
402 OOP_Object *shape;
404 data = OOP_INST_DATA(cl, o);
405 shape = msg->shape;
407 /* Bitmap changed */
408 if (NULL == shape)
410 /* Erase the old cursor */
411 draw_cursor(data, FALSE, CSD(cl));
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;
418 if (NULL != data->curs_backup)
420 OOP_DisposeObject(data->curs_backup);
421 data->curs_backup = NULL;
425 else
428 IPTR curs_width, curs_height, curs_depth;
429 IPTR mode_width, mode_height, mode_depth;
430 OOP_Object *curs_pf, *mode_sync,* mode_pf;
431 IPTR fbmode;
432 OOP_Object *new_backup;
434 struct TagItem bmtags[] =
436 { aHidd_BitMap_Displayable , FALSE },
437 { aHidd_BitMap_Width , 0 },
438 { aHidd_BitMap_Height , 0 },
439 { aHidd_BitMap_Friend , 0 },
440 { TAG_DONE , 0UL }
443 OOP_GetAttr(shape, aHidd_BitMap_Width, &curs_width);
444 OOP_GetAttr(shape, aHidd_BitMap_Height, &curs_height);
446 OOP_GetAttr(shape, aHidd_BitMap_PixFmt, (IPTR *)&curs_pf);
448 OOP_GetAttr(curs_pf, aHidd_PixFmt_Depth, &curs_depth);
449 OOP_GetAttr(data->framebuffer, aHidd_BitMap_ModeID, &fbmode);
450 HIDD_Gfx_GetMode(o, (HIDDT_ModeID)fbmode, &mode_sync, &mode_pf);
452 OOP_GetAttr(mode_sync, aHidd_Sync_HDisp, &mode_width);
453 OOP_GetAttr(mode_sync, aHidd_Sync_VDisp, &mode_height);
454 OOP_GetAttr(mode_pf, aHidd_PixFmt_Depth, &mode_depth);
456 /* Disallow very large cursors, and cursors with higher
457 depth than the framebuffer bitmap */
458 if ( ( curs_width > (mode_width / 2) )
459 || ( curs_height > (mode_height / 2) )
460 || ( curs_depth > mode_depth) )
462 D(bug("!!! FakeGfx::SetCursorShape: CURSOR BM HAS INVALID ATTRS !!!\n"));
463 return FALSE;
466 /* Create new backup bitmap */
467 bmtags[1].ti_Data = curs_width;
468 bmtags[2].ti_Data = curs_height;
469 bmtags[3].ti_Data = (IPTR)data->framebuffer;
471 new_backup = HIDD_Gfx_NewBitMap(data->gfxhidd, bmtags);
473 if (NULL == new_backup)
475 D(bug("!!! FakeGfx::SetCursorShape: COULD NOT CREATE BACKUP BM !!!\n"));
476 return FALSE;
479 data->curs_bm = shape;
481 if (data->curs_on)
483 /* Erase the old cursor */
484 draw_cursor(data, FALSE, CSD(cl));
486 /* Now that we have disposed the old image using the old
487 backup bm, we can install the new backup bm before
488 rendering the new curso
491 if (NULL != data->curs_backup)
492 OOP_DisposeObject(data->curs_backup);
494 data->curs_width = curs_width;
495 data->curs_height = curs_height;
497 data->curs_maxx = data->curs_x + curs_width - 1;
498 data->curs_maxy = data->curs_y + curs_height - 1;
499 data->curs_backup = new_backup;
501 rethink_cursor(data, CSD(cl));
503 draw_cursor(data, TRUE, CSD(cl));
506 else
509 if (NULL != data->curs_backup)
510 OOP_DisposeObject(data->curs_backup);
512 data->curs_width = curs_width;
513 data->curs_height = curs_height;
515 data->curs_maxx = data->curs_x + curs_width - 1;
516 data->curs_maxy = data->curs_y + curs_height - 1;
517 data->curs_backup = new_backup;
519 rethink_cursor(data, CSD(cl));
525 return TRUE;
528 static BOOL gfx_setcursorpos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
530 struct gfx_data *data;
532 data = OOP_INST_DATA(cl, o);
533 LFB_QUICK(data);
534 /* erase the old cursor */
535 if (data->curs_on)
536 draw_cursor(data, FALSE, CSD(cl));
538 data->curs_x = msg->x;
539 data->curs_y = msg->y;
540 data->curs_maxx = data->curs_x + data->curs_width - 1;
541 data->curs_maxy = data->curs_y + data->curs_height - 1;
543 if (data->curs_on)
544 draw_cursor(data, TRUE, CSD(cl));
545 UFB_QUICK(data);
546 return TRUE;
549 static VOID gfx_setcursorvisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
551 struct gfx_data *data;
553 data = OOP_INST_DATA(cl, o);
555 LFB_QUICK(data);
557 if (msg->visible)
559 if (!data->curs_on)
561 data->curs_on = TRUE;
562 draw_cursor(data, TRUE, CSD(cl));
565 else
567 if (data->curs_on)
569 data->curs_on = FALSE;
570 draw_cursor(data, FALSE, CSD(cl));
574 UFB_QUICK(data);
578 #define PIXEL_INSIDE(fgh, x, y) \
579 ( ( (x) >= (fgh)->curs_x ) \
580 && ( (y) >= (fgh)->curs_y ) \
581 && ( (x) <= (fgh)->curs_maxx ) \
582 && ( (y) <= (fgh)->curs_maxy ) )
584 /* NOTE: x1, y1, x2, y2 MUST be sorted */
585 #define RECT_INSIDE(fgh, x1, y1, x2, y2) \
586 ( ( (x1) <= fgh->curs_maxx ) \
587 && ( (x2) >= fgh->curs_x ) \
588 && ( (y1) <= fgh->curs_maxy ) \
589 && ( (y2) >= fgh->curs_y ) )
591 #define WRECT_INSIDE(fgh, x1, y1, width, height) \
592 RECT_INSIDE(fgh, x1, y1, (x1) + (width) - 1, (y1) + (height) - 1)
594 static IPTR gfx_copybox(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBox *msg)
596 struct gfx_data *data;
597 BOOL inside = FALSE;
598 IPTR retval;
599 struct pHidd_Gfx_CopyBox p;
601 data = OOP_INST_DATA(cl, o);
602 LFB(data);
603 p = *msg;
605 if (msg->src == data->fakefb)
607 if (WRECT_INSIDE(data, msg->srcX, msg->srcY, msg->width, msg->height))
609 inside = TRUE;
611 p.src = data->framebuffer;
614 if (msg->dest == data->fakefb)
616 if (WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
618 inside = TRUE;
620 p.dest = data->framebuffer;
623 if (inside)
625 draw_cursor(data, FALSE, CSD(cl));
627 msg = &p;
629 retval = OOP_DoMethod(data->gfxhidd, (OOP_Msg)msg);
631 if (inside)
632 draw_cursor(data, TRUE, CSD(cl));
633 UFB(data);
635 return retval;
638 static OOP_Object *gfx_show(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
640 OOP_Object *ret;
641 struct gfx_data *data;
643 data = OOP_INST_DATA(cl, o);
645 LFB(data);
646 draw_cursor(data, FALSE, CSD(cl));
648 ret = (OOP_Object *)OOP_DoMethod(data->gfxhidd, msg);
649 if (NULL != ret)
651 data->framebuffer = ret;
652 ret = data->fakefb;
654 rethink_cursor(data, CSD(cl));
655 draw_cursor(data, TRUE, CSD(cl));
657 UFB(data);
659 return ret;
661 static IPTR gfx_fwd(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
663 struct gfx_data *data;
665 data = OOP_INST_DATA(cl, o);
667 return OOP_DoMethod(data->gfxhidd, msg);
670 struct fakefb_data
672 OOP_Object *framebuffer;
673 OOP_Object *fakegfxhidd;
676 #define FGH(data) ((struct gfx_data *)data->fakegfxhidd)
677 #define REMOVE_CURSOR(data) \
678 draw_cursor(FGH(data), FALSE, CSD(cl))
680 #define RENDER_CURSOR(data) \
681 draw_cursor(FGH(data), TRUE, CSD(cl))
684 #define BITMAP_METHOD_INIT \
685 struct fakefb_data *data; \
686 BOOL inside = FALSE; \
687 IPTR retval; \
688 struct gfx_data *fgh; \
689 data = OOP_INST_DATA(cl, o); \
690 fgh = FGH(data); \
691 LFB(fgh);
693 #define FORWARD_METHOD \
694 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
696 #define BITMAP_METHOD_EXIT \
697 if (inside) { \
698 RENDER_CURSOR(data); \
700 UFB(fgh); \
701 return retval;
703 static OOP_Object *fakefb_new(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
705 OOP_Object *framebuffer;
706 OOP_Object *fakegfxhidd;
708 framebuffer = (OOP_Object *)GetTagData(aHidd_FakeFB_RealBitMap, NULL, msg->attrList);
709 fakegfxhidd = (OOP_Object *)GetTagData(aHidd_FakeFB_FakeGfxHidd, NULL, msg->attrList);
711 if (NULL == framebuffer || NULL == fakegfxhidd)
713 D(bug("!!! FakeBM::New(): MISSING FRAMEBUFFER OR FAKE GFX HIDD !!!\n"));
714 return NULL;
717 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
718 if (NULL != o)
720 struct fakefb_data *data;
721 data = OOP_INST_DATA(cl, o);
722 data->framebuffer = framebuffer;
723 data->fakegfxhidd = fakegfxhidd;
725 return o;
728 static VOID fakefb_dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
730 struct fakefb_data *data;
731 data = OOP_INST_DATA(cl, o);
732 if (NULL != data->framebuffer)
734 OOP_DisposeObject(data->framebuffer);
735 data->framebuffer = NULL;
739 static IPTR fakefb_getpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetPixel *msg)
741 BITMAP_METHOD_INIT
743 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
745 REMOVE_CURSOR(data);
746 inside = TRUE;
749 FORWARD_METHOD
751 BITMAP_METHOD_EXIT
754 static IPTR fakefb_putpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
756 BITMAP_METHOD_INIT
758 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
760 REMOVE_CURSOR(data);
761 inside = TRUE;
764 FORWARD_METHOD
766 BITMAP_METHOD_EXIT
769 static IPTR fakefb_drawpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPixel *msg)
771 BITMAP_METHOD_INIT
773 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
775 REMOVE_CURSOR(data);
776 inside = TRUE;
779 FORWARD_METHOD
781 BITMAP_METHOD_EXIT
784 static IPTR fakefb_drawline(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawLine *msg)
786 register LONG x1, y1, x2, y2;
787 BITMAP_METHOD_INIT
789 if (msg->x1 < msg->x2)
791 x1 = msg->x1; x2 = msg->x2;
793 else
795 x2 = msg->x1; x1 = msg->x2;
798 if (msg->y1 < msg->y2)
800 y1 = msg->y1; y2 = msg->y2;
802 else
804 y2 = msg->y1; y1 = msg->y2;
807 #warning Maybe do some more intelligent checking for DrawLine
808 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
810 REMOVE_CURSOR(data);
811 inside = TRUE;
814 FORWARD_METHOD
816 BITMAP_METHOD_EXIT
819 static IPTR fakefb_getimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImage *msg)
821 BITMAP_METHOD_INIT
823 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
825 REMOVE_CURSOR(data);
826 inside = TRUE;
829 FORWARD_METHOD
831 BITMAP_METHOD_EXIT
834 static IPTR fakefb_putimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImage *msg)
836 BITMAP_METHOD_INIT
838 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
840 REMOVE_CURSOR(data);
841 inside = TRUE;
844 FORWARD_METHOD
846 BITMAP_METHOD_EXIT
849 static IPTR fakefb_putalphaimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaImage *msg)
851 BITMAP_METHOD_INIT
853 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
855 REMOVE_CURSOR(data);
856 inside = TRUE;
859 FORWARD_METHOD
861 BITMAP_METHOD_EXIT
864 static IPTR fakefb_puttemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTemplate *msg)
866 BITMAP_METHOD_INIT
868 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
870 REMOVE_CURSOR(data);
871 inside = TRUE;
874 FORWARD_METHOD
876 BITMAP_METHOD_EXIT
879 static IPTR fakefb_putalphatemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaTemplate *msg)
881 BITMAP_METHOD_INIT
883 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
885 REMOVE_CURSOR(data);
886 inside = TRUE;
889 FORWARD_METHOD
891 BITMAP_METHOD_EXIT
894 static IPTR fakefb_putpattern(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPattern *msg)
896 BITMAP_METHOD_INIT
898 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
900 REMOVE_CURSOR(data);
901 inside = TRUE;
904 FORWARD_METHOD
906 BITMAP_METHOD_EXIT
909 static IPTR fakefb_getimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImageLUT *msg)
911 BITMAP_METHOD_INIT
913 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
915 REMOVE_CURSOR(data);
916 inside = TRUE;
919 FORWARD_METHOD
921 BITMAP_METHOD_EXIT
924 static IPTR fakefb_putimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg)
926 BITMAP_METHOD_INIT
928 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
930 REMOVE_CURSOR(data);
931 inside = TRUE;
934 FORWARD_METHOD
936 BITMAP_METHOD_EXIT
939 static IPTR fakefb_puttranspimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTranspImageLUT *msg)
941 BITMAP_METHOD_INIT
943 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
945 REMOVE_CURSOR(data);
946 inside = TRUE;
949 FORWARD_METHOD
951 BITMAP_METHOD_EXIT
954 static IPTR fakefb_drawrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
956 BITMAP_METHOD_INIT
958 #warning Maybe do something clever here to see if the rectangle is drawn around the cursor
959 if (RECT_INSIDE(fgh, msg->minX, msg->minY, msg->maxX, msg->maxY))
961 REMOVE_CURSOR(data);
962 inside = TRUE;
965 FORWARD_METHOD
967 BITMAP_METHOD_EXIT
970 static IPTR fakefb_fillrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
972 BITMAP_METHOD_INIT
974 /* bug("BITMAP FILLRECT(%d, %d, %d, %d), (%d, %d, %d, %d, %d, %d)\n"
975 , msg->minX, msg->minY, msg->maxX, msg->maxY
976 , fgh->curs_x, fgh->curs_y, fgh->curs_maxx, fgh->curs_maxy
977 , fgh->curs_width, fgh->curs_height);
979 if (RECT_INSIDE(fgh, msg->minX, msg->minY, msg->maxX, msg->maxY))
981 /* bug("FILLRECT: REMOVING CURSOR\n");
983 REMOVE_CURSOR(data);
985 inside = TRUE;
988 FORWARD_METHOD
990 BITMAP_METHOD_EXIT
993 static IPTR fakefb_drawellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
995 register LONG x1, y1, x2, y2;
996 BITMAP_METHOD_INIT
998 x1 = msg->x - msg->rx;
999 y1 = msg->y - msg->ry;
1000 x2 = msg->x + msg->rx;
1001 y2 = msg->y + msg->ry;
1002 #warning Maybe do something clever here to see if the rectangle is drawn around the cursor
1004 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
1006 REMOVE_CURSOR(data);
1007 inside = TRUE;
1010 FORWARD_METHOD
1012 BITMAP_METHOD_EXIT
1015 static IPTR fakefb_fillellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1017 register LONG x1, y1, x2, y2;
1018 BITMAP_METHOD_INIT
1020 x1 = msg->x - msg->rx;
1021 y1 = msg->y - msg->ry;
1022 x2 = msg->x + msg->rx;
1023 y2 = msg->y + msg->ry;
1025 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
1027 REMOVE_CURSOR(data);
1028 inside = TRUE;
1031 FORWARD_METHOD
1033 BITMAP_METHOD_EXIT
1036 static IPTR fakefb_drawpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1038 BITMAP_METHOD_INIT
1039 #warning Maybe do checking here, but it probably is not worth it
1040 REMOVE_CURSOR(data);
1041 inside = TRUE;
1043 FORWARD_METHOD
1045 BITMAP_METHOD_EXIT
1048 static IPTR fakefb_fillpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1050 BITMAP_METHOD_INIT
1051 #warning Maybe do checking here, but it probably is not worth it
1052 REMOVE_CURSOR(data);
1053 inside = TRUE;
1055 FORWARD_METHOD
1057 BITMAP_METHOD_EXIT
1061 static IPTR fakefb_drawtext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1063 BITMAP_METHOD_INIT
1065 #warning Maybe do testing here, but probably not wirth it
1066 REMOVE_CURSOR(data);
1068 FORWARD_METHOD
1070 BITMAP_METHOD_EXIT
1073 static IPTR fakefb_drawfilltext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1075 BITMAP_METHOD_INIT
1077 #warning Maybe do testing here, but probably not worth it
1078 REMOVE_CURSOR(data);
1080 FORWARD_METHOD
1082 BITMAP_METHOD_EXIT
1085 static IPTR fakefb_blitcolexp(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BlitColorExpansion *msg)
1087 BITMAP_METHOD_INIT
1089 if (WRECT_INSIDE(fgh, msg->destX, msg->destY, msg->width, msg->height))
1091 REMOVE_CURSOR(data);
1092 inside = TRUE;
1095 FORWARD_METHOD
1097 BITMAP_METHOD_EXIT
1100 static IPTR fakefb_clear(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_Clear *msg)
1102 BITMAP_METHOD_INIT
1104 inside = TRUE;
1106 FORWARD_METHOD
1108 BITMAP_METHOD_EXIT
1112 static IPTR fakefb_fillspan(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1114 BITMAP_METHOD_INIT
1116 REMOVE_CURSOR(data);
1117 inside = TRUE;
1119 FORWARD_METHOD
1121 BITMAP_METHOD_EXIT
1126 static IPTR fakefb_fwd(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1128 struct fakefb_data *data;
1129 data = OOP_INST_DATA(cl, o);
1130 // kill(getpid(), 19);
1131 // bug("BITMAP_FWD\n");
1132 return OOP_DoMethod(data->framebuffer, msg);
1137 #undef CSD
1138 #define CSD(cl) csd
1141 static OOP_Class *init_fakegfxhiddclass (struct class_static_data *csd)
1143 OOP_Class *cl = NULL;
1145 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1147 {(IPTR (*)())gfx_new , moRoot_New },
1148 {(IPTR (*)())gfx_dispose, moRoot_Dispose },
1149 {(IPTR (*)())gfx_fwd , moRoot_Get },
1150 {(IPTR (*)())gfx_fwd , moRoot_Set },
1151 { NULL , 0UL }
1154 struct OOP_MethodDescr gfxhidd_descr[num_Hidd_Gfx_Methods + 1] =
1156 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewGC },
1157 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeGC },
1158 {(IPTR (*)())gfx_newbitmap , moHidd_Gfx_NewBitMap },
1159 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeBitMap },
1160 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryModeIDs },
1161 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ReleaseModeIDs },
1162 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CheckMode },
1163 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NextModeID },
1164 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetMode },
1166 #if 0
1167 /* These are private to the gfxhidd, and we should not be called with these */
1168 {(IPTR (*)())gfx_fwd , moHidd_Gfx_RegisterPixFmt },
1169 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ReleasePixFmt },
1170 #endif
1171 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetPixFmt },
1172 {(IPTR (*)())gfx_setcursorshape , moHidd_Gfx_SetCursorShape },
1173 {(IPTR (*)())gfx_setcursorpos , moHidd_Gfx_SetCursorPos },
1174 {(IPTR (*)())gfx_setcursorvisible , moHidd_Gfx_SetCursorVisible },
1175 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetMode },
1176 {(IPTR (*)())gfx_show , moHidd_Gfx_Show },
1177 {(IPTR (*)())gfx_copybox , moHidd_Gfx_CopyBox },
1178 {NULL , 0UL }
1181 struct OOP_InterfaceDescr ifdescr[] =
1183 {root_descr , IID_Root , num_Root_Methods },
1184 {gfxhidd_descr , IID_Hidd_Gfx , num_Hidd_Gfx_Methods },
1185 {NULL , NULL , 0 }
1188 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1190 struct TagItem tags[] =
1192 /* { aMeta_SuperID , (IPTR)CLID_Hidd },*/
1193 { aMeta_SuperID , (IPTR)CLID_Root },
1194 { aMeta_InterfaceDescr , (IPTR)ifdescr },
1195 { aMeta_ID , (IPTR)CLID_Hidd_FakeGfxHidd },
1196 { aMeta_InstSize , (IPTR)sizeof (struct gfx_data) },
1197 {TAG_DONE , 0UL }
1201 D(bug("INIT FAKEGFXCLASS\n"));
1202 if ((__IHidd_FakeFB = OOP_ObtainAttrBase(IID_Hidd_FakeFB)))
1204 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1205 if(NULL != cl)
1207 D(bug("FAKE GFX CLASS INITED\n"));
1208 cl->UserData = csd;
1209 OOP_AddClass(cl);
1211 return cl;
1215 if (NULL == cl)
1216 free_fakegfxhiddclass(cl, csd);
1218 return cl;
1221 static void free_fakegfxhiddclass(OOP_Class *cl, struct class_static_data *csd)
1223 if (NULL != cl)
1225 OOP_RemoveClass(cl);
1226 OOP_DisposeObject((OOP_Object *) cl);
1227 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1231 static OOP_Class *init_fakefbclass(struct class_static_data *csd)
1233 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1235 {(IPTR (*)())fakefb_new , moRoot_New },
1236 {(IPTR (*)())fakefb_dispose, moRoot_Dispose },
1237 {(IPTR (*)())fakefb_fwd , moRoot_Get },
1238 {(IPTR (*)())fakefb_fwd , moRoot_Set },
1239 {NULL , 0UL }
1242 struct OOP_MethodDescr bitmap_descr[num_Hidd_BitMap_Methods + 1] =
1244 {(IPTR (*)())fakefb_putpixel , moHidd_BitMap_PutPixel },
1245 {(IPTR (*)())fakefb_getpixel , moHidd_BitMap_GetPixel },
1246 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColors },
1247 {(IPTR (*)())fakefb_drawpixel , moHidd_BitMap_DrawPixel },
1248 {(IPTR (*)())fakefb_drawline , moHidd_BitMap_DrawLine },
1249 {(IPTR (*)())fakefb_drawrect , moHidd_BitMap_DrawRect },
1250 {(IPTR (*)())fakefb_fillrect , moHidd_BitMap_FillRect },
1251 {(IPTR (*)())fakefb_drawellipse , moHidd_BitMap_DrawEllipse },
1252 {(IPTR (*)())fakefb_fillellipse , moHidd_BitMap_FillEllipse },
1253 {(IPTR (*)())fakefb_drawpolygon , moHidd_BitMap_DrawPolygon },
1254 {(IPTR (*)())fakefb_fillpolygon , moHidd_BitMap_FillPolygon },
1255 {(IPTR (*)())fakefb_drawtext , moHidd_BitMap_DrawText },
1256 {(IPTR (*)())fakefb_drawfilltext , moHidd_BitMap_FillText },
1257 {(IPTR (*)())fakefb_fillspan , moHidd_BitMap_FillSpan },
1258 {(IPTR (*)())fakefb_clear , moHidd_BitMap_Clear },
1259 {(IPTR (*)())fakefb_putimage , moHidd_BitMap_PutImage },
1260 {(IPTR (*)())fakefb_putalphaimage , moHidd_BitMap_PutAlphaImage },
1261 {(IPTR (*)())fakefb_puttemplate , moHidd_BitMap_PutTemplate },
1262 {(IPTR (*)())fakefb_putalphatemplate , moHidd_BitMap_PutAlphaTemplate },
1263 {(IPTR (*)())fakefb_putpattern , moHidd_BitMap_PutPattern },
1264 {(IPTR (*)())fakefb_putimagelut , moHidd_BitMap_PutImageLUT },
1265 {(IPTR (*)())fakefb_puttranspimagelut , moHidd_BitMap_PutTranspImageLUT },
1266 {(IPTR (*)())fakefb_getimage , moHidd_BitMap_GetImage },
1267 {(IPTR (*)())fakefb_getimagelut , moHidd_BitMap_GetImageLUT },
1268 {(IPTR (*)())fakefb_blitcolexp , moHidd_BitMap_BlitColorExpansion },
1269 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_BytesPerLine },
1270 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ConvertPixels },
1271 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColorMap },
1272 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_MapColor },
1273 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UnmapPixel },
1274 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ObtainDirectAccess },
1275 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ReleaseDirectAccess },
1277 /* PRIVATE METHODS */
1278 #if 0
1279 /* This is private to the gfxhidd, and we should not be called with this */
1280 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetBitMapTags },
1281 #endif
1282 {NULL, 0UL}
1285 struct OOP_InterfaceDescr ifdescr[] =
1287 {root_descr , IID_Root , num_Root_Methods },
1288 {bitmap_descr , IID_Hidd_BitMap, num_Hidd_BitMap_Methods },
1289 {NULL , NULL , 0 }
1292 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1294 struct TagItem tags[] =
1296 {aMeta_SuperID , (IPTR) CLID_Root },
1297 {aMeta_InterfaceDescr , (IPTR) ifdescr },
1298 {aMeta_ID , (IPTR) CLID_Hidd_FakeFB },
1299 {aMeta_InstSize , (IPTR) sizeof(struct fakefb_data) },
1300 {TAG_DONE , 0UL }
1303 OOP_Class *cl = NULL;
1305 if(MetaAttrBase)
1307 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1308 if(NULL != cl)
1310 cl->UserData = csd;
1311 OOP_AddClass(cl);
1313 } /* if(MetaAttrBase) */
1315 if (NULL == cl)
1316 free_fakefbclass(cl, csd);
1318 return cl;
1321 static void free_fakefbclass(OOP_Class *cl, struct class_static_data *csd)
1323 if (NULL != cl)
1325 OOP_RemoveClass(cl);
1326 OOP_DisposeObject((OOP_Object *) cl);
1331 static VOID rethink_cursor(struct gfx_data *data, struct class_static_data *csd)
1333 OOP_Object *pf, *colmap;
1334 IPTR depth, fbdepth, i;
1336 OOP_GetAttr(data->curs_backup, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1337 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &fbdepth);
1339 OOP_GetAttr(data->curs_bm, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1340 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &depth);
1341 OOP_GetAttr(data->curs_bm, aHidd_BitMap_ColorMap, (IPTR *)&colmap);
1343 if (depth > 8) depth = 8;
1345 for(i = 0; i < (1L << depth); i++)
1347 if (fbdepth > 8)
1349 HIDDT_Color col;
1351 HIDD_CM_GetColor(colmap, i, &col);
1352 data->curs_pixels[i] = HIDD_BM_MapColor(data->curs_backup, &col);
1354 else
1356 data->curs_pixels[i] = i;
1362 static VOID draw_cursor(struct gfx_data *data, BOOL draw, struct class_static_data *csd)
1364 IPTR width, height;
1365 IPTR fb_width, fb_height;
1366 ULONG x, y;
1367 LONG w2end;
1368 LONG h2end;
1370 struct TagItem gctags[] =
1372 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
1373 { TAG_DONE , 0UL }
1376 if (NULL == data->curs_bm || NULL == data->framebuffer || !data->curs_on)
1378 D(bug("!!! draw_cursor: FAKE GFX HIDD NOT PROPERLY INITIALIZED !!!\n"));
1379 D(bug("CURS BM: %p, FB: %p, ON: %d\n"
1380 , data->curs_bm, data->framebuffer, data->curs_on));
1381 return;
1384 OOP_GetAttr(data->curs_bm, aHidd_BitMap_Width, &width);
1385 OOP_GetAttr(data->curs_bm, aHidd_BitMap_Height, &height);
1387 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Width, &fb_width);
1388 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Height, &fb_height);
1390 /* Do some clipping */
1391 x = data->curs_x;
1392 y = data->curs_y;
1394 w2end = fb_width - 1 - data->curs_x;
1395 h2end = fb_height - 1 - data->curs_y;
1397 if (w2end <= 0 || h2end <= 0) /* Cursor outside framebuffer */
1398 return;
1400 if (w2end < width)
1401 width -= (width - w2end);
1403 if (h2end < height)
1404 height -= (height - h2end);
1406 OOP_SetAttrs(data->gc, gctags);
1408 if (draw)
1410 /* Backup under the new cursor image */
1411 // bug("BACKING UP RENDERED AREA\n");
1412 HIDD_Gfx_CopyBox(data->gfxhidd
1413 , data->framebuffer
1414 , data->curs_x
1415 , data->curs_y
1416 , data->curs_backup
1417 , 0, 0
1418 , width, height
1419 , data->gc
1422 data->backup_done = TRUE;
1424 // bug("RENDERING CURSOR IMAGE\n");
1425 /* Render the cursor image */
1427 #if 0
1428 HIDD_Gfx_CopyBox(data->gfxhidd
1429 , data->curs_bm
1430 , 0, 0
1431 , data->framebuffer
1432 , data->curs_x, data->curs_y
1433 , width, height
1434 , data->gc
1436 #else
1437 for(y = 0; y < height; y++)
1439 for(x = 0; x < width; x++)
1441 HIDDT_Pixel pix;
1443 pix = HIDD_BM_GetPixel(data->curs_bm, x, y);
1444 if (pix)
1446 HIDD_BM_PutPixel(data->framebuffer, data->curs_x + x, data->curs_y + y, data->curs_pixels[pix]);
1451 #endif
1454 else
1456 /* Erase the old cursor image */
1457 if (data->backup_done)
1459 // bug("PUTTING BACK BACKED UP AREA\n");
1460 HIDD_Gfx_CopyBox(data->gfxhidd
1461 , data->curs_backup
1462 , 0, 0
1463 , data->framebuffer
1464 , data->curs_x
1465 , data->curs_y
1466 , width, height
1467 , data->gc
1471 return;
1474 static OOP_Object *create_fake_fb(OOP_Object *framebuffer, struct gfx_data *data, struct class_static_data *csd)
1476 OOP_Object *fakebm;
1477 struct TagItem fakebmtags[] =
1479 { aHidd_FakeFB_RealBitMap , (IPTR)framebuffer },
1480 { aHidd_FakeFB_FakeGfxHidd , (IPTR)data },
1481 { TAG_DONE , 0UL }
1484 fakebm = OOP_NewObject(NULL, CLID_Hidd_FakeFB, fakebmtags);
1485 if (NULL != fakebm)
1487 data->framebuffer = framebuffer;
1488 data->fakefb = fakebm;
1492 return fakebm;
1495 #undef GfxBase
1497 OOP_Object *init_fakegfxhidd(OOP_Object *gfxhidd, struct class_static_data *csd, struct GfxBase *GfxBase)
1499 OOP_Object *fgo = NULL;
1501 csd->gfxbase = GfxBase;
1503 csd->fakegfxclass = init_fakegfxhiddclass(csd);
1504 csd->fakefbclass = init_fakefbclass(csd);
1506 if (NULL != csd->fakegfxclass && NULL != csd->fakefbclass)
1508 struct TagItem fgh_tags[] =
1510 { aHidd_FakeGfxHidd_RealGfxHidd , (IPTR)gfxhidd },
1511 { TAG_DONE , 0UL }
1514 fgo = OOP_NewObject(NULL, CLID_Hidd_FakeGfxHidd, fgh_tags);
1516 if (NULL != fgo)
1518 csd->fakegfxobj = fgo;
1522 if (NULL == fgo)
1523 cleanup_fakegfxhidd(csd, GfxBase);
1525 return fgo;
1528 VOID cleanup_fakegfxhidd(struct class_static_data *csd, struct GfxBase *GfxBase)
1530 if (NULL != csd->fakegfxobj)
1532 OOP_DisposeObject(csd->fakegfxobj);
1533 csd->fakegfxobj = NULL;
1536 if (NULL != csd->fakefbclass)
1538 free_fakefbclass(csd->fakefbclass, csd);
1539 csd->fakefbclass = NULL;
1542 if (NULL != csd->fakegfxclass)
1544 free_fakegfxhiddclass(csd->fakegfxclass, csd);
1545 csd->fakegfxclass = NULL;
1548 return;