2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
8 #include <proto/exec.h>
10 #include <proto/utility.h>
13 #include <aros/atomic.h>
14 #include <proto/arossupport.h>
16 #include "graphics_intern.h"
17 #include "fakegfxhidd.h"
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 /******************************************************************************/
50 OOP_Object
*framebuffer
;
59 OOP_Object
*curs_backup
;
61 HIDDT_StdPixFmt curs_pixfmt
;
72 struct SignalSemaphore fbsema
;
75 /* baseclasses for CreateObject */
80 /******************************************************************************/
82 static void gfx_setFrameBuffer(struct GfxBase
*GfxBase
, struct gfx_data
*data
, OOP_Object
*fb
);
83 static VOID
draw_cursor(struct gfx_data
*data
, BOOL draw
, BOOL updaterect
, struct GfxBase
*GfxBase
);
84 static BOOL
rethink_cursor(struct gfx_data
*data
, struct GfxBase
*GfxBase
);
85 static OOP_Object
*create_fake_fb(OOP_Object
*framebuffer
, struct gfx_data
*data
, struct GfxBase
*GfxBase
);
87 /******************************************************************************/
91 static void FakeGfxHidd_ObtainSemaphore(struct SignalSemaphore
*sigSem
, BOOL urgent
,
92 struct GfxBase
*GfxBase
)
96 /* Get pointer to current task */
99 /* Arbitrate for the semaphore structure */
103 ss_QueueCount == -1 indicates that the semaphore is
104 free, so we increment this straight away. If it then
105 equals 0, then we are the first to allocate this semaphore.
107 Note: This will need protection for SMP machines.
109 sigSem
->ss_QueueCount
++;
110 if( sigSem
->ss_QueueCount
== 0 )
112 /* We now own the semaphore. This is quick. */
113 sigSem
->ss_Owner
= me
;
114 sigSem
->ss_NestCount
++;
117 /* The semaphore was in use, but was it by us? */
118 else if( sigSem
->ss_Owner
== me
)
120 /* Yes, just increase the nesting count */
121 sigSem
->ss_NestCount
++;
125 Else, some other task must own it. We have
126 to set a waiting request here.
131 We need a node to mark our semaphore request. Lets use some
134 struct SemaphoreRequest sr
;
138 Have to clear the signal to make sure that we don't
139 return immediately. We then add the SemReq to the
140 waiters list of the semaphore. We were the last to
141 request, so we must be the last to get the semaphore.
144 AROS_ATOMIC_AND(me
->tc_SigRecvd
, ~SIGF_SINGLE
);
148 AddHead((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
152 AddTail((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
156 Finally, we simply wait, ReleaseSemaphore() will fill in
157 who owns the semaphore.
167 /******************************************************************************/
169 static void FakeGfxHidd_ReleaseSemaphore(struct SignalSemaphore
*sigSem
,
170 struct GfxBase
*GfxBase
)
172 /* Protect the semaphore structure from multiple access. */
175 /* Release one on the nest count */
176 sigSem
->ss_NestCount
--;
177 sigSem
->ss_QueueCount
--;
179 if(sigSem
->ss_NestCount
== 0)
182 There are two cases here. Either we are a shared
183 semaphore, or not. If we are not, make sure that the
184 correct Task is calling ReleaseSemaphore()
188 Do not try and wake anything unless there are a number
189 of tasks waiting. We do both the tests, this is another
190 opportunity to throw an alert if there is an error.
193 sigSem
->ss_QueueCount
>= 0
194 && sigSem
->ss_WaitQueue
.mlh_Head
->mln_Succ
!= NULL
197 struct SemaphoreRequest
*sr
, *srn
;
200 Look at the first node, but only to see whether it
203 sr
= (struct SemaphoreRequest
*)sigSem
->ss_WaitQueue
.mlh_Head
;
206 A node is shared if the ln_Name/sr_Waiter field is
207 odd (ie it has bit 1 set).
209 If the sr_Waiter field is != NULL, then this is a
210 task waiting, otherwise it is a message.
212 if( ((IPTR
)sr
->sr_Waiter
& SM_SHARED
) == SM_SHARED
)
214 /* This is a shared lock, so ss_Owner == NULL */
215 sigSem
->ss_Owner
= NULL
;
217 /* Go through all the nodes to find the shared ones */
218 ForeachNodeSafe(&sigSem
->ss_WaitQueue
, sr
, srn
)
220 srn
= (struct SemaphoreRequest
*)sr
->sr_Link
.mln_Succ
;
222 if( ((IPTR
)sr
->sr_Waiter
& SM_SHARED
) == SM_SHARED
)
224 Remove((struct Node
*)sr
);
226 /* Clear the bit, and update the owner count */
227 sr
->sr_Waiter
= (APTR
)((IPTR
)sr
->sr_Waiter
& ~1);
228 sigSem
->ss_NestCount
++;
230 /* This is a task, signal it */
231 Signal(sr
->sr_Waiter
, SIGF_SINGLE
);
236 /* This is an exclusive lock - awaken first node */
239 /* Only awaken the first of the nodes */
240 Remove((struct Node
*)sr
);
241 sigSem
->ss_NestCount
++;
243 sigSem
->ss_Owner
= sr
->sr_Waiter
;
244 Signal(sr
->sr_Waiter
, SIGF_SINGLE
);
247 } /* there are waiters */
248 /* Otherwise, there are not tasks waiting. */
251 sigSem
->ss_Owner
= NULL
;
252 sigSem
->ss_QueueCount
= -1;
255 else if(sigSem
->ss_NestCount
< 0)
258 This can't happen. It means that somebody has released
259 more times than they have obtained.
261 Alert( AN_SemCorrupt
);
269 /******************************************************************************/
271 #define LFB(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, FALSE, GfxBase)
272 #define UFB(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, GfxBase)
273 #define LFB_QUICK(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, TRUE, GfxBase)
274 #define UFB_QUICK(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, GfxBase)
276 #else /* !SPECIAL_LOCKING */
278 #define LFB(data) ObtainSemaphore(&(data)->fbsema)
279 #define UFB(data) ReleaseSemaphore(&(data)->fbsema)
280 #define LFB_QUICK(data) ObtainSemaphore(&(data)->fbsema)
281 #define UFB_QUICK(data) ReleaseSemaphore(&(data)->fbsema)
283 #endif /* SPECIAL_LOCKING */
285 /******************************************************************************/
287 #define GfxBase ((struct GfxBase *)cl->UserData)
289 static OOP_Object
*gfx_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
291 /* Create a new gfxhid object */
292 OOP_Object
*realgfxhidd
;
293 struct gfx_data
*data
;
296 realgfxhidd
= (OOP_Object
*)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd
, (IPTR
)NULL
, msg
->attrList
);
297 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
301 data
= OOP_INST_DATA(cl
, o
);
302 memset(data
, 0, sizeof (*data
));
303 InitSemaphore(&data
->fbsema
);
305 data
->basegc
= OOP_FindClass(CLID_Hidd_GC
);
306 data
->basebm
= OOP_FindClass(CLID_Hidd_BitMap
);
309 * If this is direct framebuffer driver, we draw our
310 * cursor on framebuffer bitmap.
311 * Otherwise we draw cursor on displayable bitmaps.
312 * TODO: Implement separate handling for mirrored framebuffers.
313 * In this case we actually don't need to backup pixels
314 * behind the sprite, because we can use mirror for this.
316 data
->fakefb_attr
= (OOP_GET(realgfxhidd
, aHidd_Gfx_FrameBufferType
) == vHidd_FrameBuffer_Direct
) ?
317 aHidd_BitMap_FrameBuffer
: aHidd_BitMap_Displayable
;
319 data
->gfxhidd
= realgfxhidd
;
321 if (NULL
!= data
->gfxhidd
)
323 struct TagItem gctags
[] =
328 data
->gc
= HIDD_Gfx_CreateObject(data
->gfxhidd
, data
->basegc
, gctags
);
329 if (NULL
!= data
->gc
)
339 mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
340 OOP_CoerceMethod(cl
, o
, (OOP_Msg
)&mid
);
346 static VOID
gfx_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
348 struct gfx_data
*data
;
350 data
= OOP_INST_DATA(cl
, o
);
351 if (NULL
!= data
->curs_backup
)
353 OOP_DisposeObject(data
->curs_backup
);
354 data
->curs_backup
= NULL
;
357 if (data
->curs_pixels
)
358 FreeMem(data
->curs_pixels
, data
->curs_width
* data
->curs_height
* 4);
360 if (NULL
!= data
->gc
)
362 OOP_DisposeObject(data
->gc
);
367 static void gfx_get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
369 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
371 if (msg
->attrID
== aHidd_Gfx_HWSpriteTypes
) {
372 *msg
->storage
= vHidd_SpriteType_3Plus1
|vHidd_SpriteType_DirectColor
;
376 OOP_DoMethod(data
->gfxhidd
, (OOP_Msg
)msg
);
379 static IPTR
gfx_fwd(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
381 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
383 return OOP_DoMethod(data
->gfxhidd
, msg
);
386 static OOP_Object
*gfx_createobject(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CreateObject
*msg
)
388 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
389 OOP_Object
*object
= NULL
;
391 if (msg
->cl
== data
->basebm
)
393 /* Is the user about to create a framebuffer ? */
397 create_fb
= (BOOL
)GetTagData(data
->fakefb_attr
, FALSE
, msg
->attrList
);
399 realfb
= HIDD_Gfx_CreateObject(data
->gfxhidd
, msg
->cl
, msg
->attrList
);
401 if (realfb
&& create_fb
)
403 object
= create_fake_fb(realfb
, data
, GfxBase
);
405 OOP_DisposeObject(realfb
);
412 object
= (OOP_Object
*)gfx_fwd(cl
, o
, (OOP_Msg
)msg
);
418 static BOOL
gfx_setcursorshape(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorShape
*msg
)
420 struct gfx_data
*data
;
424 data
= OOP_INST_DATA(cl
, o
);
426 D(bug("[FakeGfx] SetCursorShape(0x%p)\n", shape
));
431 /* Erase the old cursor */
432 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
433 data
->curs_on
= FALSE
;
434 data
->curs_bm
= NULL
;
435 data
->curs_x
= data
->curs_y
= 0;
436 data
->curs_maxx
= data
->curs_maxy
= 0;
437 data
->curs_width
= data
->curs_height
= 0;
438 data
->curs_xoffset
= 0;
439 data
->curs_yoffset
= 0;
441 if (NULL
!= data
->curs_backup
)
443 OOP_DisposeObject(data
->curs_backup
);
444 data
->curs_backup
= NULL
;
446 if (data
->curs_pixels
) {
447 FreeMem(data
->curs_pixels
, data
->curs_width
* data
->curs_height
* 4);
448 data
->curs_pixels
= NULL
;
453 IPTR curs_width
, curs_height
;
454 APTR new_curs_pixels
;
455 ULONG curs_pixels_len
;
457 OOP_GetAttr(shape
, aHidd_BitMap_Width
, &curs_width
);
458 OOP_GetAttr(shape
, aHidd_BitMap_Height
, &curs_height
);
460 DCURS(bug("[FakeGfx] New cursor size: %lu x %lu, framebuffer 0x%p\n", curs_width
, curs_height
, data
->framebuffer
));
462 /* Create new cursor pixelbuffer. We multiply size by 4 because we want ARGB data
464 curs_pixels_len
= curs_width
* curs_height
* 4;
465 new_curs_pixels
= AllocMem(curs_pixels_len
, MEMF_ANY
|MEMF_CLEAR
);
466 if (!new_curs_pixels
)
471 /* Erase the old cursor */
472 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
474 /* Now that we have disposed the old image using the old
475 backup bm, we can install the new image and backup bm before
476 rendering the new cursor.
477 Backup bitmap is recreated in rethink_cursor()
480 if (data
->curs_pixels
)
481 FreeMem(data
->curs_pixels
, data
->curs_width
* data
->curs_height
* 4);
483 data
->curs_bm
= shape
;
484 data
->curs_width
= curs_width
;
485 data
->curs_height
= curs_height
;
486 data
->curs_maxx
= data
->curs_x
+ curs_width
- 1;
487 data
->curs_maxy
= data
->curs_y
+ curs_height
- 1;
488 data
->curs_pixels
= new_curs_pixels
;
489 data
->curs_xoffset
= msg
->xoffset
;
490 data
->curs_yoffset
= msg
->yoffset
;
492 ok
= rethink_cursor(data
, GfxBase
);
495 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
501 static BOOL
gfx_setcursorpos(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorPos
*msg
)
503 struct gfx_data
*data
;
507 data
= OOP_INST_DATA(cl
, o
);
508 DPOS(bug("[FakeGfx] SetCursorPos(%d, %d)\n", msg
->x
, msg
->y
));
510 if (!data
->framebuffer
)
513 /* We draw our cursor on the bitmap, so we have to convert back
514 from physical to logical coordinates */
515 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_LeftEdge
, &xoffset
);
516 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_TopEdge
, &yoffset
);
519 /* erase the old cursor */
520 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
522 data
->curs_x
= msg
->x
- xoffset
;
523 data
->curs_y
= msg
->y
- yoffset
;
524 /* Shift to the hotspot location */
525 data
->curs_x
+= data
->curs_xoffset
;
526 data
->curs_y
+= data
->curs_yoffset
;
527 data
->curs_maxx
= data
->curs_x
+ data
->curs_width
- 1;
528 data
->curs_maxy
= data
->curs_y
+ data
->curs_height
- 1;
530 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
535 static VOID
gfx_setcursorvisible(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorVisible
*msg
)
537 struct gfx_data
*data
;
539 data
= OOP_INST_DATA(cl
, o
);
547 data
->curs_on
= TRUE
;
548 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
555 draw_cursor(data
, FALSE
, TRUE
, GfxBase
);
556 data
->curs_on
= FALSE
;
564 #define PIXEL_INSIDE(fgh, x, y) \
565 ( ( (x) >= (fgh)->curs_x ) \
566 && ( (y) >= (fgh)->curs_y ) \
567 && ( (x) <= (fgh)->curs_maxx ) \
568 && ( (y) <= (fgh)->curs_maxy ) )
570 /* NOTE: x1, y1, x2, y2 MUST be sorted */
571 #define RECT_INSIDE(fgh, x1, y1, x2, y2) \
572 ( ( (x1) <= fgh->curs_maxx ) \
573 && ( (x2) >= fgh->curs_x ) \
574 && ( (y1) <= fgh->curs_maxy ) \
575 && ( (y2) >= fgh->curs_y ) )
577 #define WRECT_INSIDE(fgh, x1, y1, width, height) \
578 RECT_INSIDE(fgh, x1, y1, (x1) + (width) - 1, (y1) + (height) - 1)
580 static void gfx_copybox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
582 struct gfx_data
*data
;
583 OOP_Object
*src
= NULL
;
584 OOP_Object
*dest
= NULL
;
587 data
= OOP_INST_DATA(cl
, o
);
590 /* De-masquerade bitmap objects, every of which can be fakefb object */
591 OOP_GetAttr(msg
->src
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&src
);
592 OOP_GetAttr(msg
->dest
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&dest
);
598 /* FIXME: other bitmap may belong to another instance of fakegfx which can be on
599 display on another monitor. In this case mouse cursor should be handled also
600 there. Needs further reengineering. */
601 if ((msg
->src
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->srcX
, msg
->srcY
, msg
->width
, msg
->height
))
604 if ((msg
->dest
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
608 draw_cursor(data
, FALSE
, FALSE
, GfxBase
);
610 HIDD_Gfx_CopyBox(data
->gfxhidd
, src
, msg
->srcX
, msg
->srcY
,
611 dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
, msg
->gc
);
614 draw_cursor(data
, TRUE
, FALSE
, GfxBase
);
619 static IPTR
gfx_copyboxmasked(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBoxMasked
*msg
)
621 struct gfx_data
*data
;
622 OOP_Object
*src
= NULL
;
623 OOP_Object
*dest
= NULL
;
627 data
= OOP_INST_DATA(cl
, o
);
630 /* De-masquerade bitmap objects, every of which can be fakefb object */
631 OOP_GetAttr(msg
->src
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&src
);
632 OOP_GetAttr(msg
->dest
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&dest
);
639 * FIXME: other bitmap may belong to another instance of fakegfx which can be on
640 * display on another monitor. In this case mouse cursor should be handled also
641 * there. Needs further reengineering.
643 if ((msg
->src
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->srcX
, msg
->srcY
, msg
->width
, msg
->height
))
646 if ((msg
->dest
== data
->fakefb
) && WRECT_INSIDE(data
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
650 draw_cursor(data
, FALSE
, FALSE
, GfxBase
);
652 ret
= HIDD_Gfx_CopyBoxMasked(data
->gfxhidd
, src
, msg
->srcX
, msg
->srcY
,
653 dest
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
, msg
->mask
, msg
->gc
);
656 draw_cursor(data
, TRUE
, FALSE
, GfxBase
);
663 static OOP_Object
*gfx_show(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_Show
*msg
)
666 struct gfx_data
*data
;
668 data
= OOP_INST_DATA(cl
, o
);
671 D(bug("[FakeGfx] Show(0x%p)\n", ret
));
674 * If we are attempting to show a fake bitmap, we are working
675 * in NoFrameBuffer mode where each displayable bitmap is
678 if (ret
&& (OOP_OCLASS(ret
) == CDD(GfxBase
)->fakefbclass
))
681 OOP_GetAttr(msg
->bitMap
, aHidd_FakeFB_RealBitMap
, (IPTR
*)&ret
);
682 D(bug("[FakeGfx] Bitmap is a fakefb object, real bitmap is 0x%p\n", ret
));
686 draw_cursor(data
, FALSE
, FALSE
, GfxBase
);
688 ret
= HIDD_Gfx_Show(data
->gfxhidd
, ret
, msg
->flags
);
689 D(bug("[FakeGfx] Real framebuffer object 0x%p\n", ret
));
690 gfx_setFrameBuffer(GfxBase
, data
, ret
);
693 /* FIXME: temporary workaround: at this point Intuition has already destroyed
694 the sprite image (since the last screen was closed) but we have no information
695 about it. Perhaps FreeSpriteData() should track this down somehow and inform
696 drivers about destroyed sprites.
698 data->curs_bm = NULL;*/
699 rethink_cursor(data
, GfxBase
);
700 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
704 D(bug("[FakeGfx] Returning 0x%p\n", ret
));
708 static ULONG
gfx_showviewports(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
710 /* Composition is not supported here */
714 static BOOL
gfx_getmaxspritesize(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_GetMaxSpriteSize
*msg
)
716 if (msg
->Type
& (vHidd_SpriteType_3Plus1
|vHidd_SpriteType_DirectColor
)) {
717 /* I hope these values are enough for everyone :) */
719 *msg
->Height
= 65535;
726 /* Private non-virtual method */
727 static BOOL
FakeGfx_UpdateFrameBuffer(OOP_Object
*o
)
729 OOP_Class
*cl
= OOP_OCLASS(o
);
730 struct gfx_data
*data
= OOP_INST_DATA(cl
, o
);
735 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_Width
, &data
->fb_width
);
736 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_Height
, &data
->fb_height
);
738 DCURS(bug("[FakeGfx] Changed framebuffer size: %u x %u\n", data
->fb_width
, data
->fb_height
));
740 ok
= rethink_cursor(data
, GfxBase
);
743 draw_cursor(data
, TRUE
, TRUE
, GfxBase
);
749 OOP_Object
*framebuffer
;
750 OOP_Object
*fakegfxhidd
;
753 #define FGH(data) ((struct gfx_data *)data->fakegfxhidd)
754 #define REMOVE_CURSOR(data) \
755 draw_cursor(FGH(data), FALSE, FALSE, GfxBase)
757 #define RENDER_CURSOR(data) \
758 draw_cursor(FGH(data), TRUE, FALSE, GfxBase)
761 #define BITMAP_METHOD_INIT \
762 struct fakefb_data *data; \
763 BOOL inside = FALSE; \
765 struct gfx_data *fgh; \
766 data = OOP_INST_DATA(cl, o); \
770 #define FORWARD_METHOD \
771 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
773 #define BITMAP_METHOD_EXIT \
775 RENDER_CURSOR(data); \
780 static OOP_Object
*fakefb_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
782 OOP_Object
*framebuffer
;
783 OOP_Object
*fakegfxhidd
;
785 framebuffer
= (OOP_Object
*)GetTagData(aHidd_FakeFB_RealBitMap
, 0, msg
->attrList
);
786 fakegfxhidd
= (OOP_Object
*)GetTagData(aHidd_FakeFB_FakeGfxHidd
, 0, msg
->attrList
);
788 if (NULL
== framebuffer
|| NULL
== fakegfxhidd
)
790 D(bug("!!! FakeBM::New(): MISSING FRAMEBUFFER OR FAKE GFX HIDD !!!\n"));
794 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
797 struct fakefb_data
*data
;
798 data
= OOP_INST_DATA(cl
, o
);
799 data
->framebuffer
= framebuffer
;
800 data
->fakegfxhidd
= fakegfxhidd
;
805 static VOID
fakefb_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
807 struct fakefb_data
*data
;
808 data
= OOP_INST_DATA(cl
, o
);
809 if (NULL
!= data
->framebuffer
)
811 OOP_DisposeObject(data
->framebuffer
);
812 data
->framebuffer
= NULL
;
816 static void fakefb_get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
818 struct fakefb_data
*data
= OOP_INST_DATA(cl
, o
);
820 if (msg
->attrID
== aHidd_FakeFB_RealBitMap
)
822 *msg
->storage
= (IPTR
)data
->framebuffer
;
825 else if (msg
->attrID
== aHidd_BitMap_GfxHidd
)
827 *msg
->storage
= (IPTR
)data
->fakegfxhidd
;
831 OOP_DoMethod(data
->framebuffer
, (OOP_Msg
)msg
);
834 /* Intercept framebuffer mode change */
835 static IPTR
fakefb_set(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Set
*msg
)
837 struct fakefb_data
*data
= OOP_INST_DATA(cl
, o
);
838 IPTR ret
= OOP_DoMethod(data
->framebuffer
, &msg
->mID
);
839 struct TagItem
*modeid
= FindTagItem(aHidd_BitMap_ModeID
, msg
->attrList
);
843 /* Framebuffer mode change succeeded. Update fakegfx' information */
844 ret
= FakeGfx_UpdateFrameBuffer(data
->fakegfxhidd
);
850 static IPTR
fakefb_getpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetPixel
*msg
)
854 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
865 static IPTR
fakefb_putpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPixel
*msg
)
869 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
880 static IPTR
fakefb_drawpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPixel
*msg
)
884 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
895 static IPTR
fakefb_drawline(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawLine
*msg
)
897 register LONG x1
, y1
, x2
, y2
;
900 if (msg
->x1
< msg
->x2
)
902 x1
= msg
->x1
; x2
= msg
->x2
;
906 x2
= msg
->x1
; x1
= msg
->x2
;
909 if (msg
->y1
< msg
->y2
)
911 y1
= msg
->y1
; y2
= msg
->y2
;
915 y2
= msg
->y1
; y1
= msg
->y2
;
918 /* FIXME: Maybe do some more intelligent checking for DrawLine */
919 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
930 static IPTR
fakefb_getimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetImage
*msg
)
934 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
945 static IPTR
fakefb_putimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutImage
*msg
)
949 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
960 static IPTR
fakefb_putalphaimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutAlphaImage
*msg
)
964 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
975 static IPTR
fakefb_puttemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTemplate
*msg
)
979 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
990 static IPTR
fakefb_putalphatemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutAlphaTemplate
*msg
)
994 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1005 static IPTR
fakefb_putpattern(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPattern
*msg
)
1009 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1011 REMOVE_CURSOR(data
);
1020 static IPTR
fakefb_getimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetImageLUT
*msg
)
1024 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1026 REMOVE_CURSOR(data
);
1035 static IPTR
fakefb_putimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutImageLUT
*msg
)
1039 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1041 REMOVE_CURSOR(data
);
1050 static IPTR
fakefb_puttranspimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTranspImageLUT
*msg
)
1054 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
1056 REMOVE_CURSOR(data
);
1065 static IPTR
fakefb_drawrect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
1069 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1070 if (RECT_INSIDE(fgh
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
))
1072 REMOVE_CURSOR(data
);
1081 static IPTR
fakefb_fillrect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
1085 /* bug("BITMAP FILLRECT(%d, %d, %d, %d), (%d, %d, %d, %d, %d, %d)\n"
1086 , msg->minX, msg->minY, msg->maxX, msg->maxY
1087 , fgh->curs_x, fgh->curs_y, fgh->curs_maxx, fgh->curs_maxy
1088 , fgh->curs_width, fgh->curs_height);
1090 if (RECT_INSIDE(fgh
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
))
1092 /* bug("FILLRECT: REMOVING CURSOR\n");
1094 REMOVE_CURSOR(data
);
1104 static IPTR
fakefb_drawellipse(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawEllipse
*msg
)
1106 register LONG x1
, y1
, x2
, y2
;
1109 x1
= msg
->x
- msg
->rx
;
1110 y1
= msg
->y
- msg
->ry
;
1111 x2
= msg
->x
+ msg
->rx
;
1112 y2
= msg
->y
+ msg
->ry
;
1113 /* FIXME: Maybe do something clever here to see if the rectangle is drawn around the cursor */
1115 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
1117 REMOVE_CURSOR(data
);
1126 static IPTR
fakefb_fillellipse(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawEllipse
*msg
)
1128 register LONG x1
, y1
, x2
, y2
;
1131 x1
= msg
->x
- msg
->rx
;
1132 y1
= msg
->y
- msg
->ry
;
1133 x2
= msg
->x
+ msg
->rx
;
1134 y2
= msg
->y
+ msg
->ry
;
1136 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
1138 REMOVE_CURSOR(data
);
1147 static IPTR
fakefb_drawpolygon(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPolygon
*msg
)
1150 /* FIXME: Maybe do checking here, but it probably is not worth it */
1151 REMOVE_CURSOR(data
);
1159 static IPTR
fakefb_fillpolygon(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPolygon
*msg
)
1162 /* FIXME: Maybe do checking here, but it probably is not worth it */
1163 REMOVE_CURSOR(data
);
1172 static IPTR
fakefb_drawtext(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawText
*msg
)
1176 /* FIXME: Maybe do testing here, but probably not wirth it */
1177 REMOVE_CURSOR(data
);
1184 static IPTR
fakefb_drawfilltext(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawText
*msg
)
1188 /* FIXME: Maybe do testing here, but probably not worth it */
1189 REMOVE_CURSOR(data
);
1196 static IPTR
fakefb_blitcolexp(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_BlitColorExpansion
*msg
)
1200 if (WRECT_INSIDE(fgh
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
1202 REMOVE_CURSOR(data
);
1211 static IPTR
fakefb_clear(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_Clear
*msg
)
1223 static IPTR
fakefb_fillspan(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
1227 REMOVE_CURSOR(data
);
1235 static IPTR
fakefb_scale(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_BitMapScale
*msg
)
1237 /* FIXME: should check both source and destination, similar to gfx_copybox() */
1240 if (WRECT_INSIDE(fgh
, msg
->bsa
->bsa_SrcX
, msg
->bsa
->bsa_SrcY
, msg
->bsa
->bsa_SrcWidth
, msg
->bsa
->bsa_SrcHeight
))
1242 REMOVE_CURSOR(data
);
1251 static IPTR
fakefb_fwd(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
1253 struct fakefb_data
*data
;
1254 data
= OOP_INST_DATA(cl
, o
);
1255 // kill(getpid(), 19);
1256 // bug("BITMAP_FWD\n");
1257 return OOP_DoMethod(data
->framebuffer
, msg
);
1262 static BOOL
rethink_cursor(struct gfx_data
*data
, struct GfxBase
*GfxBase
)
1264 OOP_Object
*pf
, *cmap
;
1265 IPTR fbdepth
, curdepth
, i
;
1266 UWORD curs_base
= 16;
1268 struct TagItem bmtags
[] = {
1269 { aHidd_BitMap_Width
, data
->curs_width
},
1270 { aHidd_BitMap_Height
, data
->curs_height
},
1271 { aHidd_BitMap_Friend
, (IPTR
)data
->framebuffer
},
1275 D(bug("rethink_cursor(), curs_bm is 0x%p, framebuffer is 0x%p\n", data
->curs_bm
, data
->framebuffer
));
1277 /* The first thing we do is recreating a backup bitmap. We do it every time when either
1278 cursor shape changes (because new shape may have different size) or shown bitmap
1279 changes (because new bitmap may have different depth). Note that even real framebuffer
1280 object may dynamically change its characteristics.
1282 Delete the old backup bitmap first */
1283 if (NULL
!= data
->curs_backup
) {
1284 OOP_DisposeObject(data
->curs_backup
);
1285 D(bug("[FakeGfx] Disposed old backup bitmap\n"));
1286 data
->curs_backup
= NULL
;
1289 /* If we have no cursor, we have nothing more to do.
1290 We also don't need new backup bitmap */
1294 /* We may also have no framebuffer (empty display on
1295 non-framebuffer driver). Also NOP in this case */
1296 if (!data
->framebuffer
)
1299 /* Create new backup bitmap */
1300 data
->curs_backup
= HIDD_Gfx_CreateObject(data
->gfxhidd
, data
->basebm
, bmtags
);
1301 D(bug("[FakeGfx] New backup bitmap is 0x%p\n", data
->curs_backup
));
1302 if (!data
->curs_backup
)
1305 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
1306 D(bug("[FakeGfx] Framebuffer pixelformat 0x%p\n", pf
));
1307 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &fbdepth
);
1308 D(bug("[FakeGfx] Framebuffer depth %u\n", fbdepth
));
1309 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_ColorMap
, (IPTR
*)&cmap
);
1310 D(bug("[FakeGfx] Cursor colormap 0x%p\n", cmap
));
1311 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
1312 D(bug("[FakeGfx] Cursor pixelformat 0x%p\n", pf
));
1313 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &curdepth
);
1314 D(bug("[FakeGfx] Cursor depth %u\n", curdepth
));
1316 #ifndef DISABLE_ARGB_POINTER
1317 /* We can get ARGB data from the pointer bitmap only
1318 on one of two cases:
1319 1) Pointer bitmap has more than 256 colors, in this case it
1320 stores ARGB data in itself.
1321 2) Pointer bitmap is a LUT bitmap with a colormap attached.
1322 In this case colormap should contain ARGB values for actual
1324 Of course having ARGB data makes sense only on truecolor screens. */
1325 if ((fbdepth
> 8) && ((curdepth
> 8) || cmap
)) {
1326 data
->curs_pixfmt
= vHidd_StdPixFmt_ARGB32
;
1331 data
->curs_pixfmt
= vHidd_StdPixFmt_LUT8
;
1333 /* TODO: curs_base should be somehow synchronised with SpriteBase field of ColorMap */
1334 curs_base
= (fbdepth
> 4) ? 16 : (1 << fbdepth
) - 8;
1336 /* If we have some good bitmap->bitmap blitting function with alpha channel support,
1337 we would not need this extra buffer and conversion for truecolor screens. */
1338 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
);
1339 D(bug("[FakeGfx] Obtained cursor sprite data @ 0x%p\n", data
->curs_pixels
));
1341 if (data
->curs_pixfmt
== vHidd_StdPixFmt_LUT8
)
1343 for (i
= 0; i
< data
->curs_width
* data
->curs_height
; i
++)
1345 if (data
->curs_pixels
[i
])
1346 data
->curs_pixels
[i
] += curs_base
;
1352 static VOID
draw_cursor(struct gfx_data
*data
, BOOL draw
, BOOL updaterect
, struct GfxBase
*GfxBase
)
1355 LONG fbwidth
, fbheight
;
1361 struct TagItem gctags
[] =
1363 { aHidd_GC_DrawMode
, vHidd_GC_DrawMode_Copy
},
1370 if (NULL
== data
->curs_bm
|| NULL
== data
->framebuffer
)
1372 DB2(bug("!!! draw_cursor: FAKE GFX HIDD NOT PROPERLY INITIALIZED !!!\n"));
1373 DB2(bug("CURS BM: 0x%p, FB: 0x%p\n", data
->curs_bm
, data
->framebuffer
));
1377 fbwidth
= data
->fb_width
;
1378 fbheight
= data
->fb_height
;
1379 width
= data
->curs_width
;
1380 height
= data
->curs_height
;
1384 /* Do nothing if sprite went outside of bitmap */
1385 if ((x
< -width
) || (y
< -height
)) {
1386 DCURS(bug("[FakeGfx] Cursor is beyond left or top edge\n"));
1389 if ((x
>= fbwidth
) || (y
>= fbheight
)) {
1390 DCURS(bug("[FakeGfx] Cursor is beyond right or bottom edge\n"));
1394 /* Do some clipping */
1407 w2end
= data
->fb_width
- width
;
1408 h2end
= data
->fb_height
- height
;
1412 width
-= (x
- w2end
);
1413 DCLIP(bug("[FakeGfx] Clipped sprite width to %d\n", width
));
1418 height
-= (y
- h2end
);
1419 DCLIP(bug("[FakeGfx] Clipped sprite height to %d\n", height
));
1422 /* FIXME: clip negative coordinates */
1424 OOP_SetAttrs(data
->gc
, gctags
);
1428 /* Calculate origin of sprite image according to offsets */
1429 ULONG modulo
= data
->curs_width
* data
->curs_bpp
;
1430 UBYTE
*pixels
= data
->curs_pixels
+ yoffset
* modulo
+ xoffset
* data
->curs_bpp
;
1432 /* Backup under the new cursor image */
1433 // bug("BACKING UP RENDERED AREA\n");
1434 HIDD_Gfx_CopyBox(data
->gfxhidd
1443 data
->backup_done
= TRUE
;
1445 DB2(bug("[FakeGfx] Rendering cursor, framebuffer 0x%p\n", data
->framebuffer
));
1446 /* Render the cursor image */
1447 if (data
->curs_pixfmt
== vHidd_StdPixFmt_ARGB32
)
1448 HIDD_BM_PutAlphaImage(data
->framebuffer
, data
->gc
, pixels
, modulo
, x
, y
, width
, height
);
1450 /* data->curs_bpp is always 1 here so we safely ignore it */
1451 HIDD_BM_PutTranspImageLUT(data
->framebuffer
, data
->gc
, pixels
, modulo
, x
, y
, width
, height
, NULL
, 0);
1454 HIDD_BM_UpdateRect(data
->framebuffer
, x
, y
, width
, height
);
1459 /* Erase the old cursor image */
1460 if (data
->backup_done
)
1462 DB2(bug("[FakeGfx] Restoring cursor area, framebuffer 0x%p\n", data
->framebuffer
));
1463 HIDD_Gfx_CopyBox(data
->gfxhidd
1473 HIDD_BM_UpdateRect(data
->framebuffer
, x
, y
, width
, height
);
1479 static void gfx_setFrameBuffer(struct GfxBase
*GfxBase
, struct gfx_data
*data
, OOP_Object
*fb
)
1481 data
->framebuffer
= fb
;
1485 /* Cache framebuffer size, needed by sprite rendering routine */
1486 OOP_GetAttr(fb
, aHidd_BitMap_Width
, &data
->fb_width
);
1487 OOP_GetAttr(fb
, aHidd_BitMap_Height
, &data
->fb_height
);
1489 DCURS(bug("[FakeGfx] Framebuffer size: %u x %u\n", data
->fb_width
, data
->fb_height
));
1493 static OOP_Object
*create_fake_fb(OOP_Object
*framebuffer
, struct gfx_data
*data
, struct GfxBase
*GfxBase
)
1496 struct TagItem fakebmtags
[] =
1498 { aHidd_FakeFB_RealBitMap
, (IPTR
)framebuffer
},
1499 { aHidd_FakeFB_FakeGfxHidd
, (IPTR
)data
},
1503 /* If we work with framebuffer-based driver, Show() will never be called on
1504 a fakefb object so we remember it right now */
1505 fakebm
= OOP_NewObject(CDD(GfxBase
)->fakefbclass
, NULL
, fakebmtags
);
1507 if (data
->fakefb_attr
== aHidd_BitMap_FrameBuffer
)
1509 data
->fakefb
= fakebm
;
1510 gfx_setFrameBuffer(GfxBase
, data
, framebuffer
);
1516 static OOP_Class
*init_fakegfxhiddclass (struct GfxBase
*GfxBase
)
1518 OOP_Class
*cl
= NULL
;
1520 struct OOP_MethodDescr root_descr
[num_Root_Methods
+ 1] =
1522 {(IPTR (*)())gfx_new
, moRoot_New
},
1523 {(IPTR (*)())gfx_dispose
, moRoot_Dispose
},
1524 {(IPTR (*)())gfx_get
, moRoot_Get
},
1525 {(IPTR (*)())gfx_fwd
, moRoot_Set
},
1529 struct OOP_MethodDescr gfxhidd_descr
[num_Hidd_Gfx_Methods
+ 1] =
1531 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NominalDimensions
},
1532 {(IPTR (*)())gfx_createobject
, moHidd_Gfx_CreateObject
},
1533 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_QueryModeIDs
},
1534 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ReleaseModeIDs
},
1535 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_CheckMode
},
1536 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NextModeID
},
1537 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetMode
},
1538 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetPixFmt
},
1539 {(IPTR (*)())gfx_setcursorshape
, moHidd_Gfx_SetCursorShape
},
1540 {(IPTR (*)())gfx_setcursorpos
, moHidd_Gfx_SetCursorPos
},
1541 {(IPTR (*)())gfx_setcursorvisible
, moHidd_Gfx_SetCursorVisible
},
1542 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_SetMode
},
1543 {(IPTR (*)())gfx_show
, moHidd_Gfx_Show
},
1544 {(IPTR (*)())gfx_copybox
, moHidd_Gfx_CopyBox
},
1545 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ModeProperties
},
1546 {(IPTR (*)())gfx_showviewports
, moHidd_Gfx_ShowViewPorts
},
1547 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetSync
},
1548 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetGamma
},
1549 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_SetGamma
},
1550 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_QueryHardware3D
},
1551 {(IPTR (*)())gfx_getmaxspritesize
, moHidd_Gfx_GetMaxSpriteSize
},
1552 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NewOverlay
},
1553 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_DisposeOverlay
},
1554 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_MakeViewPort
},
1555 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_CleanViewPort
},
1556 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_PrepareViewPorts
},
1557 {(IPTR (*)())gfx_copyboxmasked
, moHidd_Gfx_CopyBoxMasked
},
1561 struct OOP_InterfaceDescr ifdescr
[] =
1563 {root_descr
, IID_Root
, num_Root_Methods
},
1564 {gfxhidd_descr
, IID_Hidd_Gfx
, num_Hidd_Gfx_Methods
},
1568 OOP_AttrBase MetaAttrBase
= OOP_GetAttrBase(IID_Meta
);
1570 struct TagItem tags
[] =
1572 { aMeta_SuperID
, (IPTR
)CLID_Root
},
1573 { aMeta_InterfaceDescr
, (IPTR
)ifdescr
},
1574 { aMeta_InstSize
, (IPTR
)sizeof (struct gfx_data
) },
1579 D(bug("INIT FAKEGFXCLASS\n"));
1581 if ((__IHidd_FakeFB
= OOP_ObtainAttrBase(IID_Hidd_FakeFB
)))
1583 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
1586 D(bug("FAKE GFX CLASS INITED\n"));
1587 cl
->UserData
= GfxBase
;
1592 OOP_ReleaseAttrBase(IID_Hidd_FakeFB
);
1598 static OOP_Class
*init_fakefbclass(struct GfxBase
*GfxBase
)
1600 struct OOP_MethodDescr root_descr
[num_Root_Methods
+ 1] =
1602 {(IPTR (*)())fakefb_new
, moRoot_New
},
1603 {(IPTR (*)())fakefb_dispose
, moRoot_Dispose
},
1604 {(IPTR (*)())fakefb_get
, moRoot_Get
},
1605 {(IPTR (*)())fakefb_set
, moRoot_Set
},
1609 struct OOP_MethodDescr bitmap_descr
[num_Hidd_BitMap_Methods
+ 1] =
1611 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetColors
},
1612 {(IPTR (*)())fakefb_putpixel
, moHidd_BitMap_PutPixel
},
1613 {(IPTR (*)())fakefb_drawpixel
, moHidd_BitMap_DrawPixel
},
1614 {(IPTR (*)())fakefb_putimage
, moHidd_BitMap_PutImage
},
1615 {(IPTR (*)())fakefb_putalphaimage
, moHidd_BitMap_PutAlphaImage
},
1616 {(IPTR (*)())fakefb_puttemplate
, moHidd_BitMap_PutTemplate
},
1617 {(IPTR (*)())fakefb_putalphatemplate
, moHidd_BitMap_PutAlphaTemplate
},
1618 {(IPTR (*)())fakefb_putpattern
, moHidd_BitMap_PutPattern
},
1619 {(IPTR (*)())fakefb_getimage
, moHidd_BitMap_GetImage
},
1620 {(IPTR (*)())fakefb_getpixel
, moHidd_BitMap_GetPixel
},
1621 {(IPTR (*)())fakefb_drawline
, moHidd_BitMap_DrawLine
},
1622 {(IPTR (*)())fakefb_drawrect
, moHidd_BitMap_DrawRect
},
1623 {(IPTR (*)())fakefb_fillrect
, moHidd_BitMap_FillRect
},
1624 {(IPTR (*)())fakefb_drawellipse
, moHidd_BitMap_DrawEllipse
},
1625 {(IPTR (*)())fakefb_fillellipse
, moHidd_BitMap_FillEllipse
},
1626 {(IPTR (*)())fakefb_drawpolygon
, moHidd_BitMap_DrawPolygon
},
1627 {(IPTR (*)())fakefb_fillpolygon
, moHidd_BitMap_FillPolygon
},
1628 {(IPTR (*)())fakefb_drawtext
, moHidd_BitMap_DrawText
},
1629 {(IPTR (*)())fakefb_drawfilltext
, moHidd_BitMap_FillText
},
1630 {(IPTR (*)())fakefb_fillspan
, moHidd_BitMap_FillSpan
},
1631 {(IPTR (*)())fakefb_clear
, moHidd_BitMap_Clear
},
1632 {(IPTR (*)())fakefb_blitcolexp
, moHidd_BitMap_BlitColorExpansion
},
1633 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_MapColor
},
1634 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_UnmapPixel
},
1635 {(IPTR (*)())fakefb_putimagelut
, moHidd_BitMap_PutImageLUT
},
1636 {(IPTR (*)())fakefb_puttranspimagelut
, moHidd_BitMap_PutTranspImageLUT
},
1637 {(IPTR (*)())fakefb_getimagelut
, moHidd_BitMap_GetImageLUT
},
1638 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_BytesPerLine
},
1639 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ConvertPixels
},
1640 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect8
},
1641 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect16
},
1642 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect24
},
1643 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_FillMemRect32
},
1644 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_InvertMemRect
},
1645 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox8
},
1646 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox16
},
1647 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox24
},
1648 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyMemBox32
},
1649 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyLUTMemBox16
},
1650 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyLUTMemBox24
},
1651 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_CopyLUTMemBox32
},
1652 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMem32Image8
},
1653 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMem32Image16
},
1654 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMem32Image24
},
1655 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_GetMem32Image8
},
1656 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_GetMem32Image16
},
1657 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_GetMem32Image24
},
1658 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate8
},
1659 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate16
},
1660 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate24
},
1661 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemTemplate32
},
1662 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern8
},
1663 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern16
},
1664 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern24
},
1665 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PutMemPattern32
},
1666 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetColorMap
},
1667 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ObtainDirectAccess
},
1668 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ReleaseDirectAccess
},
1669 {(IPTR (*)())fakefb_scale
, moHidd_BitMap_BitMapScale
},
1670 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_PrivateSet
},
1671 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetRGBConversionFunction
},
1672 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_UpdateRect
},
1676 struct OOP_InterfaceDescr ifdescr
[] =
1678 {root_descr
, IID_Root
, num_Root_Methods
},
1679 {bitmap_descr
, IID_Hidd_BitMap
, num_Hidd_BitMap_Methods
},
1683 OOP_AttrBase MetaAttrBase
= OOP_GetAttrBase(IID_Meta
);
1685 struct TagItem tags
[] =
1687 {aMeta_SuperID
, (IPTR
) CLID_Root
},
1688 {aMeta_InterfaceDescr
, (IPTR
) ifdescr
},
1689 {aMeta_InstSize
, (IPTR
) sizeof(struct fakefb_data
) },
1693 OOP_Class
*cl
= NULL
;
1697 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
1699 cl
->UserData
= GfxBase
;
1700 } /* if(MetaAttrBase) */
1705 OOP_Object
*init_fakegfxhidd(OOP_Object
*gfxhidd
, struct GfxBase
*GfxBase
)
1707 struct common_driverdata
*csd
= CDD(GfxBase
);
1709 if (!csd
->fakegfxclass
)
1711 /* Lazy class initialization */
1712 csd
->fakegfxclass
= init_fakegfxhiddclass(GfxBase
);
1713 csd
->fakefbclass
= init_fakefbclass(GfxBase
);
1715 if (!csd
->fakegfxclass
|| !csd
->fakefbclass
)
1717 cleanup_fakegfxhidd(GfxBase
);
1723 return OOP_NewObjectTags(csd
->fakegfxclass
, NULL
, aHidd_FakeGfxHidd_RealGfxHidd
, gfxhidd
, TAG_DONE
);
1726 VOID
cleanup_fakegfxhidd(struct GfxBase
*GfxBase
)
1728 struct common_driverdata
*csd
= CDD(GfxBase
);
1730 if (NULL
!= csd
->fakefbclass
)
1732 OOP_DisposeObject((OOP_Object
*)csd
->fakefbclass
);
1733 csd
->fakefbclass
= NULL
;
1736 if (NULL
!= csd
->fakegfxclass
)
1738 OOP_DisposeObject((OOP_Object
*)csd
->fakegfxclass
);
1739 OOP_ReleaseAttrBase(IID_Hidd_FakeFB
);
1740 csd
->fakegfxclass
= NULL
;