Removed Gfx_ShowViewPorts method implementation, as it was identical to
[AROS.git] / rom / graphics / fakegfxhidd.c
blob519f827a794f73c3c29d1ff123e441648d3eec7a
1 /*
2 Copyright © 1995-2014, 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;
292 realgfxhidd = (OOP_Object *)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd, (IPTR)NULL, msg->attrList);
293 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
294 if (NULL == o)
295 return NULL;
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[] =
318 { TAG_DONE, 0UL }
321 data->gc = HIDD_Gfx_NewGC(data->gfxhidd, gctags);
322 if (NULL != data->gc)
324 ok = TRUE;
328 if (!ok)
330 OOP_MethodID mid;
332 mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
333 OOP_CoerceMethod(cl, o, (OOP_Msg)&mid);
336 return o;
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);
356 data->gc = NULL;
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;
366 return;
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 ? */
375 BOOL create_fb;
376 struct gfx_data *data;
377 OOP_Object *realfb;
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);
388 if (!ret)
389 OOP_DisposeObject(realfb);
391 else
392 ret = realfb;
394 return ret;
397 static BOOL gfx_setcursorshape(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorShape *msg)
399 struct gfx_data *data;
400 OOP_Object *shape;
401 BOOL ok = TRUE;
403 data = OOP_INST_DATA(cl, o);
404 shape = msg->shape;
405 D(bug("[FakeGfx] SetCursorShape(0x%p)\n", shape));
407 /* Bitmap changed */
408 if (NULL == 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;
430 else
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
442 to fit in. */
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)
446 return FALSE;
448 LFB(data);
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);
472 UFB(data);
474 draw_cursor(data, TRUE, TRUE, GfxBase);
477 return ok;
480 static BOOL gfx_setcursorpos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
482 struct gfx_data *data;
483 IPTR xoffset = 0;
484 IPTR yoffset = 0;
486 data = OOP_INST_DATA(cl, o);
487 DPOS(bug("[FakeGfx] SetCursorPos(%d, %d)\n", msg->x, msg->y));
489 if (!data->framebuffer)
490 return TRUE;
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);
497 LFB_QUICK(data);
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);
510 UFB_QUICK(data);
511 return TRUE;
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);
520 LFB_QUICK(data);
522 if (msg->visible)
524 if (!data->curs_on)
526 data->curs_on = TRUE;
527 draw_cursor(data, TRUE, TRUE, GfxBase);
530 else
532 if (data->curs_on)
534 draw_cursor(data, FALSE, TRUE, GfxBase);
535 data->curs_on = FALSE;
539 UFB_QUICK(data);
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;
564 BOOL inside = FALSE;
566 data = OOP_INST_DATA(cl, o);
567 LFB(data);
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);
572 if (!src)
573 src = msg->src;
574 if (!dest)
575 dest = msg->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))
581 inside = TRUE;
583 if ((msg->dest == data->fakefb) && WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
584 inside = TRUE;
586 if (inside)
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);
592 if (inside)
593 draw_cursor(data, TRUE, FALSE, GfxBase);
595 UFB(data);
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;
603 BOOL inside = FALSE;
604 BOOL ret;
606 data = OOP_INST_DATA(cl, o);
607 LFB(data);
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);
612 if (!src)
613 src = msg->src;
614 if (!dest)
615 dest = msg->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))
623 inside = TRUE;
625 if ((msg->dest == data->fakefb) && WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
626 inside = TRUE;
628 if (inside)
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);
634 if (inside)
635 draw_cursor(data, TRUE, FALSE, GfxBase);
637 UFB(data);
639 return ret;
642 static OOP_Object *gfx_show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
644 OOP_Object *ret;
645 struct gfx_data *data;
647 data = OOP_INST_DATA(cl, o);
648 ret = msg->bitMap;
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
655 * intercepted by us
657 if (ret && (OOP_OCLASS(ret) == CDD(GfxBase)->fakefbclass))
659 data->fakefb = ret;
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));
664 LFB(data);
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);
670 if (NULL != ret)
671 ret = data->fakefb;
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.
676 if (!msg->bitMap)
677 data->curs_bm = NULL;*/
678 rethink_cursor(data, GfxBase);
679 draw_cursor(data, TRUE, TRUE, GfxBase);
681 UFB(data);
683 D(bug("[FakeGfx] Returning 0x%p\n", ret));
684 return 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 :) */
691 *msg->Width = 65535;
692 *msg->Height = 65535;
694 return TRUE;
695 } else
696 return FALSE;
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);
713 BOOL ok;
715 LFB(data);
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);
723 UFB(data);
725 draw_cursor(data, TRUE, TRUE, GfxBase);
726 return ok;
729 struct fakefb_data
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; \
746 IPTR retval; \
747 struct gfx_data *fgh; \
748 data = OOP_INST_DATA(cl, o); \
749 fgh = FGH(data); \
750 LFB(fgh);
752 #define FORWARD_METHOD \
753 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
755 #define BITMAP_METHOD_EXIT \
756 if (inside) { \
757 RENDER_CURSOR(data); \
759 UFB(fgh); \
760 return retval;
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"));
773 return NULL;
776 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
777 if (NULL != o)
779 struct fakefb_data *data;
780 data = OOP_INST_DATA(cl, o);
781 data->framebuffer = framebuffer;
782 data->fakegfxhidd = fakegfxhidd;
784 return o;
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;
805 return;
807 else if (msg->attrID == aHidd_BitMap_GfxHidd)
809 *msg->storage = (IPTR)data->fakegfxhidd;
810 return;
812 else
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);
823 if (modeid && ret)
825 /* Framebuffer mode change succeeded. Update fakegfx' information */
826 ret = FakeGfx_UpdateFrameBuffer(data->fakegfxhidd);
829 return ret;
832 static IPTR fakefb_getpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetPixel *msg)
834 BITMAP_METHOD_INIT
836 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
838 REMOVE_CURSOR(data);
839 inside = TRUE;
842 FORWARD_METHOD
844 BITMAP_METHOD_EXIT
847 static IPTR fakefb_putpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
849 BITMAP_METHOD_INIT
851 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
853 REMOVE_CURSOR(data);
854 inside = TRUE;
857 FORWARD_METHOD
859 BITMAP_METHOD_EXIT
862 static IPTR fakefb_drawpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPixel *msg)
864 BITMAP_METHOD_INIT
866 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
868 REMOVE_CURSOR(data);
869 inside = TRUE;
872 FORWARD_METHOD
874 BITMAP_METHOD_EXIT
877 static IPTR fakefb_drawline(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawLine *msg)
879 register LONG x1, y1, x2, y2;
880 BITMAP_METHOD_INIT
882 if (msg->x1 < msg->x2)
884 x1 = msg->x1; x2 = msg->x2;
886 else
888 x2 = msg->x1; x1 = msg->x2;
891 if (msg->y1 < msg->y2)
893 y1 = msg->y1; y2 = msg->y2;
895 else
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))
903 REMOVE_CURSOR(data);
904 inside = TRUE;
907 FORWARD_METHOD
909 BITMAP_METHOD_EXIT
912 static IPTR fakefb_getimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImage *msg)
914 BITMAP_METHOD_INIT
916 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
918 REMOVE_CURSOR(data);
919 inside = TRUE;
922 FORWARD_METHOD
924 BITMAP_METHOD_EXIT
927 static IPTR fakefb_putimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImage *msg)
929 BITMAP_METHOD_INIT
931 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
933 REMOVE_CURSOR(data);
934 inside = TRUE;
937 FORWARD_METHOD
939 BITMAP_METHOD_EXIT
942 static IPTR fakefb_putalphaimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaImage *msg)
944 BITMAP_METHOD_INIT
946 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
948 REMOVE_CURSOR(data);
949 inside = TRUE;
952 FORWARD_METHOD
954 BITMAP_METHOD_EXIT
957 static IPTR fakefb_puttemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTemplate *msg)
959 BITMAP_METHOD_INIT
961 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
963 REMOVE_CURSOR(data);
964 inside = TRUE;
967 FORWARD_METHOD
969 BITMAP_METHOD_EXIT
972 static IPTR fakefb_putalphatemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaTemplate *msg)
974 BITMAP_METHOD_INIT
976 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
978 REMOVE_CURSOR(data);
979 inside = TRUE;
982 FORWARD_METHOD
984 BITMAP_METHOD_EXIT
987 static IPTR fakefb_putpattern(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPattern *msg)
989 BITMAP_METHOD_INIT
991 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
993 REMOVE_CURSOR(data);
994 inside = TRUE;
997 FORWARD_METHOD
999 BITMAP_METHOD_EXIT
1002 static IPTR fakefb_getimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImageLUT *msg)
1004 BITMAP_METHOD_INIT
1006 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1008 REMOVE_CURSOR(data);
1009 inside = TRUE;
1012 FORWARD_METHOD
1014 BITMAP_METHOD_EXIT
1017 static IPTR fakefb_putimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg)
1019 BITMAP_METHOD_INIT
1021 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1023 REMOVE_CURSOR(data);
1024 inside = TRUE;
1027 FORWARD_METHOD
1029 BITMAP_METHOD_EXIT
1032 static IPTR fakefb_puttranspimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTranspImageLUT *msg)
1034 BITMAP_METHOD_INIT
1036 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1038 REMOVE_CURSOR(data);
1039 inside = TRUE;
1042 FORWARD_METHOD
1044 BITMAP_METHOD_EXIT
1047 static IPTR fakefb_drawrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
1049 BITMAP_METHOD_INIT
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);
1055 inside = TRUE;
1058 FORWARD_METHOD
1060 BITMAP_METHOD_EXIT
1063 static IPTR fakefb_fillrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
1065 BITMAP_METHOD_INIT
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);
1078 inside = TRUE;
1081 FORWARD_METHOD
1083 BITMAP_METHOD_EXIT
1086 static IPTR fakefb_drawellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1088 register LONG x1, y1, x2, y2;
1089 BITMAP_METHOD_INIT
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);
1100 inside = TRUE;
1103 FORWARD_METHOD
1105 BITMAP_METHOD_EXIT
1108 static IPTR fakefb_fillellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1110 register LONG x1, y1, x2, y2;
1111 BITMAP_METHOD_INIT
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);
1121 inside = TRUE;
1124 FORWARD_METHOD
1126 BITMAP_METHOD_EXIT
1129 static IPTR fakefb_drawpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1131 BITMAP_METHOD_INIT
1132 /* FIXME: Maybe do checking here, but it probably is not worth it */
1133 REMOVE_CURSOR(data);
1134 inside = TRUE;
1136 FORWARD_METHOD
1138 BITMAP_METHOD_EXIT
1141 static IPTR fakefb_fillpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1143 BITMAP_METHOD_INIT
1144 /* FIXME: Maybe do checking here, but it probably is not worth it */
1145 REMOVE_CURSOR(data);
1146 inside = TRUE;
1148 FORWARD_METHOD
1150 BITMAP_METHOD_EXIT
1154 static IPTR fakefb_drawtext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1156 BITMAP_METHOD_INIT
1158 /* FIXME: Maybe do testing here, but probably not wirth it */
1159 REMOVE_CURSOR(data);
1161 FORWARD_METHOD
1163 BITMAP_METHOD_EXIT
1166 static IPTR fakefb_drawfilltext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1168 BITMAP_METHOD_INIT
1170 /* FIXME: Maybe do testing here, but probably not worth it */
1171 REMOVE_CURSOR(data);
1173 FORWARD_METHOD
1175 BITMAP_METHOD_EXIT
1178 static IPTR fakefb_blitcolexp(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BlitColorExpansion *msg)
1180 BITMAP_METHOD_INIT
1182 if (WRECT_INSIDE(fgh, msg->destX, msg->destY, msg->width, msg->height))
1184 REMOVE_CURSOR(data);
1185 inside = TRUE;
1188 FORWARD_METHOD
1190 BITMAP_METHOD_EXIT
1193 static IPTR fakefb_clear(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_Clear *msg)
1195 BITMAP_METHOD_INIT
1197 inside = TRUE;
1199 FORWARD_METHOD
1201 BITMAP_METHOD_EXIT
1205 static IPTR fakefb_fillspan(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1207 BITMAP_METHOD_INIT
1209 REMOVE_CURSOR(data);
1210 inside = TRUE;
1212 FORWARD_METHOD
1214 BITMAP_METHOD_EXIT
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() */
1220 BITMAP_METHOD_INIT
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);
1225 inside = TRUE;
1228 FORWARD_METHOD
1230 BITMAP_METHOD_EXIT
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);
1242 #undef GfxBase
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},
1254 { TAG_DONE , 0UL }
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 */
1273 if (!data->curs_bm)
1274 return TRUE;
1276 /* We may also have no framebuffer (empty display on
1277 non-framebuffer driver). Also NOP in this case */
1278 if (!data->framebuffer)
1279 return TRUE;
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)
1285 return FALSE;
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
1305 colors.
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;
1309 data->curs_bpp = 4;
1310 } else
1311 #endif
1313 data->curs_pixfmt = vHidd_StdPixFmt_LUT8;
1314 data->curs_bpp = 1;
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;
1331 return TRUE;
1334 static VOID draw_cursor(struct gfx_data *data, BOOL draw, BOOL updaterect, struct GfxBase *GfxBase)
1336 LONG width, height;
1337 LONG fbwidth, fbheight;
1338 LONG x, y;
1339 LONG w2end, h2end;
1340 ULONG xoffset = 0;
1341 ULONG yoffset = 0;
1343 struct TagItem gctags[] =
1345 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
1346 { TAG_DONE , 0UL }
1349 if (!data->curs_on)
1350 return;
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));
1356 return;
1359 fbwidth = data->fb_width;
1360 fbheight = data->fb_height;
1361 width = data->curs_width;
1362 height = data->curs_height;
1363 x = data->curs_x;
1364 y = data->curs_y;
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"));
1369 return;
1371 if ((x >= fbwidth) || (y >= fbheight)) {
1372 DCURS(bug("[FakeGfx] Cursor is beyond right or bottom edge\n"));
1373 return;
1376 /* Do some clipping */
1377 if (x < 0) {
1378 xoffset = -x;
1379 width += x;
1380 x = 0;
1383 if (y < 0) {
1384 yoffset = -y;
1385 height += y;
1386 y = 0;
1389 w2end = data->fb_width - width;
1390 h2end = data->fb_height - height;
1392 if (x > w2end)
1394 width -= (x - w2end);
1395 DCLIP(bug("[FakeGfx] Clipped sprite width to %d\n", width));
1398 if (y > h2end)
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);
1408 if (draw)
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
1417 , data->framebuffer
1418 , x, y
1419 , data->curs_backup
1420 , 0, 0
1421 , width, height
1422 , data->gc
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);
1431 else
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);
1435 if (updaterect)
1436 HIDD_BM_UpdateRect(data->framebuffer, x, y, width, height);
1439 else
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
1446 , data->curs_backup
1447 , 0, 0
1448 , data->framebuffer
1449 , x, y
1450 , width, height
1451 , data->gc
1454 if (updaterect)
1455 HIDD_BM_UpdateRect(data->framebuffer, x, y, width, height);
1458 return;
1461 static void gfx_setFrameBuffer(struct GfxBase *GfxBase, struct gfx_data *data, OOP_Object *fb)
1463 data->framebuffer = fb;
1465 if (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)
1477 OOP_Object *fakebm;
1478 struct TagItem fakebmtags[] =
1480 { aHidd_FakeFB_RealBitMap , (IPTR)framebuffer },
1481 { aHidd_FakeFB_FakeGfxHidd , (IPTR)data },
1482 { TAG_DONE , 0UL }
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);
1495 return fakebm;
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 },
1508 { NULL , 0UL }
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 },
1542 {NULL , 0UL }
1545 struct OOP_InterfaceDescr ifdescr[] =
1547 {root_descr , IID_Root , num_Root_Methods },
1548 {gfxhidd_descr , IID_Hidd_Gfx , num_Hidd_Gfx_Methods },
1549 {NULL , NULL , 0 }
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) },
1559 {TAG_DONE , 0UL }
1563 D(bug("INIT FAKEGFXCLASS\n"));
1565 if ((__IHidd_FakeFB = OOP_ObtainAttrBase(IID_Hidd_FakeFB)))
1567 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1568 if(NULL != cl)
1570 D(bug("FAKE GFX CLASS INITED\n"));
1571 cl->UserData = GfxBase;
1573 return cl;
1576 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1579 return NULL;
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 },
1590 {NULL , 0UL }
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 },
1657 {NULL , 0UL }
1660 struct OOP_InterfaceDescr ifdescr[] =
1662 {root_descr , IID_Root , num_Root_Methods },
1663 {bitmap_descr , IID_Hidd_BitMap, num_Hidd_BitMap_Methods },
1664 {NULL , NULL , 0 }
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) },
1674 {TAG_DONE , 0UL }
1677 OOP_Class *cl = NULL;
1679 if (MetaAttrBase)
1681 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1682 if (NULL != cl)
1683 cl->UserData = GfxBase;
1684 } /* if(MetaAttrBase) */
1686 return cl;
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);
1702 return NULL;
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;