forcing device into host mode requires a full config - which we will do in opendevice...
[AROS.git] / rom / graphics / fakegfxhidd.c
blob21a6eae08f26e068fb4738b87394c180d8be0f38
1 /*
2 Copyright © 1995-2011, 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 "fakegfxhidd.h"
19 #define DCLIP(x)
20 #define DCURS(x)
21 #define DPOS(x)
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 /******************************************************************************/
47 struct gfx_data
49 OOP_Object *gfxhidd;
50 OOP_Object *framebuffer;
51 OOP_Object *fakefb;
52 OOP_Object *gc;
54 ULONG fakefb_attr;
55 IPTR fb_width;
56 IPTR fb_height;
58 OOP_Object *curs_bm;
59 OOP_Object *curs_backup;
60 UBYTE *curs_pixels;
61 HIDDT_StdPixFmt curs_pixfmt;
62 UBYTE curs_bpp;
63 BOOL curs_on;
64 LONG curs_x;
65 LONG curs_y;
66 LONG curs_xoffset;
67 LONG curs_yoffset;
68 ULONG curs_width;
69 ULONG curs_height;
70 LONG curs_maxx;
71 LONG curs_maxy;
72 struct SignalSemaphore fbsema;
73 BOOL backup_done;
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 /******************************************************************************/
85 #if SPECIAL_LOCKING
87 static void FakeGfxHidd_ObtainSemaphore(struct SignalSemaphore *sigSem, BOOL urgent,
88 struct GfxBase *GfxBase)
90 struct Task *me;
92 /* Get pointer to current task */
93 me=SysBase->ThisTask;
95 /* Arbitrate for the semaphore structure */
96 Forbid();
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.
124 else
127 We need a node to mark our semaphore request. Lets use some
128 stack memory.
130 struct SemaphoreRequest sr;
131 sr.sr_Waiter = me;
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);
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 GfxBase *GfxBase)
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 #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;
290 BOOL ok = FALSE;
291 IPTR noframebuffer = FALSE;
293 realgfxhidd = (OOP_Object *)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd, (IPTR)NULL, msg->attrList);
294 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
295 if (NULL == o)
296 return NULL;
298 data = OOP_INST_DATA(cl, o);
299 memset(data, 0, sizeof (*data));
300 InitSemaphore(&data->fbsema);
302 OOP_GetAttr(realgfxhidd, aHidd_Gfx_NoFrameBuffer, &noframebuffer);
303 data->fakefb_attr = noframebuffer ? aHidd_BitMap_Displayable : aHidd_BitMap_FrameBuffer;
305 data->gfxhidd = realgfxhidd;
307 if (NULL != data->gfxhidd)
309 struct TagItem gctags[] =
311 { TAG_DONE, 0UL }
314 data->gc = HIDD_Gfx_NewGC(data->gfxhidd, gctags);
315 if (NULL != data->gc)
317 ok = TRUE;
321 if (!ok)
323 OOP_MethodID mid;
325 mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
326 OOP_CoerceMethod(cl, o, (OOP_Msg)&mid);
329 return o;
332 static VOID gfx_dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
334 struct gfx_data *data;
336 data = OOP_INST_DATA(cl, o);
337 if (NULL != data->curs_backup)
339 OOP_DisposeObject(data->curs_backup);
340 data->curs_backup = NULL;
343 if (data->curs_pixels)
344 FreeMem(data->curs_pixels, data->curs_width * data->curs_height * 4);
346 if (NULL != data->gc)
348 OOP_DisposeObject(data->gc);
349 data->gc = NULL;
353 static void gfx_get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
355 struct gfx_data *data = OOP_INST_DATA(cl, o);
357 if (msg->attrID == aHidd_Gfx_HWSpriteTypes) {
358 *msg->storage = vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor;
359 return;
362 OOP_DoMethod(data->gfxhidd, (OOP_Msg)msg);
365 static OOP_Object *gfx_newbitmap(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewBitMap *msg)
367 /* Is the user about to create a framebuffer ? */
368 BOOL create_fb;
369 struct gfx_data *data;
370 OOP_Object *realfb;
371 OOP_Object *ret = NULL;
373 data = OOP_INST_DATA(cl, o);
374 create_fb = (BOOL)GetTagData(data->fakefb_attr, FALSE, msg->attrList);
376 realfb = HIDD_Gfx_NewBitMap(data->gfxhidd, msg->attrList);
378 if (realfb && create_fb)
380 ret = create_fake_fb(realfb, data, GfxBase);
381 if (!ret)
382 OOP_DisposeObject(realfb);
384 else
385 ret = realfb;
387 return ret;
390 static BOOL gfx_setcursorshape(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorShape *msg)
392 struct gfx_data *data;
393 OOP_Object *shape;
394 BOOL ok = TRUE;
396 data = OOP_INST_DATA(cl, o);
397 shape = msg->shape;
398 D(bug("[FakeGfx] SetCursorShape(0x%p)\n", shape));
400 /* Bitmap changed */
401 if (NULL == shape)
403 /* Erase the old cursor */
404 draw_cursor(data, FALSE, TRUE, GfxBase);
405 data->curs_on = FALSE;
406 data->curs_bm = NULL;
407 data->curs_x = data->curs_y = 0;
408 data->curs_maxx = data->curs_maxy = 0;
409 data->curs_width = data->curs_height = 0;
410 data->curs_xoffset = 0;
411 data->curs_yoffset = 0;
413 if (NULL != data->curs_backup)
415 OOP_DisposeObject(data->curs_backup);
416 data->curs_backup = NULL;
418 if (data->curs_pixels) {
419 FreeMem(data->curs_pixels, data->curs_width * data->curs_height * 4);
420 data->curs_pixels = NULL;
423 else
425 IPTR curs_width, curs_height;
426 APTR new_curs_pixels;
427 ULONG curs_pixels_len;
429 OOP_GetAttr(shape, aHidd_BitMap_Width, &curs_width);
430 OOP_GetAttr(shape, aHidd_BitMap_Height, &curs_height);
432 DCURS(bug("[FakeGfx] New cursor size: %lu x %lu, framebuffer 0x%p\n", curs_width, curs_height, data->framebuffer));
434 /* Create new cursor pixelbuffer. We multiply size by 4 because we want ARGB data
435 to fit in. */
436 curs_pixels_len = curs_width * curs_height * 4;
437 new_curs_pixels = AllocMem(curs_pixels_len, MEMF_ANY|MEMF_CLEAR);
438 if (!new_curs_pixels)
439 return FALSE;
441 LFB(data);
443 /* Erase the old cursor */
444 draw_cursor(data, FALSE, TRUE, GfxBase);
446 /* Now that we have disposed the old image using the old
447 backup bm, we can install the new image and backup bm before
448 rendering the new cursor.
449 Backup bitmap is recreated in rethink_cursor()
452 if (data->curs_pixels)
453 FreeMem(data->curs_pixels, data->curs_width * data->curs_height * 4);
455 data->curs_bm = shape;
456 data->curs_width = curs_width;
457 data->curs_height = curs_height;
458 data->curs_maxx = data->curs_x + curs_width - 1;
459 data->curs_maxy = data->curs_y + curs_height - 1;
460 data->curs_pixels = new_curs_pixels;
461 data->curs_xoffset = msg->xoffset;
462 data->curs_yoffset = msg->yoffset;
464 ok = rethink_cursor(data, GfxBase);
465 UFB(data);
467 draw_cursor(data, TRUE, TRUE, GfxBase);
470 return ok;
473 static BOOL gfx_setcursorpos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
475 struct gfx_data *data;
476 IPTR xoffset = 0;
477 IPTR yoffset = 0;
479 data = OOP_INST_DATA(cl, o);
480 DPOS(bug("[FakeGfx] SetCursorPos(%d, %d)\n", msg->x, msg->y));
482 if (!data->framebuffer)
483 return TRUE;
485 /* We draw our cursor on the bitmap, so we have to convert back
486 from physical to logical coordinates */
487 OOP_GetAttr(data->framebuffer, aHidd_BitMap_LeftEdge, &xoffset);
488 OOP_GetAttr(data->framebuffer, aHidd_BitMap_TopEdge, &yoffset);
490 LFB_QUICK(data);
491 /* erase the old cursor */
492 draw_cursor(data, FALSE, TRUE, GfxBase);
494 data->curs_x = msg->x - xoffset;
495 data->curs_y = msg->y - yoffset;
496 /* Shift to the hotspot location */
497 data->curs_x += data->curs_xoffset;
498 data->curs_y += data->curs_yoffset;
499 data->curs_maxx = data->curs_x + data->curs_width - 1;
500 data->curs_maxy = data->curs_y + data->curs_height - 1;
502 draw_cursor(data, TRUE, TRUE, GfxBase);
503 UFB_QUICK(data);
504 return TRUE;
507 static VOID gfx_setcursorvisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
509 struct gfx_data *data;
511 data = OOP_INST_DATA(cl, o);
513 LFB_QUICK(data);
515 if (msg->visible)
517 if (!data->curs_on)
519 data->curs_on = TRUE;
520 draw_cursor(data, TRUE, TRUE, GfxBase);
523 else
525 if (data->curs_on)
527 draw_cursor(data, FALSE, TRUE, GfxBase);
528 data->curs_on = FALSE;
532 UFB_QUICK(data);
536 #define PIXEL_INSIDE(fgh, x, y) \
537 ( ( (x) >= (fgh)->curs_x ) \
538 && ( (y) >= (fgh)->curs_y ) \
539 && ( (x) <= (fgh)->curs_maxx ) \
540 && ( (y) <= (fgh)->curs_maxy ) )
542 /* NOTE: x1, y1, x2, y2 MUST be sorted */
543 #define RECT_INSIDE(fgh, x1, y1, x2, y2) \
544 ( ( (x1) <= fgh->curs_maxx ) \
545 && ( (x2) >= fgh->curs_x ) \
546 && ( (y1) <= fgh->curs_maxy ) \
547 && ( (y2) >= fgh->curs_y ) )
549 #define WRECT_INSIDE(fgh, x1, y1, width, height) \
550 RECT_INSIDE(fgh, x1, y1, (x1) + (width) - 1, (y1) + (height) - 1)
552 static void gfx_copybox(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBox *msg)
554 struct gfx_data *data;
555 OOP_Object *src = NULL;
556 OOP_Object *dest = NULL;
557 BOOL inside = FALSE;
559 data = OOP_INST_DATA(cl, o);
560 LFB(data);
562 /* De-masquerade bitmap objects, every of which can be fakefb object */
563 OOP_GetAttr(msg->src, aHidd_FakeFB_RealBitMap, (IPTR *)&src);
564 OOP_GetAttr(msg->dest, aHidd_FakeFB_RealBitMap, (IPTR *)&dest);
565 if (!src)
566 src = msg->src;
567 if (!dest)
568 dest = msg->dest;
570 /* FIXME: other bitmap may belong to another instance of fakegfx which can be on
571 display on another monitor. In this case mouse cursor should be handled also
572 there. Needs further reengineering. */
573 if ((msg->src == data->fakefb) && WRECT_INSIDE(data, msg->srcX, msg->srcY, msg->width, msg->height))
574 inside = TRUE;
576 if ((msg->dest == data->fakefb) && WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
577 inside = TRUE;
579 if (inside)
580 draw_cursor(data, FALSE, FALSE, GfxBase);
582 HIDD_Gfx_CopyBox(data->gfxhidd, src, msg->srcX, msg->srcY,
583 dest, msg->destX, msg->destY, msg->width, msg->height, msg->gc);
585 if (inside)
586 draw_cursor(data, TRUE, FALSE, GfxBase);
588 UFB(data);
591 static IPTR gfx_copyboxmasked(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBoxMasked *msg)
593 struct gfx_data *data;
594 OOP_Object *src = NULL;
595 OOP_Object *dest = NULL;
596 BOOL inside = FALSE;
597 BOOL ret;
599 data = OOP_INST_DATA(cl, o);
600 LFB(data);
602 /* De-masquerade bitmap objects, every of which can be fakefb object */
603 OOP_GetAttr(msg->src, aHidd_FakeFB_RealBitMap, (IPTR *)&src);
604 OOP_GetAttr(msg->dest, aHidd_FakeFB_RealBitMap, (IPTR *)&dest);
605 if (!src)
606 src = msg->src;
607 if (!dest)
608 dest = msg->dest;
611 * FIXME: other bitmap may belong to another instance of fakegfx which can be on
612 * display on another monitor. In this case mouse cursor should be handled also
613 * there. Needs further reengineering.
615 if ((msg->src == data->fakefb) && WRECT_INSIDE(data, msg->srcX, msg->srcY, msg->width, msg->height))
616 inside = TRUE;
618 if ((msg->dest == data->fakefb) && WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
619 inside = TRUE;
621 if (inside)
622 draw_cursor(data, FALSE, FALSE, GfxBase);
624 ret = HIDD_Gfx_CopyBoxMasked(data->gfxhidd, src, msg->srcX, msg->srcY,
625 dest, msg->destX, msg->destY, msg->width, msg->height, msg->mask, msg->gc);
627 if (inside)
628 draw_cursor(data, TRUE, FALSE, GfxBase);
630 UFB(data);
632 return ret;
635 static OOP_Object *gfx_show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
637 OOP_Object *ret;
638 struct gfx_data *data;
640 data = OOP_INST_DATA(cl, o);
641 ret = msg->bitMap;
643 D(bug("[FakeGfx] Show(0x%p)\n", ret));
646 * If we are attempting to show a fake bitmap, we are working
647 * in NoFrameBuffer mode where each displayable bitmap is
648 * intercepted by us
650 if (ret && (OOP_OCLASS(ret) == CDD(GfxBase)->fakefbclass))
652 data->fakefb = ret;
653 OOP_GetAttr(msg->bitMap, aHidd_FakeFB_RealBitMap, (IPTR *)&ret);
654 D(bug("[FakeGfx] Bitmap is a fakefb object, real bitmap is 0x%p\n", ret));
657 LFB(data);
658 draw_cursor(data, FALSE, FALSE, GfxBase);
660 ret = HIDD_Gfx_Show(data->gfxhidd, ret, msg->flags);
661 D(bug("[FakeGfx] Real framebuffer object 0x%p\n", ret));
662 gfx_setFrameBuffer(GfxBase, data, ret);
663 if (NULL != ret)
664 ret = data->fakefb;
665 /* FIXME: temporary workaround: at this point Intuition has already destroyed
666 the sprite image (since the last screen was closed) but we have no information
667 about it. Perhaps FreeSpriteData() should track this down somehow and inform
668 drivers about destroyed sprites.
669 if (!msg->bitMap)
670 data->curs_bm = NULL;*/
671 rethink_cursor(data, GfxBase);
672 draw_cursor(data, TRUE, TRUE, GfxBase);
674 UFB(data);
676 D(bug("[FakeGfx] Returning 0x%p\n", ret));
677 return ret;
680 static ULONG gfx_showviewports(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
682 /* Composition is not supported here */
683 return FALSE;
686 static BOOL gfx_getmaxspritesize(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMaxSpriteSize *msg)
688 if (msg->Type & (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor)) {
689 /* I hope these values are enough for everyone :) */
690 *msg->Width = 65535;
691 *msg->Height = 65535;
693 return TRUE;
694 } else
695 return FALSE;
698 static IPTR gfx_fwd(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
700 struct gfx_data *data;
702 data = OOP_INST_DATA(cl, o);
704 return OOP_DoMethod(data->gfxhidd, msg);
707 /* Private non-virtual method */
708 static BOOL FakeGfx_UpdateFrameBuffer(OOP_Object *o)
710 OOP_Class *cl = OOP_OCLASS(o);
711 struct gfx_data *data = OOP_INST_DATA(cl, o);
712 BOOL ok;
714 LFB(data);
716 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Width, &data->fb_width);
717 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Height, &data->fb_height);
719 DCURS(bug("[FakeGfx] Changed framebuffer size: %u x %u\n", data->fb_width, data->fb_height));
721 ok = rethink_cursor(data, GfxBase);
722 UFB(data);
724 draw_cursor(data, TRUE, TRUE, GfxBase);
725 return ok;
728 struct fakefb_data
730 OOP_Object *framebuffer;
731 OOP_Object *fakegfxhidd;
734 #define FGH(data) ((struct gfx_data *)data->fakegfxhidd)
735 #define REMOVE_CURSOR(data) \
736 draw_cursor(FGH(data), FALSE, FALSE, GfxBase)
738 #define RENDER_CURSOR(data) \
739 draw_cursor(FGH(data), TRUE, FALSE, GfxBase)
742 #define BITMAP_METHOD_INIT \
743 struct fakefb_data *data; \
744 BOOL inside = FALSE; \
745 IPTR retval; \
746 struct gfx_data *fgh; \
747 data = OOP_INST_DATA(cl, o); \
748 fgh = FGH(data); \
749 LFB(fgh);
751 #define FORWARD_METHOD \
752 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
754 #define BITMAP_METHOD_EXIT \
755 if (inside) { \
756 RENDER_CURSOR(data); \
758 UFB(fgh); \
759 return retval;
761 static OOP_Object *fakefb_new(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
763 OOP_Object *framebuffer;
764 OOP_Object *fakegfxhidd;
766 framebuffer = (OOP_Object *)GetTagData(aHidd_FakeFB_RealBitMap, 0, msg->attrList);
767 fakegfxhidd = (OOP_Object *)GetTagData(aHidd_FakeFB_FakeGfxHidd, 0, msg->attrList);
769 if (NULL == framebuffer || NULL == fakegfxhidd)
771 D(bug("!!! FakeBM::New(): MISSING FRAMEBUFFER OR FAKE GFX HIDD !!!\n"));
772 return NULL;
775 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
776 if (NULL != o)
778 struct fakefb_data *data;
779 data = OOP_INST_DATA(cl, o);
780 data->framebuffer = framebuffer;
781 data->fakegfxhidd = fakegfxhidd;
783 return o;
786 static VOID fakefb_dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
788 struct fakefb_data *data;
789 data = OOP_INST_DATA(cl, o);
790 if (NULL != data->framebuffer)
792 OOP_DisposeObject(data->framebuffer);
793 data->framebuffer = NULL;
797 static void fakefb_get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
799 struct fakefb_data *data = OOP_INST_DATA(cl, o);
801 if (msg->attrID == aHidd_FakeFB_RealBitMap)
803 *msg->storage = (IPTR)data->framebuffer;
804 return;
806 else if (msg->attrID == aHidd_BitMap_GfxHidd)
808 *msg->storage = (IPTR)data->fakegfxhidd;
809 return;
811 else
812 OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
815 /* Intercept framebuffer mode change */
816 static IPTR fakefb_set(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
818 struct fakefb_data *data = OOP_INST_DATA(cl, o);
819 IPTR ret = OOP_DoMethod(data->framebuffer, &msg->mID);
820 struct TagItem *modeid = FindTagItem(aHidd_BitMap_ModeID, msg->attrList);
822 if (modeid && ret)
824 /* Framebuffer mode change succeeded. Update fakegfx' information */
825 ret = FakeGfx_UpdateFrameBuffer(data->fakegfxhidd);
828 return ret;
831 static IPTR fakefb_getpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetPixel *msg)
833 BITMAP_METHOD_INIT
835 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
837 REMOVE_CURSOR(data);
838 inside = TRUE;
841 FORWARD_METHOD
843 BITMAP_METHOD_EXIT
846 static IPTR fakefb_putpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
848 BITMAP_METHOD_INIT
850 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
852 REMOVE_CURSOR(data);
853 inside = TRUE;
856 FORWARD_METHOD
858 BITMAP_METHOD_EXIT
861 static IPTR fakefb_drawpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPixel *msg)
863 BITMAP_METHOD_INIT
865 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
867 REMOVE_CURSOR(data);
868 inside = TRUE;
871 FORWARD_METHOD
873 BITMAP_METHOD_EXIT
876 static IPTR fakefb_drawline(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawLine *msg)
878 register LONG x1, y1, x2, y2;
879 BITMAP_METHOD_INIT
881 if (msg->x1 < msg->x2)
883 x1 = msg->x1; x2 = msg->x2;
885 else
887 x2 = msg->x1; x1 = msg->x2;
890 if (msg->y1 < msg->y2)
892 y1 = msg->y1; y2 = msg->y2;
894 else
896 y2 = msg->y1; y1 = msg->y2;
899 /* FIXME: Maybe do some more intelligent checking for DrawLine */
900 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
902 REMOVE_CURSOR(data);
903 inside = TRUE;
906 FORWARD_METHOD
908 BITMAP_METHOD_EXIT
911 static IPTR fakefb_getimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImage *msg)
913 BITMAP_METHOD_INIT
915 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
917 REMOVE_CURSOR(data);
918 inside = TRUE;
921 FORWARD_METHOD
923 BITMAP_METHOD_EXIT
926 static IPTR fakefb_putimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImage *msg)
928 BITMAP_METHOD_INIT
930 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
932 REMOVE_CURSOR(data);
933 inside = TRUE;
936 FORWARD_METHOD
938 BITMAP_METHOD_EXIT
941 static IPTR fakefb_putalphaimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaImage *msg)
943 BITMAP_METHOD_INIT
945 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
947 REMOVE_CURSOR(data);
948 inside = TRUE;
951 FORWARD_METHOD
953 BITMAP_METHOD_EXIT
956 static IPTR fakefb_puttemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTemplate *msg)
958 BITMAP_METHOD_INIT
960 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
962 REMOVE_CURSOR(data);
963 inside = TRUE;
966 FORWARD_METHOD
968 BITMAP_METHOD_EXIT
971 static IPTR fakefb_putalphatemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaTemplate *msg)
973 BITMAP_METHOD_INIT
975 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
977 REMOVE_CURSOR(data);
978 inside = TRUE;
981 FORWARD_METHOD
983 BITMAP_METHOD_EXIT
986 static IPTR fakefb_putpattern(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPattern *msg)
988 BITMAP_METHOD_INIT
990 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
992 REMOVE_CURSOR(data);
993 inside = TRUE;
996 FORWARD_METHOD
998 BITMAP_METHOD_EXIT
1001 static IPTR fakefb_getimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImageLUT *msg)
1003 BITMAP_METHOD_INIT
1005 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1007 REMOVE_CURSOR(data);
1008 inside = TRUE;
1011 FORWARD_METHOD
1013 BITMAP_METHOD_EXIT
1016 static IPTR fakefb_putimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg)
1018 BITMAP_METHOD_INIT
1020 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1022 REMOVE_CURSOR(data);
1023 inside = TRUE;
1026 FORWARD_METHOD
1028 BITMAP_METHOD_EXIT
1031 static IPTR fakefb_puttranspimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTranspImageLUT *msg)
1033 BITMAP_METHOD_INIT
1035 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1037 REMOVE_CURSOR(data);
1038 inside = TRUE;
1041 FORWARD_METHOD
1043 BITMAP_METHOD_EXIT
1046 static IPTR fakefb_drawrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
1048 BITMAP_METHOD_INIT
1050 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1051 if (RECT_INSIDE(fgh, msg->minX, msg->minY, msg->maxX, msg->maxY))
1053 REMOVE_CURSOR(data);
1054 inside = TRUE;
1057 FORWARD_METHOD
1059 BITMAP_METHOD_EXIT
1062 static IPTR fakefb_fillrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
1064 BITMAP_METHOD_INIT
1066 /* bug("BITMAP FILLRECT(%d, %d, %d, %d), (%d, %d, %d, %d, %d, %d)\n"
1067 , msg->minX, msg->minY, msg->maxX, msg->maxY
1068 , fgh->curs_x, fgh->curs_y, fgh->curs_maxx, fgh->curs_maxy
1069 , fgh->curs_width, fgh->curs_height);
1071 if (RECT_INSIDE(fgh, msg->minX, msg->minY, msg->maxX, msg->maxY))
1073 /* bug("FILLRECT: REMOVING CURSOR\n");
1075 REMOVE_CURSOR(data);
1077 inside = TRUE;
1080 FORWARD_METHOD
1082 BITMAP_METHOD_EXIT
1085 static IPTR fakefb_drawellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1087 register LONG x1, y1, x2, y2;
1088 BITMAP_METHOD_INIT
1090 x1 = msg->x - msg->rx;
1091 y1 = msg->y - msg->ry;
1092 x2 = msg->x + msg->rx;
1093 y2 = msg->y + msg->ry;
1094 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1096 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
1098 REMOVE_CURSOR(data);
1099 inside = TRUE;
1102 FORWARD_METHOD
1104 BITMAP_METHOD_EXIT
1107 static IPTR fakefb_fillellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1109 register LONG x1, y1, x2, y2;
1110 BITMAP_METHOD_INIT
1112 x1 = msg->x - msg->rx;
1113 y1 = msg->y - msg->ry;
1114 x2 = msg->x + msg->rx;
1115 y2 = msg->y + msg->ry;
1117 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
1119 REMOVE_CURSOR(data);
1120 inside = TRUE;
1123 FORWARD_METHOD
1125 BITMAP_METHOD_EXIT
1128 static IPTR fakefb_drawpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1130 BITMAP_METHOD_INIT
1131 /* FIXME: Maybe do checking here, but it probably is not worth it */
1132 REMOVE_CURSOR(data);
1133 inside = TRUE;
1135 FORWARD_METHOD
1137 BITMAP_METHOD_EXIT
1140 static IPTR fakefb_fillpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1142 BITMAP_METHOD_INIT
1143 /* FIXME: Maybe do checking here, but it probably is not worth it */
1144 REMOVE_CURSOR(data);
1145 inside = TRUE;
1147 FORWARD_METHOD
1149 BITMAP_METHOD_EXIT
1153 static IPTR fakefb_drawtext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1155 BITMAP_METHOD_INIT
1157 /* FIXME: Maybe do testing here, but probably not wirth it */
1158 REMOVE_CURSOR(data);
1160 FORWARD_METHOD
1162 BITMAP_METHOD_EXIT
1165 static IPTR fakefb_drawfilltext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1167 BITMAP_METHOD_INIT
1169 /* FIXME: Maybe do testing here, but probably not worth it */
1170 REMOVE_CURSOR(data);
1172 FORWARD_METHOD
1174 BITMAP_METHOD_EXIT
1177 static IPTR fakefb_blitcolexp(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BlitColorExpansion *msg)
1179 BITMAP_METHOD_INIT
1181 if (WRECT_INSIDE(fgh, msg->destX, msg->destY, msg->width, msg->height))
1183 REMOVE_CURSOR(data);
1184 inside = TRUE;
1187 FORWARD_METHOD
1189 BITMAP_METHOD_EXIT
1192 static IPTR fakefb_clear(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_Clear *msg)
1194 BITMAP_METHOD_INIT
1196 inside = TRUE;
1198 FORWARD_METHOD
1200 BITMAP_METHOD_EXIT
1204 static IPTR fakefb_fillspan(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1206 BITMAP_METHOD_INIT
1208 REMOVE_CURSOR(data);
1209 inside = TRUE;
1211 FORWARD_METHOD
1213 BITMAP_METHOD_EXIT
1216 static IPTR fakefb_scale(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BitMapScale *msg)
1218 /* FIXME: should check both source and destination, similar to gfx_copybox() */
1219 BITMAP_METHOD_INIT
1221 if (WRECT_INSIDE(fgh, msg->bsa->bsa_SrcX, msg->bsa->bsa_SrcY, msg->bsa->bsa_SrcWidth, msg->bsa->bsa_SrcHeight))
1223 REMOVE_CURSOR(data);
1224 inside = TRUE;
1227 FORWARD_METHOD
1229 BITMAP_METHOD_EXIT
1232 static IPTR fakefb_fwd(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1234 struct fakefb_data *data;
1235 data = OOP_INST_DATA(cl, o);
1236 // kill(getpid(), 19);
1237 // bug("BITMAP_FWD\n");
1238 return OOP_DoMethod(data->framebuffer, msg);
1241 #undef GfxBase
1243 static BOOL rethink_cursor(struct gfx_data *data, struct GfxBase *GfxBase)
1245 OOP_Object *pf, *cmap;
1246 IPTR fbdepth, curdepth, i;
1247 UWORD curs_base = 16;
1249 struct TagItem bmtags[] = {
1250 { aHidd_BitMap_Width , data->curs_width },
1251 { aHidd_BitMap_Height, data->curs_height },
1252 { aHidd_BitMap_Friend, (IPTR)data->framebuffer},
1253 { TAG_DONE , 0UL }
1256 D(bug("rethink_cursor(), curs_bm is 0x%p, framebuffer is 0x%p\n", data->curs_bm, data->framebuffer));
1258 /* The first thing we do is recreating a backup bitmap. We do it every time when either
1259 cursor shape changes (because new shape may have different size) or shown bitmap
1260 changes (because new bitmap may have different depth). Note that even real framebuffer
1261 object may dynamically change its characteristics.
1263 Delete the old backup bitmap first */
1264 if (NULL != data->curs_backup) {
1265 OOP_DisposeObject(data->curs_backup);
1266 D(bug("[FakeGfx] Disposed old backup bitmap\n"));
1267 data->curs_backup = NULL;
1270 /* If we have no cursor, we have nothing more to do.
1271 We also don't need new backup bitmap */
1272 if (!data->curs_bm)
1273 return TRUE;
1275 /* We may also have no framebuffer (empty display on
1276 non-framebuffer driver). Also NOP in this case */
1277 if (!data->framebuffer)
1278 return TRUE;
1280 /* Create new backup bitmap */
1281 data->curs_backup = HIDD_Gfx_NewBitMap(data->gfxhidd, bmtags);
1282 D(bug("[FakeGfx] New backup bitmap is 0x%p\n", data->curs_backup));
1283 if (!data->curs_backup)
1284 return FALSE;
1286 OOP_GetAttr(data->framebuffer, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1287 D(bug("[FakeGfx] Framebuffer pixelformat 0x%p\n", pf));
1288 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &fbdepth);
1289 D(bug("[FakeGfx] Framebuffer depth %u\n", fbdepth));
1290 OOP_GetAttr(data->curs_bm, aHidd_BitMap_ColorMap, (IPTR *)&cmap);
1291 D(bug("[FakeGfx] Cursor colormap 0x%p\n", cmap));
1292 OOP_GetAttr(data->curs_bm, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1293 D(bug("[FakeGfx] Cursor pixelformat 0x%p\n", pf));
1294 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &curdepth);
1295 D(bug("[FakeGfx] Cursor depth %u\n", curdepth));
1297 #ifndef DISABLE_ARGB_POINTER
1298 /* We can get ARGB data from the pointer bitmap only
1299 on one of two cases:
1300 1) Pointer bitmap has more than 256 colors, in this case it
1301 stores ARGB data in itself.
1302 2) Pointer bitmap is a LUT bitmap with a colormap attached.
1303 In this case colormap should contain ARGB values for actual
1304 colors.
1305 Of course having ARGB data makes sense only on truecolor screens. */
1306 if ((fbdepth > 8) && ((curdepth > 8) || cmap)) {
1307 data->curs_pixfmt = vHidd_StdPixFmt_ARGB32;
1308 data->curs_bpp = 4;
1309 } else
1310 #endif
1312 data->curs_pixfmt = vHidd_StdPixFmt_LUT8;
1313 data->curs_bpp = 1;
1314 /* TODO: curs_base should be somehow synchronised with SpriteBase field of ColorMap */
1315 curs_base = (fbdepth > 4) ? 16 : (1 << fbdepth) - 8;
1317 /* If we have some good bitmap->bitmap blitting function with alpha channel support,
1318 we would not need this extra buffer and conversion for truecolor screens. */
1319 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);
1320 D(bug("[FakeGfx] Obtained cursor sprite data @ 0x%p\n", data->curs_pixels));
1322 if (data->curs_pixfmt == vHidd_StdPixFmt_LUT8)
1324 for (i = 0; i < data->curs_width * data->curs_height; i++)
1326 if (data->curs_pixels[i])
1327 data->curs_pixels[i] += curs_base;
1330 return TRUE;
1333 static VOID draw_cursor(struct gfx_data *data, BOOL draw, BOOL updaterect, struct GfxBase *GfxBase)
1335 LONG width, height;
1336 LONG fbwidth, fbheight;
1337 LONG x, y;
1338 LONG w2end, h2end;
1339 ULONG xoffset = 0;
1340 ULONG yoffset = 0;
1342 struct TagItem gctags[] =
1344 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
1345 { TAG_DONE , 0UL }
1348 if (!data->curs_on)
1349 return;
1351 if (NULL == data->curs_bm || NULL == data->framebuffer)
1353 DB2(bug("!!! draw_cursor: FAKE GFX HIDD NOT PROPERLY INITIALIZED !!!\n"));
1354 DB2(bug("CURS BM: 0x%p, FB: 0x%p\n", data->curs_bm, data->framebuffer));
1355 return;
1358 fbwidth = data->fb_width;
1359 fbheight = data->fb_height;
1360 width = data->curs_width;
1361 height = data->curs_height;
1362 x = data->curs_x;
1363 y = data->curs_y;
1365 /* Do nothing if sprite went outside of bitmap */
1366 if ((x < -width) || (y < -height)) {
1367 DCURS(bug("[FakeGfx] Cursor is beyond left or top edge\n"));
1368 return;
1370 if ((x >= fbwidth) || (y >= fbheight)) {
1371 DCURS(bug("[FakeGfx] Cursor is beyond right or bottom edge\n"));
1372 return;
1375 /* Do some clipping */
1376 if (x < 0) {
1377 xoffset = -x;
1378 width += x;
1379 x = 0;
1382 if (y < 0) {
1383 yoffset = -y;
1384 height += y;
1385 y = 0;
1388 w2end = data->fb_width - width;
1389 h2end = data->fb_height - width;
1391 if (x > w2end)
1393 width -= (x - w2end);
1394 DCLIP(bug("[FakeGfx] Clipped sprite width to %d\n", width));
1397 if (y > h2end)
1399 height -= (y - h2end);
1400 DCLIP(bug("[FakeGfx] Clipped sprite height to %d\n", height));
1403 /* FIXME: clip negative coordinates */
1405 OOP_SetAttrs(data->gc, gctags);
1407 if (draw)
1409 /* Calculate origin of sprite image according to offsets */
1410 ULONG modulo = data->curs_width * data->curs_bpp;
1411 UBYTE *pixels = data->curs_pixels + yoffset * modulo + xoffset * data->curs_bpp;
1413 /* Backup under the new cursor image */
1414 // bug("BACKING UP RENDERED AREA\n");
1415 HIDD_Gfx_CopyBox(data->gfxhidd
1416 , data->framebuffer
1417 , x, y
1418 , data->curs_backup
1419 , 0, 0
1420 , width, height
1421 , data->gc
1424 data->backup_done = TRUE;
1426 DB2(bug("[FakeGfx] Rendering cursor, framebuffer 0x%p\n", data->framebuffer));
1427 /* Render the cursor image */
1428 if (data->curs_pixfmt == vHidd_StdPixFmt_ARGB32)
1429 HIDD_BM_PutAlphaImage(data->framebuffer, data->gc, pixels, modulo, x, y, width, height);
1430 else
1431 /* data->curs_bpp is always 1 here so we safely ignore it */
1432 HIDD_BM_PutTranspImageLUT(data->framebuffer, data->gc, pixels, modulo, x, y, width, height, NULL, 0);
1434 if (updaterect)
1435 HIDD_BM_UpdateRect(data->framebuffer, x, y, width, height);
1438 else
1440 /* Erase the old cursor image */
1441 if (data->backup_done)
1443 DB2(bug("[FakeGfx] Restoring cursor area, framebuffer 0x%p\n", data->framebuffer));
1444 HIDD_Gfx_CopyBox(data->gfxhidd
1445 , data->curs_backup
1446 , 0, 0
1447 , data->framebuffer
1448 , x, y
1449 , width, height
1450 , data->gc
1453 if (updaterect) HIDD_BM_UpdateRect(data->framebuffer, data->curs_x, data->curs_y, width, height);
1456 return;
1459 static void gfx_setFrameBuffer(struct GfxBase *GfxBase, struct gfx_data *data, OOP_Object *fb)
1461 data->framebuffer = fb;
1463 if (fb)
1465 /* Cache framebuffer size, needed by sprite rendering routine */
1466 OOP_GetAttr(fb, aHidd_BitMap_Width, &data->fb_width);
1467 OOP_GetAttr(fb, aHidd_BitMap_Height, &data->fb_height);
1469 DCURS(bug("[FakeGfx] Framebuffer size: %u x %u\n", data->fb_width, data->fb_height));
1473 static OOP_Object *create_fake_fb(OOP_Object *framebuffer, struct gfx_data *data, struct GfxBase *GfxBase)
1475 OOP_Object *fakebm;
1476 struct TagItem fakebmtags[] =
1478 { aHidd_FakeFB_RealBitMap , (IPTR)framebuffer },
1479 { aHidd_FakeFB_FakeGfxHidd , (IPTR)data },
1480 { TAG_DONE , 0UL }
1483 /* If we work with framebuffer-based driver, Show() will never be called on
1484 a fakefb object so we remember it right now */
1485 fakebm = OOP_NewObject(CDD(GfxBase)->fakefbclass, NULL, fakebmtags);
1487 if (data->fakefb_attr == aHidd_BitMap_FrameBuffer)
1489 data->fakefb = fakebm;
1490 gfx_setFrameBuffer(GfxBase, data, framebuffer);
1493 return fakebm;
1496 static OOP_Class *init_fakegfxhiddclass (struct GfxBase *GfxBase)
1498 OOP_Class *cl = NULL;
1500 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1502 {(IPTR (*)())gfx_new , moRoot_New },
1503 {(IPTR (*)())gfx_dispose, moRoot_Dispose },
1504 {(IPTR (*)())gfx_get , moRoot_Get },
1505 {(IPTR (*)())gfx_fwd , moRoot_Set },
1506 { NULL , 0UL }
1509 struct OOP_MethodDescr gfxhidd_descr[num_Hidd_Gfx_Methods + 1] =
1511 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewGC },
1512 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeGC },
1513 {(IPTR (*)())gfx_newbitmap , moHidd_Gfx_NewBitMap },
1514 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeBitMap },
1515 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryModeIDs },
1516 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ReleaseModeIDs },
1517 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CheckMode },
1518 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NextModeID },
1519 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetMode },
1520 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetPixFmt },
1521 {(IPTR (*)())gfx_setcursorshape , moHidd_Gfx_SetCursorShape },
1522 {(IPTR (*)())gfx_setcursorpos , moHidd_Gfx_SetCursorPos },
1523 {(IPTR (*)())gfx_setcursorvisible , moHidd_Gfx_SetCursorVisible},
1524 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetMode },
1525 {(IPTR (*)())gfx_show , moHidd_Gfx_Show },
1526 {(IPTR (*)())gfx_copybox , moHidd_Gfx_CopyBox },
1527 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ModeProperties },
1528 {(IPTR (*)())gfx_showviewports , moHidd_Gfx_ShowViewPorts },
1529 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetSync },
1530 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetGamma },
1531 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetGamma },
1532 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryHardware3D },
1533 {(IPTR (*)())gfx_getmaxspritesize , moHidd_Gfx_GetMaxSpriteSize},
1534 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewOverlay },
1535 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeOverlay },
1536 {(IPTR (*)())gfx_fwd , moHidd_Gfx_MakeViewPort },
1537 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CleanViewPort },
1538 {(IPTR (*)())gfx_fwd , moHidd_Gfx_PrepareViewPorts},
1539 {(IPTR (*)())gfx_copyboxmasked , moHidd_Gfx_CopyBoxMasked },
1540 {NULL , 0UL }
1543 struct OOP_InterfaceDescr ifdescr[] =
1545 {root_descr , IID_Root , num_Root_Methods },
1546 {gfxhidd_descr , IID_Hidd_Gfx , num_Hidd_Gfx_Methods },
1547 {NULL , NULL , 0 }
1550 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1552 struct TagItem tags[] =
1554 { aMeta_SuperID , (IPTR)CLID_Root },
1555 { aMeta_InterfaceDescr , (IPTR)ifdescr },
1556 { aMeta_InstSize , (IPTR)sizeof (struct gfx_data) },
1557 {TAG_DONE , 0UL }
1561 D(bug("INIT FAKEGFXCLASS\n"));
1563 if ((__IHidd_FakeFB = OOP_ObtainAttrBase(IID_Hidd_FakeFB)))
1565 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1566 if(NULL != cl)
1568 D(bug("FAKE GFX CLASS INITED\n"));
1569 cl->UserData = GfxBase;
1571 return cl;
1574 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1577 return NULL;
1580 static OOP_Class *init_fakefbclass(struct GfxBase *GfxBase)
1582 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1584 {(IPTR (*)())fakefb_new , moRoot_New },
1585 {(IPTR (*)())fakefb_dispose, moRoot_Dispose },
1586 {(IPTR (*)())fakefb_get , moRoot_Get },
1587 {(IPTR (*)())fakefb_set , moRoot_Set },
1588 {NULL , 0UL }
1591 struct OOP_MethodDescr bitmap_descr[num_Hidd_BitMap_Methods + 1] =
1593 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColors },
1594 {(IPTR (*)())fakefb_putpixel , moHidd_BitMap_PutPixel },
1595 {(IPTR (*)())fakefb_drawpixel , moHidd_BitMap_DrawPixel },
1596 {(IPTR (*)())fakefb_putimage , moHidd_BitMap_PutImage },
1597 {(IPTR (*)())fakefb_putalphaimage , moHidd_BitMap_PutAlphaImage },
1598 {(IPTR (*)())fakefb_puttemplate , moHidd_BitMap_PutTemplate },
1599 {(IPTR (*)())fakefb_putalphatemplate , moHidd_BitMap_PutAlphaTemplate },
1600 {(IPTR (*)())fakefb_putpattern , moHidd_BitMap_PutPattern },
1601 {(IPTR (*)())fakefb_getimage , moHidd_BitMap_GetImage },
1602 {(IPTR (*)())fakefb_getpixel , moHidd_BitMap_GetPixel },
1603 {(IPTR (*)())fakefb_drawline , moHidd_BitMap_DrawLine },
1604 {(IPTR (*)())fakefb_drawrect , moHidd_BitMap_DrawRect },
1605 {(IPTR (*)())fakefb_fillrect , moHidd_BitMap_FillRect },
1606 {(IPTR (*)())fakefb_drawellipse , moHidd_BitMap_DrawEllipse },
1607 {(IPTR (*)())fakefb_fillellipse , moHidd_BitMap_FillEllipse },
1608 {(IPTR (*)())fakefb_drawpolygon , moHidd_BitMap_DrawPolygon },
1609 {(IPTR (*)())fakefb_fillpolygon , moHidd_BitMap_FillPolygon },
1610 {(IPTR (*)())fakefb_drawtext , moHidd_BitMap_DrawText },
1611 {(IPTR (*)())fakefb_drawfilltext , moHidd_BitMap_FillText },
1612 {(IPTR (*)())fakefb_fillspan , moHidd_BitMap_FillSpan },
1613 {(IPTR (*)())fakefb_clear , moHidd_BitMap_Clear },
1614 {(IPTR (*)())fakefb_blitcolexp , moHidd_BitMap_BlitColorExpansion },
1615 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_MapColor },
1616 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UnmapPixel },
1617 {(IPTR (*)())fakefb_putimagelut , moHidd_BitMap_PutImageLUT },
1618 {(IPTR (*)())fakefb_puttranspimagelut , moHidd_BitMap_PutTranspImageLUT },
1619 {(IPTR (*)())fakefb_getimagelut , moHidd_BitMap_GetImageLUT },
1620 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_BytesPerLine },
1621 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ConvertPixels },
1622 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect8 },
1623 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect16 },
1624 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect24 },
1625 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect32 },
1626 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_InvertMemRect },
1627 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox8 },
1628 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox16 },
1629 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox24 },
1630 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox32 },
1631 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox16 },
1632 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox24 },
1633 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox32 },
1634 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image8 },
1635 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image16 },
1636 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image24 },
1637 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image8 },
1638 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image16 },
1639 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image24 },
1640 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate8 },
1641 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate16 },
1642 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate24 },
1643 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate32 },
1644 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern8 },
1645 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern16 },
1646 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern24 },
1647 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern32 },
1648 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColorMap },
1649 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ObtainDirectAccess },
1650 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ReleaseDirectAccess },
1651 {(IPTR (*)())fakefb_scale , moHidd_BitMap_BitMapScale },
1652 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PrivateSet },
1653 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetRGBConversionFunction },
1654 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UpdateRect },
1655 {NULL , 0UL }
1658 struct OOP_InterfaceDescr ifdescr[] =
1660 {root_descr , IID_Root , num_Root_Methods },
1661 {bitmap_descr , IID_Hidd_BitMap, num_Hidd_BitMap_Methods },
1662 {NULL , NULL , 0 }
1665 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1667 struct TagItem tags[] =
1669 {aMeta_SuperID , (IPTR) CLID_Root },
1670 {aMeta_InterfaceDescr , (IPTR) ifdescr },
1671 {aMeta_InstSize , (IPTR) sizeof(struct fakefb_data) },
1672 {TAG_DONE , 0UL }
1675 OOP_Class *cl = NULL;
1677 if (MetaAttrBase)
1679 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1680 if (NULL != cl)
1681 cl->UserData = GfxBase;
1682 } /* if(MetaAttrBase) */
1684 return cl;
1687 OOP_Object *init_fakegfxhidd(OOP_Object *gfxhidd, struct GfxBase *GfxBase)
1689 struct common_driverdata *csd = CDD(GfxBase);
1691 if (!csd->fakegfxclass)
1693 /* Lazy class initialization */
1694 csd->fakegfxclass = init_fakegfxhiddclass(GfxBase);
1695 csd->fakefbclass = init_fakefbclass(GfxBase);
1697 if (!csd->fakegfxclass || !csd->fakefbclass)
1699 cleanup_fakegfxhidd(GfxBase);
1700 return NULL;
1705 return OOP_NewObjectTags(csd->fakegfxclass, NULL, aHidd_FakeGfxHidd_RealGfxHidd, gfxhidd, TAG_DONE);
1708 VOID cleanup_fakegfxhidd(struct GfxBase *GfxBase)
1710 struct common_driverdata *csd = CDD(GfxBase);
1712 if (NULL != csd->fakefbclass)
1714 OOP_DisposeObject((OOP_Object *)csd->fakefbclass);
1715 csd->fakefbclass = NULL;
1718 if (NULL != csd->fakegfxclass)
1720 OOP_DisposeObject((OOP_Object *)csd->fakegfxclass);
1721 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1722 csd->fakegfxclass = NULL;