Improvements to comments etc.
[AROS.git] / rom / hidds / graphics / GraphicsClass.c
bloba23e01138a7d10ab4ecbc0fef49b2b2cb1f4fca5
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics hidd class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #define DEBUG 0
12 #define SDEBUG 0
13 #define DPF(x)
14 #define DCOPYBOX(x)
16 #include <aros/atomic.h>
17 #include <aros/debug.h>
18 #include <aros/symbolsets.h>
19 #include <cybergraphx/cgxvideo.h>
20 #include <exec/lists.h>
21 #include <oop/static_mid.h>
22 #include <graphics/displayinfo.h>
23 #include <graphics/view.h>
25 #include "graphics_intern.h"
27 #include <string.h>
28 #include <stddef.h>
30 #include <proto/exec.h>
31 #include <proto/utility.h>
32 #include <proto/oop.h>
33 #include <exec/libraries.h>
34 #include <exec/memory.h>
36 #include <utility/tagitem.h>
38 #include LC_LIBDEFS_FILE
40 #include <hidd/graphics.h>
42 /*****************************************************************************************
44 NAME
45 --background_graphics--
47 LOCATION
48 hidd.graphics.graphics
50 NOTES
51 When working with graphics drivers this is the first object you get.
52 It allows you to create BitMap and GC (graphics context)
53 object. The class' methods must be overidden by hardware-specific
54 subclasses where documented to do so.
56 *****************************************************************************************/
58 /*****************************************************************************************
60 NAME
61 --display_modes--
63 LOCATION
64 hidd.graphics.graphics
66 NOTES
67 Each display driver object internally stores a database of supported display mode
68 IDs. This database is normally managed by base class, the driver does not need to
69 reimplement respective methods.
71 A display mode ID in AROS is a 32-bit integer value, the same as on AmigaOS(tm).
72 However mode ID layout introduced by Commodore does not fit well for RTG systems.
73 In order to overcome its limitations, display ID on AROS may have two forms:
75 1. A chipset mode ID. These are standard IDs defined by Commodore. You may find
76 their definitions in graphics/modeid.h.
78 2. AROS RTG mode ID.
80 An RTG mode ID is composed of three parts in the form:
82 nnnn xx yy
84 nnnn - monitor ID. This number is maintained by system libraries. IDs are
85 assigned in the order in which drivers are loaded and display hardware is
86 found. Drivers do not have to care about this part, and should normally
87 mask it out if they for some reason look at mode ID. In order to
88 distinguish between chipset mode IDs and RTG mode IDs, order number starts
89 not from zero, reserving some space for C= chipset mode IDs (which appear
90 to have order numbers from 0x0000 to 0x000A). Currently RTG monitor IDs
91 start from 0x0010, however with time this value may change. So don't rely
92 on some particular values in RTG IDs. Use cybergraphics.library/IsCyberModeID()
93 function if you want to know for sure if the given mode ID belongs to an
94 RTG driver.
96 xx - A sync object index in driver's mode database.
97 yy - A pixelformat object in driver's mode database.
99 Normally the driver does not have to care about mode ID decoding. The mode
100 database is maintained by base class. The only useful things for the driver are
101 sync and pixelformat objects, from which it's possible to get different
102 information about the mode. They can be obtained from the base class using
103 HIDD_Gfx_GetMode().
105 Note that the driver object by itself does not know its monitor ID. Different
106 displays are served by different objects, any of which may belong to any class.
107 So all driver methods which return mode IDs will set monitor ID to zero. All
108 methods that take mode ID as argument are expected to ignore the monitor ID part
109 and do not make any assumptions about its value.
111 *****************************************************************************************/
113 static BOOL create_std_pixfmts(struct class_static_data *_csd);
114 static VOID delete_pixfmts(struct class_static_data *_csd);
115 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags);
117 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl);
118 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl);
119 static OOP_Object *create_and_init_object(OOP_Class *cl, UBYTE *data, ULONG datasize,
120 struct class_static_data *_csd);
122 static struct pixfmt_data *find_pixfmt(HIDDT_PixelFormat *tofind
123 , struct class_static_data *_csd);
125 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm
126 , OOP_Object *dst_bm, UWORD width, UWORD height);
128 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf, ULONG attrcheck, struct class_static_data *_csd);
130 /****************************************************************************************/
132 #define COMPUTE_HIDD_MODEID(sync, pf) \
133 ( ((sync) << 8) | (pf) )
135 #define MODEID_TO_SYNCIDX(id) (((id) & 0X0000FF00) >> 8)
136 #define MODEID_TO_PFIDX(id) ( (id) & 0x000000FF)
138 /****************************************************************************************/
140 OOP_Object *GFX__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
142 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
143 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
144 struct TagItem gctags[] =
146 {aHidd_GC_Foreground, 0},
147 {TAG_DONE , 0}
150 D(bug("Entering gfx.hidd::New\n"));
152 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
153 D(bug("Got object o=%x\n", o));
155 if (o)
157 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
158 struct TagItem *tstate = msg->attrList;
159 struct TagItem *modetags = NULL;
160 struct TagItem *tag;
161 BOOL ok;
163 InitSemaphore(&data->mdb.sema);
164 InitSemaphore(&data->fbsem);
165 data->fbmode = -1;
167 D(bug("[GFX] attrList 0x%p\n", msg->attrList));
169 while ((tag = NextTagItem(&tstate)))
171 ULONG idx;
173 Hidd_Gfx_Switch(tag->ti_Tag, idx)
175 case aoHidd_Gfx_ModeTags:
176 modetags = (struct TagItem *)tag->ti_Data;
177 break;
179 case aoHidd_Gfx_FrameBufferType:
180 data->fbmode = tag->ti_Data;
181 break;
185 /* Register modes only after other attributes are initialized */
186 ok = modetags ? register_modes(cl, o, modetags) : TRUE;
188 /* Create a gc that we can use for some rendering */
189 if (ok)
191 data->gc = OOP_NewObject(CSD(cl)->gcclass, NULL, gctags);
192 if (NULL == data->gc)
194 D(bug("Could not get gc\n"));
195 ok = FALSE;
199 if (!ok)
201 OOP_MethodID dispose_mid = msg->mID - moRoot_New + moRoot_Dispose;
203 D(bug("Not OK\n"));
204 OOP_CoerceMethod(cl, o, &dispose_mid);
205 return NULL;
209 D(bug("Leaving gfx.hidd::New o=%x\n", o));
210 return o;
213 /****************************************************************************************/
215 VOID GFX__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
217 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
218 struct HIDDGraphicsData *data;
220 data = OOP_INST_DATA(cl, o);
222 /* free the mode db stuff */
223 free_mode_db(&data->mdb, cl);
225 /* Here we should unregister pixelformats registered in our New().
226 However gfx drivers aren't supposed to be removed, so it's okay
227 not to do it at all for now. */
229 if (NULL != data->gc)
230 OOP_DisposeObject(data->gc);
232 OOP_DoSuperMethod(cl, o, msg);
235 /*****************************************************************************************
237 NAME
238 aoHidd_Gfx_IsWindowed
240 SYNOPSIS
241 [..G], BOOL
243 LOCATION
244 hidd.graphics.graphics
246 FUNCTION
247 Tells if the display driver is using hosted display in host OS' window, and mouse
248 input is handled by host OS.
250 Windowed displays may send activation events to AROS. This is needed in order to
251 correctly handle display switch in a multi-display configuration (which means that
252 the user has multiple windows on host OS desktop and can freely switch between them).
254 NOTES
255 Even in fullscreen mode drivers should still return TRUE if the host OS manages mouse
256 input (for example, X11 driver). If mouse input is not managed by the host OS
257 (for example, with Linux framebuffer driver), return FALSE.
259 EXAMPLE
261 BUGS
263 SEE ALSO
264 aoHidd_Gfx_ActiveCallBack, aoHidd_Gfx_ActiveCallBackData
266 INTERNALS
267 Base class always provides FALSE value
269 *****************************************************************************************/
271 /*****************************************************************************************
273 NAME
274 aoHidd_Gfx_DMPSLevel
276 SYNOPSIS
277 [ISG], HIDDT_DPMSLevel
279 LOCATION
280 hidd.graphics.graphics
282 FUNCTION
283 Gets or sets current DPMS level for driver's display.
284 A value can be one of:
285 vHidd_Gfx_DPMSLevel_On,
286 vHidd_Gfx_DPMSLevel_Standby,
287 vHidd_Gfx_DPMSLevel_Suspend,
288 vHidd_Gfx_DPMSLevel_Off
290 If the driver does not support some state, it's up to the driver what to do.
291 Usually it is expected to ignore the request.
293 Getting this attribute should return real current state.
295 NOTES
297 EXAMPLE
299 BUGS
301 SEE ALSO
303 INTERNALS
304 Base class always provides vHidd_Gfx_DPMSLevel_On value (comes from rootclass'
305 Get() which sets the value to 0).
307 *****************************************************************************************/
309 /*****************************************************************************************
311 NAME
312 aoHidd_Gfx_ModeTags
314 SYNOPSIS
315 [I..], struct TagItem *
317 LOCATION
318 hidd.graphics.graphics
320 FUNCTION
321 Specify a pointer to a taglist which contains description of display modes
322 supported by the driver.
324 This attribute is usually appended in moRoot_New method of the display driver
325 class.
327 This attribute is mandatory for the base class, otherwise driver object creation
328 fails.
330 Mode description taglist may contain the following tags:
331 - Any sync attributes - these attributes will specify values common for all sync
332 modes
333 - Any pixelformat attributes - these attributes will specify values common for
334 all pixelformat modes
335 - aoHidd_Gfx_SyncTags - specifies a pointer to another separate taglist containing
336 attributes for one sync (display) mode. If this tag
337 is not supplied at all, a set of default modes will be
338 generated for the driver.
339 - aoHidd_Gfx_PixFmtTags - specifies a pointer to another separate taglist containing
340 attributes for one pixelformat. This tag must be supplied
341 at least once, otherwise driver object will fail to create.
343 aoHidd_Gfx_SyncTags and aoHidd_Gfx_PixFmtTags can be specified multiple times in
344 order to associate more than one display mode with the driver. Note that common
345 values for sync and pixelformat objects need to be placed in the taglist before
346 aoHidd_Gfx_SyncTags and aoHidd_Gfx_PixFmtTags. You may specify them again between
347 these tags in order to alter common values.
349 NOTES
351 EXAMPLE
352 Partial example code of display driver supporting a truecolor display with three
353 resolutions:
355 // Our pixelformat (24-bit 0BGR)
356 struct TagItem pftags[] =
358 { aHidd_PixFmt_RedShift , 24 },
359 { aHidd_PixFmt_GreenShift , 16 },
360 { aHidd_PixFmt_BlueShift , 8 },
361 { aHidd_PixFmt_AlphaShift , 0 },
362 { aHidd_PixFmt_RedMask , 0x000000FF },
363 { aHidd_PixFmt_GreenMask , 0x0000FF00 },
364 { aHidd_PixFmt_BlueMask , 0x00FF0000 },
365 { aHidd_PixFmt_AlphaMask , 0x00000000 },
366 { aHidd_PixFmt_ColorModel , vHidd_ColorModel_TrueColor },
367 { aHidd_PixFmt_Depth , 24 },
368 { aHidd_PixFmt_BytesPerPixel, 4 },
369 { aHidd_PixFmt_BitsPerPixel , 24 },
370 { aHidd_PixFmt_StdPixFmt , vHidd_StdPixFmt_Native },
371 { aHidd_PixFmt_BitMapType , vHidd_BitMapType_Chunky },
372 { TAG_DONE , 0UL }
375 // 640x480 resolution
376 struct TagItem tags_800_600[] =
378 { aHidd_Sync_HDisp , 640 },
379 { aHidd_Sync_VDisp , 480 },
380 { TAG_DONE , 0UL }
383 // 800x600 resolution
384 struct TagItem tags_800_600[] =
386 { aHidd_Sync_HDisp , 800 },
387 { aHidd_Sync_VDisp , 600 },
388 { TAG_DONE , 0UL }
391 // 1024x768 resolution
392 struct TagItem tags_1024_768[] =
394 { aHidd_Sync_HDisp , 1024 },
395 { aHidd_Sync_VDisp , 768 },
396 { TAG_DONE , 0UL }
399 // Mode description taglist itself
400 struct TagItem mode_tags[] =
402 // Our driver supports a single pixelformat
403 { aHidd_Gfx_PixFmtTags , (IPTR)pftags },
405 // Here go sync values common for all sync modes
406 { aHidd_Sync_HMin , 112 },
407 { aHidd_Sync_VMin , 112 },
408 { aHidd_Sync_HMax , 16384 },
409 { aHidd_Sync_VMax , 16384 },
410 { aHidd_Sync_Description, (IPTR)"Example: %hx%v" },
412 // First resolution
413 { aHidd_Gfx_SyncTags , (IPTR)tags_800_600 },
415 // Next two syncs will have HMax = 32768, as an example
416 { aHidd_Sync_HMax , 32768 },
418 // Two more resolutions
419 { aHidd_Gfx_SyncTags , (IPTR)tags_800_600 },
420 { aHidd_Gfx_SyncTags , (IPTR)tags_1024_768 },
421 { TAG_DONE , 0UL }
424 // This is the attribute list which is given to New method
425 // of the base class
426 struct TagItem mytags[] =
428 { aHidd_Gfx_ModeTags , (IPTR)mode_tags },
429 { TAG_DONE , NULL }
432 BUGS
434 SEE ALSO
436 INTERNALS
438 *****************************************************************************************/
440 /*****************************************************************************************
442 NAME
443 aoHidd_Gfx_NumSyncs
445 SYNOPSIS
446 [..G], ULONG
448 LOCATION
449 hidd.graphics.graphics
451 FUNCTION
452 Gets total number of sync objects in the internal display mode database.
454 NOTES
456 EXAMPLE
458 BUGS
460 SEE ALSO
461 moHidd_Gfx_GetSync
463 INTERNALS
465 *****************************************************************************************/
467 /*****************************************************************************************
469 NAME
470 aoHidd_Gfx_SupportsHWCursor
472 SYNOPSIS
473 [..G], BOOL
475 LOCATION
476 hidd.graphics.graphics
478 FUNCTION
479 Tells whether the driver supports hardware mouse pointer sprite.
481 If the driver provides TRUE value for this attribute, it is expected to implement
482 HIDD_Gfx_SetCursorPos(), HIDD_Gfx_SetCursorShape() and HIDD_Gfx_SetCursorVisible()
483 methods.
485 Mouse pointer counts for one hardware sprite, so if the driver implements also
486 HIDD_Gfx_ModeProperties(), it should set NumHWSprites to 1 in order to provide
487 valid information about display modes.
489 The driver must implement this attribute if it implements HIDD_Gfx_ModeProperties().
490 Otherwise it will provide false information in graphics.library/GetDisplayInfoData().
491 Base class can determine NumHWSprites based on this attribute value but not vice
492 versa.
494 NOTES
495 Default implementation in the base class returns FALSE. This causes the system to
496 use software sprite emulation.
498 This attribute is obsolete and is used only by AROS graphics.library up to v41.2. In
499 new drivers consider implementing aoHidd_Gfx_HWSpriteTypes attribute.
501 EXAMPLE
503 BUGS
505 SEE ALSO
506 aoHidd_Gfx_HWSpriteTypes, moHidd_Gfx_ModeProperties
508 INTERNALS
510 *****************************************************************************************/
512 /*****************************************************************************************
514 NAME
515 aoHidd_Gfx_NoFrameBuffer
517 SYNOPSIS
518 [..G], BOOL
520 LOCATION
521 hidd.graphics.graphics
523 FUNCTION
524 Tells whether the driver does not need a framebuffer.
526 Since v1.2 this attribute is obsolete. Please use aoHidd_Gfx_FrameBufferType
527 in new code.
529 NOTES
530 Provides FALSE if not implemented in the driver.
532 EXAMPLE
534 BUGS
536 SEE ALSO
537 aoHidd_Gfx_FrameBufferType, moHidd_Gfx_Show
539 INTERNALS
541 *****************************************************************************************/
543 /*****************************************************************************************
545 NAME
546 aoHidd_Gfx_HWSpriteTypes
548 SYNOPSIS
549 [..G], BOOL
551 LOCATION
552 hidd.graphics.graphics
554 FUNCTION
555 Return hardware sprite image types supported by the driver.
557 The returned value is a combination of the following bit flags:
558 vHidd_SpriteType_3Plus1 - color 0 is transparent, 1-3 visible
559 (Amiga(tm) chipset sprite format)
560 vHidd_SpriteType_2Plus1 - color 0 is transparent, color 1 is undefined
561 (can be whatever, for example clear or inverse),
562 colors 2-3 visible.
563 vHidd_SpriteType_DirectColor - Hi- or truecolor image, or LUT image with own
564 palette, perhaps with alpha channel
566 NOTES
567 This attribute should return 0 if the driver does not support hardware mouse sprite
568 at all. Software sprite emulation is done by graphics.library.
570 Default implementation in the base class is based on aoHidd_Gfx_SupportsHWCursor
571 value. This is done for backwards compatibility.
573 EXAMPLE
575 BUGS
577 SEE ALSO
578 aoHidd_Gfx_SupportsHWCursor
580 INTERNALS
581 Default implementation in the base class queries aoHidd_Gfx_SupportsHWCursor
582 and provides (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor) in case
583 if it returns TRUE. Otherwise it returns zero. This is done for backwards
584 compatibility with old drivers.
586 *****************************************************************************************/
588 /*****************************************************************************************
590 NAME
591 aoHidd_Gfx_MemorySize
593 SYNOPSIS
594 [..G], ULONG
596 LOCATION
597 hidd.graphics.graphics
599 FUNCTION
600 Query total size of video card memory in bytes.
602 NOTES
604 EXAMPLE
606 BUGS
608 SEE ALSO
609 aoHidd_Gfx_MemoryClock
611 INTERNALS
613 *****************************************************************************************/
615 /*****************************************************************************************
617 NAME
618 aoHidd_Gfx_MemoryClock
620 SYNOPSIS
621 [..G], ULONG
623 LOCATION
624 hidd.graphics.graphics
626 FUNCTION
627 Query video card's memory clock in Hz. 0 is a valid value meaning 'unknown'.
629 NOTES
631 EXAMPLE
633 BUGS
635 SEE ALSO
636 aoHidd_Gfx_MemorySize
638 INTERNALS
640 *****************************************************************************************/
642 /*****************************************************************************************
644 NAME
645 aoHidd_Gfx_DriverName
647 SYNOPSIS
648 [..G], STRPTR
650 LOCATION
651 hidd.graphics.graphics
653 FUNCTION
654 Query CyberGraphX driver name. It is the same name which can be given to
655 cybergraphics.library/BestCModeIDTagList() as CYBRBIDTG_BoardName value.
657 NOTES
658 By default base class returns class name as value of this attribute.
659 However this can (and must for some drivers listed in BestCModeIDTagList()
660 documentation) be overriden.
662 EXAMPLE
664 BUGS
666 SEE ALSO
668 INTERNALS
670 *****************************************************************************************/
672 /*****************************************************************************************
674 NAME
675 aoHidd_Gfx_ActiveCallBack
677 SYNOPSIS
678 [.S.], void (*)(APTR userdata, OOP_Object *bitmap)
680 LOCATION
681 hidd.graphics.graphics
683 FUNCTION
684 Set display activation interrupt handler.
686 This handler needs to be called by hosted display driver, if host OS
687 windowing system is used for the display and mouse input is handled by the
688 host OS.
690 This way the driver can tell AROS when a display window has been activated so that
691 AROS will be able to switch current display correctly when working in a multi-display
692 configuration.
694 The function uses C calling convention and needs to be declared as follows:
696 void ActivationHandler(APTR userdata, OOP_Object *bitmap);
698 Parameters of this function will be:
699 userdata - Whatever is specified by aoHidd_Gfx_ActiveCallBackData attribute.
700 bitmap - Currently reserved. Drivers need to set it to NULL.
702 The function can be called from within an interrupt, so usual restrictions apply
703 to it.
705 Set this attribute to NULL in order to disable activation handling.
707 NOTES
708 When setting the activation callback function, be sure that you set correct
709 userdata before you actually set the callback pointer. Otherwise your callback
710 can be called with wrong data pointer.
712 Only one activation handler can be installed. Installing a new handler replaces
713 the previous one.
715 Native displays do not need to implement this attribute because there can be
716 no external activation events.
718 EXAMPLE
720 BUGS
722 SEE ALSO
723 aoHidd_Gfx_ActiveCallBackData, aoHidd_Gfx_IsWindowed
725 INTERNALS
726 This attribute needs to be implemented by the display driver. Base class contains
727 no implementation.
729 *****************************************************************************************/
731 /*****************************************************************************************
733 NAME
734 aoHidd_Gfx_ActiveCallBackData
736 SYNOPSIS
737 [.S.], APTR
739 LOCATION
740 hidd.graphics.graphics
742 FUNCTION
743 Set user-defined data pointer for display activation handler.
745 NOTES
747 EXAMPLE
749 BUGS
751 SEE ALSO
752 aoHidd_Gfx_ActiveCallBack
754 INTERNALS
755 This attribute needs to be implemented by the display driver. Base class contains
756 no implementation.
758 *****************************************************************************************/
760 /*****************************************************************************************
762 NAME
763 aoHidd_Gfx_DefaultGC
765 SYNOPSIS
766 [..G], OOP_Object *
768 LOCATION
769 hidd.graphics.graphics
771 FUNCTION
772 Get a pointer to shared default GC object.
774 NOTES
775 The returned GC is preset to the following:
777 DrawMode = Copy
778 FG = 0
779 BG = 0
780 LinePat = ~0
781 ColMask = ~0
783 You must not alter these settings even temporarily, because this GC is shared between
784 bitmaps and between different tasks which may perform the rendering into different
785 regions of the same bitmap (two windows on one screen, for example). This GC is intended
786 to be used for internal copying operations.
788 EXAMPLE
790 BUGS
792 SEE ALSO
793 aoHidd_Gfx_ActiveCallBack
795 INTERNALS
796 This attribute needs to be implemented by the display driver. Base class contains
797 no implementation.
799 *****************************************************************************************/
801 static UBYTE get_fbmode(OOP_Class *cl, OOP_Object *o)
803 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
805 if (data->fbmode == -1)
807 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
810 * This attribute has never been set.
811 * Fall back to obsolete NoFrameBuffer.
813 data->fbmode = OOP_GET(o, aHidd_Gfx_NoFrameBuffer) ? vHidd_FrameBuffer_None : vHidd_FrameBuffer_Direct;
816 return data->fbmode;
819 /*****************************************************************************************
821 NAME
822 aoHidd_Gfx_FrameBufferType
824 SYNOPSIS
825 [I.G], UBYTE
827 LOCATION
828 hidd.graphics.graphics
830 FUNCTION
831 Specifies fixed framebuffer type used by the driver. The value can be one of the following:
833 vHidd_FrameBuffer_None - the driver does not use framebuffer.
834 vHidd_FrameBuffer_Direct - the driver uses framefuffer which can be accessed
835 directly for both reads and writes.
836 vHidd_FrameBuffer_Mirrored - the driver uses write-only framebuffer.
838 This attribute has to be specified during driver object creation. If this is not done,
839 the OS will use value of old aoHidd_Gfx_NoFrameBuffer attribute in order to distinguish
840 between vHidd_FrameBuffer_Direct (for FALSE) and vHidd_FrameBuffer_None (for TRUE).
842 NOTES
843 A fixed framebuffer is a special bitmap in a fixed area of video RAM. If the
844 framebuffer is used, the driver is expected to copy a new bitmap into it in
845 HIDD_Gfx_Show() and optionally copy old bitmap back.
847 A framebuffer is needed if the hardware does not have enough VRAM to store many
848 bitmaps or does not have capabilities to switch the display between various VRAM
849 regions.
851 Some hardware suffers from slow VRAM reading. In this case you should use mirrored
852 mode. If you use it, the system will hold a bitmap in the memory buffer, and
853 update VRAM on demand (hence the name).
855 An example of driver using a framebuffer is hosted SDL driver. By design SDL works
856 only with single display window, which is considered a framebuffer.
858 EXAMPLE
860 BUGS
862 SEE ALSO
863 aoHidd_Gfx_NoFrameBuffer
865 INTERNALS
867 *****************************************************************************************/
869 /*****************************************************************************************
871 NAME
872 aoHidd_Gfx_SupportsGamma
874 SYNOPSIS
875 [..G], UBYTE
877 LOCATION
878 hidd.graphics.graphics
880 FUNCTION
881 Specifies if the driver supports gamma correction tables. Default implementation
882 in base class returns FALSE.
884 NOTES
886 EXAMPLE
888 BUGS
890 SEE ALSO
891 moHidd_Gfx_SetGamma
893 INTERNALS
895 *****************************************************************************************/
897 VOID GFX__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
899 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
900 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
901 ULONG idx;
903 Hidd_Gfx_Switch (msg->attrID, idx)
905 case aoHidd_Gfx_NumSyncs:
906 *msg->storage = data->mdb.num_syncs;
907 return;
909 case aoHidd_Gfx_IsWindowed:
910 case aoHidd_Gfx_SupportsHWCursor:
911 case aoHidd_Gfx_SupportsGamma:
912 *msg->storage = 0;
913 return;
915 case aoHidd_Gfx_HWSpriteTypes:
916 /* Fall back to obsolete SupportsHWCursor */
917 *msg->storage = OOP_GET(o, aHidd_Gfx_SupportsHWCursor) ? (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor) : 0;
918 return;
920 case aoHidd_Gfx_DriverName:
921 *msg->storage = (IPTR)OOP_OCLASS(o)->ClassNode.ln_Name;
922 return;
924 case aoHidd_Gfx_DefaultGC:
925 *msg->storage = (IPTR)data->gc;
926 return;
928 case aoHidd_Gfx_FrameBufferType:
929 *msg->storage = get_fbmode(cl, o);
930 return;
933 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
936 /*****************************************************************************************
938 NAME
939 moHidd_Gfx_NewGC
941 SYNOPSIS
942 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NewGC *msg);
944 OOP_Object *HIDD_Gfx_NewGC(OOP_Object *gfxHidd, struct TagItem *tagList);
946 LOCATION
947 hidd.graphics.graphics
949 FUNCTION
950 Create a GC (gfx context) object that may be used for rendering
951 into a bitmap.
953 INPUTS
954 gfxHidd - A graphics driver object with which the GC will perform
955 the rendering operations.
956 tagList - A list of GC attributes. See hidd.graphics.gc class
957 documentation for their description.
959 RESULT
960 gc - pointer to the newly created GC, ready for use for rendering
961 operations.
963 NOTES
964 A GC object is just a data storage. You may create a subclass of GC if
965 you wish to, however there's usually no need to. Additionally, this may
966 be not future-proof (since GC subclasses can not be interchanged between
967 different drivers. Please avoid using custom GCs.
969 EXAMPLE
971 BUGS
972 At the moment subclassing GCs is not supported because some parts of
973 the operating system create GC objects directly. It is unclear whether
974 subclassing GCs is actually needed.
976 SEE ALSO
977 moHidd_Gfx_DisposeGC
979 INTERNALS
981 *****************************************************************************************/
983 OOP_Object *GFX__Hidd_Gfx__NewGC(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewGC *msg)
985 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
986 OOP_Object *gc = NULL;
988 EnterFunc(bug("HIDDGfx::NewGC()\n"));
990 gc = OOP_NewObject(NULL, CLID_Hidd_GC, msg->attrList);
992 ReturnPtr("HIDDGfx::NewGC", OOP_Object *, gc);
995 /*****************************************************************************************
997 NAME
998 moHidd_Gfx_DisposeGC
1000 SYNOPSIS
1001 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_DisposeGC *msg);
1003 VOID HIDD_Gfx_DisposeGC(OOP_Object *gfxHidd, OOP_Object *gc)
1005 LOCATION
1006 hidd.graphics.graphics
1008 FUNCTION
1009 Deletes a GC (Graphics Context) object previously created
1010 by HIDD_Gfx_NewGC().
1012 Subclasses do not have to override this method
1013 unless they allocate anything additional to a gc object in
1014 their HIDD_Gfx_NewGC() implementation.
1016 INPUTS
1017 gfxHidd - A driver object which was used for creating a GC.
1018 gc - Pointer to gc object to delete.
1020 RESULT
1021 None.
1023 NOTES
1025 EXAMPLE
1027 BUGS
1029 SEE ALSO
1030 moHidd_Gfx_NewGC
1032 INTERNALS
1033 Basically just does OOP_DisposeObject(gc);
1035 *****************************************************************************************/
1037 VOID GFX__Hidd_Gfx__DisposeGC(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_DisposeGC *msg)
1039 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1041 EnterFunc(bug("HIDDGfx::DisposeGC()\n"));
1043 if (NULL != msg->gc) OOP_DisposeObject(msg->gc);
1045 ReturnVoid("HIDDGfx::DisposeGC");
1048 /****************************************************************************************/
1050 #define BMAO(x) aoHidd_BitMap_ ## x
1051 #define BMAF(x) (1L << aoHidd_BitMap_ ## x)
1053 #define BM_DIMS_AF (BMAF(Width) | BMAF(Height))
1055 #define SET_TAG(tags, idx, tag, val) \
1056 tags[idx].ti_Tag = tag ; tags[idx].ti_Data = (IPTR)val;
1058 #define SET_BM_TAG(tags, idx, tag, val) \
1059 SET_TAG(tags, idx, aHidd_BitMap_ ## tag, val)
1061 #define COPY_BM_TAG(tags, idx, tag, obj) \
1062 tags[idx].ti_Tag = aHidd_BitMap_ ## tag; \
1063 OOP_GetAttr(obj, aHidd_BitMap_ ## tag , &tags[idx].ti_Data)
1065 /*****************************************************************************************
1067 NAME
1068 moHidd_Gfx_NewBitMap
1070 SYNOPSIS
1071 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NewBitMap *msg);
1073 OOP_Object *HIDD_Gfx_NewBitMap(OOP_Object *gfxHidd, struct TagItem *tagList);
1075 LOCATION
1076 hidd.graphics.graphics
1078 FUNCTION
1079 Create a bitmap object.
1081 One graphics driver represents at least one displayable bitmap class.
1082 Additionally it may represent more classes (for example some old drivers use
1083 a separate class for nondisplayable bitmaps).
1085 These classes are private to the driver. In order to be able to use them
1086 bitmap objects are never created directly. Instead they are created using the
1087 HIDD_Gfx_NewBitMap() call. An implementation of this method in the driver
1088 should examine bitmap attributes supplied and make a decision if the bitmap
1089 should be created using the driver's own class or one of the system classes.
1091 A typical implementation should pay attention to the following bitmap attributes:
1093 aHIDD_BitMap_ModeID - If this attribute is supplied, the bitmap needs to be
1094 either displayable by this driver, or be a friend of a
1095 displayable bitmap. A friend bitmap usually repeats the
1096 internal layout of its friend so that the driver may
1097 perform blitting operations quickly.
1099 aHIDD_BitMap_Displayable - If this attribute is supplied, the bitmap NEEDS to be
1100 displayable by this driver. Usually this means that
1101 the bitmap object will contain video hardware state
1102 information. This attribute will always be accompanied
1103 by aHIDD_BitMap_ModeID.
1105 aHIDD_BitMap_FrameBuffer - The bitmap needs to be a framebuffer bitmap. A
1106 framebuffer bitmap is necessary for some kinds of
1107 hardware which have a small fixed amount of video
1108 RAM which can hold only one screen at a time. Setting
1109 this attribute requires that a valid ModeID be also set.
1111 aHIDD_BitMap_Friend - If there's no ModeID supplied, you may wish to check class
1112 of friend bitmap. This can be useful if your driver uses
1113 different classes for displayable and non-displayable bitmaps.
1114 By default base class will pick up friend's class and use it
1115 for new bitmap if nothing is specified, here you may override
1116 this behavior.
1118 If your driver wants to specify own class for the bitmap being created,
1119 it should prepend an aoHidd_BitMap_ClassPtr attribute to the supplied taglist
1120 and pass it to base class. It's not allowed to create bitmap objects directly
1121 since they need some more extra information which is added by the base class!
1123 This method must be implemented by your subclass. aHIDD_BitMap_ClassPtr or
1124 aHIDD_BitMap_ClassID must be provided to the base class for a displayable bitmap!
1126 INPUTS
1127 gfxHidd - The graphics driver object that will provide the bitmap.
1129 tagList - A list of bitmap attributes. See hidd.graphics.bitmap class
1130 documentation for their descriptions.
1132 RESULT
1133 bm - pointer to the newly created bitmap.
1135 NOTES
1136 Drivers which do not use framebuffer must always specify own class using either
1137 moHidd_BitMap_ClassPtr or moHidd_BitMap_ClassID attribute. Drivers making use of
1138 framebuffer may omit this, in this case framebuffer's class will be used for
1139 displayable bitmaps.
1141 EXAMPLE
1143 BUGS
1145 SEE ALSO
1146 moHidd_Gfx_DisposeBitMap
1148 INTERNALS
1149 The base class implementation currently does the folliwing in order to determine
1150 a class for a nondisplayable bitmap (in the listed order):
1152 1. Check aHIDD_BitMap_ClassPtr and aHIDD_BitMap_ClassID. If one of them is supplied,
1153 the class is already set by a subclass.
1154 2. Check aHIDD_BitMap_StdPixFmt. If this attribute is supplied, figure out type of
1155 the pixelformat (chunky or planar), and use one of two system's default classes.
1156 3. Check aHIDD_BitMap_Friend. If friend bitmap is supplied, obtain its class from
1157 aHIDD_BitMap_ClassPtr value of friend bitmap.
1158 4. If everything fails, bitmap creation fails too.
1160 This behavior is subject to change, but will maintain backwards compatibility.
1162 *****************************************************************************************/
1164 OOP_Object * GFX__Hidd_Gfx__NewBitMap(OOP_Class *cl, OOP_Object *o,
1165 struct pHidd_Gfx_NewBitMap *msg)
1167 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1168 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1169 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
1171 struct TagItem bmtags[] =
1173 {aHidd_BitMap_GfxHidd, 0}, /* 0 */
1174 {aHidd_BitMap_PixFmt , 0}, /* 1 */
1175 {TAG_IGNORE , 0}, /* 2 */
1176 {TAG_IGNORE , 0}, /* 3 */
1177 {TAG_IGNORE , 0}, /* 4 */
1178 {TAG_IGNORE , 0}, /* 5 */
1179 {TAG_MORE , 0}, /* 6 */
1181 OOP_Object *bm;
1183 struct TagItem *tag, *tstate = msg->attrList;
1184 ULONG idx;
1186 STRPTR classid = NULL;
1187 OOP_Class *classptr = NULL;
1188 BOOL displayable = FALSE;
1189 BOOL framebuffer = FALSE;
1190 HIDDT_StdPixFmt pixfmt = vHidd_StdPixFmt_Unknown;
1191 OOP_Object *friend_bm = NULL;
1192 OOP_Object *sync = NULL;
1193 OOP_Object *pf = NULL;
1195 BOOL gotclass = FALSE;
1196 BOOL got_width = FALSE;
1197 BOOL got_height = FALSE;
1198 BOOL got_depth = FALSE;
1200 while ((tag = NextTagItem(&tstate)))
1202 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
1204 switch (idx)
1206 case aoHidd_BitMap_Displayable:
1207 displayable = tag->ti_Data;
1208 break;
1210 case aoHidd_BitMap_FrameBuffer:
1211 framebuffer = tag->ti_Data;
1212 break;
1214 case aoHidd_BitMap_Width:
1215 got_width = TRUE;
1216 break;
1218 case aoHidd_BitMap_Height:
1219 got_height = TRUE;
1220 break;
1222 case aoHidd_BitMap_Depth:
1223 got_depth = TRUE;
1224 break;
1226 case aoHidd_BitMap_ModeID:
1227 /* Make sure it is a valid mode, and retrieve sync/pixelformat data */
1228 if (!HIDD_Gfx_GetMode(o, tag->ti_Data, &sync, &pf))
1230 D(bug("!!! Gfx::NewBitMap: USER PASSED INVALID MODEID !!!\n"));
1231 return NULL;
1233 break;
1235 case aoHidd_BitMap_Friend:
1236 friend_bm = (OOP_Object *)tag->ti_Data;
1237 break;
1239 case aoHidd_BitMap_PixFmt:
1240 D(bug("!!! Gfx::NewBitMap: USER IS NOT ALLOWED TO PASS aHidd_BitMap_PixFmt !!!\n"));
1241 return NULL;
1243 case aoHidd_BitMap_StdPixFmt:
1244 pixfmt = tag->ti_Data;
1245 break;
1247 case aoHidd_BitMap_ClassPtr:
1248 classptr = (OOP_Class *)tag->ti_Data;
1249 gotclass = TRUE;
1250 break;
1252 case aoHidd_BitMap_ClassID:
1253 classid = (STRPTR)tag->ti_Data;
1254 gotclass = TRUE;
1255 break;
1260 if (friend_bm)
1262 /* If we have a friend bitmap, we can inherit some attributes from it */
1263 if (!got_width)
1265 COPY_BM_TAG(bmtags, 2, Width, friend_bm);
1266 got_width = TRUE;
1269 if (!got_height)
1271 COPY_BM_TAG(bmtags, 3, Height, friend_bm);
1272 got_height = TRUE;
1275 if (!got_depth)
1277 COPY_BM_TAG(bmtags, 4, Depth, friend_bm);
1281 if (framebuffer)
1283 /* FrameBuffer implies Displayable */
1284 SET_BM_TAG(bmtags, 5, Displayable, TRUE);
1285 displayable = TRUE;
1287 else if (displayable)
1290 * Displayable, but not framebuffer (user's screen).
1291 * If we are working in framebuffer mode, we treat all such
1292 * bitmaps as framebuffer's friends and can inherit its class.
1294 if ((!gotclass) && data->framebuffer && (get_fbmode(cl, o) != vHidd_FrameBuffer_None))
1296 classptr = OOP_OCLASS(data->framebuffer);
1297 gotclass = TRUE;
1299 D(bug("[GFX] Using class 0x%p (%s) for displayable bitmap\n", classptr, classptr->ClassNode.ln_Name));
1303 if (displayable)
1305 /* Displayable bitmap. Here we must have ModeID and class. */
1306 if (!sync)
1308 D(bug("!!! Gfx::NewBitMap: USER HAS NOT PASSED MODEID FOR DISPLAYABLE BITMAP !!!\n"));
1309 return NULL;
1312 if (!gotclass)
1314 D(bug("!!! Gfx::NewBitMap: SUBCLASS DID NOT PASS CLASS FOR DISPLAYABLE BITMAP !!!\n"));
1315 return NULL;
1318 else /* if (!displayable) */
1321 * This is an offscreen bitmap and we need to guess its pixelformat.
1322 * In order to do this we need one of (in the order of preference):
1323 * - ModeID
1324 * - StdPixFmt
1325 * - Friend
1328 if (sync)
1331 * We have alredy got sync for the modeid case.
1332 * Obtain missing size information from it.
1334 if (!got_width)
1336 bmtags[2].ti_Tag = aHidd_BitMap_Width;
1337 OOP_GetAttr(sync, aHidd_Sync_HDisp, &bmtags[2].ti_Data);
1340 if (!got_height)
1342 bmtags[3].ti_Tag = aHidd_BitMap_Height;
1343 OOP_GetAttr(sync, aHidd_Sync_VDisp, &bmtags[3].ti_Data);
1346 else if (pixfmt != vHidd_StdPixFmt_Unknown)
1348 /* Next to look for is StdPixFmt */
1349 pf = HIDD_Gfx_GetPixFmt(o, pixfmt);
1350 if (NULL == pf)
1352 D(bug("!!! Gfx::NewBitMap(): USER PASSED BOGUS StdPixFmt !!!\n"));
1353 return NULL;
1356 else if (friend_bm)
1358 /* Last alternative is that the user passed a friend bitmap */
1360 OOP_GetAttr(friend_bm, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1363 * Inherit the class from friend bitmap (if not already specified).
1364 * We do it because friend bitmap may be a display HIDD bitmap
1366 if (!gotclass)
1368 classptr = OOP_OCLASS(friend_bm);
1369 gotclass = TRUE;
1371 D(bug("[GFX] Friend bitmap is 0x%p has class 0x%p (%s)\n", friend_bm, classptr, classptr->ClassNode.ln_Name));
1374 else
1376 D(bug("!!! Gfx::NewBitMap: INSUFFICIENT ATTRS TO CREATE OFFSCREEN BITMAP !!!\n"));
1377 return NULL;
1380 /* Did the subclass provide an offbitmap class for us? */
1381 if (!gotclass)
1383 /* Have to find a suitable class ourselves from the pixelformat */
1384 HIDDT_BitMapType bmtype;
1386 OOP_GetAttr(pf, aHidd_PixFmt_BitMapType, &bmtype);
1387 switch (bmtype)
1389 case vHidd_BitMapType_Chunky:
1390 classptr = CSD(cl)->chunkybmclass;
1391 break;
1393 case vHidd_BitMapType_Planar:
1394 classptr = CSD(cl)->planarbmclass;
1395 break;
1397 default:
1398 D(bug("!!! Gfx::NewBitMap: UNKNOWN BITMAPTYPE %d !!!\n", bmtype));
1399 return NULL;
1401 D(bug("[GFX] Bitmap type is %u, using class 0x%p\n", bmtype, classptr));
1403 } /* if (!gotclass) */
1405 } /* if (!displayable) */
1407 /* Set the tags we want to pass to the selected bitmap class */
1408 bmtags[0].ti_Data = (IPTR)o;
1409 bmtags[1].ti_Data = (IPTR)pf;
1410 bmtags[6].ti_Data = (IPTR)msg->attrList;
1412 bm = OOP_NewObject(classptr, classid, bmtags);
1414 if (framebuffer)
1416 /* Remember the framebuffer. It can be needed for default Show() implementation. */
1417 data->framebuffer = bm;
1420 return bm;
1424 /*****************************************************************************************
1426 NAME
1427 moHidd_Gfx_DisposeBitMap
1429 SYNOPSIS
1430 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_DisposeBitMap *msg);
1432 VOID HIDD_Gfx_DisposeBitMap(OOP_Object *gfxHidd, OOP_Object *bitMap);
1434 LOCATION
1435 hidd.graphics.graphics
1437 FUNCTION
1438 Deletes a bitmap object previously created by HIDD_Gfx_NewBitMap().
1440 Subclasses do not have to override this method
1441 unless they allocate anything additional to a bitmap object in
1442 their HIDD_Gfx_NewBitMap() implementation.
1444 INPUTS
1445 gfxHidd - A driver object which was used for creating a bitmap.
1446 bitMap - Pointer to a bitmap object to delete.
1448 RESULT
1449 None.
1451 NOTES
1453 EXAMPLE
1455 BUGS
1457 SEE ALSO
1458 moHidd_Gfx_NewBitMap
1460 INTERNALS
1461 Basically just does OOP_DisposeObject(bitMap);
1463 ******************************************************************************************/
1465 VOID GFX__Hidd_Gfx__DisposeBitMap(OOP_Class *cl, OOP_Object *o,
1466 struct pHidd_Gfx_DisposeBitMap *msg)
1468 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1470 if (NULL != msg->bitMap)
1471 OOP_DisposeObject(msg->bitMap);
1474 /****************************************************************************************/
1476 #define SD(x) ((struct sync_data *)x)
1477 #define PF(x) ((HIDDT_PixelFormat *)x)
1479 #define XCOORD_TO_BYTEIDX(x) ( (x) >> 3)
1480 #define COORD_TO_BYTEIDX(x, y, bpr) ( ( (y) * bpr ) + XCOORD_TO_BYTEIDX(x) )
1481 #define XCOORD_TO_MASK(x) (1L << (7 - ((x) & 0x07) ))
1482 #define WIDTH_TO_BYTES(width) ( (( (width) - 1) >> 3) + 1)
1484 /****************************************************************************************/
1486 /* modebm functions pfidx is x and syncidx is y coord in the bitmap */
1488 /****************************************************************************************/
1490 static inline BOOL alloc_mode_bm(struct mode_bm *bm, ULONG numsyncs, ULONG numpfs,
1491 OOP_Class *cl)
1493 bm->bpr = WIDTH_TO_BYTES(numpfs);
1495 bm->bm = AllocVec(bm->bpr * numsyncs, MEMF_CLEAR);
1496 if (NULL == bm->bm)
1497 return FALSE;
1499 /* We initialize the mode bitmap to all modes valid */
1500 memset(bm->bm, 0xFF, bm->bpr * numsyncs);
1502 return TRUE;
1505 /****************************************************************************************/
1507 static inline VOID free_mode_bm(struct mode_bm *bm, OOP_Class *cl)
1509 FreeVec(bm->bm);
1510 bm->bm = NULL;
1511 bm->bpr = 0;
1514 /****************************************************************************************/
1516 static inline BOOL is_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx)
1518 if (0 != (XCOORD_TO_MASK(pfidx) & bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)]))
1519 return TRUE;
1521 return FALSE;
1524 /****************************************************************************************/
1526 static inline VOID set_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx,
1527 BOOL valid)
1529 if (valid)
1530 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] |= XCOORD_TO_MASK(pfidx);
1531 else
1532 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] &= ~XCOORD_TO_MASK(pfidx);
1534 return;
1537 /****************************************************************************************/
1539 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl)
1541 BOOL ok = FALSE;
1543 if (0 == numsyncs || 0 == numpfs)
1544 return FALSE;
1546 ObtainSemaphore(&mdb->sema);
1547 /* free_mode_bm() needs this */
1548 mdb->num_pixfmts = numpfs;
1549 mdb->num_syncs = numsyncs;
1551 mdb->syncs = AllocMem(sizeof (OOP_Object *) * numsyncs, MEMF_CLEAR);
1553 if (NULL != mdb->syncs)
1555 mdb->pixfmts = AllocMem(sizeof (OOP_Object *) * numpfs, MEMF_CLEAR);
1557 if (NULL != mdb->pixfmts)
1559 if (alloc_mode_bm(&mdb->orig_mode_bm, numsyncs, numpfs, cl))
1561 if (alloc_mode_bm(&mdb->checked_mode_bm, numsyncs, numpfs, cl))
1563 ok = TRUE;
1569 if (!ok)
1570 free_mode_db(mdb, cl);
1572 ReleaseSemaphore(&mdb->sema);
1574 return ok;
1577 /****************************************************************************************/
1579 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl)
1581 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1582 ULONG i;
1584 ObtainSemaphore(&mdb->sema);
1586 if (NULL != mdb->pixfmts)
1589 /* Pixelformats are shared objects and never freed */
1590 FreeMem(mdb->pixfmts, sizeof (OOP_Object *) * mdb->num_pixfmts);
1591 mdb->pixfmts = NULL; mdb->num_pixfmts = 0;
1594 if (NULL != mdb->syncs)
1596 for (i = 0; i < mdb->num_syncs; i ++)
1598 if (NULL != mdb->syncs[i])
1601 OOP_DisposeObject(mdb->syncs[i]);
1602 mdb->syncs[i] = NULL;
1606 FreeMem(mdb->syncs, sizeof (OOP_Object *) * mdb->num_syncs);
1607 mdb->syncs = NULL; mdb->num_syncs = 0;
1610 if (NULL != mdb->orig_mode_bm.bm)
1612 free_mode_bm(&mdb->orig_mode_bm, cl);
1615 if (NULL != mdb->checked_mode_bm.bm)
1617 free_mode_bm(&mdb->checked_mode_bm, cl);
1620 ReleaseSemaphore(&mdb->sema);
1622 return;
1625 /****************************************************************************************/
1627 /* Initializes default tagarray. in numtags the TAG_MORE is not accounted for,
1628 so the array must be of size NUM_TAGS + 1
1631 /****************************************************************************************/
1633 static VOID init_def_tags(struct TagItem *tags, ULONG numtags)
1635 ULONG i;
1637 for (i = 0; i < numtags; i ++)
1639 tags[i].ti_Tag = TAG_IGNORE;
1640 tags[i].ti_Data = 0UL;
1643 tags[i].ti_Tag = TAG_MORE;
1644 tags[i].ti_Data = 0UL;
1646 return;
1649 /****************************************************************************************/
1651 #define MAKE_SYNC(name,clock,hdisp,hstart,hend,htotal,vdisp,vstart,vend,vtotal,descr) \
1652 struct TagItem sync_ ## name[]={ \
1653 { aHidd_Sync_PixelClock, clock*1000 }, \
1654 { aHidd_Sync_HDisp, hdisp }, \
1655 { aHidd_Sync_HSyncStart, hstart }, \
1656 { aHidd_Sync_HSyncEnd, hend }, \
1657 { aHidd_Sync_HTotal, htotal }, \
1658 { aHidd_Sync_VDisp, vdisp }, \
1659 { aHidd_Sync_VSyncStart, vstart }, \
1660 { aHidd_Sync_VSyncEnd, vend }, \
1661 { aHidd_Sync_VTotal, vtotal }, \
1662 { aHidd_Sync_Description, (IPTR)descr}, \
1663 { TAG_DONE, 0UL }}
1665 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags)
1667 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1668 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1669 struct TagItem *tag, *tstate;
1670 struct HIDDGraphicsData *data;
1672 MAKE_SYNC(640x480_60, 25174,
1673 640, 656, 752, 800,
1674 480, 490, 492, 525,
1675 "Default:640x480");
1677 MAKE_SYNC(800x600_56, 36000, // 36000
1678 800, 824, 896, 1024,
1679 600, 601, 603, 625,
1680 "Default:800x600");
1682 MAKE_SYNC(1024x768_60, 65000, //78654=60kHz, 75Hz. 65000=50kHz,62Hz
1683 1024, 1048, 1184, 1344,
1684 768, 771, 777, 806,
1685 "Default:1024x768");
1687 MAKE_SYNC(1152x864_60, 80000,
1688 1152, 1216, 1328, 1456,
1689 864, 870, 875, 916,
1690 "Default:1152x864");
1692 MAKE_SYNC(1280x1024_60, 108880,
1693 1280, 1360, 1496, 1712,
1694 1024, 1025, 1028, 1060,
1695 "Default:1280x1024");
1697 MAKE_SYNC(1600x1200_60, 155982,
1698 1600, 1632, 1792, 2048,
1699 1200, 1210, 1218, 1270,
1700 "Default:1600x1200");
1702 /* "new" 16:10 modes */
1704 MAKE_SYNC(1280x800_60, 83530,
1705 1280, 1344, 1480, 1680,
1706 800, 801, 804, 828,
1707 "Default:1280x800");
1709 MAKE_SYNC(1440x900_60, 106470,
1710 1440, 1520, 1672, 1904,
1711 900, 901, 904, 932,
1712 "Default:1440x900");
1714 MAKE_SYNC(1680x1050_60, 147140,
1715 1680, 1784, 1968, 2256,
1716 1050, 1051, 1054, 1087,
1717 "Default:1680x1050");
1719 MAKE_SYNC(1920x1080_60, 173000,
1720 1920, 2048, 2248, 2576,
1721 1080, 1083, 1088, 1120,
1722 "Default:1920x1080");
1724 MAKE_SYNC(1920x1200_60, 154000,
1725 1920, 1968, 2000, 2080,
1726 1200, 1203, 1209, 1235,
1727 "Default:1920x1200");
1729 struct mode_db *mdb;
1731 HIDDT_PixelFormat pixfmt_data;
1733 struct TagItem def_sync_tags[num_Hidd_Sync_Attrs + 1];
1734 struct TagItem def_pixfmt_tags[num_Hidd_PixFmt_Attrs + 1];
1736 ULONG numpfs = 0,numsyncs = 0;
1737 ULONG pfidx = 0, syncidx = 0;
1739 struct TagItem temporary_tags[] = {
1740 { aHidd_Gfx_SyncTags, (IPTR)sync_640x480_60 },
1741 { aHidd_Gfx_SyncTags, (IPTR)sync_800x600_56 },
1742 { aHidd_Gfx_SyncTags, (IPTR)sync_1024x768_60 },
1743 { aHidd_Gfx_SyncTags, (IPTR)sync_1152x864_60 },
1744 { aHidd_Gfx_SyncTags, (IPTR)sync_1280x1024_60 },
1745 { aHidd_Gfx_SyncTags, (IPTR)sync_1600x1200_60 },
1746 { aHidd_Gfx_SyncTags, (IPTR)sync_1280x800_60 },
1747 { aHidd_Gfx_SyncTags, (IPTR)sync_1440x900_60 },
1748 { aHidd_Gfx_SyncTags, (IPTR)sync_1680x1050_60 },
1749 { aHidd_Gfx_SyncTags, (IPTR)sync_1920x1080_60 },
1750 { aHidd_Gfx_SyncTags, (IPTR)sync_1920x1200_60 },
1751 { TAG_MORE, 0UL }
1754 data = OOP_INST_DATA(cl, o);
1755 mdb = &data->mdb;
1756 InitSemaphore(&mdb->sema);
1758 memset(&pixfmt_data, 0, sizeof (pixfmt_data));
1760 init_def_tags(def_sync_tags, num_Hidd_Sync_Attrs);
1761 init_def_tags(def_pixfmt_tags, num_Hidd_PixFmt_Attrs);
1763 def_sync_tags[aoHidd_Sync_GfxHidd].ti_Tag = aHidd_Sync_GfxHidd;
1764 def_sync_tags[aoHidd_Sync_GfxHidd].ti_Data = (IPTR)o;
1766 /* First we need to calculate how much memory we are to allocate by counting supplied
1767 pixel formats and syncs */
1769 for (tstate = modetags; (tag = NextTagItem(&tstate));)
1771 ULONG idx;
1773 if (IS_GFX_ATTR(tag->ti_Tag, idx))
1775 switch (idx)
1777 case aoHidd_Gfx_PixFmtTags:
1778 numpfs++;
1779 break;
1781 case aoHidd_Gfx_SyncTags:
1782 numsyncs ++;
1783 break;
1785 default:
1786 break;
1791 if (0 == numpfs)
1793 D(bug("!!! WE MUST AT LEAST HAVE ONE PIXFMT IN Gfx::RegisterModes() !!!\n"));
1796 if (0 == numsyncs)
1798 D(bug("!!! NO SYNC IN Gfx::RegisterModes() !!!\n!!! USING DEFAULT MODES !!!\n"));
1799 temporary_tags[11].ti_Tag = TAG_MORE;
1800 temporary_tags[11].ti_Data = (IPTR)modetags;
1801 modetags = &temporary_tags[0];
1802 numsyncs = 11;
1805 ObtainSemaphore(&mdb->sema);
1807 /* Allocate memory for mode db */
1808 if (!alloc_mode_db(&data->mdb, numsyncs, numpfs, cl))
1809 goto failure;
1812 for (tstate = modetags; (tag = NextTagItem(&tstate));)
1814 /* Look for Gfx, PixFmt and Sync tags */
1815 ULONG idx;
1817 if (IS_GFX_ATTR(tag->ti_Tag, idx))
1819 switch (idx)
1821 case aoHidd_Gfx_PixFmtTags:
1822 def_pixfmt_tags[num_Hidd_PixFmt_Attrs].ti_Data = tag->ti_Data;
1823 mdb->pixfmts[pfidx] = GFX__Hidd_Gfx__RegisterPixFmt(cl, def_pixfmt_tags);
1825 if (NULL == mdb->pixfmts[pfidx])
1827 D(bug("!!! UNABLE TO CREATE PIXFMT OBJECT IN Gfx::RegisterModes() !!!\n"));
1828 goto failure;
1831 pfidx ++;
1832 break;
1834 case aoHidd_Gfx_SyncTags:
1835 def_sync_tags[num_Hidd_Sync_Attrs].ti_Data = tag->ti_Data;
1837 mdb->syncs[syncidx] = OOP_NewObject(CSD(cl)->syncclass, NULL, def_sync_tags);
1838 if (!mdb->syncs[syncidx]) {
1839 D(bug("!!! UNABLE TO CREATE SYNC OBJECT IN Gfx::RegisterModes() !!!\n"));
1840 goto failure;
1843 syncidx ++;
1844 break;
1848 else if (IS_SYNC_ATTR(tag->ti_Tag, idx))
1850 if (idx >= num_Hidd_Sync_Attrs)
1852 D(bug("!!! UNKNOWN SYNC ATTR IN Gfx::New(): %d !!!\n", idx));
1854 else
1856 def_sync_tags[idx].ti_Tag = tag->ti_Tag;
1857 def_sync_tags[idx].ti_Data = tag->ti_Data;
1861 else if (IS_PIXFMT_ATTR(tag->ti_Tag, idx))
1863 if (idx >= num_Hidd_PixFmt_Attrs)
1865 D(bug("!!! UNKNOWN PIXFMT ATTR IN Gfx::New(): %d !!!\n", idx));
1867 else
1869 def_pixfmt_tags[idx].ti_Tag = tag->ti_Tag;
1870 def_pixfmt_tags[idx].ti_Data = tag->ti_Data;
1875 ReleaseSemaphore(&mdb->sema);
1877 return TRUE;
1879 failure:
1881 /* mode db is freed in dispose */
1882 ReleaseSemaphore(&mdb->sema);
1884 return FALSE;
1887 /****************************************************************************************/
1889 struct modequery
1891 struct mode_db *mdb;
1892 ULONG minwidth;
1893 ULONG maxwidth;
1894 ULONG minheight;
1895 ULONG maxheight;
1896 HIDDT_StdPixFmt *stdpfs;
1897 ULONG numfound;
1898 ULONG pfidx;
1899 ULONG syncidx;
1900 BOOL dims_ok;
1901 BOOL stdpfs_ok;
1902 BOOL check_ok;
1903 OOP_Class *cl;
1906 /****************************************************************************************/
1908 /* This is a recursive function that looks for valid modes */
1910 /****************************************************************************************/
1912 static HIDDT_ModeID *querymode(struct modequery *mq)
1914 HIDDT_ModeID *modeids;
1915 register OOP_Object *pf;
1916 register OOP_Object *sync;
1917 BOOL mode_ok = FALSE;
1918 ULONG syncidx, pfidx;
1920 mq->dims_ok = FALSE;
1921 mq->stdpfs_ok = FALSE;
1922 mq->check_ok = FALSE;
1924 /* Look at the supplied idx */
1925 if (mq->pfidx >= mq->mdb->num_pixfmts)
1927 mq->pfidx = 0;
1928 mq->syncidx ++;
1931 if (mq->syncidx >= mq->mdb->num_syncs)
1933 /* We have reached the end of the recursion. Allocate memory and go back
1936 modeids = AllocVec(sizeof (HIDDT_ModeID) * (mq->numfound + 1), MEMF_ANY);
1937 /* Get the end of the array */
1938 modeids += mq->numfound;
1939 *modeids = vHidd_ModeID_Invalid;
1941 return modeids;
1944 syncidx = mq->syncidx;
1945 pfidx = mq->pfidx;
1946 /* Get the pf and sync objects */
1947 pf = mq->mdb->pixfmts[syncidx];
1948 sync = mq->mdb->syncs[pfidx];
1951 /* Check that the mode is really usable */
1952 if (is_valid_mode(&mq->mdb->checked_mode_bm, syncidx, pfidx))
1954 mq->check_ok = TRUE;
1957 /* See if this mode matches the criterias set */
1959 if ( SD(sync)->hdisp >= mq->minwidth
1960 && SD(sync)->hdisp <= mq->maxwidth
1961 && SD(sync)->vdisp >= mq->minheight
1962 && SD(sync)->vdisp <= mq->maxheight )
1966 mq->dims_ok = TRUE;
1968 if (NULL != mq->stdpfs)
1970 register HIDDT_StdPixFmt *stdpf = mq->stdpfs;
1971 while (*stdpf)
1973 if (*stdpf == PF(pf)->stdpixfmt)
1975 mq->stdpfs_ok = TRUE;
1977 stdpf ++;
1980 else
1982 mq->stdpfs_ok = TRUE;
1988 if (mq->dims_ok && mq->stdpfs_ok && mq->check_ok)
1990 mode_ok = TRUE;
1991 mq->numfound ++;
1994 mq->pfidx ++;
1996 modeids = querymode(mq);
1998 if (NULL == modeids)
1999 return NULL;
2001 if (mode_ok)
2003 /* The mode is OK. Add it to the list */
2004 modeids --;
2005 *modeids = COMPUTE_HIDD_MODEID(syncidx, pfidx);
2008 return modeids;
2012 /*****************************************************************************************
2014 NAME
2015 moHidd_Gfx_QueryModeIDs
2017 SYNOPSIS
2018 HIDDT_ModeID *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_QueryModeIDs *msg);
2020 HIDDT_ModeID *HIDD_Gfx_QueryModeIDs(OOP_Object *gfxHidd, struct TagItem *queryTags);
2022 LOCATION
2023 hidd.graphics.graphics
2025 FUNCTION
2026 Obtain a table of all supported display mode IDs
2028 The returned address points to an array of HIDDT_ModeID containing all ModeIDs
2029 supported by this driver. The array is terminated with vHidd_ModeID_Invalid.
2031 INPUTS
2032 gfxHidd - A driver object which to query.
2033 querytags - An optional taglist containing query options. Can be NULL.
2034 The following tags are supported:
2036 tHidd_GfxMode_MinWidth (ULONG) - A minimum width of modes you are
2037 interested in
2038 tHidd_GfxMode_MaxWidth (ULONG) - A maximum width of modes you are
2039 interested in
2040 tHidd_GfxMode_MinHeight (ULONG) - A minimum height of modes you are
2041 interested in
2042 tHidd_GfxMode_MaxHeight (ULONG) - A maximum height of modes you are
2043 interested in
2044 tHidd_GfxMode_PixFmts (HIDDT_StdPifXmt *) - A pointer to an array
2045 of standard pixelformat indexes. If supplied, only mode IDs whose
2046 pixelformat numbers match any of given ones will be returned.
2048 RESULT
2049 A pointer to an array of ModeIDs or NULL in case of failure
2051 NOTES
2053 EXAMPLE
2055 BUGS
2057 SEE ALSO
2058 moHidd_Gfx_ReleaseModeIDs, moHidd_Gfx_NextModeID
2060 INTERNALS
2062 *****************************************************************************************/
2064 HIDDT_ModeID *GFX__Hidd_Gfx__QueryModeIDs(OOP_Class *cl, OOP_Object *o,
2065 struct pHidd_Gfx_QueryModeIDs *msg)
2067 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
2068 struct TagItem *tag, *tstate;
2070 HIDDT_ModeID *modeids;
2071 struct HIDDGraphicsData *data;
2072 struct mode_db *mdb;
2074 struct modequery mq =
2076 NULL, /* mode db (set later) */
2077 0, 0xFFFFFFFF, /* minwidth, maxwidth */
2078 0, 0xFFFFFFFF, /* minheight, maxheight */
2079 NULL, /* stdpfs */
2080 0, /* numfound */
2081 0, 0, /* pfidx, syncidx */
2082 FALSE, FALSE, /* dims_ok, stdpfs_ok */
2083 FALSE, /* check_ok */
2084 NULL /* class (set later) */
2089 data = OOP_INST_DATA(cl, o);
2090 mdb = &data->mdb;
2091 mq.mdb = mdb;
2092 mq.cl = cl;
2094 for (tstate = msg->queryTags; (tag = NextTagItem(&tstate)); )
2096 switch (tag->ti_Tag)
2098 case tHidd_GfxMode_MinWidth:
2099 mq.minwidth = (ULONG)tag->ti_Tag;
2100 break;
2102 case tHidd_GfxMode_MaxWidth:
2103 mq.maxwidth = (ULONG)tag->ti_Tag;
2104 break;
2106 case tHidd_GfxMode_MinHeight:
2107 mq.minheight = (ULONG)tag->ti_Tag;
2108 break;
2110 case tHidd_GfxMode_MaxHeight:
2111 mq.maxheight = (ULONG)tag->ti_Tag;
2112 break;
2114 case tHidd_GfxMode_PixFmts:
2115 mq.stdpfs = (HIDDT_StdPixFmt *)tag->ti_Data;
2116 break;
2121 ObtainSemaphoreShared(&mdb->sema);
2123 /* Recursively check all modes */
2124 modeids = querymode(&mq);
2126 ReleaseSemaphore(&mdb->sema);
2128 return modeids;
2132 /*****************************************************************************************
2134 NAME
2135 moHidd_Gfx_ReleaseModeIDs
2137 SYNOPSIS
2138 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ReleaseModeIDs *msg);
2140 VOID HIDD_Gfx_ReleaseModeIDs(OOP_Object *gfxHidd, HIDDT_ModeID *modeIDs);
2142 LOCATION
2143 hidd.graphics.graphics
2145 FUNCTION
2146 Free array of display mode IDs returned by HIDD_Gfx_QueryModeIDs()
2148 INPUTS
2149 gfxHidd - A driver object used to obtain the array
2150 modeIDs - A pointer to an array
2152 RESULT
2153 None.
2155 NOTES
2157 EXAMPLE
2159 BUGS
2161 SEE ALSO
2162 moHidd_Gfx_QueryModeIDs
2164 INTERNALS
2166 *****************************************************************************************/
2168 VOID GFX__Hidd_Gfx__ReleaseModeIDs(OOP_Class *cl, OOP_Object *o,
2169 struct pHidd_Gfx_ReleaseModeIDs *msg)
2171 FreeVec(msg->modeIDs);
2174 /*****************************************************************************************
2176 NAME
2177 moHidd_Gfx_NextModeID
2179 SYNOPSIS
2180 HIDDT_ModeID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NextModeID *msg);
2182 HIDDT_ModeID HIDD_Gfx_NextModeID(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
2183 OOP_Object **syncPtr, OOP_Object **pixFmtPtr);
2185 LOCATION
2186 hidd.graphics.graphics
2188 FUNCTION
2189 Iterate driver's internal display mode database.
2191 INPUTS
2192 gfxHidd - A driver object to query
2193 modeID - A previous mode ID or vHidd_ModeID_Invalid for start of the iteration
2194 syncPtr - A pointer to a storage where pointer to sync object will be placed
2195 pixFmtPtr - A pointer to a storage where pointer to pixelformat object will be placed
2197 RESULT
2198 Next available mode ID or vHidd_ModeID_Invalid if there are no more display modes.
2199 If the function returns vHidd_ModeID_Invalid, sync and pixelformat pointers will
2200 be set to NULL.
2202 NOTES
2204 EXAMPLE
2206 BUGS
2208 SEE ALSO
2209 moHidd_Gfx_GetMode
2211 INTERNALS
2213 *****************************************************************************************/
2215 HIDDT_ModeID GFX__Hidd_Gfx__NextModeID(OOP_Class *cl, OOP_Object *o,
2216 struct pHidd_Gfx_NextModeID *msg)
2218 struct HIDDGraphicsData *data;
2219 struct mode_db *mdb;
2220 ULONG syncidx, pfidx;
2221 HIDDT_ModeID return_id = vHidd_ModeID_Invalid;
2222 BOOL found = FALSE;
2224 data = OOP_INST_DATA(cl, o);
2225 mdb = &data->mdb;
2227 ObtainSemaphoreShared(&mdb->sema);
2228 if (vHidd_ModeID_Invalid == msg->modeID)
2230 pfidx = 0;
2231 syncidx = 0;
2233 else
2235 pfidx = MODEID_TO_PFIDX( msg->modeID );
2236 syncidx = MODEID_TO_SYNCIDX( msg->modeID );
2238 /* Increament one from the last call */
2239 pfidx ++;
2240 if (pfidx >= mdb->num_pixfmts)
2242 pfidx = 0;
2243 syncidx ++;
2247 /* Search for a new mode. We only accept valid modes */
2248 for (; syncidx < mdb->num_syncs; syncidx ++)
2250 /* We only return valid modes */
2251 for (; pfidx < mdb->num_pixfmts; pfidx ++)
2253 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
2255 found = TRUE;
2256 break;
2259 if (found)
2260 break;
2263 if (found)
2265 return_id = COMPUTE_HIDD_MODEID(syncidx, pfidx);
2266 *msg->syncPtr = mdb->syncs[syncidx];
2267 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
2269 else
2271 *msg->syncPtr = *msg->pixFmtPtr = NULL;
2274 ReleaseSemaphore(&mdb->sema);
2276 return return_id;
2279 /*****************************************************************************************
2281 NAME
2282 moHidd_Gfx_GetMode
2284 SYNOPSIS
2285 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetMode *msg);
2287 BOOL HIDD_Gfx_GetMode(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
2288 OOP_Object **syncPtr, OOP_Object **pixFmtPtr);
2290 LOCATION
2291 hidd.graphics.graphics
2293 FUNCTION
2294 Get sync and pixelformat objects for a particular display ModeID.
2296 INPUTS
2297 gfxHidd - pointer to a driver object which this ModeID belongs to
2298 syncPtr - pointer to a storage where sync object pointer will be placed
2299 pixFmtPtr - pointer to a storage where pixelformat object pointer will be placed
2301 RESULT
2302 TRUE upon success, FALSE in case of failure (e.g. given mode does not exist in
2303 driver's internal database). If the function returns FALSE, sync and pixelformat
2304 pointers will be set to NULL.
2306 NOTES
2307 Every display mode is associated with some sync and pixelformat object. If the
2308 method returns TRUE, object pointers are guaranteed to be valid.
2310 EXAMPLE
2312 BUGS
2314 SEE ALSO
2315 moHidd_Gfx_NextModeID
2317 INTERNALS
2319 *****************************************************************************************/
2321 BOOL GFX__Hidd_Gfx__GetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMode *msg)
2323 ULONG pfidx, syncidx;
2324 struct HIDDGraphicsData *data;
2325 struct mode_db *mdb;
2326 BOOL ok = FALSE;
2328 data = OOP_INST_DATA(cl, o);
2329 mdb = &data->mdb;
2331 pfidx = MODEID_TO_PFIDX(msg->modeID);
2332 syncidx = MODEID_TO_SYNCIDX(msg->modeID);
2334 ObtainSemaphoreShared(&mdb->sema);
2336 if (! (pfidx >= mdb->num_pixfmts || syncidx >= mdb->num_syncs) )
2338 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
2340 ok = TRUE;
2341 *msg->syncPtr = mdb->syncs[syncidx];
2342 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
2346 ReleaseSemaphore(&mdb->sema);
2348 if (!ok)
2350 *msg->syncPtr = *msg->pixFmtPtr = NULL;
2353 return ok;
2356 /*****************************************************************************************
2358 NAME
2359 moHidd_Gfx_SetMode
2361 SYNOPSIS
2362 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetMode *msg);
2364 BOOL HIDD_Gfx_SetMode(OOP_Object *gfxHidd, OOP_Object *sync);
2366 LOCATION
2367 hidd.graphics.graphics
2369 FUNCTION
2370 Update display mode according to changed sync object
2372 INPUTS
2373 gfxHidd - A display driver to operate on
2374 sync - A modified sync object pointer
2376 RESULT
2377 TRUE if everything went OK and FALSE in case of some error
2379 NOTES
2380 This method is used to inform the driver that some external program has changed
2381 sync data and wants to update the display if needed. It's up to the implementation to
2382 check that current display is really using this sync (frontmost screen uses this mode).
2384 EXAMPLE
2386 BUGS
2388 SEE ALSO
2390 INTERNALS
2391 Base class implementation just returns FALSE indicating that this method is
2392 not supported.
2394 *****************************************************************************************/
2396 BOOL GFX__Hidd_Gfx__SetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetMode *msg)
2398 return FALSE;
2401 /****************************************************************************************/
2403 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm,
2404 OOP_Object *dst_bm, UWORD width, UWORD height)
2406 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2407 struct HIDDGraphicsData *data;
2408 ULONG i;
2409 IPTR numentries;
2410 OOP_Object *src_colmap;
2411 APTR psrc_colmap = &src_colmap;
2413 data = OOP_INST_DATA(cl, o);
2415 /* We have to copy the colormap into the framebuffer bitmap */
2416 OOP_GetAttr(src_bm, aHidd_BitMap_ColorMap, (IPTR *)psrc_colmap);
2417 OOP_GetAttr(src_colmap, aHidd_ColorMap_NumEntries, &numentries);
2419 for (i = 0; i < numentries; i ++)
2421 HIDDT_Color col;
2423 HIDD_CM_GetColor(src_colmap, i, &col);
2424 HIDD_BM_SetColors(dst_bm, &col, i, 1);
2427 if (data->fbmode == vHidd_FrameBuffer_Mirrored)
2430 * Mirror mode, just turn on visibility.
2431 * The data will be copied to the framebuffer later,
2432 * when graphics.library calls UpdateRect() after Show().
2434 BM__Hidd_BitMap__SetVisible(CSD(cl)->bitmapclass, src_bm, TRUE);
2436 else
2439 * Direct framebuffer mode.
2440 * graphics.library will call UpdateRect() on the framebuffer object.
2441 * So we need to copy the data now.
2442 * We don't support scrolling for this mode, so we simply do the
2443 * bulk copy and ignore all offsets.
2445 HIDD_Gfx_CopyBox(o, src_bm, 0, 0,
2446 dst_bm, 0, 0, width, height, data->gc);
2450 /*****************************************************************************************
2452 NAME
2453 moHidd_Gfx_Show
2455 SYNOPSIS
2456 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Show *msg);
2458 OOP_Object *HIDD_Gfx_Show(OOP_Object *gfxHidd, OOP_Object *bitMap, ULONG flags);
2460 LOCATION
2461 hidd.graphics.graphics
2463 FUNCTION
2464 Change currently displayed bitmap on the screen.
2466 The bitmap object supplied must have been created with aHidd_BitMap_Displayable
2467 attribute set to TRUE.
2469 The function's behavior differs a lot depending on whether the driver uses a
2470 framebuffer or video hardware is able to switch screens itself.
2472 If the driver uses a framebuffer bitmap, it is supposed to copy the supplied bitmap
2473 into the framebuffer and return a framebuffer pointer. It also can be asked to
2474 copy back old framebuffer contents into previous bitmap object. It is driver's
2475 job to keep track of which bitmap object was displayed last time. This is what
2476 default implementation does. Note that it is very basic, and even does not support
2477 changing display resolution. It's not recommended to rely on it in production
2478 drivers (unless your video hardware supports only one mode).
2480 If the driver does not use a framebuffer, it is supposed to reprogram the hardware
2481 here to display an appropriate region of video RAM. Do not call the base class
2482 in this case, its implementation relies on framebuffer existance and will always
2483 return NULL which indicates an error.
2485 It is valid to get NULL value in bitMap parameter. This means that there is
2486 nothing to display and the screen needs to be blanked out. It is valid for
2487 non-framebuffer-based driver to return NULL as a reply then. In all other cases
2488 NULL return value means an error.
2490 Please avoid returning errors at all. graphics.library/LoadView() has no error
2491 indication. An error during showing a bitmap would leave the display in
2492 unpredictable state.
2494 If the driver does not use a framebuffer, consider using HIDD_Gfx_ShowViewPorts().
2495 It's more straightforward, flexible and offers support for screen composition.
2497 INPUTS
2498 gfxHidd - a display driver object, whose display you wish to change.
2499 bitMap - a pointer to a bitmap object which needs to be shown or NULL.
2500 flags - currently only one flag is defined:
2502 fHidd_Gfx_Show_CopyBack - Copy back the image data from framebuffer bitmap
2503 to old displayed bitmap. Used only if the driver
2504 needs a framebuffer.
2506 RESULT
2507 A pointer to a currently displayed bitmap object or NULL (read FUNCTION paragraph for
2508 detailed description)
2510 NOTES
2511 Drivers which use mirrored video data buffer do not have to update the display
2512 immediately in this method. moHidd_BitMap_UpdateRect will be sent to the returned
2513 bitmap if it's not NULL. Of course display blanking (if NULL bitmap was received)
2514 needs to be performed immediately.
2516 EXAMPLE
2518 BUGS
2520 SEE ALSO
2521 moHidd_Gfx_ShowViewPorts, graphics.library/LoadView()
2523 INTERNALS
2525 *****************************************************************************************/
2527 OOP_Object *GFX__Hidd_Gfx__Show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
2529 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2530 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
2531 OOP_Object *bm = msg->bitMap;
2532 IPTR oldwidth = 0;
2533 IPTR oldheight = 0;
2534 IPTR newwidth = 0;
2535 IPTR newheight = 0;
2537 if (NULL == data->framebuffer)
2539 /* We require framebuffer. Don't call us otherwise. */
2540 return NULL;
2543 ObtainSemaphore(&data->fbsem);
2545 if (data->shownbm)
2547 /* Get size of old bitmap */
2548 OOP_GetAttr(data->shownbm, aHidd_BitMap_Width, &oldwidth);
2549 OOP_GetAttr(data->shownbm, aHidd_BitMap_Height, &oldheight);
2551 if (data->fbmode == vHidd_FrameBuffer_Mirrored)
2553 BM__Hidd_BitMap__SetVisible(CSD(cl)->bitmapclass, data->shownbm, FALSE);
2555 else if (msg->flags & fHidd_Gfx_Show_CopyBack)
2557 /* Copy the framebuffer data back into the old shown bitmap */
2558 copy_bm_and_colmap(cl, o, data->framebuffer, data->shownbm, oldwidth, oldheight);
2562 if (bm == data->framebuffer)
2564 /* If showing the framebuffer itself, just detach from old bitmap and that's all. */
2565 data->shownbm = NULL;
2566 ReleaseSemaphore(&data->fbsem);
2568 return data->framebuffer;
2571 if (bm)
2573 IPTR modeid;
2576 * Switch framebuffer display mode.
2577 * This operation can fail if the bitmap has inappropriate mode.
2579 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
2580 if (!OOP_SetAttrsTags(data->framebuffer, aHidd_BitMap_ModeID, modeid, TAG_DONE))
2581 return NULL;
2583 /* Get size of new bitmap */
2584 OOP_GetAttr(bm, aHidd_BitMap_Width, &newwidth);
2585 OOP_GetAttr(bm, aHidd_BitMap_Height, &newheight);
2587 /* Copy it into the framebuffer */
2588 copy_bm_and_colmap(cl, o, bm, data->framebuffer, newwidth, newheight);
2592 * Clear remaining parts of the framebuffer (if previous bitmap was larger than new one)
2593 * Note that if the new bitmap is NULL, newwidth and newheight will both be zero.
2594 * This will cause clearing the whole display.
2596 if (oldheight) /* width and height can be zero only together, check one of them */
2598 if (newwidth < oldwidth)
2599 HIDD_BM_FillRect(data->framebuffer, data->gc, newwidth, 0, oldwidth - 1, oldheight - 1);
2600 if ((newheight < oldheight) && newwidth)
2601 HIDD_BM_FillRect(data->framebuffer, data->gc, 0, newheight, newwidth - 1, oldheight);
2604 /* Remember new displayed bitmap */
2605 data->shownbm = bm;
2607 ReleaseSemaphore(&data->fbsem);
2609 /* Return the actual bitmap to perform further operations on */
2610 return (data->fbmode == vHidd_FrameBuffer_Mirrored) ? bm : data->framebuffer;
2613 /*****************************************************************************************
2615 NAME
2616 moHidd_Gfx_ShowViewPorts
2618 SYNOPSIS
2619 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ShowViewPorts *msg);
2621 ULONG HIDD_Gfx_ShowViewPorts(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data, struct View *view);
2623 LOCATION
2624 hidd.graphics.graphics
2626 FUNCTION
2627 Show one or more bitmaps on the screen.
2629 It is completely up to the driver how to implement this function. The driver may
2630 or may not support hardware-assisted screens composition. Bitmaps are sorted
2631 in the list in descending z-order. The driver is expected to put at least frontmost
2632 bitmap on display.
2634 It is valid to get NULL pointer as data parameter. This means that there's
2635 nothing to show and the screen should go blank.
2637 Bitmaps display offsets are stored in their aHidd_BitMap_LeftEdge and
2638 aHidd_BitMap_TopEdge attributes. This function is not expected to modify their
2639 values somehow. They are assumed to be preserved between calls unless changed
2640 explicitly by the system.
2642 If you implement this method, you don't have to implement HIDD_Gfx_Show() because
2643 it will never be called.
2645 Note that there is no more error indication - the driver is expected to be
2646 error-free here.
2648 INPUTS
2649 gfxHidd - a display driver object, whose display you wish to change.
2650 data - a singly linked list of bitmap objects to show
2652 RESULT
2653 TRUE if this method is supported by the driver, FALSE otherwise
2655 NOTES
2657 EXAMPLE
2659 BUGS
2661 SEE ALSO
2662 moHidd_Gfx_Show
2664 INTERNALS
2665 Default base class implementation simply returns FALSE. This causes
2666 the system to use HIDD_Gfx_Show() instead.
2668 *****************************************************************************************/
2670 ULONG GFX__Hidd_Gfx__ShowViewPorts(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ShowViewPorts *msg)
2672 /* By default we don't support screen composition (and this method too) */
2673 return FALSE;
2676 /*****************************************************************************************
2678 NAME
2679 moHidd_Gfx_SetCursorShape
2681 SYNOPSIS
2682 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorShape *msg);
2684 BOOL HIDD_Gfx_SetCursorShape(OOP_Object *gfxHidd, OOP_Object *shape,
2685 WORD xoffset, WORD yoffset);
2687 LOCATION
2688 hidd.graphics.graphics
2690 FUNCTION
2691 Set mouse pointer shape.
2693 A pointer image is contained in the specified bitmap object. The bitmap object
2694 may contain a colormap if the system wants to specify own colors for the pointer.
2695 The supplied colormap will also contain alpha channel values.
2697 It is up to driver what to do if, for example, alpha channel is not supported by
2698 the hardware. Or if given bitmap type is not supported (for example truecolor
2699 bitmap on LUT-only hardware). It is expected that the driver converts bitmap
2700 data to a more appropriate form in such a case.
2702 A hotspot is given as an offset from the actual hotspot to the top-left corner
2703 of the pointer image. It is generally needed only for hosted display drivers
2704 which utilize host's support for mouse pointer.
2706 The default implementation in the base class just does nothing. A software mouse
2707 pointer is implemented in a special layer called fakegfx.hidd inside
2708 graphics.library. If a software pointer emulation is used, this method will
2709 never be called.
2711 INPUTS
2712 gfxHidd - a display driver object, for whose display you wish to change the pointer
2713 shape - a pointer to a bitmap object, containing pointer bitmap
2714 xoffset - a horizontal hotspot offset
2715 yoffset - a vertical hotspot offset
2717 RESULT
2718 TRUE on success, FALSE on failure
2720 NOTES
2722 EXAMPLE
2724 BUGS
2726 SEE ALSO
2727 moHidd_Gfx_SetCursorPos, moHidd_Gfx_SetCursorVisible
2729 INTERNALS
2731 *****************************************************************************************/
2733 BOOL GFX__Hidd_Gfx__SetCursorShape(OOP_Class *cl, OOP_Object *o,
2734 struct pHidd_Gfx_SetCursorShape *msg)
2736 /* We have no clue how to render the cursor */
2737 return TRUE;
2740 /*****************************************************************************************
2742 NAME
2743 moHidd_Gfx_SetCursorVisible
2745 SYNOPSIS
2746 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorVisible *msg);
2748 VOID HIDD_Gfx_SetCursorVisible(OOP_Object *gfxHidd, BOOL visible);
2750 LOCATION
2751 hidd.graphics.graphics
2753 FUNCTION
2754 Control mouse pointer visiblity.
2756 The default implementation in the base class does nothing. If a software pointer
2757 emulation is used, this method will never be called.
2759 INPUTS
2760 gfxHidd - a display driver object, on whose display you wish to turn
2761 pointer on or off
2762 visible - TRUE to enable pointer display, FALSE to disable it
2764 RESULT
2765 None.
2767 NOTES
2769 EXAMPLE
2771 BUGS
2773 SEE ALSO
2774 moHidd_Gfx_SetCursorPos, moHidd_Gfx_SetCursorVisible
2776 INTERNALS
2778 *****************************************************************************************/
2780 VOID GFX__Hidd_Gfx__SetCursorVisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
2785 /*****************************************************************************************
2787 NAME
2788 moHidd_Gfx_SetCursorPos
2790 SYNOPSIS
2791 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorPos *msg);
2793 BOOL HIDD_Gfx_SetCursorPos(OOP_Object *gfxHidd, WORD x, WORD y);
2795 LOCATION
2796 hidd.graphics.graphics
2798 FUNCTION
2799 Set current mouse pointer position.
2801 This is a real position on top-left image corner relative to top-left corner of
2802 the physical display. Neither logical screen origin nor hotspot are taken into
2803 account here.
2805 The default implementation in the base class does nothing and just returns TRUE.
2806 If a software pointer emulation is used, this method will never be called.
2808 INPUTS
2809 gfxHidd - a display driver object, on whose display you wish to position the pointer
2810 x - An x coordinate of the pointer (relative to the physical screen origin)
2811 y - A y coordinate of the pointer (relative to the physical screen origin)
2813 RESULT
2814 Always TRUE. Reserved for future, do not use it.
2816 NOTES
2817 This method is called by graphics.library/MoveSprite() which has no return value.
2818 However, for historical reasons, this method has a return value. Drivers should
2819 always return TRUE in order to ensure future compatibility.
2821 EXAMPLE
2823 BUGS
2825 SEE ALSO
2826 moHidd_Gfx_SetCursorShape, moHidd_Gfx_SetCursorVisible, graphics.library/MoveSprite()
2828 INTERNALS
2830 *****************************************************************************************/
2832 BOOL GFX__Hidd_Gfx__SetCursorPos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
2834 return TRUE;
2837 /*****************************************************************************************
2839 NAME
2840 moHidd_Gfx_CopyBox
2842 SYNOPSIS
2843 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg);
2845 VOID HIDD_Gfx_CopyBox(OOP_Object *gfxHidd, OOP_Object *src, WORD srcX, WORD srcY,
2846 OOP_Object *dest, WORD destX, WORD destY, UWORD width, UWORD height,
2847 OOP_Object *gc);
2849 LOCATION
2850 hidd.graphics.graphics
2852 FUNCTION
2853 Perform rectangle copy (blit) operation from one bitmap to another.
2855 Given bitmaps may belong to different display drivers. The driver may attempt to
2856 use hardware for acceleration (if available), and if it's impossible, pass the
2857 operation on to the base class.
2859 Always check class of the supplied bitmap before attempting to look at its
2860 private data.
2862 A GC is used in order to specify raster operation performed between the source
2863 and destination according to its aHidd_GC_DrawMode attribute value.
2865 INPUTS
2866 gfxHidd - a display driver object that you are going to use for copying
2867 src - a pointer to source bitmap object
2868 srcX - an X coordinate of the source rectangle
2869 srcY - a Y coordinate of the source rectangle
2870 dest - a pointer to destination bitmap object
2871 destX - an X coordinate of the destination rectangle
2872 destY - a Y coordinate of the destination rectangle
2873 width - width of the rectangle to copy
2874 height - height of the rectangle to copy
2875 gc - graphics context holding draw mode on the destination
2877 RESULT
2878 None.
2880 NOTES
2881 You must specify valid coordinates (non-negative and inside the actual bitmap
2882 area), no checks are done.
2884 It is valid to specify two overlapped areas of the same bitmap as source
2885 and destination.
2887 EXAMPLE
2889 BUGS
2891 SEE ALSO
2893 INTERNALS
2895 *****************************************************************************************/
2897 VOID GFX__Hidd_Gfx__CopyBox(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg)
2899 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2900 WORD x, y;
2901 WORD srcX = msg->srcX, destX = msg->destX;
2902 WORD srcY = msg->srcY, destY = msg->destY;
2903 WORD startX, endX, deltaX, startY, endY, deltaY;
2904 ULONG memFG;
2905 HIDDT_PixelFormat *srcpf, *dstpf;
2906 OOP_Object *dest, *src;
2907 OOP_Object *gc;
2908 APTR srcPixels = NULL;
2909 APTR destPixels = NULL;
2911 dest = msg->dest;
2912 src = msg->src;
2914 /* If source/dest overlap, direction of operation is important */
2916 if (srcX < destX)
2918 startX = msg->width - 1; endX = -1; deltaX = -1;
2920 else
2922 startX = 0; endX = msg->width; deltaX = 1;
2925 if (srcY < destY)
2927 startY = msg->height - 1; endY = -1; deltaY = -1;
2929 else
2931 startY = 0; endY = msg->height; deltaY = 1;
2934 /* Get the source pixel format */
2935 srcpf = (HIDDT_PixelFormat *)HBM(src)->prot.pixfmt;
2937 DCOPYBOX(bug("COPYBOX: obj=0x%p (%s), src=0x%p at (%d, %d), dst=0x%p at (%d, %d), size=%dx%d\n", obj, OOP_OCLASS(obj)->ClassNode.ln_Name,
2938 msg->src, srcX, srcY, msg->dest, destX, destY, msg->width, msg->height));
2939 DCOPYBOX(bug("COPYBOX: GC=0x%p, DrawMode %ld, ColMask 0x%08X\n", msg->gc, GC_DRMD(msg->gc), GC_COLMASK(msg->gc)));
2941 #ifdef COPYBOX_DUMP_DIMS
2943 IPTR sw, sh, dw, dh;
2945 OOP_GetAttr(obj, aHidd_BitMap_Width, &sw);
2946 OOP_GetAttr(obj, aHidd_BitMap_Height, &sh);
2947 OOP_GetAttr(msg->dest, aHidd_BitMap_Width, &dw);
2948 OOP_GetAttr(msg->dest, aHidd_BitMap_Height, &dh);
2950 bug("src dims: %dx%d dest dims: %dx%d\n", sw, sh, dw, dh);
2952 #endif
2954 dstpf = (HIDDT_PixelFormat *)HBM(dest)->prot.pixfmt;
2956 OOP_GetAttr(msg->src, aHidd_ChunkyBM_Buffer, (APTR)&srcPixels);
2957 OOP_GetAttr(msg->dest, aHidd_ChunkyBM_Buffer, (APTR)&destPixels);
2959 if (srcPixels && destPixels)
2962 * Both bitmaps are chunky ones and they have directly accessible buffer.
2963 * We can use optimized routines to do the copy.
2965 IPTR src_bytesperline, dest_bytesperline;
2967 OOP_GetAttr(msg->src, aHidd_BitMap_BytesPerRow, &src_bytesperline);
2968 OOP_GetAttr(msg->dest, aHidd_BitMap_BytesPerRow, &dest_bytesperline);
2970 switch(GC_DRMD(msg->gc))
2972 case vHidd_GC_DrawMode_Copy:
2973 /* At the moment we optimize only bulk copy */
2975 if (srcpf == dstpf)
2978 * The same pixelformat. Extremely great!
2980 * FIXME: Bulk copy to the same pixelformat is also handled in ConvertPixels very well
2981 * (optimized to either per-line or bulk memcpy()). But it can't handle
2982 * overlapping regions (which seems to be a requirement for CopyBox).
2983 * If this is fixed, we can even throw away HIDD_BM_CopyMemBoxXX at all, reducing
2984 * kickstart size.
2986 switch(srcpf->bytes_per_pixel)
2988 case 1:
2990 * In fact all these methods are static, they ignore object pointer, and it's
2991 * needed only for OOP_DoMethod() to fetch class information.
2992 * We use destination bitmap pointer, we can also source one.
2994 HIDD_BM_CopyMemBox8(msg->dest,
2995 srcPixels, msg->srcX, msg->srcY,
2996 destPixels, msg->destX, msg->destY,
2997 msg->width, msg->height,
2998 src_bytesperline, dest_bytesperline);
2999 return;
3001 case 2:
3002 HIDD_BM_CopyMemBox16(msg->dest,
3003 srcPixels, msg->srcX, msg->srcY,
3004 destPixels, msg->destX, msg->destY,
3005 msg->width, msg->height,
3006 src_bytesperline, dest_bytesperline);
3007 return;
3009 case 3:
3010 HIDD_BM_CopyMemBox24(msg->dest,
3011 srcPixels, msg->srcX, msg->srcY,
3012 destPixels, msg->destX, msg->destY,
3013 msg->width, msg->height,
3014 src_bytesperline, dest_bytesperline);
3015 return;
3017 case 4:
3018 HIDD_BM_CopyMemBox32(msg->dest,
3019 srcPixels, msg->srcX, msg->srcY,
3020 destPixels, msg->destX, msg->destY,
3021 msg->width, msg->height,
3022 src_bytesperline, dest_bytesperline);
3023 return;
3025 } /* switch(srcpf->bytes_per_pixel) */
3026 } /* srcpf == dstpf */
3027 else
3030 * Pixelformats are different. This can't be the same bitmap,
3031 * and it's safe to use ConvertPixels method (see FIXME above).
3033 srcPixels += (msg->srcY * src_bytesperline ) + (msg->srcX * srcpf->bytes_per_pixel);
3034 destPixels += (msg->destY * dest_bytesperline) + (msg->destX * dstpf->bytes_per_pixel);
3037 * Supply NULL pixlut. In this case bitmap's own colormap will be used
3038 * for color lookup (if needed).
3040 HIDD_BM_ConvertPixels(msg->dest,
3041 &srcPixels, srcpf, src_bytesperline,
3042 &destPixels, dstpf, dest_bytesperline,
3043 msg->width, msg->height, NULL);
3045 return;
3048 break;
3050 /* TODO: Optimize other DrawModes here */
3052 } /* switch(mode) */
3054 } /* srcPixels && destPixels */
3056 gc = msg->gc;
3058 memFG = GC_FG(msg->gc);
3060 /* All else have failed, copy pixel by pixel */
3061 if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf))
3063 if (IS_TRUECOLOR(srcpf))
3065 DCOPYBOX(bug("COPY FROM TRUECOLOR TO TRUECOLOR\n"));
3067 for(y = startY; y != endY; y += deltaY)
3069 HIDDT_Color col;
3071 /* if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
3072 bug("[%d,%d] ", memSrcX, memDestX);
3074 for(x = startX; x != endX; x += deltaX)
3076 HIDDT_Pixel pix = GETPIXEL(cl, src, srcX + x, srcY + y);
3078 #if COPYBOX_CHECK_FOR_ALIKE_PIXFMT
3079 if (srcpf == dstpf)
3081 GC_FG(gc) = pix;
3083 else
3084 #endif
3086 HIDD_BM_UnmapPixel(src, pix, &col);
3087 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, &col);
3090 DRAWPIXEL(cl, dest, gc, destX + x, destY + y);
3092 /*if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
3093 bug("[%d,%d] ", srcY, destY);
3097 } /* if (IS_TRUECOLOR(srcpf)) */
3098 else
3100 /* Two palette bitmaps.
3101 For this case we do NOT convert through RGB,
3102 but copy the pixel indexes directly
3104 DCOPYBOX(bug("COPY FROM PALETTE TO PALETTE\n"));
3106 /* FIXME: This might not work very well with two StaticPalette bitmaps */
3108 for(y = startY; y != endY; y += deltaY)
3110 for(x = startX; x != endX; x += deltaX)
3112 GC_FG(gc) = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3114 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
3119 } /* if (IS_TRUECOLOR(srcpf)) else ... */
3121 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) */
3122 else
3124 /* Two unlike bitmaps */
3125 if (IS_TRUECOLOR(srcpf))
3127 for(y = startY; y != endY; y += deltaY)
3129 for(x = startX; x != endX; x += deltaX)
3131 HIDDT_Pixel pix;
3132 HIDDT_Color col;
3134 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3135 HIDD_BM_UnmapPixel(src, pix, &col);
3137 HIDD_BM_PutPixel(dest, destX + x, destY + y,
3138 HIDD_BM_MapColor(dest, &col));
3142 else if (IS_TRUECOLOR(dstpf))
3144 /* Get the colortab */
3145 HIDDT_Color *ctab = ((HIDDT_ColorLUT *)HBM(src)->colmap)->colors;
3147 DCOPYBOX(bug("COPY FROM PALETTE TO TRUECOLOR, DRAWMODE %d, CTAB %p\n", GC_DRMD(gc), ctab));
3149 for(y = startY; y != endY; y += deltaY)
3151 for(x = startX; x != endX; x += deltaX)
3153 register HIDDT_Pixel pix;
3154 register HIDDT_Color *col;
3156 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3157 col = &ctab[pix];
3159 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, col);
3160 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
3166 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) else ... */
3168 GC_FG(gc) = memFG;
3171 /*****************************************************************************************
3173 NAME
3174 moHidd_Gfx_CopyBoxMasked
3176 SYNOPSIS
3177 IPTR OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CopyBoxMasked *msg);
3179 IPTR HIDD_Gfx_CopyBoxMasked(OOP_Object *gfxHidd, OOP_Object *src, WORD srcX, WORD srcY,
3180 OOP_Object *dest, WORD destX, WORD destY, UWORD width, UWORD height,
3181 PLANEPTR mask, OOP_Object *gc);
3183 LOCATION
3184 hidd.graphics.graphics
3186 FUNCTION
3187 Perform rectangle copy (blit) operation from one bitmap to another,
3188 using a cookie cutter mask.
3190 Given bitmaps must be on the same display driver.
3192 A GC is used in order to specify raster operation performed between the source
3193 and destination according to its aHidd_GC_DrawMode attribute value.
3195 INPUTS
3196 gfxHidd - a display driver object that you are going to use for copying
3197 src - a pointer to source bitmap object
3198 srcX - an X coordinate of the source rectangle
3199 srcY - a Y coordinate of the source rectangle
3200 dest - a pointer to destination bitmap object
3201 destX - an X coordinate of the destination rectangle
3202 destY - a Y coordinate of the destination rectangle
3203 width - width of the rectangle to copy
3204 height - height of the rectangle to copy
3205 mask - single bitplane mask
3206 gc - graphics context holding draw mode on the destination
3208 RESULT
3209 TRUE is the operation succeeded and FALSE in case of some error, for example
3210 if the system was too low on memory.
3212 NOTES
3213 You must specify valid coordinates (non-negative and inside the actual bitmap
3214 area), no checks are done.
3216 It is valid to specify two overlapped areas of the same bitmap as source
3217 and destination.
3219 Mask size must correspond to full source bitmap size (including alignment).
3221 EXAMPLE
3223 BUGS
3225 SEE ALSO
3227 INTERNALS
3229 *****************************************************************************************/
3231 /* Nominal size of the pixel conversion buffer */
3232 #ifdef __mc68000
3233 #define NUMPIX 4096 /* Not that much room to spare */
3234 #else
3235 #define NUMPIX 100000
3236 #endif
3238 IPTR GFX__Hidd_Gfx__CopyBoxMasked(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBoxMasked *msg)
3240 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3241 ULONG pixfmt = vHidd_StdPixFmt_Native32;
3242 OOP_Object *src_pf, *dest_pf;
3243 HIDDT_ColorModel src_colmod, dest_colmod;
3244 HIDDT_Color *ctab = NULL;
3245 ULONG bytes_per_line, lines_per_step, doing_lines, lines_done;
3246 IPTR mask_align, mask_bpr;
3247 UBYTE *srcbuf;
3249 OOP_GetAttr(msg->src , aHidd_BitMap_PixFmt, (IPTR *)&src_pf);
3250 OOP_GetAttr(msg->dest, aHidd_BitMap_PixFmt, (IPTR *)&dest_pf);
3252 OOP_GetAttr(src_pf, aHidd_PixFmt_ColorModel, &src_colmod);
3253 OOP_GetAttr(dest_pf, aHidd_PixFmt_ColorModel, &dest_colmod);
3255 if ((src_colmod == vHidd_ColorModel_Palette) && (dest_colmod == vHidd_ColorModel_TrueColor))
3258 * LUT->truecolor conversion. We need a colormap (palette).
3259 * If the source is displayable (screen) bitmap, it will have own palette. In this case
3260 * we should use it.
3261 * If it's just a bitmap in memory, it won't have a palette (colmap will be NULL). In this
3262 * case destination bitmap needs to have a palette. This will happen if it's either a displayable
3263 * bitmap, or is a friend of displayable bitmap (will share friend's palette then).
3265 HIDDT_ColorLUT *colmap = (HIDDT_ColorLUT *)HBM(msg->src)->colmap;
3267 if (!colmap)
3268 colmap = (HIDDT_ColorLUT *)HBM(msg->dest)->colmap;
3270 if (!colmap)
3272 D(bug("BltMaskBitMapRastPort could not retrieve pixel table for blit from palette to truecolor bitmap"));
3273 return FALSE;
3276 ctab = colmap->colors;
3278 else if ((src_colmod == vHidd_ColorModel_TrueColor) && (dest_colmod == vHidd_ColorModel_TrueColor))
3280 if (src_pf != dest_pf)
3283 * Pixelformats are different, conversion needed.
3284 * First, we use two operations on destination bitmap (get and put), and only one
3285 * operation on source bitmap (get).
3286 * Second, we map LUT source pixels on destination bitmap's pixelformat.
3287 * Resume: we use destination's pixelformat for the whole operation. Conversion
3288 * happens during GetImage on the source bitmap.
3290 OOP_GetAttr(dest_pf, aHidd_PixFmt_StdPixFmt, (IPTR *)&pixfmt);
3293 else if ((src_colmod == vHidd_ColorModel_TrueColor) && (dest_colmod == vHidd_ColorModel_Palette))
3295 D(bug("BltMaskBitMapRastPort from truecolor bitmap to palette bitmap not supported!"));
3296 return FALSE;
3299 /* Mask width in pixels corresponds to full bitmap width (including alignment) */
3300 OOP_GetAttr(msg->src, aHidd_BitMap_Width, &mask_bpr);
3301 OOP_GetAttr(msg->src, aHidd_BitMap_Align, &mask_align);
3303 mask_align--;
3304 mask_bpr = ((mask_bpr + mask_align) & ~mask_align) >> 3;
3307 * TODO: Here we use a temporary buffer to perform the operation. This is slow and
3308 * actually unnecessary is many cases. If one of source or destination bitmaps is
3309 * directly accessible, we should use their own buffers. This will increase the speed
3310 * and decrease memory usage, because of omitted copy operations.
3313 /* Based on the NUMPIX advice, figure out how many
3314 * lines per step we can allocate
3316 bytes_per_line = msg->width * sizeof(HIDDT_Pixel);
3317 lines_per_step = NUMPIX / bytes_per_line;
3318 if (lines_per_step == 0)
3319 lines_per_step = 1;
3321 /* Allocate a temporary buffer */
3322 srcbuf = AllocMem(2 * lines_per_step * bytes_per_line, MEMF_ANY);
3324 /* Try line-at-a-time if we can't allocate a big buffer */
3325 if (!srcbuf && lines_per_step > 1)
3327 lines_per_step = 1;
3328 srcbuf = AllocMem(2 * lines_per_step * bytes_per_line, MEMF_ANY);
3331 if (srcbuf)
3333 UBYTE *destbuf = srcbuf + lines_per_step * bytes_per_line;
3334 HIDDT_DrawMode drawmode = GC_DRMD(msg->gc);
3336 /* PutImage needs to be called in Copy mode for proper operation */
3337 GC_DRMD(msg->gc) = vHidd_GC_DrawMode_Copy;
3339 for (lines_done = 0; lines_done != msg->height; lines_done += doing_lines)
3341 HIDDT_Pixel *srcpixelbuf;
3342 HIDDT_Pixel *destpixelbuf;
3343 UBYTE *mask;
3344 UWORD x, y;
3346 doing_lines = lines_per_step;
3347 if (lines_done + doing_lines > msg->height)
3348 doing_lines = msg->height - lines_done;
3350 HIDD_BM_GetImage(msg->src, srcbuf, bytes_per_line,
3351 msg->srcX, msg->srcY + lines_done,
3352 msg->width, doing_lines, pixfmt);
3354 HIDD_BM_GetImage(msg->dest, destbuf, bytes_per_line,
3355 msg->destX, msg->destY + lines_done,
3356 msg->width, doing_lines, pixfmt);
3358 mask = &msg->mask[COORD_TO_BYTEIDX(0, msg->srcY + lines_done, mask_bpr)];
3360 srcpixelbuf = (HIDDT_Pixel *)srcbuf;
3361 destpixelbuf = (HIDDT_Pixel *)destbuf;
3363 switch (drawmode)
3365 case vHidd_GC_DrawMode_Or: /* (ABC|ABNC|ANBC) if copy source and blit thru mask */
3366 case vHidd_GC_DrawMode_Copy: /* (ABC|ABNC = 0xC0) - compatibility with AOS3 */
3367 for (y = 0; y < doing_lines; y++)
3369 for (x = 0; x < msg->width; x++)
3371 if (mask[XCOORD_TO_BYTEIDX(msg->srcX + x)] & XCOORD_TO_MASK(msg->srcX + x))
3373 HIDDT_Pixel pix = *srcpixelbuf;
3375 if (ctab)
3378 * TODO:
3379 * Here and in several other places we use colormap data for palette->truecolor conversion.
3380 * The algorithm is as follows: take LUT pixel value (which is effectively color index), find RGB
3381 * entry in the LUT, then compose a pixel from RGB triplet using MapColor method on the destination
3382 * bitmap.
3383 * This two-step operation is slow. graphics.library internally uses cached version of the palette
3384 * (HIDDT_PixLut), where all colors are already decoded into pixel values.
3385 * Since HIDD subsystem also needs this, this pixlut (called pixtab - pixel table in graphics.library),
3386 * should be moved here. In fact a good place for it is a bitmap object (since pixlut = colormap + pixfmt,
3387 * and pixfmt is a bitmap's property.
3388 * graphics.library has pixlut attached to a BitMap structure (using HIDD_BM_PIXTAB() macro).
3390 pix = HIDD_BM_MapColor(msg->dest, &ctab[pix]);
3393 *destpixelbuf = pix;
3395 srcpixelbuf++;
3396 destpixelbuf++;
3398 mask += mask_bpr;
3400 break;
3402 case vHidd_GC_DrawMode_AndInverted: /* (ANBC) if invert source and blit thru mask */
3403 D(bug("CopyBoxMasked does not support ANBC minterm yet"));
3404 break;
3406 default:
3407 D(bug("CopyBoxMasked: DrawMode 0x%x not handled.\n", drawmode));
3408 break;
3411 HIDD_BM_PutImage(msg->dest, msg->gc, destbuf, bytes_per_line,
3412 msg->destX, msg->destY + lines_done,
3413 msg->width, doing_lines, pixfmt);
3415 } /* for(lines_done = 0; lines_done != height; lines_done += doing_lines) */
3417 /* Restore GC state */
3418 GC_DRMD(msg->gc) = drawmode;
3420 /* Free our temporary buffer */
3421 FreeMem(srcbuf, 2 * lines_per_step * bytes_per_line);
3423 return TRUE;
3424 } /* if (lines_per_step) */
3425 else
3427 /* urk :-( pixelbuffer too small to hold two lines) */
3428 D(bug("BltMaskBitMapRastPort found pixelbuffer to be too small"));
3429 return FALSE;
3434 /*****************************************************************************************
3436 NAME
3437 moHidd_Gfx_ShowImminentReset
3439 SYNOPSIS
3440 VOID OOP_DoMethod(OOP_Object *obj, OOP_Msg msg);
3442 LOCATION
3443 hidd.graphics.graphics
3445 FUNCTION
3446 Indicate upcoming machine reset. Obsolete.
3448 Since graphics.library v41.4 this method is not used any more. Considered
3449 reserved. Do not use it in any way.
3451 INPUTS
3452 None.
3454 RESULT
3455 None.
3457 NOTES
3459 EXAMPLE
3461 BUGS
3463 SEE ALSO
3465 INTERNALS
3467 *****************************************************************************************/
3469 VOID GFX__Hidd_Gfx__ShowImminentReset(OOP_Class *cl, OOP_Object *obj, OOP_Msg msg)
3473 /****************************************************************************************/
3476 * The following two methods are private, static, and not virtual.
3477 * They operate only on static data and don't need object pointer.
3480 OOP_Object *GFX__Hidd_Gfx__RegisterPixFmt(OOP_Class *cl, struct TagItem *pixFmtTags)
3482 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3483 HIDDT_PixelFormat cmp_pf;
3484 struct class_static_data *data;
3485 struct pixfmt_data *retpf = NULL;
3487 memset(&cmp_pf, 0, sizeof(cmp_pf));
3489 data = CSD(cl);
3490 if (!parse_pixfmt_tags(pixFmtTags, &cmp_pf, 0, CSD(cl)))
3492 D(bug("!!! FAILED PARSING TAGS IN Gfx::RegisterPixFmt() !!!\n"));
3493 return FALSE;
3497 * Our alpha-less R8G8B8 pixelformats are defined as having depth
3498 * and size = 24, not 32 bits. Nevertheless, many hardware reports
3499 * 32 bits in such cases.
3500 * In order to avoid confusion we attempt to detect this situation and
3501 * fix up pixelformat definition. If we don't do it, we get nonstandard
3502 * pixelformat with no corresponding CGX code, which can misbehave.
3504 if ((cmp_pf.flags == PF_GRAPHTYPE(TrueColor, Chunky)) &&
3505 (cmp_pf.bytes_per_pixel == 4) && (cmp_pf.alpha_mask == 0) &&
3506 (cmp_pf.red_mask << cmp_pf.red_shift == 0xFF000000) &&
3507 (cmp_pf.green_mask << cmp_pf.green_shift == 0xFF000000) &&
3508 (cmp_pf.blue_mask << cmp_pf.blue_shift == 0xFF000000))
3510 DPF(bug("Gfx::RegisterPixFmt(): 4-byte R8G8B8 detected\n"));
3512 if (cmp_pf.depth > 24)
3514 DPF(bug("Gfx::RegisterPixFmt(): Fixing up depth %d > 24\n", cmp_pf.depth));
3515 cmp_pf.depth = 24;
3518 if (cmp_pf.size > 24)
3520 DPF(bug("Gfx::RegisterPixFmt(): Fixing up size %d > 24\n", cmp_pf.size));
3521 cmp_pf.size = 24;
3525 DPF(bug("Gfx::RegisterPixFmt(): Registering pixelformat:\n"));
3526 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
3527 , PF(&cmp_pf)->red_shift
3528 , PF(&cmp_pf)->green_shift
3529 , PF(&cmp_pf)->blue_shift
3530 , PF(&cmp_pf)->alpha_shift
3531 , PF(&cmp_pf)->red_mask
3532 , PF(&cmp_pf)->green_mask
3533 , PF(&cmp_pf)->blue_mask
3534 , PF(&cmp_pf)->alpha_mask
3535 , PF(&cmp_pf)->bytes_per_pixel
3536 , PF(&cmp_pf)->size
3537 , PF(&cmp_pf)->depth
3538 , PF(&cmp_pf)->stdpixfmt));
3540 retpf = find_pixfmt(&cmp_pf, CSD(cl));
3542 DPF(bug("Found matching pixelformat: 0x%p\n", retpf));
3543 if (retpf)
3544 /* Increase pf refcount */
3545 AROS_ATOMIC_INC(retpf->refcount);
3546 else
3548 /* Could not find an alike pf, Create a new pfdb node */
3549 /* Since we pass NULL as the taglist below, the PixFmt class will just create a dummy pixfmt */
3550 retpf = OOP_NewObject(CSD(cl)->pixfmtclass, NULL, NULL);
3551 if (retpf) {
3552 /* We have one user */
3553 retpf->refcount = 1;
3555 /* Initialize the pixfmt object the "ugly" way */
3556 memcpy(retpf, &cmp_pf, sizeof (HIDDT_PixelFormat));
3558 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
3559 , PF(&cmp_pf)->red_shift
3560 , PF(&cmp_pf)->green_shift
3561 , PF(&cmp_pf)->blue_shift
3562 , PF(&cmp_pf)->alpha_shift
3563 , PF(&cmp_pf)->red_mask
3564 , PF(&cmp_pf)->green_mask
3565 , PF(&cmp_pf)->blue_mask
3566 , PF(&cmp_pf)->alpha_mask
3567 , PF(&cmp_pf)->bytes_per_pixel
3568 , PF(&cmp_pf)->size
3569 , PF(&cmp_pf)->depth
3570 , PF(&cmp_pf)->stdpixfmt));
3572 ObtainSemaphore(&data->pfsema);
3573 AddTail((struct List *)&data->pflist, (struct Node *)&retpf->node);
3574 ReleaseSemaphore(&data->pfsema);
3578 DPF(bug("New refcount is %u\n", retpf->refcount));
3579 return (OOP_Object *)retpf;
3582 /****************************************************************************************/
3584 /* This method doesn't need object pointer, it's static. */
3586 VOID GFX__Hidd_Gfx__ReleasePixFmt(OOP_Class *cl, OOP_Object *pf)
3588 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3589 struct class_static_data *data;
3590 struct pixfmt_data *pixfmt = (struct pixfmt_data *)pf;
3592 DPF(bug("release_pixfmt 0x%p\n", pixfmt));
3594 data = CSD(cl);
3596 ObtainSemaphore(&data->pfsema);
3598 /* If refcount is already 0, this object was never registered in the database,
3599 don't touch it */
3600 DPF(bug("Old reference count is %u\n", pixfmt->refcount));
3601 if (pixfmt->refcount) {
3602 if (--pixfmt->refcount == 0) {
3603 Remove((struct Node *)&pixfmt->node);
3604 OOP_DisposeObject((OOP_Object *)pixfmt);
3608 ReleaseSemaphore(&data->pfsema);
3611 /*****************************************************************************************
3613 NAME
3614 moHidd_Gfx_CheckMode
3616 SYNOPSIS
3617 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CheckMode *msg);
3619 BOOL HIDD_Gfx_CheckMode(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
3620 OOP_Object *sync, OOP_Object *pixFmt);
3622 LOCATION
3623 hidd.graphics.graphics
3625 FUNCTION
3626 Check if given display mode is supported by the driver.
3628 Normally any resolution (sync) can be used together with any pixelformat. However
3629 on some hardware there may be exceptions from this rule. In such a case this
3630 method should be implemented, and check should be performed.
3632 The information provided by this method is used in order to exclude unsupported
3633 modes from the database
3635 Default implementation in the base class just returns TRUE for all supplied values.
3637 Note that this method can not be used in order to chech that the given mode is
3638 really present in the database and it really refers to the given sync and
3639 pixelformat objects. Use HIDD_Gfx_GetMode() for mode ID validation.
3641 INPUTS
3642 gfxHidd - A display driver object
3643 modeID - A display mode ID
3644 sync - A pointer to a sync object associated with this mode
3645 pixFmt - A pointer to a pixelformat object associated with this mode
3647 RESULT
3648 TRUE if this mode is supported and FALSE if it's not.
3650 NOTES
3652 EXAMPLE
3654 BUGS
3655 Currently base class does not call this method after driver object creation.
3656 This needs to be fixed.
3658 SEE ALSO
3659 moHidd_Gfx_GetMode
3661 INTERNALS
3663 *****************************************************************************************/
3665 BOOL GFX__Hidd_Gfx__CheckMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CheckMode *msg)
3667 /* As a default we allways return TRUE, ie. the mode is OK */
3668 return TRUE;
3671 /*****************************************************************************************
3673 NAME
3674 moHidd_Gfx_GetPixFmt
3676 SYNOPSIS
3677 OOP_Object *OOP_DoMethod(OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg);
3679 OOP_Object *HIDD_Gfx_GetPixFmt(OOP_Object *gfxHidd, HIDDT_StdPixFmt pixFmt);
3681 LOCATION
3682 hidd.graphics.graphics
3684 FUNCTION
3685 Get a standard pixelformat descriptor from internal pixelformats database.
3687 INPUTS
3688 gfxHidd - A display driver object
3689 pixFmt - An index of pixelformat (one of vHIDD_StdPixFmt_... values)
3691 RESULT
3692 A pointer to a pixelformat object or NULL if lookup failed
3694 NOTES
3695 Pixelformat objects are stored in a global system-wide database. They are not
3696 linked with a particular driver in any way and completely sharable between all
3697 drivers.
3699 EXAMPLE
3701 BUGS
3703 SEE ALSO
3705 INTERNALS
3706 This operation can never fail because all standard pixelformats are registered
3707 during early system initialization.
3709 *****************************************************************************************/
3711 OOP_Object *GFX__Hidd_Gfx__GetPixFmt(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg)
3713 OOP_Object *fmt;
3715 if (!IS_REAL_STDPIXFMT(msg->stdPixFmt))
3717 D(bug("!!! Illegal pixel format passed to Gfx::GetPixFmt(): %d\n", msg->stdPixFmt));
3718 return NULL;
3720 else
3722 fmt = (OOP_Object *)CSD(cl)->std_pixfmts[REAL_STDPIXFMT_IDX(msg->stdPixFmt)];
3725 return fmt;
3728 /*****************************************************************************************
3730 NAME
3731 moHidd_Gfx_GetSync
3733 SYNOPSIS
3734 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetSync *msg);
3736 OOP_Object *HIDD_Gfx_GetSync(OOP_Object *gfxHidd, ULONG num);
3738 LOCATION
3739 hidd.graphics.graphics
3741 FUNCTION
3742 Get a sync object from internal display mode database by index
3744 INPUTS
3745 gfxHidd - A display driver object to query
3746 num - An index of sync object starting from 0
3748 RESULT
3749 A pointer to a sync object or NULL if there's no sync with such index
3751 NOTES
3753 EXAMPLE
3755 BUGS
3757 SEE ALSO
3759 INTERNALS
3761 *****************************************************************************************/
3763 OOP_Object *GFX__Hidd_Gfx__GetSync(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetSync *msg)
3765 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
3767 if (msg->num < data->mdb.num_syncs)
3768 return data->mdb.syncs[msg->num];
3769 else {
3770 D(bug("!!! Illegal sync index passed to Gfx::GetSync(): %d\n", msg->num));
3771 return NULL;
3775 /*****************************************************************************************
3777 NAME
3778 moHidd_Gfx_ModeProperties
3780 SYNOPSIS
3781 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ModeProperties *msg);
3783 ULONG HIDD_Gfx_ModeProperties(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
3784 struct HIDD_ModeProperties *props, ULONG propsLen);
3786 LOCATION
3787 hidd.graphics.graphics
3789 FUNCTION
3790 Obtain an information about the video mode.
3792 Video mode description structure may grow in future, so be careful and always check
3793 propsLen parameter value. A system may ask you for less data than you can provide.
3794 Always return an actual value. Do not just zero out fields you don't know about,
3795 this is not expected to be backwards compatible.
3797 INPUTS
3798 gfxHidd - a pointer to a display driver object whose display mode you want to query
3799 modeID - a mode ID to query
3800 props - a pointer to a storage area where HIDD_ModeProperties structure will be put
3801 propsLen - length of the supplied buffer in bytes.
3803 RESULT
3804 Actual length of obtained structure
3806 NOTES
3807 Returned data must reflect only real hardware capabilities. For example, do not
3808 count emulated sprites. The system takes care about emulated features itself.
3810 EXAMPLE
3812 BUGS
3814 SEE ALSO
3815 aoHidd_Gfx_HWSpriteTypes, aoHidd_Gfx_SupportsHWCursor
3817 INTERNALS
3818 Default implementation in the base class relies on aHidd_Gfx_HWSpriteTypes attribute,
3819 not vice versa. If you override this method, do not forget to override this attribute too.
3821 *****************************************************************************************/
3823 ULONG GFX__Hidd_Gfx__ModeProperties(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ModeProperties *msg)
3825 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3826 struct HIDD_ModeProperties props = {0, 0, 0};
3827 IPTR has_hw_cursor = 0;
3828 ULONG len = msg->propsLen;
3830 D(bug("[GFXHIDD] Hidd::Gfx::ModeProperties(0x%08lX, 0x%p, %u)\n", msg->modeID, msg->props, msg->propsLen));
3831 OOP_GetAttr(o, aHidd_Gfx_HWSpriteTypes, &has_hw_cursor);
3832 if (has_hw_cursor) {
3833 D(bug("[GFXHIDD] Driver has hardware mouse cursor implementation\n"));
3834 props.DisplayInfoFlags = DIPF_IS_SPRITES;
3835 props.NumHWSprites = 1;
3838 if (len > sizeof(props))
3839 len = sizeof(props);
3840 D(bug("[GFXHIDD] Copying %u bytes\n", len));
3841 CopyMem(&props, msg->props, len);
3843 return len;
3846 /*****************************************************************************************
3848 NAME
3849 moHidd_Gfx_GetGamma
3851 SYNOPSIS
3852 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Gamma *msg);
3854 BOOL HIDD_Gfx_GetGamma(OOP_Object *gfxHidd, UBYTE *Red, UBYTE *Green, UBYTE *Blue);
3856 LOCATION
3857 hidd.graphics.graphics
3859 FUNCTION
3860 Get current gamma table for the display.
3862 This method was neither ever implemented nor used. Currently obsolete and
3863 considered reserved.
3865 INPUTS
3867 RESULT
3869 NOTES
3871 EXAMPLE
3873 BUGS
3875 SEE ALSO
3876 moHidd_Gfx_SetGamma
3878 INTERNALS
3880 *****************************************************************************************/
3882 BOOL GFX__Hidd_Gfx__GetGamma(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Gamma *msg)
3884 return FALSE;
3887 /*****************************************************************************************
3889 NAME
3890 moHidd_Gfx_SetGamma
3892 SYNOPSIS
3893 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Gamma *msg);
3895 BOOL HIDD_Gfx_SetGamma(OOP_Object *gfxHidd, UBYTE *Red, UBYTE *Green, UBYTE *Blue);
3897 LOCATION
3898 hidd.graphics.graphics
3900 FUNCTION
3901 Set current gamma table for the display.
3903 A gamma table consists of three 256-byte tables: one for red component, one for
3904 green and one for blue.
3906 INPUTS
3907 gfxHidd - A display driver object
3908 Red - A pointer to a 256-byte array for red component
3909 Green - A pointer to a 256-byte array for green component
3910 Blue - A pointer to a 256-byte array for blue component
3912 RESULT
3913 FALSE if the driver doesn't support gamma correction, otherwise TRUE
3915 NOTES
3917 EXAMPLE
3919 BUGS
3921 SEE ALSO
3923 INTERNALS
3925 *****************************************************************************************/
3927 BOOL GFX__Hidd_Gfx__SetGamma(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Gamma *msg)
3929 return FALSE;
3932 /*****************************************************************************************
3934 NAME
3935 moHidd_Gfx_QueryHardware3D
3937 SYNOPSIS
3938 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_QueryHardware3D *msg);
3940 BOOL HIDD_Gfx_QueryHardware3D(OOP_Object *gfxHidd, OOP_Object *pixFmt);
3942 LOCATION
3943 hidd.graphics.graphics
3945 FUNCTION
3946 Query if the driver supports hardware-accelerated 3D graphics for the given
3947 pixelformat.
3949 INPUTS
3950 gfxHidd - A display driver object
3951 pixFmt - A pointer to a pixelformat descriptor object
3953 RESULT
3954 TRUE if the driver supports hardware-accelerated 3D for the given pixelformat,
3955 FALSE otherwise.
3957 NOTES
3959 EXAMPLE
3961 BUGS
3963 SEE ALSO
3965 INTERNALS
3967 *****************************************************************************************/
3969 BOOL GFX__Hidd_Gfx__QueryHardware3D(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_QueryHardware3D *msg)
3971 return FALSE;
3974 /*****************************************************************************************
3976 NAME
3977 moHidd_Gfx_GetMaxSpriteSize
3979 SYNOPSIS
3980 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetMaxSpriteSize *msg);
3982 BOOL HIDD_Gfx_GetMaxSpriteSize(OOP_Object *gfxHidd, ULONG Type, UWORD *Width, UWORD *Height);
3984 LOCATION
3985 hidd.graphics.graphics
3987 FUNCTION
3988 Query maximum allowed size for the given sprite type.
3990 INPUTS
3991 gfxHidd - A display driver object
3992 Type - Type of the sprite image (one of vHidd_SpriteType_... values)
3993 Width - A pointer to UWORD where width will be placed.
3994 Height - A pointer to UWORD where height will be placed.
3996 RESULT
3997 FALSE is the given sprite type is not supported, otherwise TRUE.
3999 NOTES
4000 Default implementation in the base class just return some small values
4001 which it hopes can be supported by every driver if the driver supports given
4002 sprite type. It is strongly suggested to reimplement this method in the display
4003 driver.
4005 Width and Height are considered undefined if the method returns FALSE.
4007 EXAMPLE
4009 BUGS
4011 SEE ALSO
4013 INTERNALS
4015 *****************************************************************************************/
4017 BOOL GFX__Hidd_Gfx__GetMaxSpriteSize(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMaxSpriteSize *msg)
4019 IPTR types;
4020 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
4022 OOP_GetAttr(o, aHidd_Gfx_HWSpriteTypes, &types);
4024 if (types & msg->Type) {
4025 *msg->Width = 16;
4026 *msg->Height = 32;
4027 return TRUE;
4028 } else
4029 return FALSE;
4032 /*****************************************************************************************
4034 NAME
4035 moHidd_Gfx_NewOverlay
4037 SYNOPSIS
4038 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NewOverlay *msg);
4040 OOP_Object *HIDD_Gfx_NewOverlay(OOP_Object *gfxHidd, struct TagItem *tagList);
4042 LOCATION
4043 hidd.graphics.graphics
4045 FUNCTION
4046 Create a video overlay object.
4048 INPUTS
4049 gfxHidd - A graphics driver object on whose display you want to create an overlay.
4050 tagList - A list of overlay attributes. See overlay class documentation for
4051 their description.
4053 RESULT
4054 Pointer to the newly created overlay object or NULL in case of failure.
4056 NOTES
4057 Default implementation in the base class always sets VOERR_INVSCRMODE error and
4058 returns NULL meaning that hardware overlays are not supported. There's no sense
4059 in software implementation because the software is supposed to handle software
4060 rendering itself.
4062 EXAMPLE
4064 BUGS
4066 SEE ALSO
4067 moHidd_Gfx_DisposeOverlay
4069 INTERNALS
4071 *****************************************************************************************/
4073 OOP_Object *GFX__Hidd_Gfx__NewOverlay(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewOverlay *msg)
4075 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
4076 ULONG *err = (ULONG *)GetTagData(aHidd_Overlay_Error, 0, msg->attrList);
4078 if (err)
4079 *err = VOERR_INVSCRMODE;
4081 return NULL;
4084 /*****************************************************************************************
4086 NAME
4087 moHidd_Gfx_DisposeOverlay
4089 SYNOPSIS
4090 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_DisposeOverlay *msg);
4092 VOID HIDD_Gfx_DisposeOverlay(OOP_Object *gfxHidd, OOP_Object *Overlay)
4094 LOCATION
4095 hidd.graphics.graphics
4097 FUNCTION
4098 Deletes an overlay previously created by moHidd_Gfx_NewOverlay.
4100 Subclasses do not have to override this method
4101 unless they allocate anything additional to an overlay object in
4102 their HIDD_Gfx_NewOverlay() implementation.
4104 INPUTS
4105 gfxHidd - A driver object which was used for creating a GC.
4106 Overlay - Pointer to an overlay object to delete.
4108 RESULT
4109 None.
4111 NOTES
4113 EXAMPLE
4115 BUGS
4117 SEE ALSO
4118 moHidd_Gfx_NewGC
4120 INTERNALS
4121 Basically just does OOP_DisposeObject(Overlay);
4123 *****************************************************************************************/
4125 VOID GFX__Hidd_Gfx__DisposeOverlay(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_DisposeOverlay *msg)
4127 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
4128 OOP_DisposeObject(msg->Overlay);
4131 /*****************************************************************************************
4133 NAME
4134 moHidd_Gfx_MakeViewPort
4136 SYNOPSIS
4137 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_MakeViewPort *msg);
4139 ULONG HIDD_Gfx_MakeViewPort(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data)
4141 LOCATION
4142 hidd.graphics.graphics
4144 FUNCTION
4145 Performs driver-specific setup on a given ViewPort.
4147 INPUTS
4148 gfxHidd - A display driver object.
4149 data - a pointer to a HIDD_ViewPortData structure.
4151 RESULT
4152 The same code as used as return value for graphics.library/MakeVPort().
4154 NOTES
4155 When graphics.library calls this method, a complete view is not built yet.
4156 This means that data->Next pointer contains invalid data and needs to be
4157 ignored.
4159 It is valid to keep private data pointer in data->UserData accross calls.
4160 Newly created HIDD_ViewPortData is guraranteed to have NULL there.
4162 EXAMPLE
4164 BUGS
4166 SEE ALSO
4167 moHidd_Gfx_CleanViewPort
4169 INTERNALS
4170 Base class implementation just does nothing. This function is mainly intended
4171 to provide support for copperlist maintenance by Amiga(tm) chipset driver.
4173 *****************************************************************************************/
4175 ULONG GFX__Hidd_Gfx__MakeViewPort(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_MakeViewPort *msg)
4177 D(bug("Gfx::MakeViewPort: object 0x%p, data 0x%p\n", o, msg->Data));
4179 return MVP_OK;
4182 /*****************************************************************************************
4184 NAME
4185 moHidd_Gfx_CleanViewPort
4187 SYNOPSIS
4188 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CleanViewPort *msg);
4190 ULONG HIDD_Gfx_CleanViewPort(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data)
4192 LOCATION
4193 hidd.graphics.graphics
4195 FUNCTION
4196 Performs driver-specific cleanup on a given ViewPort.
4198 INPUTS
4199 gfxHidd - A display driver object.
4200 data - a pointer to a HIDD_ViewPortDats structure.
4202 RESULT
4203 The same code as used as return value for graphics.library/MakeVPort().
4205 NOTES
4206 When graphics.library calls this method, the ViewPort is already unlinked
4207 from its view, and the bitmap can already be deallocated.
4208 This means that both data->Next and data->Bitmap pointers can contain invalid
4209 values.
4211 EXAMPLE
4213 BUGS
4215 SEE ALSO
4216 moHidd_Gfx_MakeViewPort
4218 INTERNALS
4219 Base class implementation just does nothing. This function is mainly intended
4220 to provide support for copperlist disposal by Amiga(tm) chipset driver.
4222 *****************************************************************************************/
4224 void GFX__Hidd_Gfx__CleanViewPort(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CleanViewPort *msg)
4226 D(bug("Gfx::CleanViewPort: object 0x%p, data 0x%p\n", o, msg->Data));
4229 /*****************************************************************************************
4231 NAME
4232 moHidd_Gfx_PrepareViewPorts
4234 SYNOPSIS
4235 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_PrepareViewPorts *msg);
4237 ULONG HIDD_Gfx_PrepareViewPorts(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data, struct View *view)
4239 LOCATION
4240 hidd.graphics.graphics
4242 FUNCTION
4243 Performs driver-specific setup on a given view.
4245 INPUTS
4246 gfxHidd - A display driver object.
4247 data - a pointer to a chain of HIDD_ViewPortData structures.
4248 view - A pointer to graphics.library View structure being prepared.
4250 RESULT
4251 MCOP_OK if there was no error or MCOP_NO_MEM otherwise.
4252 MCOP_NOP is not allowed as a return value of this method.
4254 NOTES
4255 graphics.library calls this method in MrgCop() after the complete view
4256 is built. data->Next pointer contains valid data.
4258 This function can be repeatedly called several times, and there is no
4259 cleanup counterpart for it. This should be taken into account in method
4260 implementation.
4262 EXAMPLE
4264 BUGS
4266 SEE ALSO
4268 INTERNALS
4269 Base class implementation just does nothing. This function is mainly intended
4270 to provide support for copperlist maintenance by Amiga(tm) chipset driver.
4272 *****************************************************************************************/
4274 ULONG GFX__Hidd_Gfx__PrepareViewPorts(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ShowViewPorts *msg)
4276 return MCOP_OK;
4279 /****************************************************************************************/
4281 /* This is a private nonvirtual method */
4282 void GFX__Hidd_Gfx__UpdateBitMap(OOP_Class *cl, OOP_Object *o, OOP_Object *bm,
4283 struct pHidd_BitMap_UpdateRect *msg, struct Rectangle *display)
4285 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
4288 * We check data->shownbm twice in order to avoid unnecessary locking
4289 * when our bitmap is not on display (it may be not displayable at all).
4290 * However the second check is still needed in order to make sure that
4291 * this bitmap is still on display, because we could be preempted between
4292 * the test and ObtainSemaphore() by concurrently running Show() call.
4293 * We use shared lock because it's safe to have two concurrently running
4294 * updates even on the same region.
4296 if ((data->fbmode == vHidd_FrameBuffer_Mirrored) && (bm == data->shownbm))
4298 ObtainSemaphoreShared(&data->fbsem);
4300 if (bm == data->shownbm)
4303 * Complete update rectangle.
4304 * Display rectangle is already in bitmap's coordinates.
4306 UWORD srcX = msg->x;
4307 UWORD srcY = msg->y;
4308 UWORD xLimit = srcX + msg->width;
4309 UWORD yLimit = srcY + msg->height;
4311 /* Intersect rectangles */
4312 if (display->MinX > srcX)
4313 srcX = display->MinX;
4314 if (display->MinY > srcY)
4315 srcY = display->MinY;
4316 if (display->MaxX < xLimit)
4317 xLimit = display->MaxX;
4318 if (display->MaxY < yLimit)
4319 yLimit = display->MaxY;
4321 if ((xLimit > srcX) && (yLimit > srcY))
4323 HIDD_Gfx_CopyBox(o, bm, srcX, srcY,
4324 data->framebuffer, srcX - display->MinX, srcY - display->MinY,
4325 xLimit - srcX, yLimit - srcY, data->gc);
4329 ReleaseSemaphore(&data->fbsem);
4333 #undef csd
4335 /****************************************************************************************/
4337 static ULONG ObtainAttrBases(OOP_AttrBase *bases, CONST_STRPTR *interfaces, ULONG count, struct Library *OOPBase)
4339 ULONG i;
4340 ULONG failed = 0;
4342 for (i = 0; i < count; i++)
4344 bases[i] = OOP_ObtainAttrBase(interfaces[i]);
4345 if (!bases[i])
4346 failed++;
4349 return failed;
4352 static void ReleaseAttrBases(OOP_AttrBase *bases, CONST_STRPTR *interfaces, ULONG count, struct Library *OOPBase)
4354 ULONG i;
4356 for (i = 0; i < count; i++)
4358 if (bases[i])
4359 OOP_ReleaseAttrBase(interfaces[i]);
4363 static ULONG GetMethodBases(OOP_MethodID *bases, CONST_STRPTR *interfaces, ULONG count, struct Library *OOPBase)
4365 ULONG i;
4366 ULONG failed = 0;
4368 for (i = 0; i < count; i++)
4370 bases[i] = OOP_GetMethodID(interfaces[i], 0);
4371 if (bases[i] == -1)
4372 failed++;
4375 return failed;
4378 static CONST_STRPTR interfaces[NUM_ATTRBASES] =
4380 IID_Hidd_BitMap,
4381 IID_Hidd_Gfx,
4382 IID_Hidd_GC,
4383 IID_Hidd_ColorMap,
4384 IID_Hidd_Overlay,
4385 IID_Hidd_Sync,
4386 IID_Hidd_PixFmt,
4387 IID_Hidd_PlanarBM,
4388 IID_Hidd_ChunkyBM,
4391 static int GFX_ClassInit(LIBBASETYPEPTR LIBBASE)
4393 struct class_static_data *csd = &LIBBASE->hdg_csd;
4394 struct Library *OOPBase = csd->cs_OOPBase;
4396 if (!(csd->cs_UtilityBase = TaggedOpenLibrary(TAGGEDOPEN_UTILITY)))
4398 ReturnInt("init_gfxhiddclass", ULONG, FALSE);
4401 if (ObtainAttrBases(csd->attrBases, interfaces, NUM_ATTRBASES, OOPBase))
4403 ReturnInt("init_gfxhiddclass", ULONG, FALSE);
4406 if (GetMethodBases(csd->methodBases, interfaces, NUM_METHODBASES, OOPBase))
4408 ReturnInt("init_gfxhiddclass", ULONG, FALSE);
4411 D(bug("Creating std pixelfmts\n"));
4412 ReturnInt("init_gfxhiddclass", ULONG, create_std_pixfmts(csd));
4415 /****************************************************************************************/
4417 static int GFX_ClassFree(LIBBASETYPEPTR LIBBASE)
4419 struct class_static_data *csd = &LIBBASE->hdg_csd;
4420 struct Library *OOPBase = csd->cs_OOPBase;
4422 EnterFunc(bug("free_gfxhiddclass(csd=%p)\n", csd));
4424 delete_pixfmts(csd);
4425 ReleaseAttrBases(csd->attrBases, interfaces, NUM_ATTRBASES, OOPBase);
4426 CloseLibrary(csd->cs_UtilityBase);
4428 ReturnInt("free_gfxhiddclass", BOOL, TRUE);
4431 /****************************************************************************************/
4433 ADD2INITLIB(GFX_ClassInit, 0)
4434 ADD2EXPUNGELIB(GFX_ClassFree, 0)
4436 /****************************************************************************************/
4438 /* Since the shift/mask values of a pixel format are designed for pixel
4439 access, not byte access, they are endianess dependant */
4441 #if AROS_BIG_ENDIAN
4442 #include "stdpixfmts_be.h"
4443 #else
4444 #include "stdpixfmts_le.h"
4445 #endif
4447 /****************************************************************************************/
4449 static BOOL create_std_pixfmts(struct class_static_data *csd)
4451 ULONG i;
4452 struct pixfmt_data *pf;
4454 memset(csd->std_pixfmts, 0, sizeof (OOP_Object *) * num_Hidd_StdPixFmt);
4456 for (i = 0; i < num_Hidd_StdPixFmt; i ++)
4458 pf = (struct pixfmt_data *)create_and_init_object(csd->pixfmtclass, (UBYTE *)&stdpfs[i], sizeof (stdpfs[i]), csd);
4460 if (!pf)
4462 D(bug("FAILED TO CREATE PIXEL FORMAT %d\n", i));
4463 delete_pixfmts(csd);
4464 ReturnBool("create_stdpixfmts", FALSE);
4467 csd->std_pixfmts[i] = &pf->pf;
4468 /* We don't use semaphore protection here because we do this only during class init stage */
4469 pf->refcount = 1;
4470 AddTail((struct List *)&csd->pflist, (struct Node *)&pf->node);
4472 ReturnBool("create_stdpixfmts", TRUE);
4475 /****************************************************************************************/
4477 static VOID delete_pixfmts(struct class_static_data *csd)
4479 struct Node *n, *safe;
4480 struct Library *OOPBase = csd->cs_OOPBase;
4482 ForeachNodeSafe(&csd->pflist, n, safe)
4483 OOP_DisposeObject((OOP_Object *)PIXFMT_OBJ(n));
4486 /****************************************************************************************/
4488 static inline BOOL cmp_pfs(HIDDT_PixelFormat *tmppf, HIDDT_PixelFormat *dbpf)
4490 /* Just compare everything except stdpixfmt */
4491 /* Compare flags first (because it's a fast check) */
4492 if (tmppf->flags != dbpf->flags)
4493 return FALSE;
4494 /* If they match, compare the rest of things */
4495 return !memcmp(tmppf, dbpf, offsetof(HIDDT_PixelFormat, stdpixfmt));
4498 /****************************************************************************************/
4501 Parses the tags supplied in 'tags' and puts the result into 'pf'.
4502 It also checks to see if all needed attrs are supplied.
4503 It uses 'attrcheck' for this, so you may find attrs outside
4504 of this function, and mark them as found before calling this function
4507 #define PFAF(x) (1L << aoHidd_PixFmt_ ## x)
4508 #define PF_COMMON_AF ( PFAF(Depth) | PFAF(BitsPerPixel) | PFAF(BytesPerPixel) \
4509 | PFAF(ColorModel) | PFAF(BitMapType) )
4511 #define PF_TRUECOLOR_AF ( PFAF(RedMask) | PFAF(GreenMask) | PFAF(BlueMask) | PFAF(AlphaMask) | \
4512 PFAF(RedShift) | PFAF(GreenShift) | PFAF(BlueShift) | PFAF(AlphaShift))
4514 #define PF_PALETTE_AF ( PFAF(CLUTMask) | PFAF(CLUTShift) | PFAF(RedMask) | PFAF(GreenMask) | \
4515 PFAF(BlueMask) )
4517 #define PFAO(x) (aoHidd_PixFmt_ ## x)
4519 /****************************************************************************************/
4521 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf,
4522 ULONG ATTRCHECK(pixfmt), struct class_static_data *csd)
4524 IPTR attrs[num_Hidd_PixFmt_Attrs] = {0};
4525 struct Library *OOPBase = csd->cs_OOPBase;
4527 if (0 != OOP_ParseAttrs(tags, attrs, num_Hidd_PixFmt_Attrs,
4528 &ATTRCHECK(pixfmt), HiddPixFmtAttrBase))
4530 D(bug("!!! parse_pixfmt_tags: ERROR PARSING TAGS THROUGH OOP_ParseAttrs !!!\n"));
4531 return FALSE;
4534 if (PF_COMMON_AF != (PF_COMMON_AF & ATTRCHECK(pixfmt)))
4536 D(bug("!!! parse_pixfmt_tags: Missing PixFmt attributes passed to parse_pixfmt_tags(): %x !!!\n", ATTRCHECK(pixfmt)));
4537 return FALSE;
4540 /* Set the common attributes */
4541 pf->depth = attrs[PFAO(Depth)];
4542 pf->size = attrs[PFAO(BitsPerPixel)];
4543 pf->bytes_per_pixel = attrs[PFAO(BytesPerPixel)];
4544 /* Fill in only real StdPixFmt specification. Special values (Native and Native32)
4545 are not allowed here */
4546 if (attrs[PFAO(StdPixFmt)] >= num_Hidd_PseudoStdPixFmt)
4547 pf->stdpixfmt = attrs[PFAO(StdPixFmt)];
4549 SET_PF_COLMODEL( pf, attrs[PFAO(ColorModel)]);
4550 SET_PF_BITMAPTYPE(pf, attrs[PFAO(BitMapType)]);
4552 if (ATTRCHECK(pixfmt) & PFAF(SwapPixelBytes))
4554 SET_PF_SWAPPIXELBYTES_FLAG(pf, attrs[PFAO(SwapPixelBytes)]);
4557 /* Set the colormodel specific stuff */
4558 switch (HIDD_PF_COLMODEL(pf))
4560 case vHidd_ColorModel_TrueColor:
4561 /* Check that we got all the truecolor describing stuff */
4562 if (PF_TRUECOLOR_AF != (PF_TRUECOLOR_AF & ATTRCHECK(pixfmt)))
4564 D(bug("!!! Unsufficient true color format describing attrs to pixfmt in parse_pixfmt_tags() !!!\n"));
4565 return FALSE;
4568 /* Set the truecolor stuff */
4569 pf->red_mask = attrs[PFAO(RedMask)];
4570 pf->green_mask = attrs[PFAO(GreenMask)];
4571 pf->blue_mask = attrs[PFAO(BlueMask)];
4572 pf->alpha_mask = attrs[PFAO(AlphaMask)];
4574 pf->red_shift = attrs[PFAO(RedShift)];
4575 pf->green_shift = attrs[PFAO(GreenShift)];
4576 pf->blue_shift = attrs[PFAO(BlueShift)];
4577 pf->alpha_shift = attrs[PFAO(AlphaShift)];
4578 break;
4580 case vHidd_ColorModel_Palette:
4581 case vHidd_ColorModel_StaticPalette:
4582 if ( PF_PALETTE_AF != (PF_PALETTE_AF & ATTRCHECK(pixfmt)))
4584 D(bug("!!! Unsufficient palette format describing attrs to pixfmt in parse_pixfmt_tags() !!!\n"));
4585 return FALSE;
4588 /* set palette stuff */
4589 pf->clut_mask = attrs[PFAO(CLUTMask)];
4590 pf->clut_shift = attrs[PFAO(CLUTShift)];
4592 pf->red_mask = attrs[PFAO(RedMask)];
4593 pf->green_mask = attrs[PFAO(GreenMask)];
4594 pf->blue_mask = attrs[PFAO(BlueMask)];
4596 break;
4598 } /* shift (colormodel) */
4600 return TRUE;
4603 /****************************************************************************************/
4606 Create an empty object and initialize it the "ugly" way. This only works with
4607 CLID_Hidd_PixFmt and CLID_Hidd_Sync classes
4610 /****************************************************************************************/
4612 static OOP_Object *create_and_init_object(OOP_Class *cl, UBYTE *data, ULONG datasize,
4613 struct class_static_data *csd)
4615 OOP_Object *o;
4616 struct Library *OOPBase = csd->cs_OOPBase;
4618 o = OOP_NewObject(cl, NULL, NULL);
4619 if (NULL == o)
4621 D(bug("!!! UNABLE TO CREATE OBJECT IN create_and_init_object() !!!\n"));
4622 return NULL;
4625 memcpy(o, data, datasize);
4627 return o;
4630 /****************************************************************************************/
4632 static struct pixfmt_data *find_pixfmt(HIDDT_PixelFormat *tofind, struct class_static_data *csd)
4634 struct pixfmt_data *retpf = NULL;
4635 HIDDT_PixelFormat *db_pf;
4636 struct Node *n;
4638 /* Go through the pixel format list to see if a similar pf allready exists */
4639 ObtainSemaphoreShared(&csd->pfsema);
4641 ForeachNode(&csd->pflist, n)
4643 db_pf = PIXFMT_OBJ(n);
4644 DPF(bug("find_pixfmt(): Trying pixelformat 0x%p\n", db_pf));
4645 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n",
4646 db_pf->red_shift, db_pf->green_shift, db_pf->blue_shift, db_pf->alpha_shift,
4647 db_pf->red_mask, db_pf->green_mask, db_pf->blue_mask, db_pf->alpha_mask,
4648 db_pf->bytes_per_pixel, db_pf->size, db_pf->depth, db_pf->stdpixfmt));
4649 if (cmp_pfs(tofind, db_pf))
4651 DPF(bug("Match!\n"));
4652 retpf = (struct pixfmt_data *)db_pf;
4653 break;
4657 ReleaseSemaphore(&csd->pfsema);
4658 return retpf;