fix comment
[AROS.git] / rom / graphics / fakegfxhidd.c
blob89727b7194491789394a6952dd9a64aed2e00ad4
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=FindTask(NULL);
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 ULONG gfx_showviewports(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
689 /* Composition is not supported here */
690 return FALSE;
693 static BOOL gfx_getmaxspritesize(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMaxSpriteSize *msg)
695 if (msg->Type & (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor)) {
696 /* I hope these values are enough for everyone :) */
697 *msg->Width = 65535;
698 *msg->Height = 65535;
700 return TRUE;
701 } else
702 return FALSE;
705 static IPTR gfx_fwd(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
707 struct gfx_data *data;
709 data = OOP_INST_DATA(cl, o);
711 return OOP_DoMethod(data->gfxhidd, msg);
714 /* Private non-virtual method */
715 static BOOL FakeGfx_UpdateFrameBuffer(OOP_Object *o)
717 OOP_Class *cl = OOP_OCLASS(o);
718 struct gfx_data *data = OOP_INST_DATA(cl, o);
719 BOOL ok;
721 LFB(data);
723 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Width, &data->fb_width);
724 OOP_GetAttr(data->framebuffer, aHidd_BitMap_Height, &data->fb_height);
726 DCURS(bug("[FakeGfx] Changed framebuffer size: %u x %u\n", data->fb_width, data->fb_height));
728 ok = rethink_cursor(data, GfxBase);
729 UFB(data);
731 draw_cursor(data, TRUE, TRUE, GfxBase);
732 return ok;
735 struct fakefb_data
737 OOP_Object *framebuffer;
738 OOP_Object *fakegfxhidd;
741 #define FGH(data) ((struct gfx_data *)data->fakegfxhidd)
742 #define REMOVE_CURSOR(data) \
743 draw_cursor(FGH(data), FALSE, FALSE, GfxBase)
745 #define RENDER_CURSOR(data) \
746 draw_cursor(FGH(data), TRUE, FALSE, GfxBase)
749 #define BITMAP_METHOD_INIT \
750 struct fakefb_data *data; \
751 BOOL inside = FALSE; \
752 IPTR retval; \
753 struct gfx_data *fgh; \
754 data = OOP_INST_DATA(cl, o); \
755 fgh = FGH(data); \
756 LFB(fgh);
758 #define FORWARD_METHOD \
759 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
761 #define BITMAP_METHOD_EXIT \
762 if (inside) { \
763 RENDER_CURSOR(data); \
765 UFB(fgh); \
766 return retval;
768 static OOP_Object *fakefb_new(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
770 OOP_Object *framebuffer;
771 OOP_Object *fakegfxhidd;
773 framebuffer = (OOP_Object *)GetTagData(aHidd_FakeFB_RealBitMap, 0, msg->attrList);
774 fakegfxhidd = (OOP_Object *)GetTagData(aHidd_FakeFB_FakeGfxHidd, 0, msg->attrList);
776 if (NULL == framebuffer || NULL == fakegfxhidd)
778 D(bug("!!! FakeBM::New(): MISSING FRAMEBUFFER OR FAKE GFX HIDD !!!\n"));
779 return NULL;
782 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
783 if (NULL != o)
785 struct fakefb_data *data;
786 data = OOP_INST_DATA(cl, o);
787 data->framebuffer = framebuffer;
788 data->fakegfxhidd = fakegfxhidd;
790 return o;
793 static VOID fakefb_dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
795 struct fakefb_data *data;
796 data = OOP_INST_DATA(cl, o);
797 if (NULL != data->framebuffer)
799 OOP_DisposeObject(data->framebuffer);
800 data->framebuffer = NULL;
804 static void fakefb_get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
806 struct fakefb_data *data = OOP_INST_DATA(cl, o);
808 if (msg->attrID == aHidd_FakeFB_RealBitMap)
810 *msg->storage = (IPTR)data->framebuffer;
811 return;
813 else if (msg->attrID == aHidd_BitMap_GfxHidd)
815 *msg->storage = (IPTR)data->fakegfxhidd;
816 return;
818 else
819 OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
822 /* Intercept framebuffer mode change */
823 static IPTR fakefb_set(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
825 struct fakefb_data *data = OOP_INST_DATA(cl, o);
826 IPTR ret = OOP_DoMethod(data->framebuffer, &msg->mID);
827 struct TagItem *modeid = FindTagItem(aHidd_BitMap_ModeID, msg->attrList);
829 if (modeid && ret)
831 /* Framebuffer mode change succeeded. Update fakegfx' information */
832 ret = FakeGfx_UpdateFrameBuffer(data->fakegfxhidd);
835 return ret;
838 static IPTR fakefb_getpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetPixel *msg)
840 BITMAP_METHOD_INIT
842 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
844 REMOVE_CURSOR(data);
845 inside = TRUE;
848 FORWARD_METHOD
850 BITMAP_METHOD_EXIT
853 static IPTR fakefb_putpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPixel *msg)
855 BITMAP_METHOD_INIT
857 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
859 REMOVE_CURSOR(data);
860 inside = TRUE;
863 FORWARD_METHOD
865 BITMAP_METHOD_EXIT
868 static IPTR fakefb_drawpixel(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPixel *msg)
870 BITMAP_METHOD_INIT
872 if (PIXEL_INSIDE(fgh, msg->x, msg->y))
874 REMOVE_CURSOR(data);
875 inside = TRUE;
878 FORWARD_METHOD
880 BITMAP_METHOD_EXIT
883 static IPTR fakefb_drawline(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawLine *msg)
885 register LONG x1, y1, x2, y2;
886 BITMAP_METHOD_INIT
888 if (msg->x1 < msg->x2)
890 x1 = msg->x1; x2 = msg->x2;
892 else
894 x2 = msg->x1; x1 = msg->x2;
897 if (msg->y1 < msg->y2)
899 y1 = msg->y1; y2 = msg->y2;
901 else
903 y2 = msg->y1; y1 = msg->y2;
906 /* FIXME: Maybe do some more intelligent checking for DrawLine */
907 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
909 REMOVE_CURSOR(data);
910 inside = TRUE;
913 FORWARD_METHOD
915 BITMAP_METHOD_EXIT
918 static IPTR fakefb_getimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImage *msg)
920 BITMAP_METHOD_INIT
922 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
924 REMOVE_CURSOR(data);
925 inside = TRUE;
928 FORWARD_METHOD
930 BITMAP_METHOD_EXIT
933 static IPTR fakefb_putimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImage *msg)
935 BITMAP_METHOD_INIT
937 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
939 REMOVE_CURSOR(data);
940 inside = TRUE;
943 FORWARD_METHOD
945 BITMAP_METHOD_EXIT
948 static IPTR fakefb_putalphaimage(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaImage *msg)
950 BITMAP_METHOD_INIT
952 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
954 REMOVE_CURSOR(data);
955 inside = TRUE;
958 FORWARD_METHOD
960 BITMAP_METHOD_EXIT
963 static IPTR fakefb_puttemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTemplate *msg)
965 BITMAP_METHOD_INIT
967 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
969 REMOVE_CURSOR(data);
970 inside = TRUE;
973 FORWARD_METHOD
975 BITMAP_METHOD_EXIT
978 static IPTR fakefb_putalphatemplate(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutAlphaTemplate *msg)
980 BITMAP_METHOD_INIT
982 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
984 REMOVE_CURSOR(data);
985 inside = TRUE;
988 FORWARD_METHOD
990 BITMAP_METHOD_EXIT
993 static IPTR fakefb_putpattern(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutPattern *msg)
995 BITMAP_METHOD_INIT
997 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
999 REMOVE_CURSOR(data);
1000 inside = TRUE;
1003 FORWARD_METHOD
1005 BITMAP_METHOD_EXIT
1008 static IPTR fakefb_getimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_GetImageLUT *msg)
1010 BITMAP_METHOD_INIT
1012 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1014 REMOVE_CURSOR(data);
1015 inside = TRUE;
1018 FORWARD_METHOD
1020 BITMAP_METHOD_EXIT
1023 static IPTR fakefb_putimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutImageLUT *msg)
1025 BITMAP_METHOD_INIT
1027 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1029 REMOVE_CURSOR(data);
1030 inside = TRUE;
1033 FORWARD_METHOD
1035 BITMAP_METHOD_EXIT
1038 static IPTR fakefb_puttranspimagelut(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_PutTranspImageLUT *msg)
1040 BITMAP_METHOD_INIT
1042 if (WRECT_INSIDE(fgh, msg->x, msg->y, msg->width, msg->height))
1044 REMOVE_CURSOR(data);
1045 inside = TRUE;
1048 FORWARD_METHOD
1050 BITMAP_METHOD_EXIT
1053 static IPTR fakefb_drawrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
1055 BITMAP_METHOD_INIT
1057 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1058 if (RECT_INSIDE(fgh, msg->minX, msg->minY, msg->maxX, msg->maxY))
1060 REMOVE_CURSOR(data);
1061 inside = TRUE;
1064 FORWARD_METHOD
1066 BITMAP_METHOD_EXIT
1069 static IPTR fakefb_fillrect(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawRect *msg)
1071 BITMAP_METHOD_INIT
1073 /* bug("BITMAP FILLRECT(%d, %d, %d, %d), (%d, %d, %d, %d, %d, %d)\n"
1074 , msg->minX, msg->minY, msg->maxX, msg->maxY
1075 , fgh->curs_x, fgh->curs_y, fgh->curs_maxx, fgh->curs_maxy
1076 , fgh->curs_width, fgh->curs_height);
1078 if (RECT_INSIDE(fgh, msg->minX, msg->minY, msg->maxX, msg->maxY))
1080 /* bug("FILLRECT: REMOVING CURSOR\n");
1082 REMOVE_CURSOR(data);
1084 inside = TRUE;
1087 FORWARD_METHOD
1089 BITMAP_METHOD_EXIT
1092 static IPTR fakefb_drawellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1094 register LONG x1, y1, x2, y2;
1095 BITMAP_METHOD_INIT
1097 x1 = msg->x - msg->rx;
1098 y1 = msg->y - msg->ry;
1099 x2 = msg->x + msg->rx;
1100 y2 = msg->y + msg->ry;
1101 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1103 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
1105 REMOVE_CURSOR(data);
1106 inside = TRUE;
1109 FORWARD_METHOD
1111 BITMAP_METHOD_EXIT
1114 static IPTR fakefb_fillellipse(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawEllipse *msg)
1116 register LONG x1, y1, x2, y2;
1117 BITMAP_METHOD_INIT
1119 x1 = msg->x - msg->rx;
1120 y1 = msg->y - msg->ry;
1121 x2 = msg->x + msg->rx;
1122 y2 = msg->y + msg->ry;
1124 if (RECT_INSIDE(fgh, x1, y1, x2, y2))
1126 REMOVE_CURSOR(data);
1127 inside = TRUE;
1130 FORWARD_METHOD
1132 BITMAP_METHOD_EXIT
1135 static IPTR fakefb_drawpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1137 BITMAP_METHOD_INIT
1138 /* FIXME: Maybe do checking here, but it probably is not worth it */
1139 REMOVE_CURSOR(data);
1140 inside = TRUE;
1142 FORWARD_METHOD
1144 BITMAP_METHOD_EXIT
1147 static IPTR fakefb_fillpolygon(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawPolygon *msg)
1149 BITMAP_METHOD_INIT
1150 /* FIXME: Maybe do checking here, but it probably is not worth it */
1151 REMOVE_CURSOR(data);
1152 inside = TRUE;
1154 FORWARD_METHOD
1156 BITMAP_METHOD_EXIT
1160 static IPTR fakefb_drawtext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1162 BITMAP_METHOD_INIT
1164 /* FIXME: Maybe do testing here, but probably not wirth it */
1165 REMOVE_CURSOR(data);
1167 FORWARD_METHOD
1169 BITMAP_METHOD_EXIT
1172 static IPTR fakefb_drawfilltext(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_DrawText *msg)
1174 BITMAP_METHOD_INIT
1176 /* FIXME: Maybe do testing here, but probably not worth it */
1177 REMOVE_CURSOR(data);
1179 FORWARD_METHOD
1181 BITMAP_METHOD_EXIT
1184 static IPTR fakefb_blitcolexp(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BlitColorExpansion *msg)
1186 BITMAP_METHOD_INIT
1188 if (WRECT_INSIDE(fgh, msg->destX, msg->destY, msg->width, msg->height))
1190 REMOVE_CURSOR(data);
1191 inside = TRUE;
1194 FORWARD_METHOD
1196 BITMAP_METHOD_EXIT
1199 static IPTR fakefb_clear(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_Clear *msg)
1201 BITMAP_METHOD_INIT
1203 inside = TRUE;
1205 FORWARD_METHOD
1207 BITMAP_METHOD_EXIT
1211 static IPTR fakefb_fillspan(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1213 BITMAP_METHOD_INIT
1215 REMOVE_CURSOR(data);
1216 inside = TRUE;
1218 FORWARD_METHOD
1220 BITMAP_METHOD_EXIT
1223 static IPTR fakefb_scale(OOP_Class *cl, OOP_Object *o, struct pHidd_BitMap_BitMapScale *msg)
1225 /* FIXME: should check both source and destination, similar to gfx_copybox() */
1226 BITMAP_METHOD_INIT
1228 if (WRECT_INSIDE(fgh, msg->bsa->bsa_SrcX, msg->bsa->bsa_SrcY, msg->bsa->bsa_SrcWidth, msg->bsa->bsa_SrcHeight))
1230 REMOVE_CURSOR(data);
1231 inside = TRUE;
1234 FORWARD_METHOD
1236 BITMAP_METHOD_EXIT
1239 static IPTR fakefb_fwd(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
1241 struct fakefb_data *data;
1242 data = OOP_INST_DATA(cl, o);
1243 // kill(getpid(), 19);
1244 // bug("BITMAP_FWD\n");
1245 return OOP_DoMethod(data->framebuffer, msg);
1248 #undef GfxBase
1250 static BOOL rethink_cursor(struct gfx_data *data, struct GfxBase *GfxBase)
1252 OOP_Object *pf, *cmap;
1253 IPTR fbdepth, curdepth, i;
1254 UWORD curs_base = 16;
1256 struct TagItem bmtags[] = {
1257 { aHidd_BitMap_Width , data->curs_width },
1258 { aHidd_BitMap_Height, data->curs_height },
1259 { aHidd_BitMap_Friend, (IPTR)data->framebuffer},
1260 { TAG_DONE , 0UL }
1263 D(bug("rethink_cursor(), curs_bm is 0x%p, framebuffer is 0x%p\n", data->curs_bm, data->framebuffer));
1265 /* The first thing we do is recreating a backup bitmap. We do it every time when either
1266 cursor shape changes (because new shape may have different size) or shown bitmap
1267 changes (because new bitmap may have different depth). Note that even real framebuffer
1268 object may dynamically change its characteristics.
1270 Delete the old backup bitmap first */
1271 if (NULL != data->curs_backup) {
1272 OOP_DisposeObject(data->curs_backup);
1273 D(bug("[FakeGfx] Disposed old backup bitmap\n"));
1274 data->curs_backup = NULL;
1277 /* If we have no cursor, we have nothing more to do.
1278 We also don't need new backup bitmap */
1279 if (!data->curs_bm)
1280 return TRUE;
1282 /* We may also have no framebuffer (empty display on
1283 non-framebuffer driver). Also NOP in this case */
1284 if (!data->framebuffer)
1285 return TRUE;
1287 /* Create new backup bitmap */
1288 data->curs_backup = HIDD_Gfx_NewBitMap(data->gfxhidd, bmtags);
1289 D(bug("[FakeGfx] New backup bitmap is 0x%p\n", data->curs_backup));
1290 if (!data->curs_backup)
1291 return FALSE;
1293 OOP_GetAttr(data->framebuffer, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1294 D(bug("[FakeGfx] Framebuffer pixelformat 0x%p\n", pf));
1295 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &fbdepth);
1296 D(bug("[FakeGfx] Framebuffer depth %u\n", fbdepth));
1297 OOP_GetAttr(data->curs_bm, aHidd_BitMap_ColorMap, (IPTR *)&cmap);
1298 D(bug("[FakeGfx] Cursor colormap 0x%p\n", cmap));
1299 OOP_GetAttr(data->curs_bm, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1300 D(bug("[FakeGfx] Cursor pixelformat 0x%p\n", pf));
1301 OOP_GetAttr(pf, aHidd_PixFmt_Depth, &curdepth);
1302 D(bug("[FakeGfx] Cursor depth %u\n", curdepth));
1304 #ifndef DISABLE_ARGB_POINTER
1305 /* We can get ARGB data from the pointer bitmap only
1306 on one of two cases:
1307 1) Pointer bitmap has more than 256 colors, in this case it
1308 stores ARGB data in itself.
1309 2) Pointer bitmap is a LUT bitmap with a colormap attached.
1310 In this case colormap should contain ARGB values for actual
1311 colors.
1312 Of course having ARGB data makes sense only on truecolor screens. */
1313 if ((fbdepth > 8) && ((curdepth > 8) || cmap)) {
1314 data->curs_pixfmt = vHidd_StdPixFmt_ARGB32;
1315 data->curs_bpp = 4;
1316 } else
1317 #endif
1319 data->curs_pixfmt = vHidd_StdPixFmt_LUT8;
1320 data->curs_bpp = 1;
1321 /* TODO: curs_base should be somehow synchronised with SpriteBase field of ColorMap */
1322 curs_base = (fbdepth > 4) ? 16 : (1 << fbdepth) - 8;
1324 /* If we have some good bitmap->bitmap blitting function with alpha channel support,
1325 we would not need this extra buffer and conversion for truecolor screens. */
1326 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);
1327 D(bug("[FakeGfx] Obtained cursor sprite data @ 0x%p\n", data->curs_pixels));
1329 if (data->curs_pixfmt == vHidd_StdPixFmt_LUT8)
1331 for (i = 0; i < data->curs_width * data->curs_height; i++)
1333 if (data->curs_pixels[i])
1334 data->curs_pixels[i] += curs_base;
1337 return TRUE;
1340 static VOID draw_cursor(struct gfx_data *data, BOOL draw, BOOL updaterect, struct GfxBase *GfxBase)
1342 LONG width, height;
1343 LONG fbwidth, fbheight;
1344 LONG x, y;
1345 LONG w2end, h2end;
1346 ULONG xoffset = 0;
1347 ULONG yoffset = 0;
1349 struct TagItem gctags[] =
1351 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy },
1352 { TAG_DONE , 0UL }
1355 if (!data->curs_on)
1356 return;
1358 if (NULL == data->curs_bm || NULL == data->framebuffer)
1360 DB2(bug("!!! draw_cursor: FAKE GFX HIDD NOT PROPERLY INITIALIZED !!!\n"));
1361 DB2(bug("CURS BM: 0x%p, FB: 0x%p\n", data->curs_bm, data->framebuffer));
1362 return;
1365 fbwidth = data->fb_width;
1366 fbheight = data->fb_height;
1367 width = data->curs_width;
1368 height = data->curs_height;
1369 x = data->curs_x;
1370 y = data->curs_y;
1372 /* Do nothing if sprite went outside of bitmap */
1373 if ((x < -width) || (y < -height)) {
1374 DCURS(bug("[FakeGfx] Cursor is beyond left or top edge\n"));
1375 return;
1377 if ((x >= fbwidth) || (y >= fbheight)) {
1378 DCURS(bug("[FakeGfx] Cursor is beyond right or bottom edge\n"));
1379 return;
1382 /* Do some clipping */
1383 if (x < 0) {
1384 xoffset = -x;
1385 width += x;
1386 x = 0;
1389 if (y < 0) {
1390 yoffset = -y;
1391 height += y;
1392 y = 0;
1395 w2end = data->fb_width - width;
1396 h2end = data->fb_height - height;
1398 if (x > w2end)
1400 width -= (x - w2end);
1401 DCLIP(bug("[FakeGfx] Clipped sprite width to %d\n", width));
1404 if (y > h2end)
1406 height -= (y - h2end);
1407 DCLIP(bug("[FakeGfx] Clipped sprite height to %d\n", height));
1410 /* FIXME: clip negative coordinates */
1412 OOP_SetAttrs(data->gc, gctags);
1414 if (draw)
1416 /* Calculate origin of sprite image according to offsets */
1417 ULONG modulo = data->curs_width * data->curs_bpp;
1418 UBYTE *pixels = data->curs_pixels + yoffset * modulo + xoffset * data->curs_bpp;
1420 /* Backup under the new cursor image */
1421 // bug("BACKING UP RENDERED AREA\n");
1422 HIDD_Gfx_CopyBox(data->gfxhidd
1423 , data->framebuffer
1424 , x, y
1425 , data->curs_backup
1426 , 0, 0
1427 , width, height
1428 , data->gc
1431 data->backup_done = TRUE;
1433 DB2(bug("[FakeGfx] Rendering cursor, framebuffer 0x%p\n", data->framebuffer));
1434 /* Render the cursor image */
1435 if (data->curs_pixfmt == vHidd_StdPixFmt_ARGB32)
1436 HIDD_BM_PutAlphaImage(data->framebuffer, data->gc, pixels, modulo, x, y, width, height);
1437 else
1438 /* data->curs_bpp is always 1 here so we safely ignore it */
1439 HIDD_BM_PutTranspImageLUT(data->framebuffer, data->gc, pixels, modulo, x, y, width, height, NULL, 0);
1441 if (updaterect)
1442 HIDD_BM_UpdateRect(data->framebuffer, x, y, width, height);
1445 else
1447 /* Erase the old cursor image */
1448 if (data->backup_done)
1450 DB2(bug("[FakeGfx] Restoring cursor area, framebuffer 0x%p\n", data->framebuffer));
1451 HIDD_Gfx_CopyBox(data->gfxhidd
1452 , data->curs_backup
1453 , 0, 0
1454 , data->framebuffer
1455 , x, y
1456 , width, height
1457 , data->gc
1460 if (updaterect)
1461 HIDD_BM_UpdateRect(data->framebuffer, x, y, width, height);
1464 return;
1467 static void gfx_setFrameBuffer(struct GfxBase *GfxBase, struct gfx_data *data, OOP_Object *fb)
1469 data->framebuffer = fb;
1471 if (fb)
1473 /* Cache framebuffer size, needed by sprite rendering routine */
1474 OOP_GetAttr(fb, aHidd_BitMap_Width, &data->fb_width);
1475 OOP_GetAttr(fb, aHidd_BitMap_Height, &data->fb_height);
1477 DCURS(bug("[FakeGfx] Framebuffer size: %u x %u\n", data->fb_width, data->fb_height));
1481 static OOP_Object *create_fake_fb(OOP_Object *framebuffer, struct gfx_data *data, struct GfxBase *GfxBase)
1483 OOP_Object *fakebm;
1484 struct TagItem fakebmtags[] =
1486 { aHidd_FakeFB_RealBitMap , (IPTR)framebuffer },
1487 { aHidd_FakeFB_FakeGfxHidd , (IPTR)data },
1488 { TAG_DONE , 0UL }
1491 /* If we work with framebuffer-based driver, Show() will never be called on
1492 a fakefb object so we remember it right now */
1493 fakebm = OOP_NewObject(CDD(GfxBase)->fakefbclass, NULL, fakebmtags);
1495 if (data->fakefb_attr == aHidd_BitMap_FrameBuffer)
1497 data->fakefb = fakebm;
1498 gfx_setFrameBuffer(GfxBase, data, framebuffer);
1501 return fakebm;
1504 static OOP_Class *init_fakegfxhiddclass (struct GfxBase *GfxBase)
1506 OOP_Class *cl = NULL;
1508 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1510 {(IPTR (*)())gfx_new , moRoot_New },
1511 {(IPTR (*)())gfx_dispose, moRoot_Dispose },
1512 {(IPTR (*)())gfx_get , moRoot_Get },
1513 {(IPTR (*)())gfx_fwd , moRoot_Set },
1514 { NULL , 0UL }
1517 struct OOP_MethodDescr gfxhidd_descr[num_Hidd_Gfx_Methods + 1] =
1519 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewGC },
1520 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeGC },
1521 {(IPTR (*)())gfx_newbitmap , moHidd_Gfx_NewBitMap },
1522 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeBitMap },
1523 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryModeIDs },
1524 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ReleaseModeIDs },
1525 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CheckMode },
1526 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NextModeID },
1527 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetMode },
1528 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetPixFmt },
1529 {(IPTR (*)())gfx_setcursorshape , moHidd_Gfx_SetCursorShape },
1530 {(IPTR (*)())gfx_setcursorpos , moHidd_Gfx_SetCursorPos },
1531 {(IPTR (*)())gfx_setcursorvisible , moHidd_Gfx_SetCursorVisible},
1532 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetMode },
1533 {(IPTR (*)())gfx_show , moHidd_Gfx_Show },
1534 {(IPTR (*)())gfx_copybox , moHidd_Gfx_CopyBox },
1535 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ModeProperties },
1536 {(IPTR (*)())gfx_showviewports , moHidd_Gfx_ShowViewPorts },
1537 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetSync },
1538 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetGamma },
1539 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetGamma },
1540 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryHardware3D },
1541 {(IPTR (*)())gfx_getmaxspritesize , moHidd_Gfx_GetMaxSpriteSize},
1542 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewOverlay },
1543 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeOverlay },
1544 {(IPTR (*)())gfx_fwd , moHidd_Gfx_MakeViewPort },
1545 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CleanViewPort },
1546 {(IPTR (*)())gfx_fwd , moHidd_Gfx_PrepareViewPorts},
1547 {(IPTR (*)())gfx_copyboxmasked , moHidd_Gfx_CopyBoxMasked },
1548 {NULL , 0UL }
1551 struct OOP_InterfaceDescr ifdescr[] =
1553 {root_descr , IID_Root , num_Root_Methods },
1554 {gfxhidd_descr , IID_Hidd_Gfx , num_Hidd_Gfx_Methods },
1555 {NULL , NULL , 0 }
1558 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1560 struct TagItem tags[] =
1562 { aMeta_SuperID , (IPTR)CLID_Root },
1563 { aMeta_InterfaceDescr , (IPTR)ifdescr },
1564 { aMeta_InstSize , (IPTR)sizeof (struct gfx_data) },
1565 {TAG_DONE , 0UL }
1569 D(bug("INIT FAKEGFXCLASS\n"));
1571 if ((__IHidd_FakeFB = OOP_ObtainAttrBase(IID_Hidd_FakeFB)))
1573 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1574 if(NULL != cl)
1576 D(bug("FAKE GFX CLASS INITED\n"));
1577 cl->UserData = GfxBase;
1579 return cl;
1582 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1585 return NULL;
1588 static OOP_Class *init_fakefbclass(struct GfxBase *GfxBase)
1590 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1592 {(IPTR (*)())fakefb_new , moRoot_New },
1593 {(IPTR (*)())fakefb_dispose, moRoot_Dispose },
1594 {(IPTR (*)())fakefb_get , moRoot_Get },
1595 {(IPTR (*)())fakefb_set , moRoot_Set },
1596 {NULL , 0UL }
1599 struct OOP_MethodDescr bitmap_descr[num_Hidd_BitMap_Methods + 1] =
1601 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColors },
1602 {(IPTR (*)())fakefb_putpixel , moHidd_BitMap_PutPixel },
1603 {(IPTR (*)())fakefb_drawpixel , moHidd_BitMap_DrawPixel },
1604 {(IPTR (*)())fakefb_putimage , moHidd_BitMap_PutImage },
1605 {(IPTR (*)())fakefb_putalphaimage , moHidd_BitMap_PutAlphaImage },
1606 {(IPTR (*)())fakefb_puttemplate , moHidd_BitMap_PutTemplate },
1607 {(IPTR (*)())fakefb_putalphatemplate , moHidd_BitMap_PutAlphaTemplate },
1608 {(IPTR (*)())fakefb_putpattern , moHidd_BitMap_PutPattern },
1609 {(IPTR (*)())fakefb_getimage , moHidd_BitMap_GetImage },
1610 {(IPTR (*)())fakefb_getpixel , moHidd_BitMap_GetPixel },
1611 {(IPTR (*)())fakefb_drawline , moHidd_BitMap_DrawLine },
1612 {(IPTR (*)())fakefb_drawrect , moHidd_BitMap_DrawRect },
1613 {(IPTR (*)())fakefb_fillrect , moHidd_BitMap_FillRect },
1614 {(IPTR (*)())fakefb_drawellipse , moHidd_BitMap_DrawEllipse },
1615 {(IPTR (*)())fakefb_fillellipse , moHidd_BitMap_FillEllipse },
1616 {(IPTR (*)())fakefb_drawpolygon , moHidd_BitMap_DrawPolygon },
1617 {(IPTR (*)())fakefb_fillpolygon , moHidd_BitMap_FillPolygon },
1618 {(IPTR (*)())fakefb_drawtext , moHidd_BitMap_DrawText },
1619 {(IPTR (*)())fakefb_drawfilltext , moHidd_BitMap_FillText },
1620 {(IPTR (*)())fakefb_fillspan , moHidd_BitMap_FillSpan },
1621 {(IPTR (*)())fakefb_clear , moHidd_BitMap_Clear },
1622 {(IPTR (*)())fakefb_blitcolexp , moHidd_BitMap_BlitColorExpansion },
1623 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_MapColor },
1624 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UnmapPixel },
1625 {(IPTR (*)())fakefb_putimagelut , moHidd_BitMap_PutImageLUT },
1626 {(IPTR (*)())fakefb_puttranspimagelut , moHidd_BitMap_PutTranspImageLUT },
1627 {(IPTR (*)())fakefb_getimagelut , moHidd_BitMap_GetImageLUT },
1628 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_BytesPerLine },
1629 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ConvertPixels },
1630 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect8 },
1631 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect16 },
1632 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect24 },
1633 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect32 },
1634 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_InvertMemRect },
1635 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox8 },
1636 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox16 },
1637 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox24 },
1638 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox32 },
1639 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox16 },
1640 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox24 },
1641 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox32 },
1642 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image8 },
1643 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image16 },
1644 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image24 },
1645 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image8 },
1646 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image16 },
1647 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image24 },
1648 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate8 },
1649 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate16 },
1650 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate24 },
1651 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate32 },
1652 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern8 },
1653 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern16 },
1654 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern24 },
1655 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern32 },
1656 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColorMap },
1657 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ObtainDirectAccess },
1658 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ReleaseDirectAccess },
1659 {(IPTR (*)())fakefb_scale , moHidd_BitMap_BitMapScale },
1660 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PrivateSet },
1661 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetRGBConversionFunction },
1662 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UpdateRect },
1663 {NULL , 0UL }
1666 struct OOP_InterfaceDescr ifdescr[] =
1668 {root_descr , IID_Root , num_Root_Methods },
1669 {bitmap_descr , IID_Hidd_BitMap, num_Hidd_BitMap_Methods },
1670 {NULL , NULL , 0 }
1673 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1675 struct TagItem tags[] =
1677 {aMeta_SuperID , (IPTR) CLID_Root },
1678 {aMeta_InterfaceDescr , (IPTR) ifdescr },
1679 {aMeta_InstSize , (IPTR) sizeof(struct fakefb_data) },
1680 {TAG_DONE , 0UL }
1683 OOP_Class *cl = NULL;
1685 if (MetaAttrBase)
1687 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1688 if (NULL != cl)
1689 cl->UserData = GfxBase;
1690 } /* if(MetaAttrBase) */
1692 return cl;
1695 OOP_Object *init_fakegfxhidd(OOP_Object *gfxhidd, struct GfxBase *GfxBase)
1697 struct common_driverdata *csd = CDD(GfxBase);
1699 if (!csd->fakegfxclass)
1701 /* Lazy class initialization */
1702 csd->fakegfxclass = init_fakegfxhiddclass(GfxBase);
1703 csd->fakefbclass = init_fakefbclass(GfxBase);
1705 if (!csd->fakegfxclass || !csd->fakefbclass)
1707 cleanup_fakegfxhidd(GfxBase);
1708 return NULL;
1713 return OOP_NewObjectTags(csd->fakegfxclass, NULL, aHidd_FakeGfxHidd_RealGfxHidd, gfxhidd, TAG_DONE);
1716 VOID cleanup_fakegfxhidd(struct GfxBase *GfxBase)
1718 struct common_driverdata *csd = CDD(GfxBase);
1720 if (NULL != csd->fakefbclass)
1722 OOP_DisposeObject((OOP_Object *)csd->fakefbclass);
1723 csd->fakefbclass = NULL;
1726 if (NULL != csd->fakegfxclass)
1728 OOP_DisposeObject((OOP_Object *)csd->fakegfxclass);
1729 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1730 csd->fakegfxclass = NULL;