2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
8 #include <proto/exec.h>
10 #include <proto/utility.h>
12 #include <hidd/graphics.h>
13 #include <aros/atomic.h>
14 #include <proto/arossupport.h>
16 #include "graphics_intern.h"
17 #include "graphics_internal.h"
18 #include "fakegfxhidd.h"
21 #include <aros/debug.h>
23 /******************************************************************************/
25 #define SPECIAL_LOCKING 1 /* When activated mouse cursor relevant locks are
26 treated in some kind of privileged way, by
27 inserting wait-for-sem-requests at head of
28 wait queue, instead of at tail */
30 /******************************************************************************/
32 static OOP_Class
*init_fakefbclass(struct class_static_data
*csd
);
33 static VOID
free_fakefbclass(OOP_Class
*cl
, struct class_static_data
*csd
);
35 static OOP_Class
*init_fakegfxhiddclass (struct class_static_data
*csd
);
36 static VOID
free_fakegfxhiddclass(OOP_Class
*cl
, struct class_static_data
*csd
);
38 /******************************************************************************/
43 OOP_Object
*framebuffer
;
48 OOP_Object
*curs_backup
;
49 HIDDT_Pixel curs_pixels
[256];
57 struct SignalSemaphore fbsema
;
61 /******************************************************************************/
63 static VOID
draw_cursor(struct gfx_data
*data
, BOOL draw
, struct class_static_data
*csd
);
64 static VOID
rethink_cursor(struct gfx_data
*data
, struct class_static_data
*csd
);
65 static OOP_Object
*create_fake_fb(OOP_Object
*framebuffer
, struct gfx_data
*data
, struct class_static_data
*csd
);
67 /******************************************************************************/
69 #define LFB(data) ObtainSemaphore(&(data)->fbsema)
70 #define UFB(data) ReleaseSemaphore(&(data)->fbsema)
71 #define LFB_QUICK(data) ObtainSemaphore(&(data)->fbsema)
72 #define UFB_QUICK(data) ReleaseSemaphore(&(data)->fbsema)
74 #define CSD(cl) ((struct class_static_data *)cl->UserData)
76 #define __IHidd_FakeFB (CSD(cl)->hiddFakeFBAttrBase)
78 /******************************************************************************/
82 /******************************************************************************/
86 static void FakeGfxHidd_ObtainSemaphore(struct SignalSemaphore
*sigSem
, BOOL urgent
,
87 struct ExecBase
*SysBase
)
91 /* Get pointer to current task */
94 /* Arbitrate for the semaphore structure */
98 ss_QueueCount == -1 indicates that the semaphore is
99 free, so we increment this straight away. If it then
100 equals 0, then we are the first to allocate this semaphore.
102 Note: This will need protection for SMP machines.
104 sigSem
->ss_QueueCount
++;
105 if( sigSem
->ss_QueueCount
== 0 )
107 /* We now own the semaphore. This is quick. */
108 sigSem
->ss_Owner
= me
;
109 sigSem
->ss_NestCount
++;
112 /* The semaphore was in use, but was it by us? */
113 else if( sigSem
->ss_Owner
== me
)
115 /* Yes, just increase the nesting count */
116 sigSem
->ss_NestCount
++;
120 Else, some other task must own it. We have
121 to set a waiting request here.
126 We need a node to mark our semaphore request. Lets use some
129 struct SemaphoreRequest sr
;
133 Have to clear the signal to make sure that we don't
134 return immediately. We then add the SemReq to the
135 waiters list of the semaphore. We were the last to
136 request, so we must be the last to get the semaphore.
139 #warning This must be atomic!
140 AROS_ATOMIC_AND(me
->tc_SigRecvd
, ~SIGF_SINGLE
);
144 AddHead((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
148 AddTail((struct List
*)&sigSem
->ss_WaitQueue
, (struct Node
*)&sr
);
152 Finally, we simply wait, ReleaseSemaphore() will fill in
153 who owns the semaphore.
163 /******************************************************************************/
165 static void FakeGfxHidd_ReleaseSemaphore(struct SignalSemaphore
*sigSem
,
166 struct ExecBase
*SysBase
)
168 /* Protect the semaphore structure from multiple access. */
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
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 */
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. */
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
);
265 /******************************************************************************/
272 #define LFB(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, FALSE, SysBase)
273 #define UFB(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, SysBase)
275 #define LFB_QUICK(data) FakeGfxHidd_ObtainSemaphore(&(data)->fbsema, TRUE, SysBase)
276 #define UFB_QUICK(data) FakeGfxHidd_ReleaseSemaphore(&(data)->fbsema, SysBase)
279 /******************************************************************************/
281 #endif /* SPECIAL_LOCKING */
283 /******************************************************************************/
286 #define GfxBase (CSD(cl)->gfxbase)
288 static OOP_Object
*gfx_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
290 /* Create a new gfxhid object */
291 OOP_Object
*realgfxhidd
;
292 struct gfx_data
*data
;
295 realgfxhidd
= (OOP_Object
*)GetTagData(aHidd_FakeGfxHidd_RealGfxHidd
, (IPTR
)NULL
, msg
->attrList
);
296 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
300 data
= OOP_INST_DATA(cl
, o
);
301 memset(data
, 0, sizeof (*data
));
302 InitSemaphore(&data
->fbsema
);
304 data
->gfxhidd
= realgfxhidd
;
306 if (NULL
!= data
->gfxhidd
)
308 struct TagItem gctags
[] =
313 data
->gc
= HIDD_Gfx_NewGC(data
->gfxhidd
, gctags
);
314 if (NULL
!= data
->gc
)
324 mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
325 OOP_CoerceMethod(cl
, o
, (OOP_Msg
)&mid
);
331 static VOID
gfx_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
333 struct gfx_data
*data
;
335 data
= OOP_INST_DATA(cl
, o
);
336 if (NULL
!= data
->curs_backup
)
338 OOP_DisposeObject(data
->curs_backup
);
339 data
->curs_backup
= NULL
;
342 if (NULL
!= data
->gc
)
344 OOP_DisposeObject(data
->gc
);
349 if (NULL
!= data
->gfxhidd
)
351 OOP_DisposeObject(data
->gfxhidd
);
352 data
->gfxhidd
= NULL
;
357 static OOP_Object
*gfx_newbitmap(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_NewBitMap
*msg
)
359 /* Is the user about to create a framebuffer ? */
361 struct gfx_data
*data
;
363 OOP_Object
*ret
= NULL
;
366 data
= OOP_INST_DATA(cl
, o
);
367 create_fb
= (BOOL
)GetTagData(aHidd_BitMap_FrameBuffer
, FALSE
, msg
->attrList
);
369 realfb
= HIDD_Gfx_NewBitMap(data
->gfxhidd
, msg
->attrList
);
371 if (NULL
!= realfb
&& create_fb
)
374 fakefb
= create_fake_fb(realfb
, data
, CSD(cl
));
378 data
->framebuffer
= realfb
;
392 OOP_DisposeObject(realfb
);
399 static BOOL
gfx_setcursorshape(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorShape
*msg
)
401 struct gfx_data
*data
;
404 data
= OOP_INST_DATA(cl
, o
);
410 /* Erase the old cursor */
411 draw_cursor(data
, FALSE
, CSD(cl
));
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;
418 if (NULL
!= data
->curs_backup
)
420 OOP_DisposeObject(data
->curs_backup
);
421 data
->curs_backup
= NULL
;
428 IPTR curs_width
, curs_height
, curs_depth
;
429 IPTR mode_width
, mode_height
, mode_depth
;
430 OOP_Object
*curs_pf
, *mode_sync
,* mode_pf
;
432 OOP_Object
*new_backup
;
434 struct TagItem bmtags
[] =
436 { aHidd_BitMap_Displayable
, FALSE
},
437 { aHidd_BitMap_Width
, 0 },
438 { aHidd_BitMap_Height
, 0 },
439 { aHidd_BitMap_Friend
, 0 },
443 OOP_GetAttr(shape
, aHidd_BitMap_Width
, &curs_width
);
444 OOP_GetAttr(shape
, aHidd_BitMap_Height
, &curs_height
);
446 OOP_GetAttr(shape
, aHidd_BitMap_PixFmt
, (IPTR
*)&curs_pf
);
448 OOP_GetAttr(curs_pf
, aHidd_PixFmt_Depth
, &curs_depth
);
449 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_ModeID
, &fbmode
);
450 HIDD_Gfx_GetMode(o
, (HIDDT_ModeID
)fbmode
, &mode_sync
, &mode_pf
);
452 OOP_GetAttr(mode_sync
, aHidd_Sync_HDisp
, &mode_width
);
453 OOP_GetAttr(mode_sync
, aHidd_Sync_VDisp
, &mode_height
);
454 OOP_GetAttr(mode_pf
, aHidd_PixFmt_Depth
, &mode_depth
);
456 /* Disallow very large cursors, and cursors with higher
457 depth than the framebuffer bitmap */
458 if ( ( curs_width
> (mode_width
/ 2) )
459 || ( curs_height
> (mode_height
/ 2) )
460 || ( curs_depth
> mode_depth
) )
462 D(bug("!!! FakeGfx::SetCursorShape: CURSOR BM HAS INVALID ATTRS !!!\n"));
466 /* Create new backup bitmap */
467 bmtags
[1].ti_Data
= curs_width
;
468 bmtags
[2].ti_Data
= curs_height
;
469 bmtags
[3].ti_Data
= (IPTR
)data
->framebuffer
;
471 new_backup
= HIDD_Gfx_NewBitMap(data
->gfxhidd
, bmtags
);
473 if (NULL
== new_backup
)
475 D(bug("!!! FakeGfx::SetCursorShape: COULD NOT CREATE BACKUP BM !!!\n"));
479 data
->curs_bm
= shape
;
483 /* Erase the old cursor */
484 draw_cursor(data
, FALSE
, CSD(cl
));
486 /* Now that we have disposed the old image using the old
487 backup bm, we can install the new backup bm before
488 rendering the new curso
491 if (NULL
!= data
->curs_backup
)
492 OOP_DisposeObject(data
->curs_backup
);
494 data
->curs_width
= curs_width
;
495 data
->curs_height
= curs_height
;
497 data
->curs_maxx
= data
->curs_x
+ curs_width
- 1;
498 data
->curs_maxy
= data
->curs_y
+ curs_height
- 1;
499 data
->curs_backup
= new_backup
;
501 rethink_cursor(data
, CSD(cl
));
503 draw_cursor(data
, TRUE
, CSD(cl
));
509 if (NULL
!= data
->curs_backup
)
510 OOP_DisposeObject(data
->curs_backup
);
512 data
->curs_width
= curs_width
;
513 data
->curs_height
= curs_height
;
515 data
->curs_maxx
= data
->curs_x
+ curs_width
- 1;
516 data
->curs_maxy
= data
->curs_y
+ curs_height
- 1;
517 data
->curs_backup
= new_backup
;
519 rethink_cursor(data
, CSD(cl
));
528 static BOOL
gfx_setcursorpos(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorPos
*msg
)
530 struct gfx_data
*data
;
532 data
= OOP_INST_DATA(cl
, o
);
534 /* erase the old cursor */
536 draw_cursor(data
, FALSE
, CSD(cl
));
538 data
->curs_x
= msg
->x
;
539 data
->curs_y
= msg
->y
;
540 data
->curs_maxx
= data
->curs_x
+ data
->curs_width
- 1;
541 data
->curs_maxy
= data
->curs_y
+ data
->curs_height
- 1;
544 draw_cursor(data
, TRUE
, CSD(cl
));
549 static VOID
gfx_setcursorvisible(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_SetCursorVisible
*msg
)
551 struct gfx_data
*data
;
553 data
= OOP_INST_DATA(cl
, o
);
561 data
->curs_on
= TRUE
;
562 draw_cursor(data
, TRUE
, CSD(cl
));
569 data
->curs_on
= FALSE
;
570 draw_cursor(data
, FALSE
, CSD(cl
));
578 #define PIXEL_INSIDE(fgh, x, y) \
579 ( ( (x) >= (fgh)->curs_x ) \
580 && ( (y) >= (fgh)->curs_y ) \
581 && ( (x) <= (fgh)->curs_maxx ) \
582 && ( (y) <= (fgh)->curs_maxy ) )
584 /* NOTE: x1, y1, x2, y2 MUST be sorted */
585 #define RECT_INSIDE(fgh, x1, y1, x2, y2) \
586 ( ( (x1) <= fgh->curs_maxx ) \
587 && ( (x2) >= fgh->curs_x ) \
588 && ( (y1) <= fgh->curs_maxy ) \
589 && ( (y2) >= fgh->curs_y ) )
591 #define WRECT_INSIDE(fgh, x1, y1, width, height) \
592 RECT_INSIDE(fgh, x1, y1, (x1) + (width) - 1, (y1) + (height) - 1)
594 static IPTR
gfx_copybox(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_Gfx_CopyBox
*msg
)
596 struct gfx_data
*data
;
599 struct pHidd_Gfx_CopyBox p
;
601 data
= OOP_INST_DATA(cl
, o
);
605 if (msg
->src
== data
->fakefb
)
607 if (WRECT_INSIDE(data
, msg
->srcX
, msg
->srcY
, msg
->width
, msg
->height
))
611 p
.src
= data
->framebuffer
;
614 if (msg
->dest
== data
->fakefb
)
616 if (WRECT_INSIDE(data
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
620 p
.dest
= data
->framebuffer
;
625 draw_cursor(data
, FALSE
, CSD(cl
));
629 retval
= OOP_DoMethod(data
->gfxhidd
, (OOP_Msg
)msg
);
632 draw_cursor(data
, TRUE
, CSD(cl
));
638 static OOP_Object
*gfx_show(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
641 struct gfx_data
*data
;
643 data
= OOP_INST_DATA(cl
, o
);
646 draw_cursor(data
, FALSE
, CSD(cl
));
648 ret
= (OOP_Object
*)OOP_DoMethod(data
->gfxhidd
, msg
);
651 data
->framebuffer
= ret
;
654 rethink_cursor(data
, CSD(cl
));
655 draw_cursor(data
, TRUE
, CSD(cl
));
661 static IPTR
gfx_fwd(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
663 struct gfx_data
*data
;
665 data
= OOP_INST_DATA(cl
, o
);
667 return OOP_DoMethod(data
->gfxhidd
, msg
);
672 OOP_Object
*framebuffer
;
673 OOP_Object
*fakegfxhidd
;
676 #define FGH(data) ((struct gfx_data *)data->fakegfxhidd)
677 #define REMOVE_CURSOR(data) \
678 draw_cursor(FGH(data), FALSE, CSD(cl))
680 #define RENDER_CURSOR(data) \
681 draw_cursor(FGH(data), TRUE, CSD(cl))
684 #define BITMAP_METHOD_INIT \
685 struct fakefb_data *data; \
686 BOOL inside = FALSE; \
688 struct gfx_data *fgh; \
689 data = OOP_INST_DATA(cl, o); \
693 #define FORWARD_METHOD \
694 retval = OOP_DoMethod(data->framebuffer, (OOP_Msg)msg);
696 #define BITMAP_METHOD_EXIT \
698 RENDER_CURSOR(data); \
703 static OOP_Object
*fakefb_new(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
705 OOP_Object
*framebuffer
;
706 OOP_Object
*fakegfxhidd
;
708 framebuffer
= (OOP_Object
*)GetTagData(aHidd_FakeFB_RealBitMap
, NULL
, msg
->attrList
);
709 fakegfxhidd
= (OOP_Object
*)GetTagData(aHidd_FakeFB_FakeGfxHidd
, NULL
, msg
->attrList
);
711 if (NULL
== framebuffer
|| NULL
== fakegfxhidd
)
713 D(bug("!!! FakeBM::New(): MISSING FRAMEBUFFER OR FAKE GFX HIDD !!!\n"));
717 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
720 struct fakefb_data
*data
;
721 data
= OOP_INST_DATA(cl
, o
);
722 data
->framebuffer
= framebuffer
;
723 data
->fakegfxhidd
= fakegfxhidd
;
728 static VOID
fakefb_dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
730 struct fakefb_data
*data
;
731 data
= OOP_INST_DATA(cl
, o
);
732 if (NULL
!= data
->framebuffer
)
734 OOP_DisposeObject(data
->framebuffer
);
735 data
->framebuffer
= NULL
;
739 static IPTR
fakefb_getpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetPixel
*msg
)
743 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
754 static IPTR
fakefb_putpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPixel
*msg
)
758 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
769 static IPTR
fakefb_drawpixel(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPixel
*msg
)
773 if (PIXEL_INSIDE(fgh
, msg
->x
, msg
->y
))
784 static IPTR
fakefb_drawline(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawLine
*msg
)
786 register LONG x1
, y1
, x2
, y2
;
789 if (msg
->x1
< msg
->x2
)
791 x1
= msg
->x1
; x2
= msg
->x2
;
795 x2
= msg
->x1
; x1
= msg
->x2
;
798 if (msg
->y1
< msg
->y2
)
800 y1
= msg
->y1
; y2
= msg
->y2
;
804 y2
= msg
->y1
; y1
= msg
->y2
;
807 #warning Maybe do some more intelligent checking for DrawLine
808 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
819 static IPTR
fakefb_getimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetImage
*msg
)
823 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
834 static IPTR
fakefb_putimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutImage
*msg
)
838 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
849 static IPTR
fakefb_putalphaimage(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutAlphaImage
*msg
)
853 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
864 static IPTR
fakefb_puttemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTemplate
*msg
)
868 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
879 static IPTR
fakefb_putalphatemplate(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutAlphaTemplate
*msg
)
883 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
894 static IPTR
fakefb_putpattern(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutPattern
*msg
)
898 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
909 static IPTR
fakefb_getimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_GetImageLUT
*msg
)
913 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
924 static IPTR
fakefb_putimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutImageLUT
*msg
)
928 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
939 static IPTR
fakefb_puttranspimagelut(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_PutTranspImageLUT
*msg
)
943 if (WRECT_INSIDE(fgh
, msg
->x
, msg
->y
, msg
->width
, msg
->height
))
954 static IPTR
fakefb_drawrect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
958 #warning Maybe do something clever here to see if the rectangle is drawn around the cursor
959 if (RECT_INSIDE(fgh
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
))
970 static IPTR
fakefb_fillrect(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawRect
*msg
)
974 /* bug("BITMAP FILLRECT(%d, %d, %d, %d), (%d, %d, %d, %d, %d, %d)\n"
975 , msg->minX, msg->minY, msg->maxX, msg->maxY
976 , fgh->curs_x, fgh->curs_y, fgh->curs_maxx, fgh->curs_maxy
977 , fgh->curs_width, fgh->curs_height);
979 if (RECT_INSIDE(fgh
, msg
->minX
, msg
->minY
, msg
->maxX
, msg
->maxY
))
981 /* bug("FILLRECT: REMOVING CURSOR\n");
993 static IPTR
fakefb_drawellipse(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawEllipse
*msg
)
995 register LONG x1
, y1
, x2
, y2
;
998 x1
= msg
->x
- msg
->rx
;
999 y1
= msg
->y
- msg
->ry
;
1000 x2
= msg
->x
+ msg
->rx
;
1001 y2
= msg
->y
+ msg
->ry
;
1002 #warning Maybe do something clever here to see if the rectangle is drawn around the cursor
1004 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
1006 REMOVE_CURSOR(data
);
1015 static IPTR
fakefb_fillellipse(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawEllipse
*msg
)
1017 register LONG x1
, y1
, x2
, y2
;
1020 x1
= msg
->x
- msg
->rx
;
1021 y1
= msg
->y
- msg
->ry
;
1022 x2
= msg
->x
+ msg
->rx
;
1023 y2
= msg
->y
+ msg
->ry
;
1025 if (RECT_INSIDE(fgh
, x1
, y1
, x2
, y2
))
1027 REMOVE_CURSOR(data
);
1036 static IPTR
fakefb_drawpolygon(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPolygon
*msg
)
1039 #warning Maybe do checking here, but it probably is not worth it
1040 REMOVE_CURSOR(data
);
1048 static IPTR
fakefb_fillpolygon(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawPolygon
*msg
)
1051 #warning Maybe do checking here, but it probably is not worth it
1052 REMOVE_CURSOR(data
);
1061 static IPTR
fakefb_drawtext(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawText
*msg
)
1065 #warning Maybe do testing here, but probably not wirth it
1066 REMOVE_CURSOR(data
);
1073 static IPTR
fakefb_drawfilltext(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_DrawText
*msg
)
1077 #warning Maybe do testing here, but probably not worth it
1078 REMOVE_CURSOR(data
);
1085 static IPTR
fakefb_blitcolexp(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_BlitColorExpansion
*msg
)
1089 if (WRECT_INSIDE(fgh
, msg
->destX
, msg
->destY
, msg
->width
, msg
->height
))
1091 REMOVE_CURSOR(data
);
1100 static IPTR
fakefb_clear(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_BitMap_Clear
*msg
)
1112 static IPTR
fakefb_fillspan(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
1116 REMOVE_CURSOR(data
);
1126 static IPTR
fakefb_fwd(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
1128 struct fakefb_data
*data
;
1129 data
= OOP_INST_DATA(cl
, o
);
1130 // kill(getpid(), 19);
1131 // bug("BITMAP_FWD\n");
1132 return OOP_DoMethod(data
->framebuffer
, msg
);
1141 static OOP_Class
*init_fakegfxhiddclass (struct class_static_data
*csd
)
1143 OOP_Class
*cl
= NULL
;
1145 struct OOP_MethodDescr root_descr
[num_Root_Methods
+ 1] =
1147 {(IPTR (*)())gfx_new
, moRoot_New
},
1148 {(IPTR (*)())gfx_dispose
, moRoot_Dispose
},
1149 {(IPTR (*)())gfx_fwd
, moRoot_Get
},
1150 {(IPTR (*)())gfx_fwd
, moRoot_Set
},
1154 struct OOP_MethodDescr gfxhidd_descr
[num_Hidd_Gfx_Methods
+ 1] =
1156 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NewGC
},
1157 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_DisposeGC
},
1158 {(IPTR (*)())gfx_newbitmap
, moHidd_Gfx_NewBitMap
},
1159 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_DisposeBitMap
},
1160 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_QueryModeIDs
},
1161 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ReleaseModeIDs
},
1162 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_CheckMode
},
1163 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_NextModeID
},
1164 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetMode
},
1167 /* These are private to the gfxhidd, and we should not be called with these */
1168 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_RegisterPixFmt
},
1169 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_ReleasePixFmt
},
1171 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_GetPixFmt
},
1172 {(IPTR (*)())gfx_setcursorshape
, moHidd_Gfx_SetCursorShape
},
1173 {(IPTR (*)())gfx_setcursorpos
, moHidd_Gfx_SetCursorPos
},
1174 {(IPTR (*)())gfx_setcursorvisible
, moHidd_Gfx_SetCursorVisible
},
1175 {(IPTR (*)())gfx_fwd
, moHidd_Gfx_SetMode
},
1176 {(IPTR (*)())gfx_show
, moHidd_Gfx_Show
},
1177 {(IPTR (*)())gfx_copybox
, moHidd_Gfx_CopyBox
},
1181 struct OOP_InterfaceDescr ifdescr
[] =
1183 {root_descr
, IID_Root
, num_Root_Methods
},
1184 {gfxhidd_descr
, IID_Hidd_Gfx
, num_Hidd_Gfx_Methods
},
1188 OOP_AttrBase MetaAttrBase
= OOP_GetAttrBase(IID_Meta
);
1190 struct TagItem tags
[] =
1192 /* { aMeta_SuperID , (IPTR)CLID_Hidd },*/
1193 { aMeta_SuperID
, (IPTR
)CLID_Root
},
1194 { aMeta_InterfaceDescr
, (IPTR
)ifdescr
},
1195 { aMeta_ID
, (IPTR
)CLID_Hidd_FakeGfxHidd
},
1196 { aMeta_InstSize
, (IPTR
)sizeof (struct gfx_data
) },
1201 D(bug("INIT FAKEGFXCLASS\n"));
1202 if ((__IHidd_FakeFB
= OOP_ObtainAttrBase(IID_Hidd_FakeFB
)))
1204 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
1207 D(bug("FAKE GFX CLASS INITED\n"));
1216 free_fakegfxhiddclass(cl
, csd
);
1221 static void free_fakegfxhiddclass(OOP_Class
*cl
, struct class_static_data
*csd
)
1225 OOP_RemoveClass(cl
);
1226 OOP_DisposeObject((OOP_Object
*) cl
);
1227 OOP_ReleaseAttrBase(IID_Hidd_FakeFB
);
1231 static OOP_Class
*init_fakefbclass(struct class_static_data
*csd
)
1233 struct OOP_MethodDescr root_descr
[num_Root_Methods
+ 1] =
1235 {(IPTR (*)())fakefb_new
, moRoot_New
},
1236 {(IPTR (*)())fakefb_dispose
, moRoot_Dispose
},
1237 {(IPTR (*)())fakefb_fwd
, moRoot_Get
},
1238 {(IPTR (*)())fakefb_fwd
, moRoot_Set
},
1242 struct OOP_MethodDescr bitmap_descr
[num_Hidd_BitMap_Methods
+ 1] =
1244 {(IPTR (*)())fakefb_putpixel
, moHidd_BitMap_PutPixel
},
1245 {(IPTR (*)())fakefb_getpixel
, moHidd_BitMap_GetPixel
},
1246 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetColors
},
1247 {(IPTR (*)())fakefb_drawpixel
, moHidd_BitMap_DrawPixel
},
1248 {(IPTR (*)())fakefb_drawline
, moHidd_BitMap_DrawLine
},
1249 {(IPTR (*)())fakefb_drawrect
, moHidd_BitMap_DrawRect
},
1250 {(IPTR (*)())fakefb_fillrect
, moHidd_BitMap_FillRect
},
1251 {(IPTR (*)())fakefb_drawellipse
, moHidd_BitMap_DrawEllipse
},
1252 {(IPTR (*)())fakefb_fillellipse
, moHidd_BitMap_FillEllipse
},
1253 {(IPTR (*)())fakefb_drawpolygon
, moHidd_BitMap_DrawPolygon
},
1254 {(IPTR (*)())fakefb_fillpolygon
, moHidd_BitMap_FillPolygon
},
1255 {(IPTR (*)())fakefb_drawtext
, moHidd_BitMap_DrawText
},
1256 {(IPTR (*)())fakefb_drawfilltext
, moHidd_BitMap_FillText
},
1257 {(IPTR (*)())fakefb_fillspan
, moHidd_BitMap_FillSpan
},
1258 {(IPTR (*)())fakefb_clear
, moHidd_BitMap_Clear
},
1259 {(IPTR (*)())fakefb_putimage
, moHidd_BitMap_PutImage
},
1260 {(IPTR (*)())fakefb_putalphaimage
, moHidd_BitMap_PutAlphaImage
},
1261 {(IPTR (*)())fakefb_puttemplate
, moHidd_BitMap_PutTemplate
},
1262 {(IPTR (*)())fakefb_putalphatemplate
, moHidd_BitMap_PutAlphaTemplate
},
1263 {(IPTR (*)())fakefb_putpattern
, moHidd_BitMap_PutPattern
},
1264 {(IPTR (*)())fakefb_putimagelut
, moHidd_BitMap_PutImageLUT
},
1265 {(IPTR (*)())fakefb_puttranspimagelut
, moHidd_BitMap_PutTranspImageLUT
},
1266 {(IPTR (*)())fakefb_getimage
, moHidd_BitMap_GetImage
},
1267 {(IPTR (*)())fakefb_getimagelut
, moHidd_BitMap_GetImageLUT
},
1268 {(IPTR (*)())fakefb_blitcolexp
, moHidd_BitMap_BlitColorExpansion
},
1269 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_BytesPerLine
},
1270 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ConvertPixels
},
1271 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetColorMap
},
1272 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_MapColor
},
1273 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_UnmapPixel
},
1274 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ObtainDirectAccess
},
1275 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_ReleaseDirectAccess
},
1276 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetRGBConversionFunction
},
1278 /* PRIVATE METHODS */
1280 /* This is private to the gfxhidd, and we should not be called with this */
1281 {(IPTR (*)())fakefb_fwd
, moHidd_BitMap_SetBitMapTags
},
1286 struct OOP_InterfaceDescr ifdescr
[] =
1288 {root_descr
, IID_Root
, num_Root_Methods
},
1289 {bitmap_descr
, IID_Hidd_BitMap
, num_Hidd_BitMap_Methods
},
1293 OOP_AttrBase MetaAttrBase
= OOP_GetAttrBase(IID_Meta
);
1295 struct TagItem tags
[] =
1297 {aMeta_SuperID
, (IPTR
) CLID_Root
},
1298 {aMeta_InterfaceDescr
, (IPTR
) ifdescr
},
1299 {aMeta_ID
, (IPTR
) CLID_Hidd_FakeFB
},
1300 {aMeta_InstSize
, (IPTR
) sizeof(struct fakefb_data
) },
1304 OOP_Class
*cl
= NULL
;
1308 cl
= OOP_NewObject(NULL
, CLID_HiddMeta
, tags
);
1314 } /* if(MetaAttrBase) */
1317 free_fakefbclass(cl
, csd
);
1322 static void free_fakefbclass(OOP_Class
*cl
, struct class_static_data
*csd
)
1326 OOP_RemoveClass(cl
);
1327 OOP_DisposeObject((OOP_Object
*) cl
);
1332 static VOID
rethink_cursor(struct gfx_data
*data
, struct class_static_data
*csd
)
1334 OOP_Object
*pf
, *colmap
;
1335 IPTR depth
, fbdepth
, i
;
1337 D(bug("rethink_cursor()\n"));
1338 OOP_GetAttr(data
->curs_backup
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
1339 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &fbdepth
);
1341 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_PixFmt
, (IPTR
*)&pf
);
1342 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
1343 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_ColorMap
, (IPTR
*)&colmap
);
1345 if (depth
> 8) depth
= 8;
1347 for(i
= 0; i
< (1L << depth
); i
++)
1353 HIDD_CM_GetColor(colmap
, i
, &col
);
1354 data
->curs_pixels
[i
] = HIDD_BM_MapColor(data
->curs_backup
, &col
);
1358 /* FIXME: this assumes fbdepth > 3 */
1360 data
->curs_pixels
[i
] = i
+ 16;
1362 data
->curs_pixels
[i
] = i
+ (1 << fbdepth
) - 8;
1368 static VOID
draw_cursor(struct gfx_data
*data
, BOOL draw
, struct class_static_data
*csd
)
1371 IPTR fb_width
, fb_height
;
1376 struct TagItem gctags
[] =
1378 { aHidd_GC_DrawMode
, vHidd_GC_DrawMode_Copy
},
1382 if (NULL
== data
->curs_bm
|| NULL
== data
->framebuffer
|| !data
->curs_on
)
1384 D(bug("!!! draw_cursor: FAKE GFX HIDD NOT PROPERLY INITIALIZED !!!\n"));
1385 D(bug("CURS BM: %p, FB: %p, ON: %d\n"
1386 , data
->curs_bm
, data
->framebuffer
, data
->curs_on
));
1390 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_Width
, &width
);
1391 OOP_GetAttr(data
->curs_bm
, aHidd_BitMap_Height
, &height
);
1393 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_Width
, &fb_width
);
1394 OOP_GetAttr(data
->framebuffer
, aHidd_BitMap_Height
, &fb_height
);
1396 /* Do some clipping */
1400 w2end
= fb_width
- 1 - data
->curs_x
;
1401 h2end
= fb_height
- 1 - data
->curs_y
;
1403 if (w2end
<= 0 || h2end
<= 0) /* Cursor outside framebuffer */
1407 width
-= (width
- w2end
);
1410 height
-= (height
- h2end
);
1412 OOP_SetAttrs(data
->gc
, gctags
);
1416 /* Backup under the new cursor image */
1417 // bug("BACKING UP RENDERED AREA\n");
1418 HIDD_Gfx_CopyBox(data
->gfxhidd
1428 data
->backup_done
= TRUE
;
1430 // bug("RENDERING CURSOR IMAGE\n");
1431 /* Render the cursor image */
1434 HIDD_Gfx_CopyBox(data
->gfxhidd
1438 , data
->curs_x
, data
->curs_y
1443 for(y
= 0; y
< height
; y
++)
1445 for(x
= 0; x
< width
; x
++)
1449 pix
= HIDD_BM_GetPixel(data
->curs_bm
, x
, y
);
1452 HIDD_BM_PutPixel(data
->framebuffer
, data
->curs_x
+ x
, data
->curs_y
+ y
, data
->curs_pixels
[pix
]);
1462 /* Erase the old cursor image */
1463 if (data
->backup_done
)
1465 // bug("PUTTING BACK BACKED UP AREA\n");
1466 HIDD_Gfx_CopyBox(data
->gfxhidd
1480 static OOP_Object
*create_fake_fb(OOP_Object
*framebuffer
, struct gfx_data
*data
, struct class_static_data
*csd
)
1483 struct TagItem fakebmtags
[] =
1485 { aHidd_FakeFB_RealBitMap
, (IPTR
)framebuffer
},
1486 { aHidd_FakeFB_FakeGfxHidd
, (IPTR
)data
},
1490 fakebm
= OOP_NewObject(NULL
, CLID_Hidd_FakeFB
, fakebmtags
);
1493 data
->framebuffer
= framebuffer
;
1494 data
->fakefb
= fakebm
;
1503 OOP_Object
*init_fakegfxhidd(OOP_Object
*gfxhidd
, struct class_static_data
*csd
, struct GfxBase
*GfxBase
)
1505 OOP_Object
*fgo
= NULL
;
1507 csd
->gfxbase
= GfxBase
;
1509 csd
->fakegfxclass
= init_fakegfxhiddclass(csd
);
1510 csd
->fakefbclass
= init_fakefbclass(csd
);
1512 if (NULL
!= csd
->fakegfxclass
&& NULL
!= csd
->fakefbclass
)
1514 struct TagItem fgh_tags
[] =
1516 { aHidd_FakeGfxHidd_RealGfxHidd
, (IPTR
)gfxhidd
},
1520 fgo
= OOP_NewObject(NULL
, CLID_Hidd_FakeGfxHidd
, fgh_tags
);
1524 csd
->fakegfxobj
= fgo
;
1529 cleanup_fakegfxhidd(csd
, GfxBase
);
1534 VOID
cleanup_fakegfxhidd(struct class_static_data
*csd
, struct GfxBase
*GfxBase
)
1536 if (NULL
!= csd
->fakegfxobj
)
1538 OOP_DisposeObject(csd
->fakegfxobj
);
1539 csd
->fakegfxobj
= NULL
;
1542 if (NULL
!= csd
->fakefbclass
)
1544 free_fakefbclass(csd
->fakefbclass
, csd
);
1545 csd
->fakefbclass
= NULL
;
1548 if (NULL
!= csd
->fakegfxclass
)
1550 free_fakegfxhiddclass(csd
->fakegfxclass
, csd
);
1551 csd
->fakegfxclass
= NULL
;