Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / hidds / graphics / GraphicsClass.c
blob0be44e200fbb31368d0b5edf28818df6516da197
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics hidd class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #include <aros/config.h>
12 #include <aros/symbolsets.h>
13 #include <exec/lists.h>
15 #include "graphics_intern.h"
17 #include <string.h>
19 #include <proto/exec.h>
20 #include <proto/utility.h>
21 #include <proto/oop.h>
22 #include <exec/libraries.h>
23 #include <exec/memory.h>
25 #include <utility/tagitem.h>
26 #include <hidd/graphics.h>
28 #include LC_LIBDEFS_FILE
30 #undef SDEBUG
31 #undef DEBUG
32 #define SDEBUG 0
33 #define DEBUG 0
34 #include <aros/debug.h>
36 /****************************************************************************************/
38 static BOOL create_std_pixfmts(struct class_static_data *_csd);
39 static VOID delete_std_pixfmts(struct class_static_data *_csd);
40 static VOID free_objectlist(struct List *list, BOOL OOP_DisposeObjects,
41 struct class_static_data *_csd);
42 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags);
44 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl);
45 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl);
46 static OOP_Object *create_and_init_object(OOP_Class *cl, UBYTE *data, ULONG datasize,
47 struct class_static_data *_csd);
49 static struct pfnode *find_pixfmt(struct MinList *pflist
50 , HIDDT_PixelFormat *tofind
51 , struct class_static_data *_csd);
53 static OOP_Object *find_stdpixfmt(HIDDT_PixelFormat *tofind
54 , struct class_static_data *_csd);
55 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm
56 , OOP_Object *dst_bm, OOP_Object *dims_bm);
58 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf, ULONG attrcheck, struct class_static_data *_csd);
59 BOOL parse_sync_tags(struct TagItem *tags, struct sync_data *data, ULONG attrcheck, struct class_static_data *_csd);
61 /****************************************************************************************/
63 #define COMPUTE_HIDD_MODEID(sync, pf) \
64 ( ((sync) << 16) | (pf) )
66 #define MODEID_TO_SYNCIDX(id) ( (id) >> 16 )
67 #define MODEID_TO_PFIDX(id) ( (id) & 0x0000FFFF )
69 /****************************************************************************************/
71 OOP_Object *GFX__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
73 struct HIDDGraphicsData *data;
74 BOOL ok = FALSE;
75 struct TagItem *modetags;
76 struct TagItem gctags[] =
78 {TAG_DONE, 0UL}
81 D(bug("Entering gfx.hidd::New\n"));
83 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
84 if (NULL == o)
85 return NULL;
87 D(bug("Got object o=%x\n", o));
89 data = OOP_INST_DATA(cl, o);
91 NEWLIST(&data->pflist);
93 InitSemaphore(&data->mdb.sema);
94 InitSemaphore(&data->pfsema);
95 data->curmode = vHidd_ModeID_Invalid;
97 /* Get the mode tags */
98 modetags = (struct TagItem *)GetTagData(aHidd_Gfx_ModeTags, NULL, msg->attrList);
99 if (NULL != modetags)
101 /* Parse it and register the gfxmodes */
102 if (register_modes(cl, o, modetags))
104 ok = TRUE;
106 else
107 D(bug("Could not register modes\n"));
109 else
110 D(bug("Could not get ModeTags\n"));
112 /* Create a gc that we can use for some rendering */
113 if (ok)
115 data->gc = OOP_NewObject(CSD(cl)->gcclass, NULL, gctags);
116 if (NULL == data->gc)
118 D(bug("Could not get gc\n"));
119 ok = FALSE;
123 if (!ok)
125 D(bug("Not OK\n"));
126 OOP_MethodID dispose_mid;
128 dispose_mid = OOP_GetMethodID(IID_Root, moRoot_Dispose);
129 OOP_CoerceMethod(cl, o, (OOP_Msg)&dispose_mid);
130 o = NULL;
133 D(bug("Leaving gfx.hidd::New o=%x\n", o));
135 return o;
138 /****************************************************************************************/
140 VOID GFX__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
142 struct HIDDGraphicsData *data;
144 data = OOP_INST_DATA(cl, o);
146 /* free the mode db stuff */
147 free_mode_db(&data->mdb, cl);
149 ObtainSemaphore(&data->pfsema);
150 free_objectlist((struct List *)&data->pflist, TRUE, CSD(cl));
151 ReleaseSemaphore(&data->pfsema);
153 if (NULL != data->gc)
154 OOP_DisposeObject(data->gc);
156 OOP_DoSuperMethod(cl, o, msg);
159 /****************************************************************************************/
161 VOID GFX__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
163 struct HIDDGraphicsData *data;
164 BOOL found = FALSE;
165 ULONG idx;
167 data = OOP_INST_DATA(cl, o);
169 if (IS_GFX_ATTR(msg->attrID, idx))
171 switch (idx)
173 case aoHidd_Gfx_NumSyncs:
175 found = TRUE;
176 *msg->storage = data->mdb.num_syncs;
177 break;
180 case aoHidd_Gfx_SupportsHWCursor:
181 found = TRUE;
182 *msg->storage = FALSE;
183 break;
185 case aoHidd_Gfx_IsWindowed:
186 found = TRUE;
187 *msg->storage = FALSE;
188 break;
190 default: /* Keep compiler happy */
191 break;
195 if (!found)
196 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
198 return;
201 /****************************************************************************************/
203 OOP_Object *GFX__Hidd_Gfx__NewGC(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewGC *msg)
205 OOP_Object *gc = NULL;
207 EnterFunc(bug("HIDDGfx::NewGC()\n"));
209 gc = OOP_NewObject(NULL, CLID_Hidd_GC, msg->attrList);
211 ReturnPtr("HIDDGfx::NewGC", OOP_Object *, gc);
214 /****************************************************************************************/
216 VOID GFX__Hidd_Gfx__DisposeGC(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_DisposeGC *msg)
218 EnterFunc(bug("HIDDGfx::DisposeGC()\n"));
220 if (NULL != msg->gc) OOP_DisposeObject(msg->gc);
222 ReturnVoid("HIDDGfx::DisposeGC");
225 /****************************************************************************************/
227 #define BMAO(x) aoHidd_BitMap_ ## x
228 #define BMAF(x) (1L << aoHidd_BitMap_ ## x)
230 #define BM_DIMS_AF (BMAF(Width) | BMAF(Height))
232 #define SET_TAG(tags, idx, tag, val) \
233 tags[idx].ti_Tag = tag ; tags[idx].ti_Data = (IPTR)val;
235 #define SET_BM_TAG(tags, idx, tag, val) \
236 SET_TAG(tags, idx, aHidd_BitMap_ ## tag, val)
238 /****************************************************************************************/
240 OOP_Object * GFX__Hidd_Gfx__NewBitMap(OOP_Class *cl, OOP_Object *o,
241 struct pHidd_Gfx_NewBitMap *msg)
243 struct TagItem bmtags[7];
245 IPTR attrs[num_Total_BitMap_Attrs];
246 STRPTR classid = NULL;
247 OOP_Class *classptr = NULL;
248 BOOL displayable = FALSE; /* Default attr value */
249 BOOL framebuffer = FALSE;
250 OOP_Object *pf = NULL, *sync;
251 APTR ptr_pf = &pf;
252 HIDDT_ModeID modeid = 0;
253 OOP_Object *bm;
254 struct HIDDGraphicsData *data;
256 DECLARE_ATTRCHECK(bitmap);
258 BOOL gotclass = FALSE;
260 data = OOP_INST_DATA(cl, o);
262 if (0 != OOP_ParseAttrs(msg->attrList, attrs, num_Total_BitMap_Attrs,
263 &ATTRCHECK(bitmap), HiddBitMapAttrBase))
265 D(bug("!!! FAILED TO PARSE ATTRS IN Gfx::NewBitMap !!!\n"));
266 return NULL;
269 if (GOT_BM_ATTR(PixFmt))
271 D(bug("!!! Gfx::NewBitMap: USER IS NOT ALLOWED TO PASS aHidd_BitMap_PixFmt !!!\n"));
272 return NULL;
275 /* Get class supplied by superclass */
276 if (GOT_BM_ATTR(ClassPtr))
278 classptr = (OOP_Class *)attrs[BMAO(ClassPtr)];
279 gotclass = TRUE;
281 else
283 if (GOT_BM_ATTR(ClassID))
285 classid = (STRPTR)attrs[BMAO(ClassID)];
286 gotclass = TRUE;
290 if (GOT_BM_ATTR(Displayable))
291 displayable = (BOOL)attrs[BMAO(Displayable)];
293 if (GOT_BM_ATTR(FrameBuffer))
295 framebuffer = (BOOL)attrs[BMAO(FrameBuffer)];
296 if (framebuffer) displayable = TRUE;
299 if (GOT_BM_ATTR(ModeID))
301 modeid = attrs[BMAO(ModeID)];
303 /* Check that it is a valid mode */
304 if (!HIDD_Gfx_GetMode(o, modeid, &sync, &pf))
306 D(bug("!!! Gfx::NewBitMap: USER PASSED INVALID MODEID !!!\n"));
310 /* First argument is gfxhidd */
311 SET_BM_TAG(bmtags, 0, GfxHidd, o);
312 SET_BM_TAG(bmtags, 1, Displayable, displayable);
315 if (displayable || framebuffer)
317 /* The user has to supply a modeid */
318 if (!GOT_BM_ATTR(ModeID))
320 D(bug("!!! Gfx::NewBitMap: USER HAS NOT PASSED MODEID FOR DISPLAYABLE BITMAP !!!\n"));
321 return NULL;
324 if (!gotclass)
326 D(bug("!!! Gfx::NewBitMap: SUBCLASS DID NOT PASS CLASS FOR DISPLAYABLE BITMAP !!!\n"));
327 return NULL;
330 SET_BM_TAG(bmtags, 2, ModeID, modeid);
331 SET_BM_TAG(bmtags, 3, PixFmt, pf);
333 if (framebuffer)
335 SET_BM_TAG(bmtags, 4, FrameBuffer, TRUE);
337 else
339 SET_TAG(bmtags, 4, TAG_IGNORE, 0UL);
341 SET_TAG(bmtags, 5, TAG_MORE, msg->attrList);
344 else
345 { /* if (displayable) */
346 IPTR width, height;
348 /* To get a pixfmt for an offscreen bitmap we either need
349 (ModeID || ( (Width && Height) && StdPixFmt) || ( (Width && Height) && Friend))
352 if (GOT_BM_ATTR(ModeID))
354 /* We have allredy gotten pixelformat and sync for the modeid case */
355 OOP_GetAttr(sync, aHidd_Sync_HDisp, &width);
356 OOP_GetAttr(sync, aHidd_Sync_VDisp, &height);
358 else
360 /* Next to look for is StdPixFmt */
362 /* Check that we have width && height */
363 if (BM_DIMS_AF != (BM_DIMS_AF & ATTRCHECK(bitmap)))
365 D(bug("!!! Gfx::NewBitMap() MISSING WIDTH/HEIGHT TAGS !!!\n"));
366 return NULL;
369 width = attrs[BMAO(Width)];
370 height = attrs[BMAO(Height)];
372 if (GOT_BM_ATTR(StdPixFmt))
374 pf = HIDD_Gfx_GetPixFmt(o, (HIDDT_StdPixFmt)attrs[BMAO(StdPixFmt)]);
375 if (NULL == pf)
377 D(bug("!!! Gfx::NewBitMap(): USER PASSED BOGUS StdPixFmt !!!\n"));
378 return NULL;
381 else
383 /* Last alternative is that the user passed a friend bitmap */
384 if (GOT_BM_ATTR(Friend))
386 OOP_GetAttr((OOP_Object *)attrs[BMAO(Friend)], aHidd_BitMap_PixFmt, (IPTR *)ptr_pf);
388 else
390 D(bug("!!! Gfx::NewBitMap: UNSIFFICIENT ATTRS TO CREATE OFFSCREEN BITMAP !!!\n"));
391 return NULL;
396 /* Did the subclass provide an offbitmap class for us ? */
397 if (!gotclass)
399 /* Have to find a suitable class ourselves */
400 HIDDT_BitMapType bmtype;
402 OOP_GetAttr(pf, aHidd_PixFmt_BitMapType, &bmtype);
403 switch (bmtype)
405 case vHidd_BitMapType_Chunky:
406 classptr = CSD(cl)->chunkybmclass;
407 break;
409 case vHidd_BitMapType_Planar:
410 classptr = CSD(cl)->planarbmclass;
411 break;
413 default:
414 D(bug("!!! Gfx::NewBitMap: UNKNOWN BITMAPTYPE %d !!!\n", bmtype));
415 return NULL;
419 } /* if (!gotclass) */
421 /* Set the tags we want to pass to the selected bitmap class */
422 SET_BM_TAG(bmtags, 2, Width, width);
423 SET_BM_TAG(bmtags, 3, Height, height);
424 SET_BM_TAG(bmtags, 4, PixFmt, pf);
426 if (GOT_BM_ATTR(Friend))
428 SET_BM_TAG(bmtags, 5, Friend, attrs[BMAO(Friend)]);
430 else
432 SET_TAG(bmtags, 5, TAG_IGNORE, 0UL);
434 SET_TAG(bmtags, 6, TAG_MORE, msg->attrList);
436 } /* if (!displayable) */
439 bm = OOP_NewObject(classptr, classid, bmtags);
441 if (framebuffer)
442 data->framebuffer = bm;
444 return bm;
448 /****************************************************************************************/
450 VOID GFX__Hidd_Gfx__DisposeBitMap(OOP_Class *cl, OOP_Object *o,
451 struct pHidd_Gfx_DisposeBitMap *msg)
453 if (NULL != msg->bitMap)
454 OOP_DisposeObject(msg->bitMap);
457 /****************************************************************************************/
459 #define SD(x) ((struct sync_data *)x)
460 #define PF(x) ((HIDDT_PixelFormat *)x)
462 #define XCOORD_TO_BYTEIDX(x) ( (x) >> 3)
463 #define COORD_TO_BYTEIDX(x, y, bpr) ( ( (y) * bpr ) + XCOORD_TO_BYTEIDX(x) )
464 #define XCOORD_TO_MASK(x) (1L << (7 - ((x) & 0x07) ))
465 #define WIDTH_TO_BYTES(width) ( (( (width) - 1) >> 3) + 1)
467 /****************************************************************************************/
469 /* modebm functions pfidx is x and syncidx is y coord in the bitmap */
471 /****************************************************************************************/
473 static inline BOOL alloc_mode_bm(struct mode_bm *bm, ULONG numsyncs, ULONG numpfs,
474 OOP_Class *cl)
476 bm->bpr = WIDTH_TO_BYTES(numpfs);
478 bm->bm = AllocVec(bm->bpr * numsyncs, MEMF_CLEAR);
479 if (NULL == bm->bm)
480 return FALSE;
482 /* We initialize the mode bitmap to all modes valid */
483 memset(bm->bm, 0xFF, bm->bpr * numsyncs);
485 return TRUE;
488 /****************************************************************************************/
490 static inline VOID free_mode_bm(struct mode_bm *bm, OOP_Class *cl)
492 FreeVec(bm->bm);
493 bm->bm = NULL;
494 bm->bpr = 0;
497 /****************************************************************************************/
499 static inline BOOL is_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx)
501 if (0 != (XCOORD_TO_MASK(pfidx) & bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)]))
502 return TRUE;
504 return FALSE;
507 /****************************************************************************************/
509 static inline VOID set_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx,
510 BOOL valid)
512 if (valid)
513 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] |= XCOORD_TO_MASK(pfidx);
514 else
515 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] &= ~XCOORD_TO_MASK(pfidx);
517 return;
520 /****************************************************************************************/
522 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl)
524 BOOL ok = FALSE;
526 if (0 == numsyncs || 0 == numpfs)
527 return FALSE;
529 ObtainSemaphore(&mdb->sema);
530 /* free_mode_bm() needs this */
531 mdb->num_pixfmts = numpfs;
532 mdb->num_syncs = numsyncs;
534 mdb->syncs = AllocMem(sizeof (OOP_Object *) * numsyncs, MEMF_CLEAR);
536 if (NULL != mdb->syncs)
538 mdb->pixfmts = AllocMem(sizeof (OOP_Object *) * numpfs, MEMF_CLEAR);
540 if (NULL != mdb->pixfmts)
542 if (alloc_mode_bm(&mdb->orig_mode_bm, numsyncs, numpfs, cl))
544 if (alloc_mode_bm(&mdb->checked_mode_bm, numsyncs, numpfs, cl))
546 ok = TRUE;
552 if (!ok)
553 free_mode_db(mdb, cl);
555 ReleaseSemaphore(&mdb->sema);
557 return ok;
560 /****************************************************************************************/
562 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl)
564 ULONG i;
566 ObtainSemaphore(&mdb->sema);
568 if (NULL != mdb->pixfmts)
571 /****** !!! NB !!! The Pixel formats are registerd in the
572 GfxMode Database and is freed in the
573 free_object_list functions
575 for (i = 0; i < mdb->num_pixfmts; i ++)
577 if (NULL != mdb->pixfmts[i])
579 OOP_DisposeObject(mdb->pixfmts[i]);
580 mdb->pixfmts[i] = NULL;
585 FreeMem(mdb->pixfmts, sizeof (OOP_Object *) * mdb->num_pixfmts);
586 mdb->pixfmts = NULL; mdb->num_pixfmts = 0;
589 if (NULL != mdb->syncs)
591 for (i = 0; i < mdb->num_syncs; i ++)
593 if (NULL != mdb->syncs[i])
596 OOP_DisposeObject(mdb->syncs[i]);
597 mdb->syncs[i] = NULL;
601 FreeMem(mdb->syncs, sizeof (OOP_Object *) * mdb->num_syncs);
602 mdb->syncs = NULL; mdb->num_syncs = 0;
605 if (NULL != mdb->orig_mode_bm.bm)
607 free_mode_bm(&mdb->orig_mode_bm, cl);
610 if (NULL != mdb->checked_mode_bm.bm)
612 free_mode_bm(&mdb->checked_mode_bm, cl);
615 ReleaseSemaphore(&mdb->sema);
617 return;
620 /****************************************************************************************/
622 /* Initializes default tagarray. in numtags the TAG_MORE is not accounted for,
623 so the array must be of size NUM_TAGS + 1
626 /****************************************************************************************/
628 static VOID init_def_tags(struct TagItem *tags, ULONG numtags)
630 ULONG i;
632 for (i = 0; i < numtags; i ++)
634 tags[i].ti_Tag = TAG_IGNORE;
635 tags[i].ti_Data = 0UL;
638 tags[i].ti_Tag = TAG_MORE;
639 tags[i].ti_Data = 0UL;
641 return;
644 /****************************************************************************************/
646 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags)
648 struct TagItem *tag, *tstate;
649 struct HIDDGraphicsData *data;
651 DECLARE_ATTRCHECK(sync);
653 struct mode_db *mdb;
655 HIDDT_PixelFormat pixfmt_data;
656 struct sync_data sync_data;
658 struct TagItem def_sync_tags[num_Hidd_Sync_Attrs + 1];
659 struct TagItem def_pixfmt_tags[num_Hidd_PixFmt_Attrs + 1];
661 ULONG numpfs = 0,numsyncs = 0;
662 ULONG pfidx = 0, syncidx = 0;
664 data = OOP_INST_DATA(cl, o);
665 mdb = &data->mdb;
666 InitSemaphore(&mdb->sema);
668 memset(&pixfmt_data, 0, sizeof (pixfmt_data));
669 memset(&sync_data, 0, sizeof (sync_data));
671 init_def_tags(def_sync_tags, num_Hidd_Sync_Attrs);
672 init_def_tags(def_pixfmt_tags, num_Hidd_PixFmt_Attrs);
674 /* First we need to calculate how much memory we are to allocate by counting supplied
675 pixel formats and syncs */
677 for (tstate = modetags; (tag = NextTagItem((const struct TagItem **)&tstate));)
679 ULONG idx;
681 if (IS_GFX_ATTR(tag->ti_Tag, idx))
683 switch (idx)
685 case aoHidd_Gfx_PixFmtTags:
686 numpfs++;
687 break;
689 case aoHidd_Gfx_SyncTags:
690 numsyncs ++;
691 break;
693 default:
694 break;
699 if (0 == numpfs || 0 == numsyncs)
701 D(bug("!!! WE MUST AT LEAST HAVE ONE PIXFMT AND ONE SYNC IN Gfx::RegisterModes() !!!\n"));
704 ObtainSemaphore(&mdb->sema);
706 /* Allocate memory for mode db */
707 if (!alloc_mode_db(&data->mdb, numsyncs, numpfs, cl))
708 goto failure;
711 for (tstate = modetags; (tag = NextTagItem((const struct TagItem **)&tstate));)
713 /* Look for Gfx, PixFmt and Sync tags */
714 ULONG idx;
716 if (IS_GFX_ATTR(tag->ti_Tag, idx))
718 switch (idx)
720 case aoHidd_Gfx_PixFmtTags:
721 def_pixfmt_tags[num_Hidd_PixFmt_Attrs].ti_Data = tag->ti_Data;
722 mdb->pixfmts[pfidx] = HIDD_Gfx_RegisterPixFmt(o, def_pixfmt_tags);
724 if (NULL == mdb->pixfmts[pfidx])
726 D(bug("!!! UNABLE TO CREATE PIXFMT OBJECT IN Gfx::RegisterModes() !!!\n"));
727 goto failure;
730 pfidx ++;
731 break;
733 case aoHidd_Gfx_SyncTags:
734 def_sync_tags[num_Hidd_Sync_Attrs].ti_Data = tag->ti_Data;
735 if (!parse_sync_tags(def_sync_tags
736 , &sync_data
737 , ATTRCHECK(sync)
738 , CSD(cl) ))
740 D(bug("!!! ERROR PARSING SYNC TAGS IN Gfx::RegisterModes() !!!\n"));
741 goto failure;
743 else
745 mdb->syncs[syncidx] = create_and_init_object(CSD(cl)->syncclass
746 , (UBYTE *)&sync_data
747 , sizeof (sync_data)
748 , CSD(cl) );
750 if (NULL == mdb->syncs[syncidx])
752 D(bug("!!! UNABLE TO CREATE PIXFMT OBJECT IN Gfx::RegisterModes() !!!\n"));
753 goto failure;
755 syncidx ++;
757 break;
761 else if (IS_SYNC_ATTR(tag->ti_Tag, idx))
763 if (idx >= num_Hidd_Sync_Attrs)
765 D(bug("!!! UNKNOWN SYNC ATTR IN Gfx::New(): %d !!!\n", idx));
767 else
769 def_sync_tags[idx].ti_Tag = tag->ti_Tag;
770 def_sync_tags[idx].ti_Data = tag->ti_Data;
774 else if (IS_PIXFMT_ATTR(tag->ti_Tag, idx))
776 if (idx >= num_Hidd_PixFmt_Attrs)
778 D(bug("!!! UNKNOWN PIXFMT ATTR IN Gfx::New(): %d !!!\n", idx));
780 else
782 def_pixfmt_tags[idx].ti_Tag = tag->ti_Tag;
783 def_pixfmt_tags[idx].ti_Data = tag->ti_Data;
788 ReleaseSemaphore(&mdb->sema);
790 return TRUE;
792 failure:
794 /* mode db is freed in dispose */
795 ReleaseSemaphore(&mdb->sema);
797 return FALSE;
800 /****************************************************************************************/
802 struct modequery
804 struct mode_db *mdb;
805 ULONG minwidth;
806 ULONG maxwidth;
807 ULONG minheight;
808 ULONG maxheight;
809 HIDDT_StdPixFmt *stdpfs;
810 ULONG numfound;
811 ULONG pfidx;
812 ULONG syncidx;
813 BOOL dims_ok;
814 BOOL stdpfs_ok;
815 BOOL check_ok;
816 OOP_Class *cl;
819 /****************************************************************************************/
821 /* This is a recursive function that looks for valid modes */
823 /****************************************************************************************/
825 static HIDDT_ModeID *querymode(struct modequery *mq)
827 HIDDT_ModeID *modeids;
828 register OOP_Object *pf;
829 register OOP_Object *sync;
830 BOOL mode_ok = FALSE;
831 OOP_Class *cl = mq->cl;
832 ULONG syncidx, pfidx;
834 mq->dims_ok = FALSE;
835 mq->stdpfs_ok = FALSE;
836 mq->check_ok = FALSE;
838 /* Look at the supplied idx */
839 if (mq->pfidx >= mq->mdb->num_pixfmts)
841 mq->pfidx = 0;
842 mq->syncidx ++;
845 if (mq->syncidx >= mq->mdb->num_syncs)
847 /* We have reached the end of the recursion. Allocate memory and go back
850 modeids = AllocVec(sizeof (HIDDT_ModeID) * (mq->numfound + 1), MEMF_ANY);
851 /* Get the end of the array */
852 modeids += mq->numfound;
853 *modeids = vHidd_ModeID_Invalid;
855 return modeids;
858 syncidx = mq->syncidx;
859 pfidx = mq->pfidx;
860 /* Get the pf and sync objects */
861 pf = mq->mdb->pixfmts[syncidx];
862 sync = mq->mdb->syncs[pfidx];
865 /* Check that the mode is really usable */
866 if (is_valid_mode(&mq->mdb->checked_mode_bm, syncidx, pfidx))
868 mq->check_ok = TRUE;
871 /* See if this mode matches the criterias set */
873 if ( SD(sync)->hdisp >= mq->minwidth
874 && SD(sync)->hdisp <= mq->maxwidth
875 && SD(sync)->vdisp >= mq->minheight
876 && SD(sync)->vdisp <= mq->maxheight )
880 mq->dims_ok = TRUE;
882 if (NULL != mq->stdpfs)
884 register HIDDT_StdPixFmt *stdpf = mq->stdpfs;
885 while (*stdpf)
887 if (*stdpf == PF(pf)->stdpixfmt)
889 mq->stdpfs_ok = TRUE;
891 stdpf ++;
894 else
896 mq->stdpfs_ok = TRUE;
902 if (mq->dims_ok && mq->stdpfs_ok && mq->check_ok)
904 mode_ok = TRUE;
905 mq->numfound ++;
908 mq->pfidx ++;
910 modeids = querymode(mq);
912 if (NULL == modeids)
913 return NULL;
915 if (mode_ok)
917 /* The mode is OK. Add it to the list */
918 modeids --;
919 *modeids = COMPUTE_HIDD_MODEID(syncidx, pfidx);
922 return modeids;
926 /****************************************************************************************/
928 HIDDT_ModeID *GFX__Hidd_Gfx__QueryModeIDs(OOP_Class *cl, OOP_Object *o,
929 struct pHidd_Gfx_QueryModeIDs *msg)
931 struct TagItem *tag, *tstate;
933 HIDDT_ModeID *modeids;
934 struct HIDDGraphicsData *data;
935 struct mode_db *mdb;
937 struct modequery mq =
939 NULL, /* mode db (set later) */
940 0, 0xFFFFFFFF, /* minwidth, maxwidth */
941 0, 0xFFFFFFFF, /* minheight, maxheight */
942 NULL, /* stdpfs */
943 0, /* numfound */
944 0, 0, /* pfidx, syncidx */
945 FALSE, FALSE, /* dims_ok, stdpfs_ok */
946 FALSE, /* check_ok */
947 NULL /* class (set later) */
952 data = OOP_INST_DATA(cl, o);
953 mdb = &data->mdb;
954 mq.mdb = mdb;
955 mq.cl = cl;
957 for (tstate = msg->queryTags; (tag = NextTagItem((const struct TagItem **)&tstate)); )
959 switch (tag->ti_Tag)
961 case tHidd_GfxMode_MinWidth:
962 mq.minwidth = (ULONG)tag->ti_Tag;
963 break;
965 case tHidd_GfxMode_MaxWidth:
966 mq.maxwidth = (ULONG)tag->ti_Tag;
967 break;
969 case tHidd_GfxMode_MinHeight:
970 mq.minheight = (ULONG)tag->ti_Tag;
971 break;
973 case tHidd_GfxMode_MaxHeight:
974 mq.maxheight = (ULONG)tag->ti_Tag;
975 break;
977 case tHidd_GfxMode_PixFmts:
978 mq.stdpfs = (HIDDT_StdPixFmt *)tag->ti_Data;
979 break;
984 ObtainSemaphoreShared(&mdb->sema);
986 /* Recursively check all modes */
987 modeids = querymode(&mq);
989 ReleaseSemaphore(&mdb->sema);
991 return modeids;
995 /****************************************************************************************/
997 VOID GFX__Hidd_Gfx__ReleaseModeIDs(OOP_Class *cl, OOP_Object *o,
998 struct pHidd_Gfx_ReleaseModeIDs *msg)
1000 FreeVec(msg->modeIDs);
1003 /****************************************************************************************/
1005 HIDDT_ModeID GFX__Hidd_Gfx__NextModeID(OOP_Class *cl, OOP_Object *o,
1006 struct pHidd_Gfx_NextModeID *msg)
1008 struct HIDDGraphicsData *data;
1009 struct mode_db *mdb;
1010 ULONG syncidx, pfidx;
1011 HIDDT_ModeID return_id = vHidd_ModeID_Invalid;
1012 BOOL found = FALSE;
1014 data = OOP_INST_DATA(cl, o);
1015 mdb = &data->mdb;
1017 ObtainSemaphoreShared(&mdb->sema);
1018 if (vHidd_ModeID_Invalid == msg->modeID)
1020 pfidx = 0;
1021 syncidx = 0;
1023 else
1025 pfidx = MODEID_TO_PFIDX( msg->modeID );
1026 syncidx = MODEID_TO_SYNCIDX( msg->modeID );
1028 /* Increament one from the last call */
1029 pfidx ++;
1030 if (pfidx >= mdb->num_pixfmts)
1032 pfidx = 0;
1033 syncidx ++;
1037 /* Search for a new mode. We only accept valid modes */
1038 for (; syncidx < mdb->num_syncs; syncidx ++)
1040 /* We only return valid modes */
1041 for (; pfidx < mdb->num_pixfmts; pfidx ++)
1043 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
1045 found = TRUE;
1046 break;
1049 if (found)
1050 break;
1053 if (found)
1055 return_id = COMPUTE_HIDD_MODEID(syncidx, pfidx);
1056 *msg->syncPtr = mdb->syncs[syncidx];
1057 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
1059 else
1061 *msg->syncPtr = *msg->pixFmtPtr = NULL;
1064 ReleaseSemaphore(&mdb->sema);
1066 return return_id;
1069 /****************************************************************************************/
1071 BOOL GFX__Hidd_Gfx__GetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMode *msg)
1073 ULONG pfidx, syncidx;
1074 struct HIDDGraphicsData *data;
1075 struct mode_db *mdb;
1076 BOOL ok = FALSE;
1078 data = OOP_INST_DATA(cl, o);
1079 mdb = &data->mdb;
1081 pfidx = MODEID_TO_PFIDX(msg->modeID);
1082 syncidx = MODEID_TO_SYNCIDX(msg->modeID);
1084 ObtainSemaphoreShared(&mdb->sema);
1086 if (! (pfidx >= mdb->num_pixfmts || syncidx >= mdb->num_syncs) )
1088 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
1090 ok = TRUE;
1091 *msg->syncPtr = mdb->syncs[syncidx];
1092 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
1096 ReleaseSemaphore(&mdb->sema);
1098 if (!ok)
1100 *msg->syncPtr = *msg->pixFmtPtr = NULL;
1103 return ok;
1106 /****************************************************************************************/
1108 BOOL GFX__Hidd_Gfx__SetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetMode *msg)
1110 #if 0
1111 struct HIDDGraphicsData *data;
1112 OOP_Object *sync, *pf;
1114 data = OOP_INST_DATA(cl, o);
1116 /* Check if we have a valid modeid */
1117 if (HIDD_Gfx_GetMode(o, msg->modeID, &sync, &pf))
1120 /* Mode exists. */
1121 curmode = msg->modeID;
1123 /* Do we have a framebuffer yet ? */
1124 if (NULL == data->framebuffer)
1126 /* No framebuffer. We should init one. */
1128 else
1130 /* Framebuffer created. Check if framebuffer is large enough
1131 for mode. */
1137 #endif
1138 return FALSE;
1141 /****************************************************************************************/
1143 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm,
1144 OOP_Object *dst_bm, OOP_Object *dims_bm)
1146 struct TagItem gctags[] =
1148 { aHidd_GC_DrawMode , vHidd_GC_DrawMode_Copy},
1149 { TAG_DONE , 0UL }
1151 struct HIDDGraphicsData *data;
1152 IPTR width, height;
1153 ULONG i;
1154 IPTR numentries;
1155 OOP_Object *src_colmap;
1156 APTR psrc_colmap = &src_colmap;
1158 data = OOP_INST_DATA(cl, o);
1160 /* Copy the displayable bitmap into the framebuffer */
1161 OOP_GetAttr(dims_bm, aHidd_BitMap_Width, &width);
1162 OOP_GetAttr(dims_bm, aHidd_BitMap_Height, &height);
1164 /* We have to copy the colormap into the framebuffer bitmap */
1165 OOP_GetAttr(src_bm, aHidd_BitMap_ColorMap, (IPTR *)psrc_colmap);
1166 OOP_GetAttr(src_colmap, aHidd_ColorMap_NumEntries, &numentries);
1168 for (i = 0; i < numentries; i ++)
1170 HIDDT_Color col;
1172 HIDD_CM_GetColor(src_colmap, i, &col);
1173 HIDD_BM_SetColors(dst_bm, &col, i, 1);
1177 OOP_SetAttrs(data->gc, gctags);
1178 HIDD_Gfx_CopyBox(o
1179 , src_bm
1180 , 0, 0
1181 , dst_bm
1182 , 0, 0
1183 , width, height
1184 , data->gc
1188 /****************************************************************************************/
1190 OOP_Object *GFX__Hidd_Gfx__Show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
1192 struct HIDDGraphicsData *data;
1193 OOP_Object *bm;
1194 IPTR displayable;
1196 data = OOP_INST_DATA(cl, o);
1197 bm = msg->bitMap;
1199 /* We have to do some consistency checking */
1200 if (bm)
1202 OOP_GetAttr(bm, aHidd_BitMap_Displayable, &displayable);
1205 if (bm && !displayable)
1206 /* We cannot show a non-displayable bitmap */
1207 return NULL;
1209 if (NULL == data->framebuffer)
1210 return NULL;
1212 if (NULL != data->shownbm && (msg->flags & fHidd_Gfx_Show_CopyBack))
1214 /* Copy the framebuffer data back into the old shown bitmap */
1215 copy_bm_and_colmap(cl, o, data->framebuffer, data->shownbm, data->shownbm);
1218 if (bm)
1220 copy_bm_and_colmap(cl, o, bm, data->framebuffer, bm);
1222 else
1224 #warning should clear framebuffer to black
1226 data->shownbm = bm;
1228 return data->framebuffer;
1231 /****************************************************************************************/
1233 BOOL GFX__Hidd_Gfx__SetCursorShape(OOP_Class *cl, OOP_Object *o,
1234 struct pHidd_Gfx_SetCursorShape *msg)
1236 /* We have no clue how to render the cursor */
1237 return TRUE;
1240 /****************************************************************************************/
1242 BOOL GFX__Hidd_Gfx__SetCursorVisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
1244 return TRUE;
1247 /****************************************************************************************/
1249 BOOL GFX__Hidd_Gfx__SetCursorPos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
1251 return TRUE;
1254 /*****************************************************************************************
1256 HIDDGfx::CopyBox()
1258 NAME
1259 CopyBox
1261 SYNOPSIS
1262 OOP_DoMethod(src, WORD srcX, WORD srcY,
1263 OOP_Object *dest, WORD destX, WORD destY,
1264 UWORD sizeX, UWORD sizeY);
1266 FUNCTION
1267 Copy a rectangular area from the drawing area src to the drawing
1268 area stored in dest (which may be src). The source area is not
1269 changed (except when both rectangles overlap). The mode of the GC
1270 dest determines how the copy takes place.
1272 In quick mode, the following restrictions are not checked: It's not
1273 checked whether the source or destination rectangle is completely
1274 inside the valid area or whether the areas overlap. If they
1275 overlap, the results are unpredictable. Also drawing modes are
1276 ignored. If the two bitmaps in the GCs have a different depth,
1277 copying might be slow.
1279 When copying bitmaps between two different HIDDs, the following
1280 pseudo algorithm is executed: First the destination HIDD is queried
1281 whether it does understand the format of the source HIDD. If it
1282 does, then the destination HIDD does the copying. If it doesn't,
1283 then the source is asked whether it understands the destination
1284 HIDDs' format. If it does, then the source HIDD will do the
1285 copying. If it doesn't, then the default CopyArea of the graphics
1286 HIDD base class will be invoked which copies the bitmaps pixel by
1287 pixel with BitMap::GetPixel() and BitMap::DrawPixel().
1289 INPUTS
1290 src - source bitmap object
1291 srcX, srcY - upper, left corner of the area to copy in the source
1292 dest - destination bitmap object
1293 destX, destY - upper, left corner in the destination to copy the area
1294 width, height - width and height of the area in hidd units
1296 RESULT
1298 NOTES
1300 EXAMPLE
1302 BUGS
1304 SEE ALSO
1305 GROUP=HIDD_BltBitMap
1307 INTERNALS
1309 TODO
1311 HISTORY
1313 *****************************************************************************************/
1315 VOID GFX__Hidd_Gfx__CopyBox(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg)
1317 WORD x, y;
1318 WORD srcX = msg->srcX, destX = msg->destX;
1319 WORD srcY = msg->srcY, destY = msg->destY;
1320 WORD startX, endX, deltaX, startY, endY, deltaY;
1321 ULONG memFG;
1323 HIDDT_PixelFormat *srcpf, *dstpf;
1324 OOP_Object *dest, *src;
1326 OOP_Object *gc;
1327 #if USE_FAST_GETPIXEL
1328 struct pHidd_BitMap_GetPixel get_p;
1329 #endif
1331 #if USE_FAST_DRAWPIXEL
1332 struct pHidd_BitMap_DrawPixel draw_p;
1334 draw_p.mID = CSD(cl)->drawpixel_mid;
1335 draw_p.gc = msg->gc;
1336 #endif
1338 #if USE_FAST_GETPIXEL
1339 get_p.mID = CSD(cl)->getpixel_mid;
1340 #endif
1342 dest = msg->dest;
1343 src = msg->src;
1345 /* If source/dest overlap, direction of operation is important */
1347 if (srcX < destX)
1349 startX = msg->width - 1; endX = -1; deltaX = -1;
1351 else
1353 startX = 0; endX = msg->width; deltaX = 1;
1356 if (srcY < destY)
1358 startY = msg->height - 1; endY = -1; deltaY = -1;
1360 else
1362 startY = 0; endY = msg->height; deltaY = 1;
1365 /* Get the source pixel format */
1366 srcpf = (HIDDT_PixelFormat *)HBM(src)->prot.pixfmt;
1368 /* bug("COPYBOX: SRC PF: %p, obj=%p, cl=%s, OOP_OCLASS: %s\n", srcpf, obj
1369 , cl->ClassNode.ln_Name, OOP_OCLASS(obj)->ClassNode.ln_Name);
1372 #if 0
1374 IPTR sw, sh, dw, dh;
1375 D(bug("COPYBOX: src=%p, dst=%p, width=%d, height=%d\n"
1376 , obj, msg->dest, msg->width, msg->height));
1378 OOP_GetAttr(obj, aHidd_BitMap_Width, &sw);
1379 OOP_GetAttr(obj, aHidd_BitMap_Height, &sh);
1380 OOP_GetAttr(msg->dest, aHidd_BitMap_Width, &dw);
1381 OOP_GetAttr(msg->dest, aHidd_BitMap_Height, &dh);
1382 D(bug("src dims: %d, %d dest dims: %d, %d\n", sw, sh, dw, dh));
1384 #endif
1386 dstpf = (HIDDT_PixelFormat *)HBM(dest)->prot.pixfmt;
1388 /* Compare graphtypes */
1389 if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf))
1391 /* It is ok to do a direct copy */
1393 else
1395 /* Find out the gfx formats */
1396 if ( IS_PALETTIZED(srcpf) && IS_TRUECOLOR(dstpf))
1400 else if (IS_TRUECOLOR(srcpf) && IS_PALETTIZED(dstpf))
1404 else if (IS_PALETTE(srcpf) && IS_STATICPALETTE(dstpf))
1408 else if (IS_STATICPALETTE(srcpf) && IS_PALETTE(dstpf))
1414 gc = msg->gc;
1416 memFG = GC_FG(msg->gc);
1418 /* All else have failed, copy pixel by pixel */
1421 if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf))
1423 if (IS_TRUECOLOR(srcpf))
1425 // bug("COPY FROM TRUECOLOR TO TRUECOLOR\n");
1426 for(y = startY; y != endY; y += deltaY)
1428 HIDDT_Color col;
1430 /* if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
1431 bug("[%d,%d] ", memSrcX, memDestX);
1433 for(x = startX; x != endX; x += deltaX)
1435 HIDDT_Pixel pix;
1437 #if USE_FAST_GETPIXEL
1438 get_p.x = srcX + x;
1439 get_p.y = srcY + y;
1440 pix = GETPIXEL(src, &get_p);
1441 #else
1442 pix = HIDD_BM_GetPixel(obj, srcX + x, srcY + y);
1443 #endif
1445 #if COPYBOX_CHECK_FOR_ALIKE_PIXFMT
1446 if (srcpf == dstpf)
1448 GC_FG(gc) = pix;
1450 else
1452 #endif
1453 HIDD_BM_UnmapPixel(src, pix, &col);
1454 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, &col);
1455 #if COPYBOX_CHECK_FOR_ALIKE_PIXFMT
1457 #endif
1459 // #if 0
1461 #if USE_FAST_DRAWPIXEL
1462 draw_p.x = destX + x;
1463 draw_p.y = destY + y;
1464 DRAWPIXEL(dest, &draw_p);
1465 #else
1467 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
1468 #endif
1470 // #endif
1472 /*if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
1473 bug("[%d,%d] ", srcY, destY);
1477 } /* if (IS_TRUECOLOR(srcpf)) */
1478 else
1480 /* Two palette bitmaps.
1481 For this case we do NOT convert through RGB,
1482 but copy the pixel indexes directly
1484 // bug("COPY FROM PALETTE TO PALETTE\n");
1486 #warning This might not work very well with two StaticPalette bitmaps
1488 for(y = startY; y != endY; y += deltaY)
1490 for(x = startX; x != endX; x += deltaX)
1492 GC_FG(gc) = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
1494 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
1499 } /* if (IS_TRUECOLOR(srcpf)) else ... */
1501 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) */
1502 else
1504 /* Two unlike bitmaps */
1505 if (IS_TRUECOLOR(srcpf))
1507 #warning Implement this
1508 D(bug("!! DEFAULT COPYING FROM TRUECOLOR TO PALETTIZED NOT IMPLEMENTED IN BitMap::CopyBox\n"));
1510 else if (IS_TRUECOLOR(dstpf))
1512 /* Get the colortab */
1513 HIDDT_Color *ctab = ((HIDDT_ColorLUT *)HBM(src)->colmap)->colors;
1515 // bug("COPY FROM PALETTE TO TRUECOLOR, DRAWMODE %d, CTAB %p\n", GC_DRMD(gc), ctab);
1517 for(y = startY; y != endY; y += deltaY)
1519 for(x = startX; x != endX; x += deltaX)
1521 register HIDDT_Pixel pix;
1522 register HIDDT_Color *col;
1524 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
1525 col = &ctab[pix];
1527 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, col);
1528 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
1534 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) else ... */
1536 GC_FG(gc) = memFG;
1539 /****************************************************************************************/
1541 VOID GFX__Hidd_Gfx__ShowImminentReset(OOP_Class *cl, OOP_Object *obj, OOP_Msg msg)
1545 /****************************************************************************************/
1547 OOP_Object *GFX__Hidd_Gfx__RegisterPixFmt(OOP_Class *cl, OOP_Object *o,
1548 struct pHidd_Gfx_RegisterPixFmt *msg)
1550 HIDDT_PixelFormat cmp_pf;
1551 struct HIDDGraphicsData *data;
1553 struct pfnode *pfnode;
1555 OOP_Object *retpf = NULL;
1557 memset(&cmp_pf, 0, sizeof(cmp_pf));
1559 data = OOP_INST_DATA(cl, o);
1560 if (!parse_pixfmt_tags(msg->pixFmtTags, &cmp_pf, 0, CSD(cl)))
1562 D(bug("!!! FAILED PARSING TAGS IN Gfx::RegisterPixFmt() !!!\n"));
1563 return FALSE;
1566 ObtainSemaphoreShared(&data->pfsema);
1567 pfnode = find_pixfmt(&data->pflist, &cmp_pf, CSD(cl));
1568 ReleaseSemaphore(&data->pfsema);
1570 if (NULL == pfnode)
1572 retpf = find_stdpixfmt(&cmp_pf, CSD(cl));
1574 else
1576 retpf = pfnode->pixfmt;
1577 /* Increase pf refcount */
1578 pfnode->refcount ++;
1582 if (NULL == retpf)
1584 struct pfnode *newnode;
1585 /* Could not find an alike pf, Create a new pfdb node */
1587 newnode = AllocMem(sizeof (struct pfnode), MEMF_ANY);
1588 if (NULL != newnode)
1591 /* Since we pass NULL as the taglist below, the PixFmt class will just create a dummy pixfmt */
1592 retpf = OOP_NewObject(CSD(cl)->pixfmtclass, NULL, NULL);
1593 if (NULL != retpf)
1595 newnode->pixfmt = retpf;
1597 /* We have one user */
1598 newnode->refcount = 1;
1600 /* Initialize the pixfmt object the "ugly" way */
1601 cmp_pf.stdpixfmt = vHidd_StdPixFmt_Unknown;
1602 memcpy(retpf, &cmp_pf, sizeof (HIDDT_PixelFormat));
1604 #define PF(x) ((HIDDT_PixelFormat *)x)
1606 bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
1607 , PF(&cmp_pf)->red_shift
1608 , PF(&cmp_pf)->green_shift
1609 , PF(&cmp_pf)->blue_shift
1610 , PF(&cmp_pf)->alpha_shift
1611 , PF(&cmp_pf)->red_mask
1612 , PF(&cmp_pf)->green_mask
1613 , PF(&cmp_pf)->blue_mask
1614 , PF(&cmp_pf)->alpha_mask
1615 , PF(&cmp_pf)->bytes_per_pixel
1616 , PF(&cmp_pf)->size
1617 , PF(&cmp_pf)->depth
1618 , PF(&cmp_pf)->stdpixfmt
1619 , HIDD_BP_BITMAPTYPE(&cmp_pf));
1623 ObtainSemaphore(&data->pfsema);
1624 AddTail((struct List *)&data->pflist, (struct Node *)newnode);
1625 ReleaseSemaphore(&data->pfsema);
1628 else
1630 FreeMem(newnode, sizeof (struct pfnode));
1636 return retpf;
1640 /****************************************************************************************/
1642 VOID GFX__Hidd_Gfx__ReleasePixFmt(OOP_Class *cl, OOP_Object *o,
1643 struct pHidd_Gfx_ReleasePixFmt *msg)
1645 struct HIDDGraphicsData *data;
1647 struct objectnode *n, *safe;
1650 /* bug("release_pixfmt\n");
1653 data = OOP_INST_DATA(cl, o);
1655 /* Go through the pixfmt list trying to find the object */
1656 ObtainSemaphore(&data->pfsema);
1658 ForeachNodeSafe(&data->pflist, n, safe)
1660 if (msg->pixFmt == n->object)
1662 n->refcount --;
1663 if (0 == n->refcount)
1665 /* Remove the node */
1666 Remove((struct Node *)n);
1668 /* Dispose the pixel format */
1669 OOP_DisposeObject(n->object);
1671 /* Free the node */
1672 FreeMem(n, sizeof (struct objectnode));
1675 break;
1679 ReleaseSemaphore(&data->pfsema);
1682 /*****************************************************************************************
1684 Gfx::CheckMode()
1686 This is a method which should be implemented by the subclasses.
1687 It should look at the supplied pixfmt and sync and see if it is valid.
1688 This will handle any special cases that are not covered by the
1689 pixfmts/syncs supplied in HIDD_Gfx_RegisterModes().
1690 For example some advanced modes, like 1024x768x24 @ 90 might not be available
1691 because of lack of bandwidth in the gfx hw.
1693 *****************************************************************************************/
1695 BOOL GFX__Hidd_Gfx__CheckMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CheckMode *msg)
1697 /* As a default we allways return TRUE, ie. the mode is OK */
1698 return TRUE;
1701 /****************************************************************************************/
1703 OOP_Object *GFX__Hidd_Gfx__GetPixFmt(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg)
1705 OOP_Object *fmt;
1707 if (!IS_REAL_STDPIXFMT(msg->stdPixFmt))
1709 D(bug("!!! Illegal pixel format passed to Gfx::GetPixFmt(): %d\n", msg->stdPixFmt));
1710 return NULL;
1712 else
1714 fmt = CSD(cl)->std_pixfmts[REAL_STDPIXFMT_IDX(msg->stdPixFmt)];
1717 return fmt;
1720 /****************************************************************************************/
1722 #undef csd
1724 /****************************************************************************************/
1726 static int GFX_ClassInit(LIBBASETYPEPTR LIBBASE)
1728 struct class_static_data *csd = &LIBBASE->hdg_csd;
1730 __IHidd_PixFmt = OOP_ObtainAttrBase(IID_Hidd_PixFmt);
1731 __IHidd_BitMap = OOP_ObtainAttrBase(IID_Hidd_BitMap);
1732 __IHidd_Gfx = OOP_ObtainAttrBase(IID_Hidd_Gfx);
1733 __IHidd_Sync = OOP_ObtainAttrBase(IID_Hidd_Sync);
1734 __IHidd_GC = OOP_ObtainAttrBase(IID_Hidd_GC);
1735 __IHidd_ColorMap = OOP_ObtainAttrBase(IID_Hidd_ColorMap);
1736 __IHidd_PlanarBM = OOP_ObtainAttrBase(IID_Hidd_PlanarBM);
1738 if (!__IHidd_PixFmt ||
1739 !__IHidd_BitMap ||
1740 !__IHidd_Gfx ||
1741 !__IHidd_Sync ||
1742 !__IHidd_GC ||
1743 !__IHidd_ColorMap ||
1744 !__IHidd_PlanarBM
1747 goto failexit;
1750 D(bug("Creating std pixelfmts\n"));
1751 if (!create_std_pixfmts(csd))
1752 goto failexit;
1753 D(bug("Pixfmts created\n"));
1755 /* Get two methodis required for direct method execution */
1756 #if USE_FAST_PUTPIXEL
1757 csd->putpixel_mid = OOP_GetMethodID(IID_Hidd_BitMap, moHidd_BitMap_PutPixel);
1758 #endif
1759 #if USE_FAST_GETPIXEL
1760 csd->getpixel_mid = OOP_GetMethodID(IID_Hidd_BitMap, moHidd_BitMap_GetPixel);
1761 #endif
1762 #if USE_FAST_DRAWPIXEL
1763 csd->drawpixel_mid = OOP_GetMethodID(IID_Hidd_BitMap, moHidd_BitMap_DrawPixel);
1764 #endif
1766 ReturnInt("init_gfxhiddclass", ULONG, TRUE);
1768 failexit:
1769 ReturnPtr("init_gfxhiddclass", ULONG, FALSE);
1772 /****************************************************************************************/
1774 static int GFX_ClassFree(LIBBASETYPEPTR LIBBASE)
1776 struct class_static_data *csd = &LIBBASE->hdg_csd;
1778 EnterFunc(bug("free_gfxhiddclass(csd=%p)\n", csd));
1780 if(NULL != csd)
1782 delete_std_pixfmts(csd);
1784 OOP_ReleaseAttrBase(IID_Hidd_PixFmt);
1785 OOP_ReleaseAttrBase(IID_Hidd_BitMap);
1786 OOP_ReleaseAttrBase(IID_Hidd_Gfx);
1787 OOP_ReleaseAttrBase(IID_Hidd_Sync);
1788 OOP_ReleaseAttrBase(IID_Hidd_GC);
1789 OOP_ReleaseAttrBase(IID_Hidd_ColorMap);
1790 OOP_ReleaseAttrBase(IID_Hidd_PlanarBM);
1794 ReturnInt("free_gfxhiddclass", BOOL, TRUE);
1797 /****************************************************************************************/
1799 ADD2INITLIB(GFX_ClassInit, 0)
1800 ADD2EXPUNGELIB(GFX_ClassFree, 0)
1802 /****************************************************************************************/
1804 /* Since the shift/mask values of a pixel format are designed for pixel
1805 access, not byte access, they are endianess dependant */
1807 #if AROS_BIG_ENDIAN
1808 #include "stdpixfmts_be.h"
1809 #else
1810 #include "stdpixfmts_le.h"
1811 #endif
1813 /****************************************************************************************/
1815 static BOOL create_std_pixfmts(struct class_static_data *csd)
1817 ULONG i;
1819 memset(csd->std_pixfmts, 0, sizeof (OOP_Object *) * num_Hidd_StdPixFmt);
1821 for (i = 0; i < num_Hidd_StdPixFmt; i ++)
1823 csd->std_pixfmts[i] = create_and_init_object(csd->pixfmtclass
1824 , (UBYTE *)&stdpfs[i], sizeof (stdpfs[i]), csd);
1826 if (NULL == csd->std_pixfmts[i])
1828 D(bug("FAILED TO CREATE PIXEL FORMAT %d\n", i));
1829 delete_std_pixfmts(csd);
1830 ReturnBool("create_stdpixfmts", FALSE);
1833 ReturnBool("create_stdpixfmts", TRUE);
1837 /****************************************************************************************/
1839 static VOID delete_std_pixfmts(struct class_static_data *csd)
1841 ULONG i;
1843 for (i = 0; i < num_Hidd_StdPixFmt; i ++)
1846 if (NULL != csd->std_pixfmts[i])
1848 OOP_DisposeObject(csd->std_pixfmts[i]);
1849 csd->std_pixfmts[i] = NULL;
1854 /****************************************************************************************/
1856 static VOID free_objectlist(struct List *list, BOOL OOP_DisposeObjects,
1857 struct class_static_data *csd)
1859 struct objectnode *n, *safe;
1861 ForeachNodeSafe(list, n, safe)
1863 Remove(( struct Node *)n);
1865 if (NULL != n->object && OOP_DisposeObjects)
1867 OOP_DisposeObject(n->object);
1870 FreeMem(n, sizeof (struct objectnode));
1875 /****************************************************************************************/
1877 static inline BOOL cmp_pfs(HIDDT_PixelFormat *tmppf, HIDDT_PixelFormat *dbpf)
1879 if ( dbpf->depth == tmppf->depth
1880 && HIDD_PF_COLMODEL(dbpf) == HIDD_PF_COLMODEL(tmppf))
1882 /* The pixfmts are very alike, check all attrs */
1884 HIDDT_PixelFormat *old;
1886 old = (HIDDT_PixelFormat *)tmppf->stdpixfmt;
1888 tmppf->stdpixfmt = ((HIDDT_PixelFormat *)dbpf)->stdpixfmt;
1890 if (0 == memcmp(tmppf, dbpf, sizeof (HIDDT_PixelFormat)))
1892 return TRUE;
1895 tmppf->stdpixfmt = old;
1898 return FALSE;
1901 /****************************************************************************************/
1904 Matches the supplied pixelformat against all standard pixelformats
1905 to see if there allready exsts a pixelformat object for this pixelformat
1908 /****************************************************************************************/
1910 static OOP_Object *find_stdpixfmt(HIDDT_PixelFormat *tofind,
1911 struct class_static_data *csd)
1913 OOP_Object *retpf = NULL;
1914 OOP_Object *stdpf;
1915 ULONG i;
1917 for (i = 0; i < num_Hidd_StdPixFmt; i ++)
1919 stdpf = csd->std_pixfmts[i];
1921 if (cmp_pfs(tofind, (HIDDT_PixelFormat *)stdpf))
1923 retpf = stdpf;
1924 break;
1929 return retpf;
1932 /****************************************************************************************/
1935 Parses the tags supplied in 'tags' and puts the result into 'sync'.
1936 It also checks to see if all needed attrs are supplied.
1937 It uses 'attrcheck' for this, so you may find attrs outside
1938 of this function, and mark them as found before calling this function
1941 #define SYNC_AF(code) (1L << aoHidd_Sync_ ## code)
1942 #define SYAO(x) (aoHidd_Sync_ ## x)
1944 #define X11_SYNC_AF ( \
1945 SYNC_AF(HSyncStart) | SYNC_AF(HSyncEnd) | SYNC_AF(HTotal) \
1946 | SYNC_AF(VSyncStart) | SYNC_AF(VSyncEnd) | SYNC_AF(VTotal) )
1948 #define LINUXFB_SYNC_AF ( \
1949 SYNC_AF(LeftMargin) | SYNC_AF(RightMargin) | SYNC_AF(HSyncLength) \
1950 | SYNC_AF(UpperMargin) | SYNC_AF(LowerMargin) | SYNC_AF(VSyncLength) )
1952 #define SYNC_DISP_AF ( \
1953 SYNC_AF(HDisp) | SYNC_AF(VDisp) )
1955 /****************************************************************************************/
1957 BOOL parse_sync_tags(struct TagItem *tags, struct sync_data *data, ULONG ATTRCHECK(sync),
1958 struct class_static_data *csd)
1960 IPTR attrs[num_Hidd_Sync_Attrs];
1961 BOOL ok = FALSE;
1963 if (0 != OOP_ParseAttrs(tags, attrs, num_Hidd_Sync_Attrs, &ATTRCHECK(sync), HiddSyncAttrBase))
1965 D(bug("!!! parse_sync_tags: ERROR PARSING ATTRS !!!\n"));
1966 return FALSE;
1969 /* Check that we have all attrs */
1970 if (GOT_SYNC_ATTR(PixelTime))
1972 data->pixtime = attrs[SYAO(PixelTime)];
1974 else if (GOT_SYNC_ATTR(PixelClock))
1976 #if !AROS_BOCHS_HACK
1977 #if AROS_NOFPU
1978 #warning Write code for non-FPU!
1979 data->pixtime = 0x12345678;
1980 #else
1981 /* Something in there makes Bochs freeze */
1982 DOUBLE pixclock, pixtime;
1984 /* Compute the pixtime */
1985 pixclock =(DOUBLE)attrs[SYAO(PixelClock)];
1986 pixtime = 1 / pixclock;
1987 pixtime *= 1000000000000;
1988 data->pixtime = (ULONG)pixtime;
1989 #endif
1990 #else
1991 data->pixtime = 0x12345678;
1992 #endif
1994 else
1996 D(bug("!!! MISSING PIXELTIME/CLOCK ATTR !!!\n"));
1997 return FALSE;
2000 if (GOT_SYNC_ATTR(Description))
2002 strlcpy(data->description,
2003 (STRPTR)attrs[SYAO(Description)],
2004 sizeof(data->description));
2007 /* Check that we have HDisp and VDisp */
2008 if (SYNC_DISP_AF != (SYNC_DISP_AF & ATTRCHECK(sync)))
2010 D(bug("!!! MISSING HDISP OR VDISP ATTR !!!\n"));
2012 else
2014 data->hdisp = attrs[SYAO(HDisp)];
2015 data->vdisp = attrs[SYAO(VDisp)];
2017 /* Test that the user has not supplied both X11 style and fbdev style attrs */
2018 if ( (LINUXFB_SYNC_AF & ATTRCHECK(sync)) != 0 && (X11_SYNC_AF & ATTRCHECK(sync)) != 0 )
2020 D(bug("!!! BOTH LINUXFB-STYLE AND X11-STYLE ATTRS WERE SUPPLIED !!!\n"));
2021 D(bug("!!! YOU MAY ONLY SUPPLY ONE OF THEM !!!\n"));
2023 else
2026 /* Test that we have all attrs of either the X11 style or the Linux FB style */
2027 if ((LINUXFB_SYNC_AF & ATTRCHECK(sync)) == LINUXFB_SYNC_AF)
2029 /* Set the data struct */
2030 data->left_margin = attrs[SYAO(LeftMargin)];
2031 data->right_margin = attrs[SYAO(RightMargin)];
2032 data->hsync_length = attrs[SYAO(HSyncLength)];
2034 data->upper_margin = attrs[SYAO(UpperMargin)];
2035 data->lower_margin = attrs[SYAO(LowerMargin)];
2036 data->vsync_length = attrs[SYAO(VSyncLength)];
2037 ok = TRUE;
2040 else if ((X11_SYNC_AF & ATTRCHECK(sync)) == X11_SYNC_AF)
2042 ULONG hsync_start, hsync_end, htotal;
2043 ULONG vsync_start, vsync_end, vtotal;
2045 hsync_start = attrs[SYAO(HSyncStart)];
2046 hsync_end = attrs[SYAO(HSyncEnd)];
2047 htotal = attrs[SYAO(HTotal)];
2049 vsync_start = attrs[SYAO(VSyncStart)];
2050 vsync_end = attrs[SYAO(VSyncEnd)];
2051 vtotal = attrs[SYAO(VTotal)];
2053 data->left_margin = htotal - hsync_end;
2054 data->right_margin = hsync_start - data->hdisp;
2055 data->hsync_length = hsync_end - hsync_start;
2057 data->upper_margin = vtotal - vsync_end;
2058 data->lower_margin = vsync_start - data->vdisp;
2059 data->vsync_length = vsync_end - vsync_start;
2060 ok = TRUE;
2062 else
2064 D(bug("!!! UNSUFFICIENT ATTRS PASSED TO parse_sync_tags: %x !!!\n", ATTRCHECK(sync)));
2069 return ok;
2072 /****************************************************************************************/
2075 Parses the tags supplied in 'tags' and puts the result into 'pf'.
2076 It also checks to see if all needed attrs are supplied.
2077 It uses 'attrcheck' for this, so you may find attrs outside
2078 of this function, and mark them as found before calling this function
2081 #define PFAF(x) (1L << aoHidd_PixFmt_ ## x)
2082 #define PF_COMMON_AF ( PFAF(Depth) | PFAF(BitsPerPixel) | PFAF(BytesPerPixel) \
2083 | PFAF(ColorModel) | PFAF(BitMapType) )
2085 #define PF_TRUECOLOR_AF ( PFAF(RedMask) | PFAF(GreenMask) | PFAF(BlueMask) | PFAF(AlphaMask) | \
2086 PFAF(RedShift) | PFAF(GreenShift) | PFAF(BlueShift) | PFAF(AlphaShift))
2088 #define PF_PALETTE_AF ( PFAF(CLUTMask) | PFAF(CLUTShift) | PFAF(RedMask) | PFAF(GreenMask) | \
2089 PFAF(BlueMask) )
2091 #define PFAO(x) (aoHidd_PixFmt_ ## x)
2093 /****************************************************************************************/
2095 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf,
2096 ULONG ATTRCHECK(pixfmt), struct class_static_data *csd)
2098 IPTR attrs[num_Hidd_PixFmt_Attrs];
2100 if (0 != OOP_ParseAttrs(tags, attrs, num_Hidd_PixFmt_Attrs,
2101 &ATTRCHECK(pixfmt), HiddPixFmtAttrBase))
2103 D(bug("!!! parse_pixfmt_tags: ERROR PARSING TAGS THROUGH OOP_ParseAttrs !!!\n"));
2104 return FALSE;
2107 if (PF_COMMON_AF != (PF_COMMON_AF & ATTRCHECK(pixfmt)))
2109 D(bug("!!! parse_pixfmt_tags: Missing PixFmt attributes passed to parse_pixfmt_tags(): %x !!!\n", ATTRCHECK(pixfmt)));
2110 return FALSE;
2113 /* Set the common attributes */
2114 pf->depth = attrs[PFAO(Depth)];
2115 pf->size = attrs[PFAO(BitsPerPixel)];
2116 pf->bytes_per_pixel = attrs[PFAO(BytesPerPixel)];
2118 SET_PF_COLMODEL( pf, attrs[PFAO(ColorModel)]);
2119 SET_PF_BITMAPTYPE(pf, attrs[PFAO(BitMapType)]);
2121 if (ATTRCHECK(pixfmt) & PFAF(SwapPixelBytes))
2123 SET_PF_SWAPPIXELBYTES_FLAG(pf, attrs[PFAO(SwapPixelBytes)]);
2126 /* Set the colormodel specific stuff */
2127 switch (HIDD_PF_COLMODEL(pf))
2129 case vHidd_ColorModel_TrueColor:
2130 /* Check that we got all the truecolor describing stuff */
2131 if (PF_TRUECOLOR_AF != (PF_TRUECOLOR_AF & ATTRCHECK(pixfmt)))
2133 D(bug("!!! Unsufficient true color format describing attrs to pixfmt in parse_pixfmt_tags() !!!\n"));
2134 return FALSE;
2137 /* Set the truecolor stuff */
2138 pf->red_mask = attrs[PFAO(RedMask)];
2139 pf->green_mask = attrs[PFAO(GreenMask)];
2140 pf->blue_mask = attrs[PFAO(BlueMask)];
2141 pf->alpha_mask = attrs[PFAO(AlphaMask)];
2143 pf->red_shift = attrs[PFAO(RedShift)];
2144 pf->green_shift = attrs[PFAO(GreenShift)];
2145 pf->blue_shift = attrs[PFAO(BlueShift)];
2146 pf->alpha_shift = attrs[PFAO(AlphaShift)];
2147 break;
2149 case vHidd_ColorModel_Palette:
2150 case vHidd_ColorModel_StaticPalette:
2151 if ( PF_PALETTE_AF != (PF_PALETTE_AF & ATTRCHECK(pixfmt)))
2153 D(bug("!!! Unsufficient palette format describing attrs to pixfmt in parse_pixfmt_tags() !!!\n"));
2154 return FALSE;
2157 /* set palette stuff */
2158 pf->clut_mask = attrs[PFAO(CLUTMask)];
2159 pf->clut_shift = attrs[PFAO(CLUTShift)];
2161 pf->red_mask = attrs[PFAO(RedMask)];
2162 pf->green_mask = attrs[PFAO(GreenMask)];
2163 pf->blue_mask = attrs[PFAO(BlueMask)];
2165 break;
2167 } /* shift (colormodel) */
2169 return TRUE;
2172 /****************************************************************************************/
2175 Create an empty object and initialize it the "ugly" way. This only works with
2176 CLID_Hidd_PixFmt and CLID_Hidd_Sync classes
2179 /****************************************************************************************/
2181 static OOP_Object *create_and_init_object(OOP_Class *cl, UBYTE *data, ULONG datasize,
2182 struct class_static_data *csd)
2184 OOP_Object *o;
2186 o = OOP_NewObject(cl, NULL, NULL);
2187 if (NULL == o)
2189 D(bug("!!! UNABLE TO CREATE OBJECT IN create_and_init_object() !!!\n"));
2190 return NULL;
2193 memcpy(o, data, datasize);
2195 return o;
2198 /****************************************************************************************/
2200 static struct pfnode *find_pixfmt(struct MinList *pflist, HIDDT_PixelFormat *tofind,
2201 struct class_static_data *csd)
2203 OOP_Object *retpf = NULL;
2204 HIDDT_PixelFormat *db_pf;
2205 struct pfnode *n;
2207 /* Go through the pixel format list to see if a similar pf allready exists */
2208 ForeachNode(pflist, n)
2210 db_pf = (HIDDT_PixelFormat *)n->pixfmt;
2211 if (cmp_pfs(tofind, db_pf))
2213 retpf = (OOP_Object *)db_pf;
2214 break;
2218 if (NULL != retpf)
2219 return n;
2221 return NULL;
2224 /****************************************************************************************/
2226 /* Stubs for private methods */
2228 #ifndef AROS_CREATE_ROM
2229 # define STATIC_MID static OOP_MethodID mid
2230 #else
2231 # define STATIC_MID OOP_MethodID mid = 0
2232 #endif
2234 /****************************************************************************************/
2236 OOP_Object *HIDD_Gfx_RegisterPixFmt(OOP_Object *o, struct TagItem *pixFmtTags)
2238 STATIC_MID;
2239 struct pHidd_Gfx_RegisterPixFmt p, *msg = &p;
2241 if (!mid) mid = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_RegisterPixFmt);
2243 p.mID = mid;
2245 p.pixFmtTags = pixFmtTags;
2247 return (OOP_Object *)OOP_DoMethod(o, (OOP_Msg)msg);
2251 /****************************************************************************************/
2253 VOID HIDD_Gfx_ReleasePixFmt(OOP_Object *o, OOP_Object *pixFmt)
2255 STATIC_MID;
2256 struct pHidd_Gfx_ReleasePixFmt p, *msg = &p;
2258 if (!mid) mid = OOP_GetMethodID(IID_Hidd_Gfx, moHidd_Gfx_ReleasePixFmt);
2260 p.mID = mid;
2262 p.pixFmt = pixFmt;
2264 OOP_DoMethod(o, (OOP_Msg)msg);
2268 /****************************************************************************************/