Mixed tabs/spaces to spaces.
[AROS.git] / rom / graphics / fakegfxhidd.c
blob55b3207f6a8c5b16d949e207fbc0b46a970c8c7b
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <string.h>
8 #include <proto/exec.h>
9 #include <proto/oop.h>
10 #include <proto/utility.h>
11 #include <oop/oop.h>
12 #include <hidd/graphics.h>
13 #include <aros/atomic.h>
14 #include <proto/arossupport.h>
16 #include "graphics_intern.h"
17 #include "fakegfxhidd.h"
19 #define DEBUG 0
20 #define DCLIP(x)
21 #define DCURS(x)
22 #define DPOS(x)
24 * DISABLE_ARGB_POINTER actually makes the software mouse pointer code to always
25 * behave like if a LUT framebuffer is used.
26 * Useful for debugging if you have only truecolor display modes.
27 * If you define this, make sure that ALWAYS_ALLOCATE_SPRITE_COLORS in
28 * intuition/intuition_intern.h is also defined.
30 #define DISABLE_ARGB_POINTER */
32 #include <aros/debug.h>
34 /******************************************************************************/
36 #define SPECIAL_LOCKING 1 /* When activated mouse cursor relevant locks are
37 treated in some kind of privileged way, by
38 inserting wait-for-sem-requests at head of
39 wait queue, instead of at tail */
41 /******************************************************************************/
43 static OOP_Class *init_fakefbclass(struct GfxBase *GfxBase);
44 static OOP_Class *init_fakegfxhiddclass (struct GfxBase *GfxBase);
46 /******************************************************************************/
48 struct gfx_data
50 OOP_Object *gfxhidd;
51 OOP_Object *framebuffer;
52 OOP_Object *fakefb;
53 OOP_Object *gc;
55 ULONG fakefb_attr;
56 IPTR fb_width;
57 IPTR fb_height;
59 OOP_Object *curs_bm;
60 OOP_Object *curs_backup;
61 UBYTE *curs_pixels;
62 HIDDT_StdPixFmt curs_pixfmt;
63 UBYTE curs_bpp;
64 BOOL curs_on;
65 LONG curs_x;
66 LONG curs_y;
67 LONG curs_xoffset;
68 LONG curs_yoffset;
69 ULONG curs_width;
70 ULONG curs_height;
71 LONG curs_maxx;
72 LONG curs_maxy;
73 struct SignalSemaphore fbsema;
74 BOOL backup_done;
77 /******************************************************************************/
79 static void gfx_setFrameBuffer(struct GfxBase *GfxBase, struct gfx_data *data, OOP_Object *fb);
80 static VOID draw_cursor(struct gfx_data *data, BOOL draw, BOOL updaterect, struct GfxBase *GfxBase);
81 static BOOL rethink_cursor(struct gfx_data *data, struct GfxBase *GfxBase);
82 static OOP_Object *create_fake_fb(OOP_Object *framebuffer, struct gfx_data *data, struct GfxBase *GfxBase);
84 /******************************************************************************/
86 #if SPECIAL_LOCKING
88 static void FakeGfxHidd_ObtainSemaphore(struct SignalSemaphore *sigSem, BOOL urgent,
89 struct GfxBase *GfxBase)
91 struct Task *me;
93 /* Get pointer to current task */
94 me=SysBase->ThisTask;
96 /* Arbitrate for the semaphore structure */
97 Forbid();
100 ss_QueueCount == -1 indicates that the semaphore is
101 free, so we increment this straight away. If it then
102 equals 0, then we are the first to allocate this semaphore.
104 Note: This will need protection for SMP machines.
106 sigSem->ss_QueueCount++;
107 if( sigSem->ss_QueueCount == 0 )
109 /* We now own the semaphore. This is quick. */
110 sigSem->ss_Owner = me;
111 sigSem->ss_NestCount++;
114 /* The semaphore was in use, but was it by us? */
115 else if( sigSem->ss_Owner == me )
117 /* Yes, just increase the nesting count */
118 sigSem->ss_NestCount++;
122 Else, some other task must own it. We have
123 to set a waiting request here.
125 else
128 We need a node to mark our semaphore request. Lets use some
129 stack memory.
131 struct SemaphoreRequest sr;
132 sr.sr_Waiter = me;
135 Have to clear the signal to make sure that we don't
136 return immediately. We then add the SemReq to the
137 waiters list of the semaphore. We were the last to
138 request, so we must be the last to get the semaphore.
141 AROS_ATOMIC_AND(me->tc_SigRecvd, ~SIGF_SINGLE);
143 if (urgent)
145 AddHead((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
147 else
149 AddTail((struct List *)&sigSem->ss_WaitQueue, (struct Node *)&sr);
153 Finally, we simply wait, ReleaseSemaphore() will fill in
154 who owns the semaphore.
156 Wait(SIGF_SINGLE);
159 /* All Done! */
160 Permit();
164 /******************************************************************************/
166 static void FakeGfxHidd_ReleaseSemaphore(struct SignalSemaphore *sigSem,
167 struct GfxBase *GfxBase)
169 /* Protect the semaphore structure from multiple access. */
170 Forbid();
172 /* Release one on the nest count */
173 sigSem->ss_NestCount--;
174 sigSem->ss_QueueCount--;
176 if(sigSem->ss_NestCount == 0)
179 There are two cases here. Either we are a shared
180 semaphore, or not. If we are not, make sure that the
181 correct Task is calling ReleaseSemaphore()
185 Do not try and wake anything unless there are a number
186 of tasks waiting. We do both the tests, this is another
187 opportunity to throw an alert if there is an error.
190 sigSem->ss_QueueCount >= 0
191 && sigSem->ss_WaitQueue.mlh_Head->mln_Succ != NULL
194 struct SemaphoreRequest *sr, *srn;
197 Look at the first node, but only to see whether it
198 is shared or not.
200 sr = (struct SemaphoreRequest *)sigSem->ss_WaitQueue.mlh_Head;
203 A node is shared if the ln_Name/sr_Waiter field is
204 odd (ie it has bit 1 set).
206 If the sr_Waiter field is != NULL, then this is a
207 task waiting, otherwise it is a message.
209 if( ((IPTR)sr->sr_Waiter & SM_SHARED) == SM_SHARED )
211 /* This is a shared lock, so ss_Owner == NULL */
212 sigSem->ss_Owner = NULL;
214 /* Go through all the nodes to find the shared ones */
215 ForeachNodeSafe(&sigSem->ss_WaitQueue, sr, srn)
217 srn = (struct SemaphoreRequest *)sr->sr_Link.mln_Succ;
219 if( ((IPTR)sr->sr_Waiter & SM_SHARED) == SM_SHARED )
221 Remove((struct Node *)sr);
223 /* Clear the bit, and update the owner count */
224 sr->sr_Waiter = (APTR)((IPTR)sr->sr_Waiter & ~1);
225 sigSem->ss_NestCount++;
227 /* This is a task, signal it */
228 Signal(sr->sr_Waiter, SIGF_SINGLE);
233 /* This is an exclusive lock - awaken first node */
234 else
236 /* Only awaken the first of the nodes */
237 Remove((struct Node *)sr);
238 sigSem->ss_NestCount++;
240 sigSem->ss_Owner = sr->sr_Waiter;
241 Signal(sr->sr_Waiter, SIGF_SINGLE);
244 } /* there are waiters */
245 /* Otherwise, there are not tasks waiting. */
246 else
248 sigSem->ss_Owner = NULL;
249 sigSem->ss_QueueCount = -1;
252 else if(sigSem->ss_NestCount < 0)
255 This can't happen. It means that somebody has released
256 more times than they have obtained.
258 Alert( AN_SemCorrupt );
261 /* All done. */
262 Permit();
266 /******************************************************************************/
268 #define LFB(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, FALSE, GfxBase)
269 #define UFB(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, GfxBase)
270 #define LFB_QUICK(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, TRUE, GfxBase)
271 #define UFB_QUICK(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, GfxBase)
273 #else /* !SPECIAL_LOCKING */
275 #define LFB(data) ObtainSemaphore(&(data)->fbsema)
276 #define UFB(data) ReleaseSemaphore(&(data)->fbsema)
277 #define LFB_QUICK(data) ObtainSemaphore(&(data)->fbsema)
278 #define UFB_QUICK(data) ReleaseSemaphore(&(data)->fbsema)
280 #endif /* SPECIAL_LOCKING */
282 /******************************************************************************/
284 #define GfxBase ((struct GfxBase *)cl->UserData)
286 static OOP_Object *gfx_new(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
288 /* Create a new gfxhid object */
289 OOP_Object *realgfxhidd;
290 struct gfx_data *data;
291 BOOL ok = FALSE;
292 IPTR noframebuffer = FALSE;
294 realgfxhidd = (OOP_Object *)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd, (IPTR)NULL, msg->attrList);
295 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
296 if (NULL == o)
297 return NULL;
299 data = OOP_INST_DATA(cl, o);
300 memset(data, 0, sizeof (*data));
301 InitSemaphore(&data->fbsema);
303 OOP_GetAttr(realgfxhidd, aHidd_Gfx_NoFrameBuffer, &noframebuffer);
304 data->fakefb_attr = noframebuffer ? aHidd_BitMap_Displayable : aHidd_BitMap_FrameBuffer;
306 data->gfxhidd = realgfxhidd;
308 if (NULL != data->gfxhidd)
310 struct TagItem gctags[] =
312 { TAG_DONE, 0UL }
315 data->gc = HIDD_Gfx_NewGC(data->gfxhidd, gctags);
316 if (NULL != data->gc)
318 ok = TRUE;
322 if (!ok)
324 OOP_MethodID mid;
326 mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
327 OOP_CoerceMethod(cl, o, (OOP_Msg)&mid);
330 return o;
333 static VOID gfx_dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
335 struct gfx_data *data;
337 data = OOP_INST_DATA(cl, o);
338 if (NULL != data->curs_backup)
340 OOP_DisposeObject(data->curs_backup);
341 data->curs_backup = NULL;
344 if (data->curs_pixels)
345 FreeMem(data->curs_pixels, data->curs_width * data->curs_height * 4);
347 if (NULL != data->gc)
349 OOP_DisposeObject(data->gc);
350 data->gc = NULL;
354 static void gfx_get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
356 struct gfx_data *data = OOP_INST_DATA(cl, o);
358 if (msg->attrID == aHidd_Gfx_HWSpriteTypes) {
359 *msg->storage = vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor;
360 return;
363 OOP_DoMethod(data->gfxhidd, (OOP_Msg)msg);
366 static OOP_Object *gfx_newbitmap(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewBitMap *msg)
368 /* Is the user about to create a framebuffer ? */
369 BOOL create_fb;
370 struct gfx_data *data;
371 OOP_Object *realfb;
372 OOP_Object *ret = NULL;
374 data = OOP_INST_DATA(cl, o);
375 create_fb = (BOOL)GetTagData(data->fakefb_attr, FALSE, msg->attrList);
377 realfb = HIDD_Gfx_NewBitMap(data->gfxhidd, msg->attrList);
379 if (realfb && create_fb)
381 ret = create_fake_fb(realfb, data, GfxBase);
382 if (!ret)
383 OOP_DisposeObject(realfb);
385 else
386 ret = realfb;
388 return ret;
391 static BOOL gfx_setcursorshape(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorShape *msg)
393 struct gfx_data *data;
394 OOP_Object *shape;
395 BOOL ok = TRUE;
397 data = OOP_INST_DATA(cl, o);
398 shape = msg->shape;
399 D(bug("[FakeGfx] SetCursorShape(0x%p)\n", shape));
401 /* Bitmap changed */
402 if (NULL == shape)
404 /* Erase the old cursor */
405 draw_cursor(data, FALSE, TRUE, GfxBase);
406 data->curs_on = FALSE;
407 data->curs_bm = NULL;
408 data->curs_x = data->curs_y = 0;
409 data->curs_maxx = data->curs_maxy = 0;
410 data->curs_width = data->curs_height = 0;
411 data->curs_xoffset = 0;
412 data->curs_yoffset = 0;
414 if (NULL != data->curs_backup)
416 OOP_DisposeObject(data->curs_backup);
417 data->curs_backup = NULL;
419 if (data->curs_pixels) {
420 FreeMem(data->curs_pixels, data->curs_width * data->curs_height * 4);
421 data->curs_pixels = NULL;
424 else
426 IPTR curs_width, curs_height;
427 APTR new_curs_pixels;
428 ULONG curs_pixels_len;
430 OOP_GetAttr(shape, aHidd_BitMap_Width, &curs_width);
431 OOP_GetAttr(shape, aHidd_BitMap_Height, &curs_height);
433 DCURS(bug("[FakeGfx] New cursor size: %lu x %lu, framebuffer 0x%p\n", curs_width, curs_height, data->framebuffer));
435 /* Create new cursor pixelbuffer. We multiply size by 4 because we want ARGB data
436 to fit in. */
437 curs_pixels_len = curs_width * curs_height * 4;
438 new_curs_pixels = AllocMem(curs_pixels_len, MEMF_ANY|MEMF_CLEAR);
439 if (!new_curs_pixels)
440 return FALSE;
442 LFB(data);
444 /* Erase the old cursor */
445 draw_cursor(data, FALSE, TRUE, GfxBase);
447 /* Now that we have disposed the old image using the old
448 backup bm, we can install the new image and backup bm before
449 rendering the new cursor.
450 Backup bitmap is recreated in rethink_cursor()
453 if (data->curs_pixels)
454 FreeMem(data->curs_pixels, data->curs_width * data->curs_height * 4);
456 data->curs_bm = shape;
457 data->curs_width = curs_width;
458 data->curs_height = curs_height;
459 data->curs_maxx = data->curs_x + curs_width - 1;
460 data->curs_maxy = data->curs_y + curs_height - 1;
461 data->curs_pixels = new_curs_pixels;
462 data->curs_xoffset = msg->xoffset;
463 data->curs_yoffset = msg->yoffset;
465 ok = rethink_cursor(data, GfxBase);
466 UFB(data);
468 draw_cursor(data, TRUE, TRUE, GfxBase);
471 return ok;
474 static BOOL gfx_setcursorpos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
476 struct gfx_data *data;
477 IPTR xoffset = 0;
478 IPTR yoffset = 0;
480 data = OOP_INST_DATA(cl, o);
481 DPOS(bug("[FakeGfx] SetCursorPos(%d, %d)\n", msg->x, msg->y));
483 if (!data->framebuffer)
484 return TRUE;
486 /* We draw our cursor on the bitmap, so we have to convert back
487 from physical to logical coordinates */
488 OOP_GetAttr(data->framebuffer, aHidd_BitMap_LeftEdge, &xoffset);
489 OOP_GetAttr(data->framebuffer, aHidd_BitMap_TopEdge, &yoffset);
491 LFB_QUICK(data);
492 /* erase the old cursor */
493 draw_cursor(data, FALSE, TRUE, GfxBase);
495 data->curs_x = msg->x - xoffset;
496 data->curs_y = msg->y - yoffset;
497 /* Shift to the hotspot location */
498 data->curs_x += data->curs_xoffset;
499 data->curs_y += data->curs_yoffset;
500 data->curs_maxx = data->curs_x + data->curs_width - 1;
501 data->curs_maxy = data->curs_y + data->curs_height - 1;
503 draw_cursor(data, TRUE, TRUE, GfxBase);
504 UFB_QUICK(data);
505 return TRUE;
508 static VOID gfx_setcursorvisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
510 struct gfx_data *data;
512 data = OOP_INST_DATA(cl, o);
514 LFB_QUICK(data);
516 if (msg->visible)
518 if (!data->curs_on)
520 data->curs_on = TRUE;
521 draw_cursor(data, TRUE, TRUE, GfxBase);
524 else
526 if (data->curs_on)
528 draw_cursor(data, FALSE, TRUE, GfxBase);
529 data->curs_on = FALSE;
533 UFB_QUICK(data);
537 #define PIXEL_INSIDE(fgh, x, y) \
538 ( ( (x) >= (fgh)->curs_x ) \
539 && ( (y) >= (fgh)->curs_y ) \
540 && ( (x) <= (fgh)->curs_maxx ) \
541 && ( (y) <= (fgh)->curs_maxy ) )
543 /* NOTE: x1, y1, x2, y2 MUST be sorted */
544 #define RECT_INSIDE(fgh, x1, y1, x2, y2) \
545 ( ( (x1) <= fgh->curs_maxx ) \
546 && ( (x2) >= fgh->curs_x ) \
547 && ( (y1) <= fgh->curs_maxy ) \
548 && ( (y2) >= fgh->curs_y ) )
550 #define WRECT_INSIDE(fgh, x1, y1, width, height) \
551 RECT_INSIDE(fgh, x1, y1, (x1) + (width) - 1, (y1) + (height) - 1)
553 static void gfx_copybox(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBox *msg)
555 struct gfx_data *data;
556 OOP_Object *src = NULL;
557 OOP_Object *dest = NULL;
558 BOOL inside = FALSE;
560 data = OOP_INST_DATA(cl, o);
561 LFB(data);
563 /* De-masquerade bitmap objects, every of which can be fakefb object */
564 OOP_GetAttr(msg->src, aHidd_FakeFB_RealBitMap, (IPTR *)&src);
565 OOP_GetAttr(msg->dest, aHidd_FakeFB_RealBitMap, (IPTR *)&dest);
566 if (!src)
567 src = msg->src;
568 if (!dest)
569 dest = msg->dest;
571 /* FIXME: other bitmap may belong to another instance of fakegfx which can be on
572 display on another monitor. In this case mouse cursor should be handled also
573 there. Needs further reengineering. */
574 if ((msg->src == data->fakefb) && WRECT_INSIDE(data, msg->srcX, msg->srcY, msg->width, msg->height))
575 inside = TRUE;
577 if ((msg->dest == data->fakefb) && WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
578 inside = TRUE;
580 if (inside)
581 draw_cursor(data, FALSE, FALSE, GfxBase);
583 HIDD_Gfx_CopyBox(data->gfxhidd, src, msg->srcX, msg->srcY,
584 dest, msg->destX, msg->destY, msg->width, msg->height, msg->gc);
586 if (inside)
587 draw_cursor(data, TRUE, FALSE, GfxBase);
589 UFB(data);
592 static IPTR gfx_copyboxmasked(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBoxMasked *msg)
594 struct gfx_data *data;
595 OOP_Object *src = NULL;
596 OOP_Object *dest = NULL;
597 BOOL inside = FALSE;
598 BOOL ret;
600 data = OOP_INST_DATA(cl, o);
601 LFB(data);
603 /* De-masquerade bitmap objects, every of which can be fakefb object */
604 OOP_GetAttr(msg->src, aHidd_FakeFB_RealBitMap, (IPTR *)&src);
605 OOP_GetAttr(msg->dest, aHidd_FakeFB_RealBitMap, (IPTR *)&dest);
606 if (!src)
607 src = msg->src;
608 if (!dest)
609 dest = msg->dest;
612 * FIXME: other bitmap may belong to another instance of fakegfx which can be on
613 * display on another monitor. In this case mouse cursor should be handled also
614 * there. Needs further reengineering.
616 if ((msg->src == data->fakefb) && WRECT_INSIDE(data, msg->srcX, msg->srcY, msg->width, msg->height))
617 inside = TRUE;
619 if ((msg->dest == data->fakefb) && WRECT_INSIDE(data, msg->destX, msg->destY, msg->width, msg->height))
620 inside = TRUE;
622 if (inside)
623 draw_cursor(data, FALSE, FALSE, GfxBase);
625 ret = HIDD_Gfx_CopyBoxMasked(data->gfxhidd, src, msg->srcX, msg->srcY,
626 dest, msg->destX, msg->destY, msg->width, msg->height, msg->mask, msg->gc);
628 if (inside)
629 draw_cursor(data, TRUE, FALSE, GfxBase);
631 UFB(data);
633 return ret;
636 static OOP_Object *gfx_show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
638 OOP_Object *ret;
639 struct gfx_data *data;
641 data = OOP_INST_DATA(cl, o);
642 ret = msg->bitMap;
644 D(bug("[FakeGfx] Show(0x%p)\n", ret));
647 * If we are attempting to show a fake bitmap, we are working
648 * in NoFrameBuffer mode where each displayable bitmap is
649 * intercepted by us
651 if (ret && (OOP_OCLASS(ret) == CDD(GfxBase)->fakefbclass))
653 data->fakefb = ret;
654 OOP_GetAttr(msg->bitMap, aHidd_FakeFB_RealBitMap, (IPTR *)&ret);
655 D(bug("[FakeGfx] Bitmap is a fakefb object, real bitmap is 0x%p\n", ret));
658 LFB(data);
659 draw_cursor(data, FALSE, FALSE, GfxBase);
661 ret = HIDD_Gfx_Show(data->gfxhidd, ret, msg->flags);
662 D(bug("[FakeGfx] Real framebuffer object 0x%p\n", ret));
663 gfx_setFrameBuffer(GfxBase, data, ret);
664 if (NULL != ret)
665 ret = data->fakefb;
666 /* FIXME: temporary workaround: at this point Intuition has already destroyed
667 the sprite image (since the last screen was closed) but we have no information
668 about it. Perhaps FreeSpriteData() should track this down somehow and inform
669 drivers about destroyed sprites.
670 if (!msg->bitMap)
671 data->curs_bm = NULL;*/
672 rethink_cursor(data, GfxBase);
673 draw_cursor(data, TRUE, TRUE, GfxBase);
675 UFB(data);
677 D(bug("[FakeGfx] Returning 0x%p\n", ret));
678 return ret;
681 static ULONG gfx_showviewports(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
683 /* Composition is not supported here */
684 return FALSE;
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 - width;
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) HIDD_BM_UpdateRect(data->framebuffer, data->curs_x, data->curs_y, width, height);
1457 return;
1460 static void gfx_setFrameBuffer(struct GfxBase *GfxBase, struct gfx_data *data, OOP_Object *fb)
1462 data->framebuffer = fb;
1464 if (fb)
1466 /* Cache framebuffer size, needed by sprite rendering routine */
1467 OOP_GetAttr(fb, aHidd_BitMap_Width, &data->fb_width);
1468 OOP_GetAttr(fb, aHidd_BitMap_Height, &data->fb_height);
1470 DCURS(bug("[FakeGfx] Framebuffer size: %u x %u\n", data->fb_width, data->fb_height));
1474 static OOP_Object *create_fake_fb(OOP_Object *framebuffer, struct gfx_data *data, struct GfxBase *GfxBase)
1476 OOP_Object *fakebm;
1477 struct TagItem fakebmtags[] =
1479 { aHidd_FakeFB_RealBitMap , (IPTR)framebuffer },
1480 { aHidd_FakeFB_FakeGfxHidd , (IPTR)data },
1481 { TAG_DONE , 0UL }
1484 /* If we work with framebuffer-based driver, Show() will never be called on
1485 a fakefb object so we remember it right now */
1486 fakebm = OOP_NewObject(CDD(GfxBase)->fakefbclass, NULL, fakebmtags);
1488 if (data->fakefb_attr == aHidd_BitMap_FrameBuffer)
1490 data->fakefb = fakebm;
1491 gfx_setFrameBuffer(GfxBase, data, framebuffer);
1494 return fakebm;
1497 static OOP_Class *init_fakegfxhiddclass (struct GfxBase *GfxBase)
1499 OOP_Class *cl = NULL;
1501 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1503 {(IPTR (*)())gfx_new , moRoot_New },
1504 {(IPTR (*)())gfx_dispose, moRoot_Dispose },
1505 {(IPTR (*)())gfx_get , moRoot_Get },
1506 {(IPTR (*)())gfx_fwd , moRoot_Set },
1507 { NULL , 0UL }
1510 struct OOP_MethodDescr gfxhidd_descr[num_Hidd_Gfx_Methods + 1] =
1512 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewGC },
1513 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeGC },
1514 {(IPTR (*)())gfx_newbitmap , moHidd_Gfx_NewBitMap },
1515 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeBitMap },
1516 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryModeIDs },
1517 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ReleaseModeIDs },
1518 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CheckMode },
1519 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NextModeID },
1520 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetMode },
1521 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetPixFmt },
1522 {(IPTR (*)())gfx_setcursorshape , moHidd_Gfx_SetCursorShape },
1523 {(IPTR (*)())gfx_setcursorpos , moHidd_Gfx_SetCursorPos },
1524 {(IPTR (*)())gfx_setcursorvisible , moHidd_Gfx_SetCursorVisible},
1525 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetMode },
1526 {(IPTR (*)())gfx_show , moHidd_Gfx_Show },
1527 {(IPTR (*)())gfx_copybox , moHidd_Gfx_CopyBox },
1528 {(IPTR (*)())gfx_fwd , moHidd_Gfx_ModeProperties },
1529 {(IPTR (*)())gfx_showviewports , moHidd_Gfx_ShowViewPorts },
1530 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetSync },
1531 {(IPTR (*)())gfx_fwd , moHidd_Gfx_GetGamma },
1532 {(IPTR (*)())gfx_fwd , moHidd_Gfx_SetGamma },
1533 {(IPTR (*)())gfx_fwd , moHidd_Gfx_QueryHardware3D },
1534 {(IPTR (*)())gfx_getmaxspritesize , moHidd_Gfx_GetMaxSpriteSize},
1535 {(IPTR (*)())gfx_fwd , moHidd_Gfx_NewOverlay },
1536 {(IPTR (*)())gfx_fwd , moHidd_Gfx_DisposeOverlay },
1537 {(IPTR (*)())gfx_fwd , moHidd_Gfx_MakeViewPort },
1538 {(IPTR (*)())gfx_fwd , moHidd_Gfx_CleanViewPort },
1539 {(IPTR (*)())gfx_fwd , moHidd_Gfx_PrepareViewPorts},
1540 {(IPTR (*)())gfx_copyboxmasked , moHidd_Gfx_CopyBoxMasked },
1541 {NULL , 0UL }
1544 struct OOP_InterfaceDescr ifdescr[] =
1546 {root_descr , IID_Root , num_Root_Methods },
1547 {gfxhidd_descr , IID_Hidd_Gfx , num_Hidd_Gfx_Methods },
1548 {NULL , NULL , 0 }
1551 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1553 struct TagItem tags[] =
1555 { aMeta_SuperID , (IPTR)CLID_Root },
1556 { aMeta_InterfaceDescr , (IPTR)ifdescr },
1557 { aMeta_InstSize , (IPTR)sizeof (struct gfx_data) },
1558 {TAG_DONE , 0UL }
1562 D(bug("INIT FAKEGFXCLASS\n"));
1564 if ((__IHidd_FakeFB = OOP_ObtainAttrBase(IID_Hidd_FakeFB)))
1566 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1567 if(NULL != cl)
1569 D(bug("FAKE GFX CLASS INITED\n"));
1570 cl->UserData = GfxBase;
1572 return cl;
1575 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1578 return NULL;
1581 static OOP_Class *init_fakefbclass(struct GfxBase *GfxBase)
1583 struct OOP_MethodDescr root_descr[num_Root_Methods + 1] =
1585 {(IPTR (*)())fakefb_new , moRoot_New },
1586 {(IPTR (*)())fakefb_dispose, moRoot_Dispose },
1587 {(IPTR (*)())fakefb_get , moRoot_Get },
1588 {(IPTR (*)())fakefb_set , moRoot_Set },
1589 {NULL , 0UL }
1592 struct OOP_MethodDescr bitmap_descr[num_Hidd_BitMap_Methods + 1] =
1594 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColors },
1595 {(IPTR (*)())fakefb_putpixel , moHidd_BitMap_PutPixel },
1596 {(IPTR (*)())fakefb_drawpixel , moHidd_BitMap_DrawPixel },
1597 {(IPTR (*)())fakefb_putimage , moHidd_BitMap_PutImage },
1598 {(IPTR (*)())fakefb_putalphaimage , moHidd_BitMap_PutAlphaImage },
1599 {(IPTR (*)())fakefb_puttemplate , moHidd_BitMap_PutTemplate },
1600 {(IPTR (*)())fakefb_putalphatemplate , moHidd_BitMap_PutAlphaTemplate },
1601 {(IPTR (*)())fakefb_putpattern , moHidd_BitMap_PutPattern },
1602 {(IPTR (*)())fakefb_getimage , moHidd_BitMap_GetImage },
1603 {(IPTR (*)())fakefb_getpixel , moHidd_BitMap_GetPixel },
1604 {(IPTR (*)())fakefb_drawline , moHidd_BitMap_DrawLine },
1605 {(IPTR (*)())fakefb_drawrect , moHidd_BitMap_DrawRect },
1606 {(IPTR (*)())fakefb_fillrect , moHidd_BitMap_FillRect },
1607 {(IPTR (*)())fakefb_drawellipse , moHidd_BitMap_DrawEllipse },
1608 {(IPTR (*)())fakefb_fillellipse , moHidd_BitMap_FillEllipse },
1609 {(IPTR (*)())fakefb_drawpolygon , moHidd_BitMap_DrawPolygon },
1610 {(IPTR (*)())fakefb_fillpolygon , moHidd_BitMap_FillPolygon },
1611 {(IPTR (*)())fakefb_drawtext , moHidd_BitMap_DrawText },
1612 {(IPTR (*)())fakefb_drawfilltext , moHidd_BitMap_FillText },
1613 {(IPTR (*)())fakefb_fillspan , moHidd_BitMap_FillSpan },
1614 {(IPTR (*)())fakefb_clear , moHidd_BitMap_Clear },
1615 {(IPTR (*)())fakefb_blitcolexp , moHidd_BitMap_BlitColorExpansion },
1616 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_MapColor },
1617 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UnmapPixel },
1618 {(IPTR (*)())fakefb_putimagelut , moHidd_BitMap_PutImageLUT },
1619 {(IPTR (*)())fakefb_puttranspimagelut , moHidd_BitMap_PutTranspImageLUT },
1620 {(IPTR (*)())fakefb_getimagelut , moHidd_BitMap_GetImageLUT },
1621 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_BytesPerLine },
1622 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ConvertPixels },
1623 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect8 },
1624 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect16 },
1625 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect24 },
1626 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_FillMemRect32 },
1627 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_InvertMemRect },
1628 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox8 },
1629 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox16 },
1630 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox24 },
1631 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyMemBox32 },
1632 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox16 },
1633 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox24 },
1634 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_CopyLUTMemBox32 },
1635 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image8 },
1636 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image16 },
1637 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMem32Image24 },
1638 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image8 },
1639 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image16 },
1640 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_GetMem32Image24 },
1641 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate8 },
1642 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate16 },
1643 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate24 },
1644 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemTemplate32 },
1645 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern8 },
1646 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern16 },
1647 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern24 },
1648 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PutMemPattern32 },
1649 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetColorMap },
1650 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ObtainDirectAccess },
1651 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_ReleaseDirectAccess },
1652 {(IPTR (*)())fakefb_scale , moHidd_BitMap_BitMapScale },
1653 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_PrivateSet },
1654 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_SetRGBConversionFunction },
1655 {(IPTR (*)())fakefb_fwd , moHidd_BitMap_UpdateRect },
1656 {NULL , 0UL }
1659 struct OOP_InterfaceDescr ifdescr[] =
1661 {root_descr , IID_Root , num_Root_Methods },
1662 {bitmap_descr , IID_Hidd_BitMap, num_Hidd_BitMap_Methods },
1663 {NULL , NULL , 0 }
1666 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
1668 struct TagItem tags[] =
1670 {aMeta_SuperID , (IPTR) CLID_Root },
1671 {aMeta_InterfaceDescr , (IPTR) ifdescr },
1672 {aMeta_InstSize , (IPTR) sizeof(struct fakefb_data) },
1673 {TAG_DONE , 0UL }
1676 OOP_Class *cl = NULL;
1678 if (MetaAttrBase)
1680 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
1681 if (NULL != cl)
1682 cl->UserData = GfxBase;
1683 } /* if(MetaAttrBase) */
1685 return cl;
1688 OOP_Object *init_fakegfxhidd(OOP_Object *gfxhidd, struct GfxBase *GfxBase)
1690 struct common_driverdata *csd = CDD(GfxBase);
1692 if (!csd->fakegfxclass)
1694 /* Lazy class initialization */
1695 csd->fakegfxclass = init_fakegfxhiddclass(GfxBase);
1696 csd->fakefbclass = init_fakefbclass(GfxBase);
1698 if (!csd->fakegfxclass || !csd->fakefbclass)
1700 cleanup_fakegfxhidd(GfxBase);
1701 return NULL;
1706 return OOP_NewObjectTags(csd->fakegfxclass, NULL, aHidd_FakeGfxHidd_RealGfxHidd, gfxhidd, TAG_DONE);
1709 VOID cleanup_fakegfxhidd(struct GfxBase *GfxBase)
1711 struct common_driverdata *csd = CDD(GfxBase);
1713 if (NULL != csd->fakefbclass)
1715 OOP_DisposeObject((OOP_Object *)csd->fakefbclass);
1716 csd->fakefbclass = NULL;
1719 if (NULL != csd->fakegfxclass)
1721 OOP_DisposeObject((OOP_Object *)csd->fakegfxclass);
1722 OOP_ReleaseAttrBase(IID_Hidd_FakeFB);
1723 csd->fakegfxclass = NULL;