wip prep commit in lieu of gfx subsystem update changes.
[AROS.git] / rom / hidds / graphics / gfx_hiddclass.c
blob566c47af49c59fbdfde983c59ce3b8224c13c7d1
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics hidd class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #include "gfx_debug.h"
13 #include <aros/atomic.h>
14 #include <aros/debug.h>
15 #include <aros/symbolsets.h>
16 #include <aros/config.h>
17 #include <cybergraphx/cgxvideo.h>
18 #include <exec/lists.h>
19 #include <oop/static_mid.h>
20 #include <graphics/displayinfo.h>
21 #include <graphics/view.h>
23 #include "gfx_intern.h"
25 #include <string.h>
26 #include <stddef.h>
28 #include <proto/exec.h>
29 #include <proto/utility.h>
30 #include <proto/oop.h>
31 #include <exec/libraries.h>
32 #include <exec/memory.h>
34 #include <utility/tagitem.h>
36 #include LC_LIBDEFS_FILE
38 #include <hidd/gfx.h>
40 /*****************************************************************************************
42 NAME
43 --background_graphics--
45 LOCATION
46 hidd.gfx.driver
48 NOTES
49 When working with graphics drivers this is the first object you get.
50 It allows you to create BitMap and GC (graphics context)
51 object. The class' methods must be overidden by hardware-specific
52 subclasses where documented to do so.
54 *****************************************************************************************/
56 /*****************************************************************************************
58 NAME
59 --display_modes--
61 LOCATION
62 hidd.gfx.driver
64 NOTES
65 Each display driver object internally stores a database of supported display mode
66 IDs. This database is normally managed by base class, the driver does not need to
67 reimplement respective methods.
69 A display mode ID in AROS is a 32-bit integer value, the same as on AmigaOS(tm).
70 However mode ID layout introduced by Commodore does not fit well for RTG systems.
71 In order to overcome its limitations, display ID on AROS may have two forms:
73 1. A chipset mode ID. These are standard IDs defined by Commodore. You may find
74 their definitions in graphics/modeid.h.
76 2. AROS RTG mode ID.
78 An RTG mode ID is composed of three parts in the form:
80 nnnn xx yy
82 nnnn - monitor ID. This number is maintained by system libraries. IDs are
83 assigned in the order in which drivers are loaded and display hardware is
84 found. Drivers do not have to care about this part, and should normally
85 mask it out if they for some reason look at mode ID. In order to
86 distinguish between chipset mode IDs and RTG mode IDs, order number starts
87 not from zero, reserving some space for C= chipset mode IDs (which appear
88 to have order numbers from 0x0000 to 0x000A). Currently RTG monitor IDs
89 start from 0x0010, however with time this value may change. So don't rely
90 on some particular values in RTG IDs. Use cybergraphics.library/IsCyberModeID()
91 function if you want to know for sure if the given mode ID belongs to an
92 RTG driver.
94 xx - A sync object index in driver's mode database.
95 yy - A pixelformat object in driver's mode database.
97 Normally the driver does not have to care about mode ID decoding. The mode
98 database is maintained by base class. The only useful things for the driver are
99 sync and pixelformat objects, from which it's possible to get different
100 information about the mode. They can be obtained from the base class using
101 HIDD_Gfx_GetMode().
103 Note that the driver object by itself does not know its monitor ID. Different
104 displays are served by different objects, any of which may belong to any class.
105 So all driver methods which return mode IDs will set monitor ID to zero. All
106 methods that take mode ID as argument are expected to ignore the monitor ID part
107 and do not make any assumptions about its value.
109 *****************************************************************************************/
111 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags);
113 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl);
114 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl);
116 static struct pixfmt_data *find_pixfmt(HIDDT_PixelFormat *tofind
117 , struct class_static_data *_csd);
119 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm
120 , OOP_Object *dst_bm, UWORD width, UWORD height);
122 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf, ULONG attrcheck, struct class_static_data *_csd);
124 /****************************************************************************************/
126 #define COMPUTE_HIDD_MODEID(sync, pf) \
127 ( ((sync) << 8) | (pf) )
129 #define MODEID_TO_SYNCIDX(id) (((id) & 0X0000FF00) >> 8)
130 #define MODEID_TO_PFIDX(id) ( (id) & 0x000000FF)
132 /****************************************************************************************/
134 OOP_Object *GFXHIDD__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
136 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
137 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
138 struct TagItem gctags[] =
140 {aHidd_GC_Foreground, 0},
141 {TAG_DONE , 0}
143 struct TagItem new_tags[] =
145 {aHidd_Name, 0 },
146 {aHidd_HardwareName, 0 },
147 {aHidd_ProducerName, 0 },
148 {TAG_MORE, (IPTR)msg->attrList }
150 struct pRoot_New new_msg =
152 .mID = msg->mID,
153 .attrList = new_tags
156 D(bug("Entering gfx.hidd::New\n"));
158 new_tags[0].ti_Data = GetTagData(aHidd_Name, (IPTR)"gfx.hidd", msg->attrList);
159 new_tags[1].ti_Data = GetTagData(aHidd_HardwareName, (IPTR)"Software Rasterizer", msg->attrList);
160 new_tags[2].ti_Data = GetTagData(aHidd_ProducerName, (IPTR)"The AROS development team", msg->attrList);
162 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&new_msg);
164 D(bug("Got object o=%x\n", o));
166 if (o)
168 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
169 struct TagItem *tstate = msg->attrList;
170 struct TagItem *modetags = NULL;
171 struct TagItem *tag;
172 BOOL ok;
174 InitSemaphore(&data->mdb.sema);
175 InitSemaphore(&data->fbsem);
176 data->fbmode = -1;
178 D(bug("[GFX] attrList 0x%p\n", msg->attrList));
180 while ((tag = NextTagItem(&tstate)))
182 ULONG idx;
184 Hidd_Gfx_Switch(tag->ti_Tag, idx)
186 case aoHidd_Gfx_ModeTags:
187 modetags = (struct TagItem *)tag->ti_Data;
188 break;
190 case aoHidd_Gfx_FrameBufferType:
191 data->fbmode = tag->ti_Data;
192 break;
196 /* Register modes only after other attributes are initialized */
197 ok = modetags ? register_modes(cl, o, modetags) : TRUE;
199 /* Create a gc that we can use for some rendering */
200 if (ok)
202 data->gc = OOP_NewObject(CSD(cl)->gcclass, NULL, gctags);
203 if (NULL == data->gc)
205 D(bug("Could not get gc\n"));
206 ok = FALSE;
210 if (!ok)
212 OOP_MethodID dispose_mid = msg->mID - moRoot_New + moRoot_Dispose;
214 D(bug("Not OK\n"));
215 OOP_CoerceMethod(cl, o, &dispose_mid);
216 return NULL;
220 D(bug("Leaving gfx.hidd::New o=%x\n", o));
221 return o;
224 /****************************************************************************************/
226 VOID GFXHIDD__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
228 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
229 struct HiddGfxData *data;
231 data = OOP_INST_DATA(cl, o);
233 /* free the mode db stuff */
234 free_mode_db(&data->mdb, cl);
236 /* Here we should unregister pixelformats registered in our New().
237 However gfx drivers aren't supposed to be removed, so it's okay
238 not to do it at all for now. */
240 if (NULL != data->gc)
241 OOP_DisposeObject(data->gc);
243 OOP_DoSuperMethod(cl, o, msg);
246 /*****************************************************************************************
248 NAME
249 aoHidd_Gfx_IsWindowed
251 SYNOPSIS
252 [..G], BOOL
254 LOCATION
255 hidd.gfx.driver
257 FUNCTION
258 Tells if the display driver is using hosted display in host OS' window, and mouse
259 input is handled by host OS.
261 Windowed displays may send activation events to AROS. This is needed in order to
262 correctly handle display switch in a multi-display configuration (which means that
263 the user has multiple windows on host OS desktop and can freely switch between them).
265 NOTES
266 Even in fullscreen mode drivers should still return TRUE if the host OS manages mouse
267 input (for example, X11 driver). If mouse input is not managed by the host OS
268 (for example, with Linux framebuffer driver), return FALSE.
270 EXAMPLE
272 BUGS
274 SEE ALSO
275 aoHidd_Gfx_ActiveCallBack, aoHidd_Gfx_ActiveCallBackData
277 INTERNALS
278 Base class always provides FALSE value
280 *****************************************************************************************/
282 /*****************************************************************************************
284 NAME
285 aoHidd_Gfx_DMPSLevel
287 SYNOPSIS
288 [ISG], HIDDT_DPMSLevel
290 LOCATION
291 hidd.gfx.driver
293 FUNCTION
294 Gets or sets current DPMS level for driver's display.
295 A value can be one of:
296 vHidd_Gfx_DPMSLevel_On,
297 vHidd_Gfx_DPMSLevel_Standby,
298 vHidd_Gfx_DPMSLevel_Suspend,
299 vHidd_Gfx_DPMSLevel_Off
301 If the driver does not support some state, it's up to the driver what to do.
302 Usually it is expected to ignore the request.
304 Getting this attribute should return real current state.
306 NOTES
308 EXAMPLE
310 BUGS
312 SEE ALSO
314 INTERNALS
315 Base class always provides vHidd_Gfx_DPMSLevel_On value (comes from rootclass'
316 Get() which sets the value to 0).
318 *****************************************************************************************/
320 /*****************************************************************************************
322 NAME
323 aoHidd_Gfx_ModeTags
325 SYNOPSIS
326 [I..], struct TagItem *
328 LOCATION
329 hidd.gfx.driver
331 FUNCTION
332 Specify a pointer to a taglist which contains description of display modes
333 supported by the driver.
335 This attribute is usually appended in moRoot_New method of the display driver
336 class.
338 This attribute is mandatory for the base class, otherwise driver object creation
339 fails.
341 Mode description taglist may contain the following tags:
342 - Any sync attributes - these attributes will specify values common for all sync
343 modes
344 - Any pixelformat attributes - these attributes will specify values common for
345 all pixelformat modes
346 - aoHidd_Gfx_SyncTags - specifies a pointer to another separate taglist containing
347 attributes for one sync (display) mode. If this tag
348 is not supplied at all, a set of default modes will be
349 generated for the driver.
350 - aoHidd_Gfx_PixFmtTags - specifies a pointer to another separate taglist containing
351 attributes for one pixelformat. This tag must be supplied
352 at least once, otherwise driver object will fail to create.
354 aoHidd_Gfx_SyncTags and aoHidd_Gfx_PixFmtTags can be specified multiple times in
355 order to associate more than one display mode with the driver. Note that common
356 values for sync and pixelformat objects need to be placed in the taglist before
357 aoHidd_Gfx_SyncTags and aoHidd_Gfx_PixFmtTags. You may specify them again between
358 these tags in order to alter common values.
360 NOTES
362 EXAMPLE
363 Partial example code of display driver supporting a truecolor display with three
364 resolutions:
366 // Our pixelformat (24-bit 0BGR)
367 struct TagItem pftags[] =
369 { aHidd_PixFmt_RedShift , 24 },
370 { aHidd_PixFmt_GreenShift , 16 },
371 { aHidd_PixFmt_BlueShift , 8 },
372 { aHidd_PixFmt_AlphaShift , 0 },
373 { aHidd_PixFmt_RedMask , 0x000000FF },
374 { aHidd_PixFmt_GreenMask , 0x0000FF00 },
375 { aHidd_PixFmt_BlueMask , 0x00FF0000 },
376 { aHidd_PixFmt_AlphaMask , 0x00000000 },
377 { aHidd_PixFmt_ColorModel , vHidd_ColorModel_TrueColor },
378 { aHidd_PixFmt_Depth , 24 },
379 { aHidd_PixFmt_BytesPerPixel, 4 },
380 { aHidd_PixFmt_BitsPerPixel , 24 },
381 { aHidd_PixFmt_StdPixFmt , vHidd_StdPixFmt_Native },
382 { aHidd_PixFmt_BitMapType , vHidd_BitMapType_Chunky },
383 { TAG_DONE , 0UL }
386 // 640x480 resolution
387 struct TagItem tags_800_600[] =
389 { aHidd_Sync_HDisp , 640 },
390 { aHidd_Sync_VDisp , 480 },
391 { TAG_DONE , 0UL }
394 // 800x600 resolution
395 struct TagItem tags_800_600[] =
397 { aHidd_Sync_HDisp , 800 },
398 { aHidd_Sync_VDisp , 600 },
399 { TAG_DONE , 0UL }
402 // 1024x768 resolution
403 struct TagItem tags_1024_768[] =
405 { aHidd_Sync_HDisp , 1024 },
406 { aHidd_Sync_VDisp , 768 },
407 { TAG_DONE , 0UL }
410 // Mode description taglist itself
411 struct TagItem mode_tags[] =
413 // Our driver supports a single pixelformat
414 { aHidd_Gfx_PixFmtTags , (IPTR)pftags },
416 // Here go sync values common for all sync modes
417 { aHidd_Sync_HMin , 112 },
418 { aHidd_Sync_VMin , 112 },
419 { aHidd_Sync_HMax , 16384 },
420 { aHidd_Sync_VMax , 16384 },
421 { aHidd_Sync_Description, (IPTR)"Example: %hx%v" },
423 // First resolution
424 { aHidd_Gfx_SyncTags , (IPTR)tags_800_600 },
426 // Next two syncs will have HMax = 32768, as an example
427 { aHidd_Sync_HMax , 32768 },
429 // Two more resolutions
430 { aHidd_Gfx_SyncTags , (IPTR)tags_800_600 },
431 { aHidd_Gfx_SyncTags , (IPTR)tags_1024_768 },
432 { TAG_DONE , 0UL }
435 // This is the attribute list which is given to New method
436 // of the base class
437 struct TagItem mytags[] =
439 { aHidd_Gfx_ModeTags , (IPTR)mode_tags },
440 { TAG_DONE , NULL }
443 BUGS
445 SEE ALSO
447 INTERNALS
449 *****************************************************************************************/
451 /*****************************************************************************************
453 NAME
454 aoHidd_Gfx_NumSyncs
456 SYNOPSIS
457 [..G], ULONG
459 LOCATION
460 hidd.gfx.driver
462 FUNCTION
463 Gets total number of sync objects in the internal display mode database.
465 NOTES
467 EXAMPLE
469 BUGS
471 SEE ALSO
472 moHidd_Gfx_GetSync
474 INTERNALS
476 *****************************************************************************************/
478 /*****************************************************************************************
480 NAME
481 aoHidd_Gfx_SupportsHWCursor
483 SYNOPSIS
484 [..G], BOOL
486 LOCATION
487 hidd.gfx.driver
489 FUNCTION
490 Tells whether the driver supports hardware mouse pointer sprite.
492 If the driver provides TRUE value for this attribute, it is expected to implement
493 HIDD_Gfx_SetCursorPos(), HIDD_Gfx_SetCursorShape() and HIDD_Gfx_SetCursorVisible()
494 methods.
496 Mouse pointer counts for one hardware sprite, so if the driver implements also
497 HIDD_Gfx_ModeProperties(), it should set NumHWSprites to 1 in order to provide
498 valid information about display modes.
500 The driver must implement this attribute if it implements HIDD_Gfx_ModeProperties().
501 Otherwise it will provide false information in graphics.library/GetDisplayInfoData().
502 Base class can determine NumHWSprites based on this attribute value but not vice
503 versa.
505 NOTES
506 Default implementation in the base class returns FALSE. This causes the system to
507 use software sprite emulation.
509 This attribute is obsolete and is used only by AROS graphics.library up to v41.2. In
510 new drivers consider implementing aoHidd_Gfx_HWSpriteTypes attribute.
512 EXAMPLE
514 BUGS
516 SEE ALSO
517 aoHidd_Gfx_HWSpriteTypes, moHidd_Gfx_ModeProperties
519 INTERNALS
521 *****************************************************************************************/
523 /*****************************************************************************************
525 NAME
526 aoHidd_Gfx_NoFrameBuffer
528 SYNOPSIS
529 [..G], BOOL
531 LOCATION
532 hidd.gfx.driver
534 FUNCTION
535 Tells whether the driver does not need a framebuffer.
537 Since v1.2 this attribute is obsolete. Please use aoHidd_Gfx_FrameBufferType
538 in new code.
540 NOTES
541 Provides FALSE if not implemented in the driver.
543 EXAMPLE
545 BUGS
547 SEE ALSO
548 aoHidd_Gfx_FrameBufferType, moHidd_Gfx_Show
550 INTERNALS
552 *****************************************************************************************/
554 /*****************************************************************************************
556 NAME
557 aoHidd_Gfx_HWSpriteTypes
559 SYNOPSIS
560 [..G], BOOL
562 LOCATION
563 hidd.gfx.driver
565 FUNCTION
566 Return hardware sprite image types supported by the driver.
568 The returned value is a combination of the following bit flags:
569 vHidd_SpriteType_3Plus1 - color 0 is transparent, 1-3 visible
570 (Amiga(tm) chipset sprite format)
571 vHidd_SpriteType_2Plus1 - color 0 is transparent, color 1 is undefined
572 (can be whatever, for example clear or inverse),
573 colors 2-3 visible.
574 vHidd_SpriteType_DirectColor - Hi- or truecolor image, or LUT image with own
575 palette, perhaps with alpha channel
577 NOTES
578 This attribute should return 0 if the driver does not support hardware mouse sprite
579 at all. Software sprite emulation is done by graphics.library.
581 Default implementation in the base class is based on aoHidd_Gfx_SupportsHWCursor
582 value. This is done for backwards compatibility.
584 EXAMPLE
586 BUGS
588 SEE ALSO
589 aoHidd_Gfx_SupportsHWCursor
591 INTERNALS
592 Default implementation in the base class queries aoHidd_Gfx_SupportsHWCursor
593 and provides (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor) in case
594 if it returns TRUE. Otherwise it returns zero. This is done for backwards
595 compatibility with old drivers.
597 *****************************************************************************************/
599 /*****************************************************************************************
601 NAME
602 aoHidd_Gfx_MemorySize
604 SYNOPSIS
605 [..G], ULONG
607 LOCATION
608 hidd.gfx.driver
610 FUNCTION
611 Query total size of video card memory in bytes.
613 NOTES
615 EXAMPLE
617 BUGS
619 SEE ALSO
620 aoHidd_Gfx_MemoryClock
622 INTERNALS
624 *****************************************************************************************/
626 /*****************************************************************************************
628 NAME
629 aoHidd_Gfx_MemoryClock
631 SYNOPSIS
632 [..G], ULONG
634 LOCATION
635 hidd.gfx.driver
637 FUNCTION
638 Query video card's memory clock in Hz. 0 is a valid value meaning 'unknown'.
640 NOTES
642 EXAMPLE
644 BUGS
646 SEE ALSO
647 aoHidd_Gfx_MemorySize
649 INTERNALS
651 *****************************************************************************************/
653 /*****************************************************************************************
655 NAME
656 aoHidd_Gfx_DriverName
658 SYNOPSIS
659 [..G], STRPTR
661 LOCATION
662 hidd.gfx.driver
664 FUNCTION
665 Query CyberGraphX driver name. It is the same name which can be given to
666 cybergraphics.library/BestCModeIDTagList() as CYBRBIDTG_BoardName value.
668 NOTES
669 By default base class returns class name as value of this attribute.
670 However this can (and must for some drivers listed in BestCModeIDTagList()
671 documentation) be overriden.
673 EXAMPLE
675 BUGS
677 SEE ALSO
679 INTERNALS
681 *****************************************************************************************/
683 /*****************************************************************************************
685 NAME
686 aoHidd_Gfx_ActiveCallBack
688 SYNOPSIS
689 [.S.], void (*)(APTR userdata, OOP_Object *bitmap)
691 LOCATION
692 hidd.gfx.driver
694 FUNCTION
695 Set display activation interrupt handler.
697 This handler needs to be called by hosted display driver, if host OS
698 windowing system is used for the display and mouse input is handled by the
699 host OS.
701 This way the driver can tell AROS when a display window has been activated so that
702 AROS will be able to switch current display correctly when working in a multi-display
703 configuration.
705 The function uses C calling convention and needs to be declared as follows:
707 void ActivationHandler(APTR userdata, OOP_Object *bitmap);
709 Parameters of this function will be:
710 userdata - Whatever is specified by aoHidd_Gfx_ActiveCallBackData attribute.
711 bitmap - Currently reserved. Drivers need to set it to NULL.
713 The function can be called from within an interrupt, so usual restrictions apply
714 to it.
716 Set this attribute to NULL in order to disable activation handling.
718 NOTES
719 When setting the activation callback function, be sure that you set correct
720 userdata before you actually set the callback pointer. Otherwise your callback
721 can be called with wrong data pointer.
723 Only one activation handler can be installed. Installing a new handler replaces
724 the previous one.
726 Native displays do not need to implement this attribute because there can be
727 no external activation events.
729 EXAMPLE
731 BUGS
733 SEE ALSO
734 aoHidd_Gfx_ActiveCallBackData, aoHidd_Gfx_IsWindowed
736 INTERNALS
737 This attribute needs to be implemented by the display driver. Base class contains
738 no implementation.
740 *****************************************************************************************/
742 /*****************************************************************************************
744 NAME
745 aoHidd_Gfx_ActiveCallBackData
747 SYNOPSIS
748 [.S.], APTR
750 LOCATION
751 hidd.gfx.driver
753 FUNCTION
754 Set user-defined data pointer for display activation handler.
756 NOTES
758 EXAMPLE
760 BUGS
762 SEE ALSO
763 aoHidd_Gfx_ActiveCallBack
765 INTERNALS
766 This attribute needs to be implemented by the display driver. Base class contains
767 no implementation.
769 *****************************************************************************************/
771 /*****************************************************************************************
773 NAME
774 aoHidd_Gfx_DefaultGC
776 SYNOPSIS
777 [..G], OOP_Object *
779 LOCATION
780 hidd.gfx.driver
782 FUNCTION
783 Get a pointer to shared default GC object.
785 NOTES
786 The returned GC is preset to the following:
788 DrawMode = Copy
789 FG = 0
790 BG = 0
791 LinePat = ~0
792 ColMask = ~0
794 You must not alter these settings even temporarily, because this GC is shared between
795 bitmaps and between different tasks which may perform the rendering into different
796 regions of the same bitmap (two windows on one screen, for example). This GC is intended
797 to be used for internal copying operations.
799 EXAMPLE
801 BUGS
803 SEE ALSO
804 aoHidd_Gfx_ActiveCallBack
806 INTERNALS
807 This attribute needs to be implemented by the display driver. Base class contains
808 no implementation.
810 *****************************************************************************************/
812 static UBYTE get_fbmode(OOP_Class *cl, OOP_Object *o)
814 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
816 if (data->fbmode == -1)
818 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
821 * This attribute has never been set.
822 * Fall back to obsolete NoFrameBuffer.
824 data->fbmode = OOP_GET(o, aHidd_Gfx_NoFrameBuffer) ? vHidd_FrameBuffer_None : vHidd_FrameBuffer_Direct;
827 return data->fbmode;
830 /*****************************************************************************************
832 NAME
833 aoHidd_Gfx_FrameBufferType
835 SYNOPSIS
836 [I.G], UBYTE
838 LOCATION
839 hidd.gfx.driver
841 FUNCTION
842 Specifies fixed framebuffer type used by the driver. The value can be one of the following:
844 vHidd_FrameBuffer_None - the driver does not use framebuffer.
845 vHidd_FrameBuffer_Direct - the driver uses framefuffer which can be accessed
846 directly for both reads and writes.
847 vHidd_FrameBuffer_Mirrored - the driver uses write-only framebuffer.
849 This attribute has to be specified during driver object creation. If this is not done,
850 the OS will use value of old aoHidd_Gfx_NoFrameBuffer attribute in order to distinguish
851 between vHidd_FrameBuffer_Direct (for FALSE) and vHidd_FrameBuffer_None (for TRUE).
853 NOTES
854 A fixed framebuffer is a special bitmap in a fixed area of video RAM. If the
855 framebuffer is used, the driver is expected to copy a new bitmap into it in
856 HIDD_Gfx_Show() and optionally copy old bitmap back.
858 A framebuffer is needed if the hardware does not have enough VRAM to store many
859 bitmaps or does not have capabilities to switch the display between various VRAM
860 regions.
862 Some hardware suffers from slow VRAM reading. In this case you should use mirrored
863 mode. If you use it, the system will hold a bitmap in the memory buffer, and
864 update VRAM on demand (hence the name).
866 An example of driver using a framebuffer is hosted SDL driver. By design SDL works
867 only with single display window, which is considered a framebuffer.
869 EXAMPLE
871 BUGS
873 SEE ALSO
874 aoHidd_Gfx_NoFrameBuffer
876 INTERNALS
878 *****************************************************************************************/
880 /*****************************************************************************************
882 NAME
883 aoHidd_Gfx_SupportsGamma
885 SYNOPSIS
886 [..G], UBYTE
888 LOCATION
889 hidd.gfx.driver
891 FUNCTION
892 Specifies if the driver supports gamma correction tables. Default implementation
893 in base class returns FALSE.
895 NOTES
897 EXAMPLE
899 BUGS
901 SEE ALSO
902 moHidd_Gfx_SetGamma
904 INTERNALS
906 *****************************************************************************************/
908 VOID GFXHIDD__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
910 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
911 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
912 ULONG idx;
914 Hidd_Gfx_Switch (msg->attrID, idx)
916 case aoHidd_Gfx_NumSyncs:
917 *msg->storage = data->mdb.num_syncs;
918 return;
920 case aoHidd_Gfx_IsWindowed:
921 case aoHidd_Gfx_SupportsHWCursor:
922 case aoHidd_Gfx_SupportsGamma:
923 *msg->storage = 0;
924 return;
926 case aoHidd_Gfx_HWSpriteTypes:
927 /* Fall back to obsolete SupportsHWCursor */
928 *msg->storage = OOP_GET(o, aHidd_Gfx_SupportsHWCursor) ? (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor) : 0;
929 return;
931 case aoHidd_Gfx_DriverName:
932 *msg->storage = (IPTR)OOP_OCLASS(o)->ClassNode.ln_Name;
933 return;
935 case aoHidd_Gfx_DefaultGC:
936 *msg->storage = (IPTR)data->gc;
937 return;
939 case aoHidd_Gfx_FrameBufferType:
940 *msg->storage = get_fbmode(cl, o);
941 return;
944 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
947 /*****************************************************************************************
949 NAME
950 moHidd_Gfx_NominalDimensions
952 SYNOPSIS
953 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NominalDimensions *msg);
955 OOP_Object *HIDD_Gfx_NominalDimensions(OOP_Object *gfxHidd, UWORD *width, UWORD *height, UBYTE *depth);
957 LOCATION
958 hidd.gfx.driver
960 FUNCTION
962 INPUTS
963 gfxHidd - The graphics driver used to create the object.
965 RESULT
967 NOTES
969 EXAMPLE
971 BUGS
973 SEE ALSO
975 INTERNALS
977 *****************************************************************************************/
978 VOID GFXHIDD__Hidd_Gfx__NominalDimensions(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NominalDimensions *msg)
980 EnterFunc(bug("HIDDGfx::NominalDimensions()\n"));
982 if (msg->width)
983 *(msg->width) = AROS_NOMINAL_WIDTH;
984 if (msg->height)
985 *(msg->height) = AROS_NOMINAL_HEIGHT;
986 if (msg->depth)
987 *(msg->depth) = AROS_NOMINAL_DEPTH;
990 /*****************************************************************************************
992 NAME
993 moHidd_Gfx_CreateObject
995 SYNOPSIS
996 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CreateObject *msg);
998 OOP_Object *HIDD_Gfx_CreateObject(OOP_Object *gfxHidd, OOP_Class *cl, struct TagItem *tagList);
1000 LOCATION
1001 hidd.gfx.driver
1003 FUNCTION
1004 Create a driver specific Gfx Object of the type "classID"
1006 INPUTS
1007 gfxHidd - The graphics driver used to create the object.
1008 cl - The base OOP_Class of the object to be created.
1009 tagList - Object specific attributes.
1011 RESULT
1012 pointer to the newly created OOP_Object, or NULL on failure.
1014 NOTES
1015 Drivers should query the gfx.hidd, or support class for the base class Ptr that
1016 the driver objects should use. The gfx hidd itself defines the following -:
1019 A GC object is just used for data storage. It is possible to subclass, however
1020 it is not recommended since it may not be future-proof due to the fact
1021 GC subclasses can not be interchanged between different drivers.
1022 Avoid using custom GCs.
1024 BitMap
1026 Each graphics driver exposes at least one displayable bitmap class.
1027 More may be exposed at the drivers discretion to represent nondisplayable bitmaps
1028 or other driver specific bitmap types.
1030 Generally bitmap objects are never created directly. Instead they are created
1031 using the HIDD_Gfx_CreateObject() call. An implementation of this method in the
1032 driver should examine bitmap attributes supplied and make a decision if the bitmap
1033 should be created using the driver's own class or one of the system classes.
1035 A typical implementation should pay attention to the following bitmap attributes:
1037 aHIDD_BitMap_ModeID - If this attribute is supplied, the bitmap needs to be
1038 either displayable by this driver, or be a friend of a
1039 displayable bitmap. A friend bitmap usually repeats the
1040 internal layout of its friend so that the driver may
1041 perform blitting operations quickly.
1043 aHIDD_BitMap_Displayable - If this attribute is supplied, the bitmap NEEDS to be
1044 displayable by this driver. Usually this means that
1045 the bitmap object will contain video hardware state
1046 information. This attribute will always be accompanied
1047 by aHIDD_BitMap_ModeID.
1049 aHIDD_BitMap_FrameBuffer - The bitmap needs to be a framebuffer bitmap. A
1050 framebuffer bitmap is necessary for some kinds of
1051 hardware which have a small fixed amount of video
1052 RAM which can hold only one screen at a time. Setting
1053 this attribute requires that a valid ModeID be also set.
1055 aHIDD_BitMap_Friend - If there's no ModeID supplied, you may wish to check class
1056 of friend bitmap. This can be useful if your driver uses
1057 different classes for displayable and non-displayable bitmaps.
1058 By default base class will pick up friend's class and use it
1059 for new bitmap if nothing is specified, here you may override
1060 this behavior.
1062 If a driver wants to specify a custom class for the bitmap being created,
1063 it should pass the aoHidd_BitMap_ClassPtr attribute to the base class.
1064 Bitmap objects should not be directly created, otherwise necessary information
1065 provided by the base class will be missing.
1067 This method must be implemented by the subclass. aHIDD_BitMap_ClassPtr or
1068 aHIDD_BitMap_ClassID must be provided to the base class for a displayable bitmap.
1070 EXAMPLE
1072 BUGS
1074 SEE ALSO
1076 INTERNALS
1077 The base class implementation currently does the folliwing in order to determine
1078 a class for a nondisplayable bitmap (in the listed order):
1080 1. Check aHIDD_BitMap_ClassPtr and aHIDD_BitMap_ClassID. If one of them is supplied,
1081 the class is already set by a subclass.
1082 2. Check aHIDD_BitMap_StdPixFmt. If this attribute is supplied, figure out type of
1083 the pixelformat (chunky or planar), and use one of two system's default classes.
1084 3. Check aHIDD_BitMap_Friend. If friend bitmap is supplied, obtain its class from
1085 aHIDD_BitMap_ClassPtr value of friend bitmap.
1086 4. If everything fails, bitmap creation fails too.
1088 This behavior is subject to change, but will maintain backwards compatibility.
1090 *****************************************************************************************/
1091 OOP_Object *GFXHIDD__Hidd_Gfx__CreateObject(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CreateObject *msg)
1093 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1094 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
1095 OOP_Object *object = NULL;
1097 EnterFunc(bug("HIDDGfx::CreateObject()\n"));
1099 if (msg->cl == CSD(cl)->gcclass)
1101 object = OOP_NewObject(NULL, CLID_Hidd_GC, msg->attrList);
1103 else if (msg->cl == CSD(cl)->bitmapclass)
1105 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1107 struct TagItem bmtags[] =
1109 {aHidd_BitMap_GfxHidd, 0}, /* 0 */
1110 {aHidd_BitMap_PixFmt , 0}, /* 1 */
1111 {TAG_IGNORE , 0}, /* 2 */
1112 {TAG_IGNORE , 0}, /* 3 */
1113 {TAG_IGNORE , 0}, /* 4 */
1114 {TAG_IGNORE , 0}, /* 5 */
1115 {TAG_MORE , 0}, /* 6 */
1117 struct TagItem *tag, *tstate = msg->attrList;
1118 ULONG idx;
1120 STRPTR classid = NULL;
1121 OOP_Class *classptr = NULL;
1122 BOOL displayable = FALSE;
1123 BOOL framebuffer = FALSE;
1124 HIDDT_StdPixFmt pixfmt = vHidd_StdPixFmt_Unknown;
1125 OOP_Object *friend_bm = NULL;
1126 OOP_Object *sync = NULL;
1127 OOP_Object *pf = NULL;
1129 BOOL gotclass = FALSE;
1130 BOOL got_width = FALSE;
1131 BOOL got_height = FALSE;
1132 BOOL got_depth = FALSE;
1134 #define BMAO(x) aoHidd_BitMap_ ## x
1135 #define BMAF(x) (1L << aoHidd_BitMap_ ## x)
1137 #define BM_DIMS_AF (BMAF(Width) | BMAF(Height))
1139 #define SET_TAG(tags, idx, tag, val) \
1140 tags[idx].ti_Tag = tag ; tags[idx].ti_Data = (IPTR)val;
1142 #define SET_BM_TAG(tags, idx, tag, val) \
1143 SET_TAG(tags, idx, aHidd_BitMap_ ## tag, val)
1145 #define COPY_BM_TAG(tags, idx, tag, obj) \
1146 tags[idx].ti_Tag = aHidd_BitMap_ ## tag; \
1147 OOP_GetAttr(obj, aHidd_BitMap_ ## tag , &tags[idx].ti_Data)
1149 while ((tag = NextTagItem(&tstate)))
1151 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
1153 switch (idx)
1155 case aoHidd_BitMap_Displayable:
1156 displayable = tag->ti_Data;
1157 break;
1159 case aoHidd_BitMap_FrameBuffer:
1160 framebuffer = tag->ti_Data;
1161 break;
1163 case aoHidd_BitMap_Width:
1164 got_width = TRUE;
1165 break;
1167 case aoHidd_BitMap_Height:
1168 got_height = TRUE;
1169 break;
1171 case aoHidd_BitMap_Depth:
1172 got_depth = TRUE;
1173 break;
1175 case aoHidd_BitMap_ModeID:
1176 /* Make sure it is a valid mode, and retrieve sync/pixelformat data */
1177 if (!HIDD_Gfx_GetMode(o, tag->ti_Data, &sync, &pf))
1179 D(bug("!!! Gfx::CreateObject: USER PASSED INVALID MODEID !!!\n"));
1180 return NULL;
1182 break;
1184 case aoHidd_BitMap_Friend:
1185 friend_bm = (OOP_Object *)tag->ti_Data;
1186 break;
1188 case aoHidd_BitMap_PixFmt:
1189 D(bug("!!! Gfx::CreateObject: USER IS NOT ALLOWED TO PASS aHidd_BitMap_PixFmt !!!\n"));
1190 return NULL;
1192 case aoHidd_BitMap_StdPixFmt:
1193 pixfmt = tag->ti_Data;
1194 break;
1196 case aoHidd_BitMap_ClassPtr:
1197 classptr = (OOP_Class *)tag->ti_Data;
1198 gotclass = TRUE;
1199 break;
1201 case aoHidd_BitMap_ClassID:
1202 classid = (STRPTR)tag->ti_Data;
1203 gotclass = TRUE;
1204 break;
1209 /* If we have a friend bitmap, we can inherit some attributes from it */
1210 if (friend_bm)
1212 if (!got_width)
1214 COPY_BM_TAG(bmtags, 2, Width, friend_bm);
1215 got_width = TRUE;
1218 if (!got_height)
1220 COPY_BM_TAG(bmtags, 3, Height, friend_bm);
1221 got_height = TRUE;
1224 if (!got_depth)
1226 COPY_BM_TAG(bmtags, 4, Depth, friend_bm);
1230 if (framebuffer)
1232 /* FrameBuffer implies Displayable */
1233 SET_BM_TAG(bmtags, 5, Displayable, TRUE);
1234 displayable = TRUE;
1236 else if (displayable)
1239 * Displayable, but not framebuffer (user's screen).
1240 * If we are working in framebuffer mode, we treat all such
1241 * bitmaps as framebuffer's friends and can inherit its class.
1243 if ((!gotclass) && data->framebuffer && (get_fbmode(cl, o) != vHidd_FrameBuffer_None))
1245 classptr = OOP_OCLASS(data->framebuffer);
1246 gotclass = TRUE;
1248 D(bug("[GFX] Using class 0x%p (%s) for displayable bitmap\n", classptr, classptr->ClassNode.ln_Name));
1252 if (displayable)
1254 /* Displayable bitmap. Here we must have ModeID and class. */
1255 if (!sync)
1257 D(bug("!!! Gfx::CreateObject: USER HAS NOT PASSED MODEID FOR DISPLAYABLE BITMAP !!!\n"));
1258 return NULL;
1261 if (!gotclass)
1263 D(bug("!!! Gfx::CreateObject: SUBCLASS DID NOT PASS CLASS FOR DISPLAYABLE BITMAP !!!\n"));
1264 return NULL;
1267 else /* if (!displayable) */
1270 * This is an offscreen bitmap and we need to guess its pixelformat.
1271 * In order to do this we need one of (in the order of preference):
1272 * - ModeID
1273 * - StdPixFmt
1274 * - Friend
1277 if (sync)
1280 * We have alredy got sync for the modeid case.
1281 * Obtain missing size information from it.
1283 if (!got_width)
1285 bmtags[2].ti_Tag = aHidd_BitMap_Width;
1286 OOP_GetAttr(sync, aHidd_Sync_HDisp, &bmtags[2].ti_Data);
1289 if (!got_height)
1291 bmtags[3].ti_Tag = aHidd_BitMap_Height;
1292 OOP_GetAttr(sync, aHidd_Sync_VDisp, &bmtags[3].ti_Data);
1295 else if (pixfmt != vHidd_StdPixFmt_Unknown)
1297 /* Next to look for is StdPixFmt */
1298 pf = HIDD_Gfx_GetPixFmt(o, pixfmt);
1299 if (NULL == pf)
1301 D(bug("!!! Gfx::CreateObject(): USER PASSED BOGUS StdPixFmt !!!\n"));
1302 return NULL;
1305 else if (friend_bm)
1307 /* Last alternative is that the user passed a friend bitmap */
1309 OOP_GetAttr(friend_bm, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1312 * Inherit the class from friend bitmap (if not already specified).
1313 * We do it because friend bitmap may be a display HIDD bitmap
1315 if (!gotclass)
1317 classptr = OOP_OCLASS(friend_bm);
1318 gotclass = TRUE;
1320 D(bug("[GFX] Friend bitmap is 0x%p has class 0x%p (%s)\n", friend_bm, classptr, classptr->ClassNode.ln_Name));
1323 else
1325 D(bug("!!! Gfx::CreateObject: INSUFFICIENT ATTRS TO CREATE OFFSCREEN BITMAP !!!\n"));
1326 return NULL;
1329 /* Did the subclass provide an offbitmap class for us? */
1330 if (!gotclass)
1332 /* Have to find a suitable class ourselves from the pixelformat */
1333 HIDDT_BitMapType bmtype;
1335 OOP_GetAttr(pf, aHidd_PixFmt_BitMapType, &bmtype);
1336 switch (bmtype)
1338 case vHidd_BitMapType_Chunky:
1339 classptr = CSD(cl)->chunkybmclass;
1340 break;
1342 case vHidd_BitMapType_Planar:
1343 classptr = CSD(cl)->planarbmclass;
1344 break;
1346 default:
1347 D(bug("!!! Gfx::CreateObject: UNKNOWN BITMAPTYPE %d !!!\n", bmtype));
1348 return NULL;
1350 D(bug("[GFX] Bitmap type is %u, using class 0x%p\n", bmtype, classptr));
1352 } /* if (!gotclass) */
1354 } /* if (!displayable) */
1356 /* Set the tags we want to pass to the selected bitmap class */
1357 bmtags[0].ti_Data = (IPTR)o;
1358 bmtags[1].ti_Data = (IPTR)pf;
1359 bmtags[6].ti_Data = (IPTR)msg->attrList;
1361 object = OOP_NewObject(classptr, classid, bmtags);
1363 /* Remember the framebuffer. It can be needed for default Show() implementation. */
1364 if (framebuffer)
1365 data->framebuffer = object;
1368 ReturnPtr("HIDDGfx::CreateObject", OOP_Object *, object);
1371 /****************************************************************************************/
1373 #define SD(x) ((struct sync_data *)x)
1374 #define PF(x) ((HIDDT_PixelFormat *)x)
1376 #define XCOORD_TO_BYTEIDX(x) ( (x) >> 3)
1377 #define COORD_TO_BYTEIDX(x, y, bpr) ( ( (y) * bpr ) + XCOORD_TO_BYTEIDX(x) )
1378 #define XCOORD_TO_MASK(x) (1L << (7 - ((x) & 0x07) ))
1379 #define WIDTH_TO_BYTES(width) ( (( (width) - 1) >> 3) + 1)
1381 /****************************************************************************************/
1383 /* modebm functions pfidx is x and syncidx is y coord in the bitmap */
1385 /****************************************************************************************/
1387 static inline BOOL alloc_mode_bm(struct mode_bm *bm, ULONG numsyncs, ULONG numpfs,
1388 OOP_Class *cl)
1390 bm->bpr = WIDTH_TO_BYTES(numpfs);
1392 bm->bm = AllocVec(bm->bpr * numsyncs, MEMF_CLEAR);
1393 if (NULL == bm->bm)
1394 return FALSE;
1396 /* We initialize the mode bitmap to all modes valid */
1397 memset(bm->bm, 0xFF, bm->bpr * numsyncs);
1399 return TRUE;
1402 /****************************************************************************************/
1404 static inline VOID free_mode_bm(struct mode_bm *bm, OOP_Class *cl)
1406 FreeVec(bm->bm);
1407 bm->bm = NULL;
1408 bm->bpr = 0;
1411 /****************************************************************************************/
1413 static inline BOOL is_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx)
1415 if (0 != (XCOORD_TO_MASK(pfidx) & bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)]))
1416 return TRUE;
1418 return FALSE;
1421 /****************************************************************************************/
1423 static inline VOID set_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx,
1424 BOOL valid)
1426 if (valid)
1427 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] |= XCOORD_TO_MASK(pfidx);
1428 else
1429 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] &= ~XCOORD_TO_MASK(pfidx);
1431 return;
1434 /****************************************************************************************/
1436 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl)
1438 BOOL ok = FALSE;
1440 if (0 == numsyncs || 0 == numpfs)
1441 return FALSE;
1443 ObtainSemaphore(&mdb->sema);
1444 /* free_mode_bm() needs this */
1445 mdb->num_pixfmts = numpfs;
1446 mdb->num_syncs = numsyncs;
1448 mdb->syncs = AllocMem(sizeof (OOP_Object *) * numsyncs, MEMF_CLEAR);
1450 if (NULL != mdb->syncs)
1452 mdb->pixfmts = AllocMem(sizeof (OOP_Object *) * numpfs, MEMF_CLEAR);
1454 if (NULL != mdb->pixfmts)
1456 if (alloc_mode_bm(&mdb->orig_mode_bm, numsyncs, numpfs, cl))
1458 if (alloc_mode_bm(&mdb->checked_mode_bm, numsyncs, numpfs, cl))
1460 ok = TRUE;
1466 if (!ok)
1467 free_mode_db(mdb, cl);
1469 ReleaseSemaphore(&mdb->sema);
1471 return ok;
1474 /****************************************************************************************/
1476 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl)
1478 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1479 ULONG i;
1481 ObtainSemaphore(&mdb->sema);
1483 if (NULL != mdb->pixfmts)
1486 /* Pixelformats are shared objects and never freed */
1487 FreeMem(mdb->pixfmts, sizeof (OOP_Object *) * mdb->num_pixfmts);
1488 mdb->pixfmts = NULL; mdb->num_pixfmts = 0;
1491 if (NULL != mdb->syncs)
1493 for (i = 0; i < mdb->num_syncs; i ++)
1495 if (NULL != mdb->syncs[i])
1498 OOP_DisposeObject(mdb->syncs[i]);
1499 mdb->syncs[i] = NULL;
1503 FreeMem(mdb->syncs, sizeof (OOP_Object *) * mdb->num_syncs);
1504 mdb->syncs = NULL; mdb->num_syncs = 0;
1507 if (NULL != mdb->orig_mode_bm.bm)
1509 free_mode_bm(&mdb->orig_mode_bm, cl);
1512 if (NULL != mdb->checked_mode_bm.bm)
1514 free_mode_bm(&mdb->checked_mode_bm, cl);
1517 ReleaseSemaphore(&mdb->sema);
1519 return;
1522 /****************************************************************************************/
1524 /* Initializes default tagarray. in numtags the TAG_MORE is not accounted for,
1525 so the array must be of size NUM_TAGS + 1
1528 /****************************************************************************************/
1530 static VOID init_def_tags(struct TagItem *tags, ULONG numtags)
1532 ULONG i;
1534 for (i = 0; i < numtags; i ++)
1536 tags[i].ti_Tag = TAG_IGNORE;
1537 tags[i].ti_Data = 0UL;
1540 tags[i].ti_Tag = TAG_MORE;
1541 tags[i].ti_Data = 0UL;
1543 return;
1546 /****************************************************************************************/
1548 #define MAKE_SYNC(name,clock,hdisp,hstart,hend,htotal,vdisp,vstart,vend,vtotal,descr) \
1549 struct TagItem sync_ ## name[]={ \
1550 { aHidd_Sync_PixelClock, clock*1000 }, \
1551 { aHidd_Sync_HDisp, hdisp }, \
1552 { aHidd_Sync_HSyncStart, hstart }, \
1553 { aHidd_Sync_HSyncEnd, hend }, \
1554 { aHidd_Sync_HTotal, htotal }, \
1555 { aHidd_Sync_VDisp, vdisp }, \
1556 { aHidd_Sync_VSyncStart, vstart }, \
1557 { aHidd_Sync_VSyncEnd, vend }, \
1558 { aHidd_Sync_VTotal, vtotal }, \
1559 { aHidd_Sync_Description, (IPTR)descr}, \
1560 { TAG_DONE, 0UL }}
1562 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags)
1564 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1565 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1566 struct TagItem *tag, *tstate;
1567 struct HiddGfxData *data;
1569 MAKE_SYNC(640x480_60, 25174,
1570 640, 656, 752, 800,
1571 480, 490, 492, 525,
1572 "Default:640x480");
1574 MAKE_SYNC(800x600_56, 36000, // 36000
1575 800, 824, 896, 1024,
1576 600, 601, 603, 625,
1577 "Default:800x600");
1579 MAKE_SYNC(1024x768_60, 65000, //78654=60kHz, 75Hz. 65000=50kHz,62Hz
1580 1024, 1048, 1184, 1344,
1581 768, 771, 777, 806,
1582 "Default:1024x768");
1584 MAKE_SYNC(1152x864_60, 80000,
1585 1152, 1216, 1328, 1456,
1586 864, 870, 875, 916,
1587 "Default:1152x864");
1589 MAKE_SYNC(1280x1024_60, 108880,
1590 1280, 1360, 1496, 1712,
1591 1024, 1025, 1028, 1060,
1592 "Default:1280x1024");
1594 MAKE_SYNC(1600x1200_60, 155982,
1595 1600, 1632, 1792, 2048,
1596 1200, 1210, 1218, 1270,
1597 "Default:1600x1200");
1599 /* "new" 16:10 modes */
1601 MAKE_SYNC(1280x800_60, 83530,
1602 1280, 1344, 1480, 1680,
1603 800, 801, 804, 828,
1604 "Default:1280x800");
1606 MAKE_SYNC(1440x900_60, 106470,
1607 1440, 1520, 1672, 1904,
1608 900, 901, 904, 932,
1609 "Default:1440x900");
1611 MAKE_SYNC(1680x1050_60, 147140,
1612 1680, 1784, 1968, 2256,
1613 1050, 1051, 1054, 1087,
1614 "Default:1680x1050");
1616 MAKE_SYNC(1920x1080_60, 173000,
1617 1920, 2048, 2248, 2576,
1618 1080, 1083, 1088, 1120,
1619 "Default:1920x1080");
1621 MAKE_SYNC(1920x1200_60, 154000,
1622 1920, 1968, 2000, 2080,
1623 1200, 1203, 1209, 1235,
1624 "Default:1920x1200");
1626 struct mode_db *mdb;
1628 HIDDT_PixelFormat pixfmt_data;
1630 struct TagItem def_sync_tags[num_Hidd_Sync_Attrs + 1];
1631 struct TagItem def_pixfmt_tags[num_Hidd_PixFmt_Attrs + 1];
1633 ULONG numpfs = 0,numsyncs = 0;
1634 ULONG pfidx = 0, syncidx = 0;
1636 struct TagItem temporary_tags[] = {
1637 { aHidd_Gfx_SyncTags, (IPTR)sync_640x480_60 },
1638 { aHidd_Gfx_SyncTags, (IPTR)sync_800x600_56 },
1639 { aHidd_Gfx_SyncTags, (IPTR)sync_1024x768_60 },
1640 { aHidd_Gfx_SyncTags, (IPTR)sync_1152x864_60 },
1641 { aHidd_Gfx_SyncTags, (IPTR)sync_1280x1024_60 },
1642 { aHidd_Gfx_SyncTags, (IPTR)sync_1600x1200_60 },
1643 { aHidd_Gfx_SyncTags, (IPTR)sync_1280x800_60 },
1644 { aHidd_Gfx_SyncTags, (IPTR)sync_1440x900_60 },
1645 { aHidd_Gfx_SyncTags, (IPTR)sync_1680x1050_60 },
1646 { aHidd_Gfx_SyncTags, (IPTR)sync_1920x1080_60 },
1647 { aHidd_Gfx_SyncTags, (IPTR)sync_1920x1200_60 },
1648 { TAG_MORE, 0UL }
1651 data = OOP_INST_DATA(cl, o);
1652 mdb = &data->mdb;
1653 InitSemaphore(&mdb->sema);
1655 memset(&pixfmt_data, 0, sizeof (pixfmt_data));
1657 init_def_tags(def_sync_tags, num_Hidd_Sync_Attrs);
1658 init_def_tags(def_pixfmt_tags, num_Hidd_PixFmt_Attrs);
1660 def_sync_tags[aoHidd_Sync_GfxHidd].ti_Tag = aHidd_Sync_GfxHidd;
1661 def_sync_tags[aoHidd_Sync_GfxHidd].ti_Data = (IPTR)o;
1663 /* First we need to calculate how much memory we are to allocate by counting supplied
1664 pixel formats and syncs */
1666 for (tstate = modetags; (tag = NextTagItem(&tstate));)
1668 ULONG idx;
1670 if (IS_GFX_ATTR(tag->ti_Tag, idx))
1672 switch (idx)
1674 case aoHidd_Gfx_PixFmtTags:
1675 numpfs++;
1676 break;
1678 case aoHidd_Gfx_SyncTags:
1679 numsyncs ++;
1680 break;
1682 default:
1683 break;
1688 if (0 == numpfs)
1690 D(bug("!!! WE MUST AT LEAST HAVE ONE PIXFMT IN Gfx::RegisterModes() !!!\n"));
1693 if (0 == numsyncs)
1695 D(bug("!!! NO SYNC IN Gfx::RegisterModes() !!!\n!!! USING DEFAULT MODES !!!\n"));
1696 temporary_tags[11].ti_Tag = TAG_MORE;
1697 temporary_tags[11].ti_Data = (IPTR)modetags;
1698 modetags = &temporary_tags[0];
1699 numsyncs = 11;
1702 ObtainSemaphore(&mdb->sema);
1704 /* Allocate memory for mode db */
1705 if (!alloc_mode_db(&data->mdb, numsyncs, numpfs, cl))
1706 goto failure;
1709 for (tstate = modetags; (tag = NextTagItem(&tstate));)
1711 /* Look for Gfx, PixFmt and Sync tags */
1712 ULONG idx;
1714 if (IS_GFX_ATTR(tag->ti_Tag, idx))
1716 switch (idx)
1718 case aoHidd_Gfx_PixFmtTags:
1719 def_pixfmt_tags[num_Hidd_PixFmt_Attrs].ti_Data = tag->ti_Data;
1720 mdb->pixfmts[pfidx] = GFXHIDD__Hidd_Gfx__RegisterPixFmt(cl, def_pixfmt_tags);
1722 if (NULL == mdb->pixfmts[pfidx])
1724 D(bug("!!! UNABLE TO CREATE PIXFMT OBJECT IN Gfx::RegisterModes() !!!\n"));
1725 goto failure;
1728 pfidx ++;
1729 break;
1731 case aoHidd_Gfx_SyncTags:
1732 def_sync_tags[num_Hidd_Sync_Attrs].ti_Data = tag->ti_Data;
1734 mdb->syncs[syncidx] = OOP_NewObject(CSD(cl)->syncclass, NULL, def_sync_tags);
1735 if (!mdb->syncs[syncidx]) {
1736 D(bug("!!! UNABLE TO CREATE SYNC OBJECT IN Gfx::RegisterModes() !!!\n"));
1737 goto failure;
1740 syncidx ++;
1741 break;
1745 else if (IS_SYNC_ATTR(tag->ti_Tag, idx))
1747 if (idx >= num_Hidd_Sync_Attrs)
1749 D(bug("!!! UNKNOWN SYNC ATTR IN Gfx::New(): %d !!!\n", idx));
1751 else
1753 def_sync_tags[idx].ti_Tag = tag->ti_Tag;
1754 def_sync_tags[idx].ti_Data = tag->ti_Data;
1758 else if (IS_PIXFMT_ATTR(tag->ti_Tag, idx))
1760 if (idx >= num_Hidd_PixFmt_Attrs)
1762 D(bug("!!! UNKNOWN PIXFMT ATTR IN Gfx::New(): %d !!!\n", idx));
1764 else
1766 def_pixfmt_tags[idx].ti_Tag = tag->ti_Tag;
1767 def_pixfmt_tags[idx].ti_Data = tag->ti_Data;
1772 ReleaseSemaphore(&mdb->sema);
1774 return TRUE;
1776 failure:
1778 /* mode db is freed in dispose */
1779 ReleaseSemaphore(&mdb->sema);
1781 return FALSE;
1784 /****************************************************************************************/
1786 struct modequery
1788 struct mode_db *mdb;
1789 ULONG minwidth;
1790 ULONG maxwidth;
1791 ULONG minheight;
1792 ULONG maxheight;
1793 HIDDT_StdPixFmt *stdpfs;
1794 ULONG numfound;
1795 ULONG pfidx;
1796 ULONG syncidx;
1797 BOOL dims_ok;
1798 BOOL stdpfs_ok;
1799 BOOL check_ok;
1800 OOP_Class *cl;
1803 /****************************************************************************************/
1805 /* This is a recursive function that looks for valid modes */
1807 /****************************************************************************************/
1809 static HIDDT_ModeID *querymode(struct modequery *mq)
1811 HIDDT_ModeID *modeids;
1812 register OOP_Object *pf;
1813 register OOP_Object *sync;
1814 BOOL mode_ok = FALSE;
1815 ULONG syncidx, pfidx;
1817 mq->dims_ok = FALSE;
1818 mq->stdpfs_ok = FALSE;
1819 mq->check_ok = FALSE;
1821 /* Look at the supplied idx */
1822 if (mq->pfidx >= mq->mdb->num_pixfmts)
1824 mq->pfidx = 0;
1825 mq->syncidx ++;
1828 if (mq->syncidx >= mq->mdb->num_syncs)
1830 /* We have reached the end of the recursion. Allocate memory and go back
1833 modeids = AllocVec(sizeof (HIDDT_ModeID) * (mq->numfound + 1), MEMF_ANY);
1834 /* Get the end of the array */
1835 modeids += mq->numfound;
1836 *modeids = vHidd_ModeID_Invalid;
1838 return modeids;
1841 syncidx = mq->syncidx;
1842 pfidx = mq->pfidx;
1843 /* Get the pf and sync objects */
1844 pf = mq->mdb->pixfmts[syncidx];
1845 sync = mq->mdb->syncs[pfidx];
1848 /* Check that the mode is really usable */
1849 if (is_valid_mode(&mq->mdb->checked_mode_bm, syncidx, pfidx))
1851 mq->check_ok = TRUE;
1854 /* See if this mode matches the criterias set */
1856 if ( SD(sync)->hdisp >= mq->minwidth
1857 && SD(sync)->hdisp <= mq->maxwidth
1858 && SD(sync)->vdisp >= mq->minheight
1859 && SD(sync)->vdisp <= mq->maxheight )
1863 mq->dims_ok = TRUE;
1865 if (NULL != mq->stdpfs)
1867 register HIDDT_StdPixFmt *stdpf = mq->stdpfs;
1868 while (*stdpf)
1870 if (*stdpf == PF(pf)->stdpixfmt)
1872 mq->stdpfs_ok = TRUE;
1874 stdpf ++;
1877 else
1879 mq->stdpfs_ok = TRUE;
1885 if (mq->dims_ok && mq->stdpfs_ok && mq->check_ok)
1887 mode_ok = TRUE;
1888 mq->numfound ++;
1891 mq->pfidx ++;
1893 modeids = querymode(mq);
1895 if (NULL == modeids)
1896 return NULL;
1898 if (mode_ok)
1900 /* The mode is OK. Add it to the list */
1901 modeids --;
1902 *modeids = COMPUTE_HIDD_MODEID(syncidx, pfidx);
1905 return modeids;
1909 /*****************************************************************************************
1911 NAME
1912 moHidd_Gfx_QueryModeIDs
1914 SYNOPSIS
1915 HIDDT_ModeID *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_QueryModeIDs *msg);
1917 HIDDT_ModeID *HIDD_Gfx_QueryModeIDs(OOP_Object *gfxHidd, struct TagItem *queryTags);
1919 LOCATION
1920 hidd.gfx.driver
1922 FUNCTION
1923 Obtain a table of all supported display mode IDs
1925 The returned address points to an array of HIDDT_ModeID containing all ModeIDs
1926 supported by this driver. The array is terminated with vHidd_ModeID_Invalid.
1928 INPUTS
1929 gfxHidd - A driver object which to query.
1930 querytags - An optional taglist containing query options. Can be NULL.
1931 The following tags are supported:
1933 tHidd_GfxMode_MinWidth (ULONG) - A minimum width of modes you are
1934 interested in
1935 tHidd_GfxMode_MaxWidth (ULONG) - A maximum width of modes you are
1936 interested in
1937 tHidd_GfxMode_MinHeight (ULONG) - A minimum height of modes you are
1938 interested in
1939 tHidd_GfxMode_MaxHeight (ULONG) - A maximum height of modes you are
1940 interested in
1941 tHidd_GfxMode_PixFmts (HIDDT_StdPifXmt *) - A pointer to an array
1942 of standard pixelformat indexes. If supplied, only mode IDs whose
1943 pixelformat numbers match any of given ones will be returned.
1945 RESULT
1946 A pointer to an array of ModeIDs or NULL in case of failure
1948 NOTES
1950 EXAMPLE
1952 BUGS
1954 SEE ALSO
1955 moHidd_Gfx_ReleaseModeIDs, moHidd_Gfx_NextModeID
1957 INTERNALS
1959 *****************************************************************************************/
1961 HIDDT_ModeID *GFXHIDD__Hidd_Gfx__QueryModeIDs(OOP_Class *cl, OOP_Object *o,
1962 struct pHidd_Gfx_QueryModeIDs *msg)
1964 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1965 struct TagItem *tag, *tstate;
1967 HIDDT_ModeID *modeids;
1968 struct HiddGfxData *data;
1969 struct mode_db *mdb;
1971 struct modequery mq =
1973 NULL, /* mode db (set later) */
1974 0, 0xFFFFFFFF, /* minwidth, maxwidth */
1975 0, 0xFFFFFFFF, /* minheight, maxheight */
1976 NULL, /* stdpfs */
1977 0, /* numfound */
1978 0, 0, /* pfidx, syncidx */
1979 FALSE, FALSE, /* dims_ok, stdpfs_ok */
1980 FALSE, /* check_ok */
1981 NULL /* class (set later) */
1986 data = OOP_INST_DATA(cl, o);
1987 mdb = &data->mdb;
1988 mq.mdb = mdb;
1989 mq.cl = cl;
1991 for (tstate = msg->queryTags; (tag = NextTagItem(&tstate)); )
1993 switch (tag->ti_Tag)
1995 case tHidd_GfxMode_MinWidth:
1996 mq.minwidth = (ULONG)tag->ti_Tag;
1997 break;
1999 case tHidd_GfxMode_MaxWidth:
2000 mq.maxwidth = (ULONG)tag->ti_Tag;
2001 break;
2003 case tHidd_GfxMode_MinHeight:
2004 mq.minheight = (ULONG)tag->ti_Tag;
2005 break;
2007 case tHidd_GfxMode_MaxHeight:
2008 mq.maxheight = (ULONG)tag->ti_Tag;
2009 break;
2011 case tHidd_GfxMode_PixFmts:
2012 mq.stdpfs = (HIDDT_StdPixFmt *)tag->ti_Data;
2013 break;
2018 ObtainSemaphoreShared(&mdb->sema);
2020 /* Recursively check all modes */
2021 modeids = querymode(&mq);
2023 ReleaseSemaphore(&mdb->sema);
2025 return modeids;
2029 /*****************************************************************************************
2031 NAME
2032 moHidd_Gfx_ReleaseModeIDs
2034 SYNOPSIS
2035 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ReleaseModeIDs *msg);
2037 VOID HIDD_Gfx_ReleaseModeIDs(OOP_Object *gfxHidd, HIDDT_ModeID *modeIDs);
2039 LOCATION
2040 hidd.gfx.driver
2042 FUNCTION
2043 Free array of display mode IDs returned by HIDD_Gfx_QueryModeIDs()
2045 INPUTS
2046 gfxHidd - A driver object used to obtain the array
2047 modeIDs - A pointer to an array
2049 RESULT
2050 None.
2052 NOTES
2054 EXAMPLE
2056 BUGS
2058 SEE ALSO
2059 moHidd_Gfx_QueryModeIDs
2061 INTERNALS
2063 *****************************************************************************************/
2065 VOID GFXHIDD__Hidd_Gfx__ReleaseModeIDs(OOP_Class *cl, OOP_Object *o,
2066 struct pHidd_Gfx_ReleaseModeIDs *msg)
2068 FreeVec(msg->modeIDs);
2071 /*****************************************************************************************
2073 NAME
2074 moHidd_Gfx_NextModeID
2076 SYNOPSIS
2077 HIDDT_ModeID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NextModeID *msg);
2079 HIDDT_ModeID HIDD_Gfx_NextModeID(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
2080 OOP_Object **syncPtr, OOP_Object **pixFmtPtr);
2082 LOCATION
2083 hidd.gfx.driver
2085 FUNCTION
2086 Iterate driver's internal display mode database.
2088 INPUTS
2089 gfxHidd - A driver object to query
2090 modeID - A previous mode ID or vHidd_ModeID_Invalid for start of the iteration
2091 syncPtr - A pointer to a storage where pointer to sync object will be placed
2092 pixFmtPtr - A pointer to a storage where pointer to pixelformat object will be placed
2094 RESULT
2095 Next available mode ID or vHidd_ModeID_Invalid if there are no more display modes.
2096 If the function returns vHidd_ModeID_Invalid, sync and pixelformat pointers will
2097 be set to NULL.
2099 NOTES
2101 EXAMPLE
2103 BUGS
2105 SEE ALSO
2106 moHidd_Gfx_GetMode
2108 INTERNALS
2110 *****************************************************************************************/
2112 HIDDT_ModeID GFXHIDD__Hidd_Gfx__NextModeID(OOP_Class *cl, OOP_Object *o,
2113 struct pHidd_Gfx_NextModeID *msg)
2115 struct HiddGfxData *data;
2116 struct mode_db *mdb;
2117 ULONG syncidx, pfidx;
2118 HIDDT_ModeID return_id = vHidd_ModeID_Invalid;
2119 BOOL found = FALSE;
2121 data = OOP_INST_DATA(cl, o);
2122 mdb = &data->mdb;
2124 ObtainSemaphoreShared(&mdb->sema);
2125 if (vHidd_ModeID_Invalid == msg->modeID)
2127 pfidx = 0;
2128 syncidx = 0;
2130 else
2132 pfidx = MODEID_TO_PFIDX( msg->modeID );
2133 syncidx = MODEID_TO_SYNCIDX( msg->modeID );
2135 /* Increament one from the last call */
2136 pfidx ++;
2137 if (pfidx >= mdb->num_pixfmts)
2139 pfidx = 0;
2140 syncidx ++;
2144 /* Search for a new mode. We only accept valid modes */
2145 for (; syncidx < mdb->num_syncs; syncidx ++)
2147 /* We only return valid modes */
2148 for (; pfidx < mdb->num_pixfmts; pfidx ++)
2150 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
2152 found = TRUE;
2153 break;
2156 if (found)
2157 break;
2160 if (found)
2162 return_id = COMPUTE_HIDD_MODEID(syncidx, pfidx);
2163 *msg->syncPtr = mdb->syncs[syncidx];
2164 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
2166 else
2168 *msg->syncPtr = *msg->pixFmtPtr = NULL;
2171 ReleaseSemaphore(&mdb->sema);
2173 return return_id;
2176 /*****************************************************************************************
2178 NAME
2179 moHidd_Gfx_GetMode
2181 SYNOPSIS
2182 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetMode *msg);
2184 BOOL HIDD_Gfx_GetMode(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
2185 OOP_Object **syncPtr, OOP_Object **pixFmtPtr);
2187 LOCATION
2188 hidd.gfx.driver
2190 FUNCTION
2191 Get sync and pixelformat objects for a particular display ModeID.
2193 INPUTS
2194 gfxHidd - pointer to a driver object which this ModeID belongs to
2195 syncPtr - pointer to a storage where sync object pointer will be placed
2196 pixFmtPtr - pointer to a storage where pixelformat object pointer will be placed
2198 RESULT
2199 TRUE upon success, FALSE in case of failure (e.g. given mode does not exist in
2200 driver's internal database). If the function returns FALSE, sync and pixelformat
2201 pointers will be set to NULL.
2203 NOTES
2204 Every display mode is associated with some sync and pixelformat object. If the
2205 method returns TRUE, object pointers are guaranteed to be valid.
2207 EXAMPLE
2209 BUGS
2211 SEE ALSO
2212 moHidd_Gfx_NextModeID
2214 INTERNALS
2216 *****************************************************************************************/
2218 BOOL GFXHIDD__Hidd_Gfx__GetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMode *msg)
2220 ULONG pfidx, syncidx;
2221 struct HiddGfxData *data;
2222 struct mode_db *mdb;
2223 BOOL ok = FALSE;
2225 data = OOP_INST_DATA(cl, o);
2226 mdb = &data->mdb;
2228 pfidx = MODEID_TO_PFIDX(msg->modeID);
2229 syncidx = MODEID_TO_SYNCIDX(msg->modeID);
2231 ObtainSemaphoreShared(&mdb->sema);
2233 if (! (pfidx >= mdb->num_pixfmts || syncidx >= mdb->num_syncs) )
2235 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
2237 ok = TRUE;
2238 *msg->syncPtr = mdb->syncs[syncidx];
2239 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
2243 ReleaseSemaphore(&mdb->sema);
2245 if (!ok)
2247 *msg->syncPtr = *msg->pixFmtPtr = NULL;
2250 return ok;
2253 /*****************************************************************************************
2255 NAME
2256 moHidd_Gfx_SetMode
2258 SYNOPSIS
2259 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetMode *msg);
2261 BOOL HIDD_Gfx_SetMode(OOP_Object *gfxHidd, OOP_Object *sync);
2263 LOCATION
2264 hidd.gfx.driver
2266 FUNCTION
2267 Update display mode according to changed sync object
2269 INPUTS
2270 gfxHidd - A display driver to operate on
2271 sync - A modified sync object pointer
2273 RESULT
2274 TRUE if everything went OK and FALSE in case of some error
2276 NOTES
2277 This method is used to inform the driver that some external program has changed
2278 sync data and wants to update the display if needed. It's up to the implementation to
2279 check that current display is really using this sync (frontmost screen uses this mode).
2281 EXAMPLE
2283 BUGS
2285 SEE ALSO
2287 INTERNALS
2288 Base class implementation just returns FALSE indicating that this method is
2289 not supported.
2291 *****************************************************************************************/
2293 BOOL GFXHIDD__Hidd_Gfx__SetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetMode *msg)
2295 return FALSE;
2298 /****************************************************************************************/
2300 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm,
2301 OOP_Object *dst_bm, UWORD width, UWORD height)
2303 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2304 struct HiddGfxData *data;
2305 ULONG i;
2306 IPTR numentries;
2307 OOP_Object *src_colmap;
2308 APTR psrc_colmap = &src_colmap;
2310 data = OOP_INST_DATA(cl, o);
2312 /* We have to copy the colormap into the framebuffer bitmap */
2313 OOP_GetAttr(src_bm, aHidd_BitMap_ColorMap, (IPTR *)psrc_colmap);
2314 OOP_GetAttr(src_colmap, aHidd_ColorMap_NumEntries, &numentries);
2316 for (i = 0; i < numentries; i ++)
2318 HIDDT_Color col;
2320 HIDD_CM_GetColor(src_colmap, i, &col);
2321 HIDD_BM_SetColors(dst_bm, &col, i, 1);
2324 if (data->fbmode == vHidd_FrameBuffer_Mirrored)
2327 * Mirror mode, just turn on visibility.
2328 * The data will be copied to the framebuffer later,
2329 * when graphics.library calls UpdateRect() after Show().
2331 BM__Hidd_BitMap__SetVisible(CSD(cl)->bitmapclass, src_bm, TRUE);
2333 else
2336 * Direct framebuffer mode.
2337 * graphics.library will call UpdateRect() on the framebuffer object.
2338 * So we need to copy the data now.
2339 * We don't support scrolling for this mode, so we simply do the
2340 * bulk copy and ignore all offsets.
2342 HIDD_Gfx_CopyBox(o, src_bm, 0, 0,
2343 dst_bm, 0, 0, width, height, data->gc);
2347 /*****************************************************************************************
2349 NAME
2350 moHidd_Gfx_Show
2352 SYNOPSIS
2353 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Show *msg);
2355 OOP_Object *HIDD_Gfx_Show(OOP_Object *gfxHidd, OOP_Object *bitMap, ULONG flags);
2357 LOCATION
2358 hidd.gfx.driver
2360 FUNCTION
2361 Change currently displayed bitmap on the screen.
2363 The bitmap object supplied must have been created with aHidd_BitMap_Displayable
2364 attribute set to TRUE.
2366 The function's behavior differs a lot depending on whether the driver uses a
2367 framebuffer or video hardware is able to switch screens itself.
2369 If the driver uses a framebuffer bitmap, it is supposed to copy the supplied bitmap
2370 into the framebuffer and return a framebuffer pointer. It also can be asked to
2371 copy back old framebuffer contents into previous bitmap object. It is driver's
2372 job to keep track of which bitmap object was displayed last time. This is what
2373 default implementation does. Note that it is very basic, and even does not support
2374 changing display resolution. It's not recommended to rely on it in production
2375 drivers (unless your video hardware supports only one mode).
2377 If the driver does not use a framebuffer, it is supposed to reprogram the hardware
2378 here to display an appropriate region of video RAM. Do not call the base class
2379 in this case, its implementation relies on framebuffer existance and will always
2380 return NULL which indicates an error.
2382 It is valid to get NULL value in bitMap parameter. This means that there is
2383 nothing to display and the screen needs to be blanked out. It is valid for
2384 non-framebuffer-based driver to return NULL as a reply then. In all other cases
2385 NULL return value means an error.
2387 Please avoid returning errors at all. graphics.library/LoadView() has no error
2388 indication. An error during showing a bitmap would leave the display in
2389 unpredictable state.
2391 If the driver does not use a framebuffer, consider using HIDD_Gfx_ShowViewPorts().
2392 It's more straightforward, flexible and offers support for screen composition.
2394 INPUTS
2395 gfxHidd - a display driver object, whose display you wish to change.
2396 bitMap - a pointer to a bitmap object which needs to be shown or NULL.
2397 flags - currently only one flag is defined:
2399 fHidd_Gfx_Show_CopyBack - Copy back the image data from framebuffer bitmap
2400 to old displayed bitmap. Used only if the driver
2401 needs a framebuffer.
2403 RESULT
2404 A pointer to a currently displayed bitmap object or NULL (read FUNCTION paragraph for
2405 detailed description)
2407 NOTES
2408 Drivers which use mirrored video data buffer do not have to update the display
2409 immediately in this method. moHidd_BitMap_UpdateRect will be sent to the returned
2410 bitmap if it's not NULL. Of course display blanking (if NULL bitmap was received)
2411 needs to be performed immediately.
2413 EXAMPLE
2415 BUGS
2417 SEE ALSO
2418 moHidd_Gfx_ShowViewPorts, graphics.library/LoadView()
2420 INTERNALS
2422 *****************************************************************************************/
2424 OOP_Object *GFXHIDD__Hidd_Gfx__Show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
2426 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2427 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
2428 OOP_Object *bm = msg->bitMap;
2429 IPTR oldwidth = 0;
2430 IPTR oldheight = 0;
2431 IPTR newwidth = 0;
2432 IPTR newheight = 0;
2434 if (NULL == data->framebuffer)
2436 /* We require framebuffer. Don't call us otherwise. */
2437 return NULL;
2440 ObtainSemaphore(&data->fbsem);
2442 if (data->shownbm)
2444 /* Get size of old bitmap */
2445 OOP_GetAttr(data->shownbm, aHidd_BitMap_Width, &oldwidth);
2446 OOP_GetAttr(data->shownbm, aHidd_BitMap_Height, &oldheight);
2448 if (data->fbmode == vHidd_FrameBuffer_Mirrored)
2450 BM__Hidd_BitMap__SetVisible(CSD(cl)->bitmapclass, data->shownbm, FALSE);
2452 else if (msg->flags & fHidd_Gfx_Show_CopyBack)
2454 /* Copy the framebuffer data back into the old shown bitmap */
2455 copy_bm_and_colmap(cl, o, data->framebuffer, data->shownbm, oldwidth, oldheight);
2459 if (bm == data->framebuffer)
2461 /* If showing the framebuffer itself, just detach from old bitmap and that's all. */
2462 data->shownbm = NULL;
2463 ReleaseSemaphore(&data->fbsem);
2465 return data->framebuffer;
2468 if (bm)
2470 IPTR modeid;
2473 * Switch framebuffer display mode.
2474 * This operation can fail if the bitmap has inappropriate mode.
2476 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
2477 if (!OOP_SetAttrsTags(data->framebuffer, aHidd_BitMap_ModeID, modeid, TAG_DONE))
2478 return NULL;
2480 /* Get size of new bitmap */
2481 OOP_GetAttr(bm, aHidd_BitMap_Width, &newwidth);
2482 OOP_GetAttr(bm, aHidd_BitMap_Height, &newheight);
2484 /* Copy it into the framebuffer */
2485 copy_bm_and_colmap(cl, o, bm, data->framebuffer, newwidth, newheight);
2489 * Clear remaining parts of the framebuffer (if previous bitmap was larger than new one)
2490 * Note that if the new bitmap is NULL, newwidth and newheight will both be zero.
2491 * This will cause clearing the whole display.
2493 if (oldheight) /* width and height can be zero only together, check one of them */
2495 if (newwidth < oldwidth)
2496 HIDD_BM_FillRect(data->framebuffer, data->gc, newwidth, 0, oldwidth - 1, oldheight - 1);
2497 if ((newheight < oldheight) && newwidth)
2498 HIDD_BM_FillRect(data->framebuffer, data->gc, 0, newheight, newwidth - 1, oldheight);
2501 /* Remember new displayed bitmap */
2502 data->shownbm = bm;
2504 ReleaseSemaphore(&data->fbsem);
2506 /* Return the actual bitmap to perform further operations on */
2507 return (data->fbmode == vHidd_FrameBuffer_Mirrored) ? bm : data->framebuffer;
2510 /*****************************************************************************************
2512 NAME
2513 moHidd_Gfx_ShowViewPorts
2515 SYNOPSIS
2516 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ShowViewPorts *msg);
2518 ULONG HIDD_Gfx_ShowViewPorts(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data, struct View *view);
2520 LOCATION
2521 hidd.gfx.driver
2523 FUNCTION
2524 Show one or more bitmaps on the screen.
2526 It is completely up to the driver how to implement this function. The driver may
2527 or may not support hardware-assisted screens composition. Bitmaps are sorted
2528 in the list in descending z-order. The driver is expected to put at least frontmost
2529 bitmap on display.
2531 It is valid to get NULL pointer as data parameter. This means that there's
2532 nothing to show and the screen should go blank.
2534 Bitmaps display offsets are stored in their aHidd_BitMap_LeftEdge and
2535 aHidd_BitMap_TopEdge attributes. This function is not expected to modify their
2536 values somehow. They are assumed to be preserved between calls unless changed
2537 explicitly by the system.
2539 If you implement this method, you don't have to implement HIDD_Gfx_Show() because
2540 it will never be called.
2542 Note that there is no more error indication - the driver is expected to be
2543 error-free here.
2545 INPUTS
2546 gfxHidd - a display driver object, whose display you wish to change.
2547 data - a singly linked list of bitmap objects to show
2549 RESULT
2550 TRUE if this method is supported by the driver, FALSE otherwise
2552 NOTES
2554 EXAMPLE
2556 BUGS
2558 SEE ALSO
2559 moHidd_Gfx_Show
2561 INTERNALS
2562 Default base class implementation simply returns FALSE. This causes
2563 the system to use HIDD_Gfx_Show() instead.
2565 *****************************************************************************************/
2567 ULONG GFXHIDD__Hidd_Gfx__ShowViewPorts(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ShowViewPorts *msg)
2569 /* By default we don't support screen composition (and this method too) */
2570 return FALSE;
2573 /*****************************************************************************************
2575 NAME
2576 moHidd_Gfx_SetCursorShape
2578 SYNOPSIS
2579 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorShape *msg);
2581 BOOL HIDD_Gfx_SetCursorShape(OOP_Object *gfxHidd, OOP_Object *shape,
2582 WORD xoffset, WORD yoffset);
2584 LOCATION
2585 hidd.gfx.driver
2587 FUNCTION
2588 Set mouse pointer shape.
2590 A pointer image is contained in the specified bitmap object. The bitmap object
2591 may contain a colormap if the system wants to specify own colors for the pointer.
2592 The supplied colormap will also contain alpha channel values.
2594 It is up to driver what to do if, for example, alpha channel is not supported by
2595 the hardware. Or if given bitmap type is not supported (for example truecolor
2596 bitmap on LUT-only hardware). It is expected that the driver converts bitmap
2597 data to a more appropriate form in such a case.
2599 A hotspot is given as an offset from the actual hotspot to the top-left corner
2600 of the pointer image. It is generally needed only for hosted display drivers
2601 which utilize host's support for mouse pointer.
2603 The default implementation in the base class just does nothing. A software mouse
2604 pointer is implemented in a special layer called fakegfx.hidd inside
2605 graphics.library. If a software pointer emulation is used, this method will
2606 never be called.
2608 INPUTS
2609 gfxHidd - a display driver object, for whose display you wish to change the pointer
2610 shape - a pointer to a bitmap object, containing pointer bitmap
2611 xoffset - a horizontal hotspot offset
2612 yoffset - a vertical hotspot offset
2614 RESULT
2615 TRUE on success, FALSE on failure
2617 NOTES
2619 EXAMPLE
2621 BUGS
2623 SEE ALSO
2624 moHidd_Gfx_SetCursorPos, moHidd_Gfx_SetCursorVisible
2626 INTERNALS
2628 *****************************************************************************************/
2630 BOOL GFXHIDD__Hidd_Gfx__SetCursorShape(OOP_Class *cl, OOP_Object *o,
2631 struct pHidd_Gfx_SetCursorShape *msg)
2633 /* We have no clue how to render the cursor */
2634 return TRUE;
2637 /*****************************************************************************************
2639 NAME
2640 moHidd_Gfx_SetCursorVisible
2642 SYNOPSIS
2643 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorVisible *msg);
2645 VOID HIDD_Gfx_SetCursorVisible(OOP_Object *gfxHidd, BOOL visible);
2647 LOCATION
2648 hidd.gfx.driver
2650 FUNCTION
2651 Control mouse pointer visiblity.
2653 The default implementation in the base class does nothing. If a software pointer
2654 emulation is used, this method will never be called.
2656 INPUTS
2657 gfxHidd - a display driver object, on whose display you wish to turn
2658 pointer on or off
2659 visible - TRUE to enable pointer display, FALSE to disable it
2661 RESULT
2662 None.
2664 NOTES
2666 EXAMPLE
2668 BUGS
2670 SEE ALSO
2671 moHidd_Gfx_SetCursorPos, moHidd_Gfx_SetCursorVisible
2673 INTERNALS
2675 *****************************************************************************************/
2677 VOID GFXHIDD__Hidd_Gfx__SetCursorVisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
2682 /*****************************************************************************************
2684 NAME
2685 moHidd_Gfx_SetCursorPos
2687 SYNOPSIS
2688 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorPos *msg);
2690 BOOL HIDD_Gfx_SetCursorPos(OOP_Object *gfxHidd, WORD x, WORD y);
2692 LOCATION
2693 hidd.gfx.driver
2695 FUNCTION
2696 Set current mouse pointer position.
2698 This is a real position on top-left image corner relative to top-left corner of
2699 the physical display. Neither logical screen origin nor hotspot are taken into
2700 account here.
2702 The default implementation in the base class does nothing and just returns TRUE.
2703 If a software pointer emulation is used, this method will never be called.
2705 INPUTS
2706 gfxHidd - a display driver object, on whose display you wish to position the pointer
2707 x - An x coordinate of the pointer (relative to the physical screen origin)
2708 y - A y coordinate of the pointer (relative to the physical screen origin)
2710 RESULT
2711 Always TRUE. Reserved for future, do not use it.
2713 NOTES
2714 This method is called by graphics.library/MoveSprite() which has no return value.
2715 However, for historical reasons, this method has a return value. Drivers should
2716 always return TRUE in order to ensure future compatibility.
2718 EXAMPLE
2720 BUGS
2722 SEE ALSO
2723 moHidd_Gfx_SetCursorShape, moHidd_Gfx_SetCursorVisible, graphics.library/MoveSprite()
2725 INTERNALS
2727 *****************************************************************************************/
2729 BOOL GFXHIDD__Hidd_Gfx__SetCursorPos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
2731 return TRUE;
2734 /*****************************************************************************************
2736 NAME
2737 moHidd_Gfx_CopyBox
2739 SYNOPSIS
2740 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg);
2742 VOID HIDD_Gfx_CopyBox(OOP_Object *gfxHidd, OOP_Object *src, WORD srcX, WORD srcY,
2743 OOP_Object *dest, WORD destX, WORD destY, UWORD width, UWORD height,
2744 OOP_Object *gc);
2746 LOCATION
2747 hidd.gfx.driver
2749 FUNCTION
2750 Perform rectangle copy (blit) operation from one bitmap to another.
2752 Given bitmaps may belong to different display drivers. The driver may attempt to
2753 use hardware for acceleration (if available), and if it's impossible, pass the
2754 operation on to the base class.
2756 Always check class of the supplied bitmap before attempting to look at its
2757 private data.
2759 A GC is used in order to specify raster operation performed between the source
2760 and destination according to its aHidd_GC_DrawMode attribute value.
2762 INPUTS
2763 gfxHidd - a display driver object that you are going to use for copying
2764 src - a pointer to source bitmap object
2765 srcX - an X coordinate of the source rectangle
2766 srcY - a Y coordinate of the source rectangle
2767 dest - a pointer to destination bitmap object
2768 destX - an X coordinate of the destination rectangle
2769 destY - a Y coordinate of the destination rectangle
2770 width - width of the rectangle to copy
2771 height - height of the rectangle to copy
2772 gc - graphics context holding draw mode on the destination
2774 RESULT
2775 None.
2777 NOTES
2778 You must specify valid coordinates (non-negative and inside the actual bitmap
2779 area), no checks are done.
2781 It is valid to specify two overlapped areas of the same bitmap as source
2782 and destination.
2784 EXAMPLE
2786 BUGS
2788 SEE ALSO
2790 INTERNALS
2792 *****************************************************************************************/
2794 VOID GFXHIDD__Hidd_Gfx__CopyBox(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg)
2796 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2797 WORD x, y;
2798 WORD srcX = msg->srcX, destX = msg->destX;
2799 WORD srcY = msg->srcY, destY = msg->destY;
2800 WORD startX, endX, deltaX, startY, endY, deltaY;
2801 ULONG memFG;
2802 HIDDT_PixelFormat *srcpf, *dstpf;
2803 OOP_Object *dest, *src;
2804 OOP_Object *gc;
2805 APTR srcPixels = NULL;
2806 APTR destPixels = NULL;
2808 dest = msg->dest;
2809 src = msg->src;
2811 /* If source/dest overlap, direction of operation is important */
2813 if (srcX < destX)
2815 startX = msg->width - 1; endX = -1; deltaX = -1;
2817 else
2819 startX = 0; endX = msg->width; deltaX = 1;
2822 if (srcY < destY)
2824 startY = msg->height - 1; endY = -1; deltaY = -1;
2826 else
2828 startY = 0; endY = msg->height; deltaY = 1;
2831 /* Get the source pixel format */
2832 srcpf = (HIDDT_PixelFormat *)HBM(src)->prot.pixfmt;
2834 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,
2835 msg->src, srcX, srcY, msg->dest, destX, destY, msg->width, msg->height));
2836 DCOPYBOX(bug("COPYBOX: GC=0x%p, DrawMode %ld, ColMask 0x%08X\n", msg->gc, GC_DRMD(msg->gc), GC_COLMASK(msg->gc)));
2838 #ifdef COPYBOX_DUMP_DIMS
2840 IPTR sw, sh, dw, dh;
2842 OOP_GetAttr(obj, aHidd_BitMap_Width, &sw);
2843 OOP_GetAttr(obj, aHidd_BitMap_Height, &sh);
2844 OOP_GetAttr(msg->dest, aHidd_BitMap_Width, &dw);
2845 OOP_GetAttr(msg->dest, aHidd_BitMap_Height, &dh);
2847 bug("src dims: %dx%d dest dims: %dx%d\n", sw, sh, dw, dh);
2849 #endif
2851 dstpf = (HIDDT_PixelFormat *)HBM(dest)->prot.pixfmt;
2853 OOP_GetAttr(msg->src, aHidd_ChunkyBM_Buffer, (APTR)&srcPixels);
2854 OOP_GetAttr(msg->dest, aHidd_ChunkyBM_Buffer, (APTR)&destPixels);
2856 if (srcPixels && destPixels)
2859 * Both bitmaps are chunky ones and they have directly accessible buffer.
2860 * We can use optimized routines to do the copy.
2862 IPTR src_bytesperline, dest_bytesperline;
2864 OOP_GetAttr(msg->src, aHidd_BitMap_BytesPerRow, &src_bytesperline);
2865 OOP_GetAttr(msg->dest, aHidd_BitMap_BytesPerRow, &dest_bytesperline);
2867 switch(GC_DRMD(msg->gc))
2869 case vHidd_GC_DrawMode_Copy:
2870 /* At the moment we optimize only bulk copy */
2872 if (srcpf == dstpf)
2875 * The same pixelformat. Extremely great!
2877 * FIXME: Bulk copy to the same pixelformat is also handled in ConvertPixels very well
2878 * (optimized to either per-line or bulk memcpy()). But it can't handle
2879 * overlapping regions (which seems to be a requirement for CopyBox).
2880 * If this is fixed, we can even throw away HIDD_BM_CopyMemBoxXX at all, reducing
2881 * kickstart size.
2883 switch(srcpf->bytes_per_pixel)
2885 case 1:
2887 * In fact all these methods are static, they ignore object pointer, and it's
2888 * needed only for OOP_DoMethod() to fetch class information.
2889 * We use destination bitmap pointer, we can also source one.
2891 HIDD_BM_CopyMemBox8(msg->dest,
2892 srcPixels, msg->srcX, msg->srcY,
2893 destPixels, msg->destX, msg->destY,
2894 msg->width, msg->height,
2895 src_bytesperline, dest_bytesperline);
2896 return;
2898 case 2:
2899 HIDD_BM_CopyMemBox16(msg->dest,
2900 srcPixels, msg->srcX, msg->srcY,
2901 destPixels, msg->destX, msg->destY,
2902 msg->width, msg->height,
2903 src_bytesperline, dest_bytesperline);
2904 return;
2906 case 3:
2907 HIDD_BM_CopyMemBox24(msg->dest,
2908 srcPixels, msg->srcX, msg->srcY,
2909 destPixels, msg->destX, msg->destY,
2910 msg->width, msg->height,
2911 src_bytesperline, dest_bytesperline);
2912 return;
2914 case 4:
2915 HIDD_BM_CopyMemBox32(msg->dest,
2916 srcPixels, msg->srcX, msg->srcY,
2917 destPixels, msg->destX, msg->destY,
2918 msg->width, msg->height,
2919 src_bytesperline, dest_bytesperline);
2920 return;
2922 } /* switch(srcpf->bytes_per_pixel) */
2923 } /* srcpf == dstpf */
2924 else
2927 * Pixelformats are different. This can't be the same bitmap,
2928 * and it's safe to use ConvertPixels method (see FIXME above).
2930 srcPixels += (msg->srcY * src_bytesperline ) + (msg->srcX * srcpf->bytes_per_pixel);
2931 destPixels += (msg->destY * dest_bytesperline) + (msg->destX * dstpf->bytes_per_pixel);
2934 * Supply NULL pixlut. In this case bitmap's own colormap will be used
2935 * for color lookup (if needed).
2937 HIDD_BM_ConvertPixels(msg->dest,
2938 &srcPixels, srcpf, src_bytesperline,
2939 &destPixels, dstpf, dest_bytesperline,
2940 msg->width, msg->height, NULL);
2942 return;
2945 break;
2947 /* TODO: Optimize other DrawModes here */
2949 } /* switch(mode) */
2951 } /* srcPixels && destPixels */
2953 gc = msg->gc;
2955 memFG = GC_FG(msg->gc);
2957 /* All else have failed, copy pixel by pixel */
2958 if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf))
2960 if (IS_TRUECOLOR(srcpf))
2962 DCOPYBOX(bug("COPY FROM TRUECOLOR TO TRUECOLOR\n"));
2964 for(y = startY; y != endY; y += deltaY)
2966 HIDDT_Color col;
2968 /* if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
2969 bug("[%d,%d] ", memSrcX, memDestX);
2971 for(x = startX; x != endX; x += deltaX)
2973 HIDDT_Pixel pix = GETPIXEL(cl, src, srcX + x, srcY + y);
2975 #if COPYBOX_CHECK_FOR_ALIKE_PIXFMT
2976 if (srcpf == dstpf)
2978 GC_FG(gc) = pix;
2980 else
2981 #endif
2983 HIDD_BM_UnmapPixel(src, pix, &col);
2984 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, &col);
2987 DRAWPIXEL(cl, dest, gc, destX + x, destY + y);
2989 /*if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
2990 bug("[%d,%d] ", srcY, destY);
2994 } /* if (IS_TRUECOLOR(srcpf)) */
2995 else
2997 /* Two palette bitmaps.
2998 For this case we do NOT convert through RGB,
2999 but copy the pixel indexes directly
3001 DCOPYBOX(bug("COPY FROM PALETTE TO PALETTE\n"));
3003 /* FIXME: This might not work very well with two StaticPalette bitmaps */
3005 for(y = startY; y != endY; y += deltaY)
3007 for(x = startX; x != endX; x += deltaX)
3009 GC_FG(gc) = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3011 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
3016 } /* if (IS_TRUECOLOR(srcpf)) else ... */
3018 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) */
3019 else
3021 /* Two unlike bitmaps */
3022 if (IS_TRUECOLOR(srcpf))
3024 for(y = startY; y != endY; y += deltaY)
3026 for(x = startX; x != endX; x += deltaX)
3028 HIDDT_Pixel pix;
3029 HIDDT_Color col;
3031 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3032 HIDD_BM_UnmapPixel(src, pix, &col);
3034 HIDD_BM_PutPixel(dest, destX + x, destY + y,
3035 HIDD_BM_MapColor(dest, &col));
3039 else if (IS_TRUECOLOR(dstpf))
3041 /* Get the colortab */
3042 HIDDT_Color *ctab = ((HIDDT_ColorLUT *)HBM(src)->colmap)->colors;
3044 DCOPYBOX(bug("COPY FROM PALETTE TO TRUECOLOR, DRAWMODE %d, CTAB %p\n", GC_DRMD(gc), ctab));
3046 for(y = startY; y != endY; y += deltaY)
3048 for(x = startX; x != endX; x += deltaX)
3050 register HIDDT_Pixel pix;
3051 HIDDT_Color col;
3053 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3054 col = ctab[pix];
3057 * !!!! HIDD_BM_MapColor() pokes pixval of the passed HIDDT_Color,
3058 * so if the address of the entry in the colormap is passed, the colormap
3059 * itself will be modified, if we pass "&ctab[pix]" to HIDD_BM_MapColor() !!!!
3062 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, &col);
3063 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
3069 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) else ... */
3071 GC_FG(gc) = memFG;
3074 /*****************************************************************************************
3076 NAME
3077 moHidd_Gfx_CopyBoxMasked
3079 SYNOPSIS
3080 IPTR OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CopyBoxMasked *msg);
3082 IPTR HIDD_Gfx_CopyBoxMasked(OOP_Object *gfxHidd, OOP_Object *src, WORD srcX, WORD srcY,
3083 OOP_Object *dest, WORD destX, WORD destY, UWORD width, UWORD height,
3084 PLANEPTR mask, OOP_Object *gc);
3086 LOCATION
3087 hidd.gfx.driver
3089 FUNCTION
3090 Perform rectangle copy (blit) operation from one bitmap to another,
3091 using a cookie cutter mask.
3093 Given bitmaps must be on the same display driver.
3095 A GC is used in order to specify raster operation performed between the source
3096 and destination according to its aHidd_GC_DrawMode attribute value.
3098 INPUTS
3099 gfxHidd - a display driver object that you are going to use for copying
3100 src - a pointer to source bitmap object
3101 srcX - an X coordinate of the source rectangle
3102 srcY - a Y coordinate of the source rectangle
3103 dest - a pointer to destination bitmap object
3104 destX - an X coordinate of the destination rectangle
3105 destY - a Y coordinate of the destination rectangle
3106 width - width of the rectangle to copy
3107 height - height of the rectangle to copy
3108 mask - single bitplane mask
3109 gc - graphics context holding draw mode on the destination
3111 RESULT
3112 TRUE is the operation succeeded and FALSE in case of some error, for example
3113 if the system was too low on memory.
3115 NOTES
3116 You must specify valid coordinates (non-negative and inside the actual bitmap
3117 area), no checks are done.
3119 It is valid to specify two overlapped areas of the same bitmap as source
3120 and destination.
3122 Mask size must correspond to full source bitmap size (including alignment).
3124 EXAMPLE
3126 BUGS
3128 SEE ALSO
3130 INTERNALS
3132 *****************************************************************************************/
3134 /* Nominal size of the pixel conversion buffer */
3135 #ifdef __mc68000
3136 #define NUMPIX 4096 /* Not that much room to spare */
3137 #else
3138 #define NUMPIX 100000
3139 #endif
3141 IPTR GFXHIDD__Hidd_Gfx__CopyBoxMasked(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBoxMasked *msg)
3143 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3144 ULONG pixfmt = vHidd_StdPixFmt_Native32;
3145 OOP_Object *src_pf, *dest_pf;
3146 HIDDT_ColorModel src_colmod, dest_colmod;
3147 HIDDT_Color *ctab = NULL;
3148 ULONG bytes_per_line, lines_per_step, doing_lines, lines_done;
3149 IPTR mask_align, mask_bpr;
3150 UBYTE *srcbuf;
3152 OOP_GetAttr(msg->src , aHidd_BitMap_PixFmt, (IPTR *)&src_pf);
3153 OOP_GetAttr(msg->dest, aHidd_BitMap_PixFmt, (IPTR *)&dest_pf);
3155 OOP_GetAttr(src_pf, aHidd_PixFmt_ColorModel, &src_colmod);
3156 OOP_GetAttr(dest_pf, aHidd_PixFmt_ColorModel, &dest_colmod);
3158 if ((src_colmod == vHidd_ColorModel_Palette) && (dest_colmod == vHidd_ColorModel_TrueColor))
3161 * LUT->truecolor conversion. We need a colormap (palette).
3162 * If the source is displayable (screen) bitmap, it will have own palette. In this case
3163 * we should use it.
3164 * If it's just a bitmap in memory, it won't have a palette (colmap will be NULL). In this
3165 * case destination bitmap needs to have a palette. This will happen if it's either a displayable
3166 * bitmap, or is a friend of displayable bitmap (will share friend's palette then).
3168 HIDDT_ColorLUT *colmap = (HIDDT_ColorLUT *)HBM(msg->src)->colmap;
3170 if (!colmap)
3171 colmap = (HIDDT_ColorLUT *)HBM(msg->dest)->colmap;
3173 if (!colmap)
3175 D(bug("BltMaskBitMapRastPort could not retrieve pixel table for blit from palette to truecolor bitmap"));
3176 return FALSE;
3179 ctab = colmap->colors;
3181 else if ((src_colmod == vHidd_ColorModel_TrueColor) && (dest_colmod == vHidd_ColorModel_TrueColor))
3183 if (src_pf != dest_pf)
3186 * Pixelformats are different, conversion needed.
3187 * First, we use two operations on destination bitmap (get and put), and only one
3188 * operation on source bitmap (get).
3189 * Second, we map LUT source pixels on destination bitmap's pixelformat.
3190 * Resume: we use destination's pixelformat for the whole operation. Conversion
3191 * happens during GetImage on the source bitmap.
3193 OOP_GetAttr(dest_pf, aHidd_PixFmt_StdPixFmt, (IPTR *)&pixfmt);
3196 else if ((src_colmod == vHidd_ColorModel_TrueColor) && (dest_colmod == vHidd_ColorModel_Palette))
3198 D(bug("BltMaskBitMapRastPort from truecolor bitmap to palette bitmap not supported!"));
3199 return FALSE;
3202 /* Mask width in pixels corresponds to full bitmap width (including alignment) */
3203 OOP_GetAttr(msg->src, aHidd_BitMap_Width, &mask_bpr);
3204 OOP_GetAttr(msg->src, aHidd_BitMap_Align, &mask_align);
3206 mask_align--;
3207 mask_bpr = ((mask_bpr + mask_align) & ~mask_align) >> 3;
3210 * TODO: Here we use a temporary buffer to perform the operation. This is slow and
3211 * actually unnecessary is many cases. If one of source or destination bitmaps is
3212 * directly accessible, we should use their own buffers. This will increase the speed
3213 * and decrease memory usage, because of omitted copy operations.
3216 /* Based on the NUMPIX advice, figure out how many
3217 * lines per step we can allocate
3219 bytes_per_line = msg->width * sizeof(HIDDT_Pixel);
3220 lines_per_step = NUMPIX / bytes_per_line;
3221 if (lines_per_step == 0)
3222 lines_per_step = 1;
3224 /* Allocate a temporary buffer */
3225 srcbuf = AllocMem(2 * lines_per_step * bytes_per_line, MEMF_ANY);
3227 /* Try line-at-a-time if we can't allocate a big buffer */
3228 if (!srcbuf && lines_per_step > 1)
3230 lines_per_step = 1;
3231 srcbuf = AllocMem(2 * lines_per_step * bytes_per_line, MEMF_ANY);
3234 if (srcbuf)
3236 UBYTE *destbuf = srcbuf + lines_per_step * bytes_per_line;
3237 HIDDT_DrawMode drawmode = GC_DRMD(msg->gc);
3239 /* PutImage needs to be called in Copy mode for proper operation */
3240 GC_DRMD(msg->gc) = vHidd_GC_DrawMode_Copy;
3242 for (lines_done = 0; lines_done != msg->height; lines_done += doing_lines)
3244 HIDDT_Pixel *srcpixelbuf;
3245 HIDDT_Pixel *destpixelbuf;
3246 UBYTE *mask;
3247 UWORD x, y;
3249 doing_lines = lines_per_step;
3250 if (lines_done + doing_lines > msg->height)
3251 doing_lines = msg->height - lines_done;
3253 HIDD_BM_GetImage(msg->src, srcbuf, bytes_per_line,
3254 msg->srcX, msg->srcY + lines_done,
3255 msg->width, doing_lines, pixfmt);
3257 HIDD_BM_GetImage(msg->dest, destbuf, bytes_per_line,
3258 msg->destX, msg->destY + lines_done,
3259 msg->width, doing_lines, pixfmt);
3261 mask = &msg->mask[COORD_TO_BYTEIDX(0, msg->srcY + lines_done, mask_bpr)];
3263 srcpixelbuf = (HIDDT_Pixel *)srcbuf;
3264 destpixelbuf = (HIDDT_Pixel *)destbuf;
3266 switch (drawmode)
3268 case vHidd_GC_DrawMode_Or: /* (ABC|ABNC|ANBC) if copy source and blit thru mask */
3269 case vHidd_GC_DrawMode_Copy: /* (ABC|ABNC = 0xC0) - compatibility with AOS3 */
3270 for (y = 0; y < doing_lines; y++)
3272 for (x = 0; x < msg->width; x++)
3274 if (mask[XCOORD_TO_BYTEIDX(msg->srcX + x)] & XCOORD_TO_MASK(msg->srcX + x))
3276 HIDDT_Pixel pix = *srcpixelbuf;
3278 if (ctab)
3281 * TODO:
3282 * Here and in several other places we use colormap data for palette->truecolor conversion.
3283 * The algorithm is as follows: take LUT pixel value (which is effectively color index), find RGB
3284 * entry in the LUT, then compose a pixel from RGB triplet using MapColor method on the destination
3285 * bitmap.
3286 * This two-step operation is slow. graphics.library internally uses cached version of the palette
3287 * (HIDDT_PixLut), where all colors are already decoded into pixel values.
3288 * Since HIDD subsystem also needs this, this pixlut (called pixtab - pixel table in graphics.library),
3289 * should be moved here. In fact a good place for it is a bitmap object (since pixlut = colormap + pixfmt,
3290 * and pixfmt is a bitmap's property.
3291 * graphics.library has pixlut attached to a BitMap structure (using HIDD_BM_PIXTAB() macro).
3295 * !!!! HIDD_BM_MapColor() pokes pixval of the passed HIDDT_Color,
3296 * so if the address of the entry in the colormap is passed, the colormap
3297 * itself will be modified, if we pass "&ctab[pix]" to HIDD_BM_MapColor() !!!!
3300 HIDDT_Color col = ctab[pix];
3302 pix = HIDD_BM_MapColor(msg->dest, &col);
3305 *destpixelbuf = pix;
3307 srcpixelbuf++;
3308 destpixelbuf++;
3310 mask += mask_bpr;
3312 break;
3314 case vHidd_GC_DrawMode_AndInverted: /* (ANBC) if invert source and blit thru mask */
3315 D(bug("CopyBoxMasked does not support ANBC minterm yet"));
3316 break;
3318 default:
3319 D(bug("CopyBoxMasked: DrawMode 0x%x not handled.\n", drawmode));
3320 break;
3323 HIDD_BM_PutImage(msg->dest, msg->gc, destbuf, bytes_per_line,
3324 msg->destX, msg->destY + lines_done,
3325 msg->width, doing_lines, pixfmt);
3327 } /* for(lines_done = 0; lines_done != height; lines_done += doing_lines) */
3329 /* Restore GC state */
3330 GC_DRMD(msg->gc) = drawmode;
3332 /* Free our temporary buffer */
3333 FreeMem(srcbuf, 2 * lines_per_step * bytes_per_line);
3335 return TRUE;
3336 } /* if (lines_per_step) */
3337 else
3339 /* urk :-( pixelbuffer too small to hold two lines) */
3340 D(bug("BltMaskBitMapRastPort found pixelbuffer to be too small"));
3341 return FALSE;
3346 /*****************************************************************************************
3348 NAME
3349 moHidd_Gfx_ShowImminentReset
3351 SYNOPSIS
3352 VOID OOP_DoMethod(OOP_Object *obj, OOP_Msg msg);
3354 LOCATION
3355 hidd.gfx.driver
3357 FUNCTION
3358 Indicate upcoming machine reset. Obsolete.
3360 Since graphics.library v41.4 this method is not used any more. Considered
3361 reserved. Do not use it in any way.
3363 INPUTS
3364 None.
3366 RESULT
3367 None.
3369 NOTES
3371 EXAMPLE
3373 BUGS
3375 SEE ALSO
3377 INTERNALS
3379 *****************************************************************************************/
3381 VOID GFXHIDD__Hidd_Gfx__ShowImminentReset(OOP_Class *cl, OOP_Object *obj, OOP_Msg msg)
3385 /****************************************************************************************/
3388 * The following two methods are private, static, and not virtual.
3389 * They operate only on static data and don't need object pointer.
3392 OOP_Object *GFXHIDD__Hidd_Gfx__RegisterPixFmt(OOP_Class *cl, struct TagItem *pixFmtTags)
3394 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3395 HIDDT_PixelFormat cmp_pf;
3396 struct class_static_data *data;
3397 struct pixfmt_data *retpf = NULL;
3399 memset(&cmp_pf, 0, sizeof(cmp_pf));
3401 data = CSD(cl);
3402 if (!parse_pixfmt_tags(pixFmtTags, &cmp_pf, 0, CSD(cl)))
3404 D(bug("!!! FAILED PARSING TAGS IN Gfx::RegisterPixFmt() !!!\n"));
3405 return FALSE;
3409 * Our alpha-less R8G8B8 pixelformats are defined as having depth
3410 * and size = 24, not 32 bits. Nevertheless, many hardware reports
3411 * 32 bits in such cases.
3412 * In order to avoid confusion we attempt to detect this situation and
3413 * fix up pixelformat definition. If we don't do it, we get nonstandard
3414 * pixelformat with no corresponding CGX code, which can misbehave.
3416 if ((cmp_pf.flags == PF_GRAPHTYPE(TrueColor, Chunky)) &&
3417 (cmp_pf.bytes_per_pixel == 4) && (cmp_pf.alpha_mask == 0) &&
3418 (cmp_pf.red_mask << cmp_pf.red_shift == 0xFF000000) &&
3419 (cmp_pf.green_mask << cmp_pf.green_shift == 0xFF000000) &&
3420 (cmp_pf.blue_mask << cmp_pf.blue_shift == 0xFF000000))
3422 DPF(bug("Gfx::RegisterPixFmt(): 4-byte R8G8B8 detected\n"));
3424 if (cmp_pf.depth > 24)
3426 DPF(bug("Gfx::RegisterPixFmt(): Fixing up depth %d > 24\n", cmp_pf.depth));
3427 cmp_pf.depth = 24;
3430 if (cmp_pf.size > 24)
3432 DPF(bug("Gfx::RegisterPixFmt(): Fixing up size %d > 24\n", cmp_pf.size));
3433 cmp_pf.size = 24;
3437 DPF(bug("Gfx::RegisterPixFmt(): Registering pixelformat:\n"));
3438 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
3439 , PF(&cmp_pf)->red_shift
3440 , PF(&cmp_pf)->green_shift
3441 , PF(&cmp_pf)->blue_shift
3442 , PF(&cmp_pf)->alpha_shift
3443 , PF(&cmp_pf)->red_mask
3444 , PF(&cmp_pf)->green_mask
3445 , PF(&cmp_pf)->blue_mask
3446 , PF(&cmp_pf)->alpha_mask
3447 , PF(&cmp_pf)->bytes_per_pixel
3448 , PF(&cmp_pf)->size
3449 , PF(&cmp_pf)->depth
3450 , PF(&cmp_pf)->stdpixfmt));
3452 retpf = find_pixfmt(&cmp_pf, CSD(cl));
3454 DPF(bug("Found matching pixelformat: 0x%p\n", retpf));
3455 if (retpf)
3456 /* Increase pf refcount */
3457 AROS_ATOMIC_INC(retpf->refcount);
3458 else
3460 /* Could not find an alike pf, Create a new pfdb node */
3461 /* Since we pass NULL as the taglist below, the PixFmt class will just create a dummy pixfmt */
3462 retpf = OOP_NewObject(CSD(cl)->pixfmtclass, NULL, NULL);
3463 if (retpf) {
3464 /* We have one user */
3465 retpf->refcount = 1;
3467 /* Initialize the pixfmt object the "ugly" way */
3468 memcpy(retpf, &cmp_pf, sizeof (HIDDT_PixelFormat));
3470 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
3471 , PF(&cmp_pf)->red_shift
3472 , PF(&cmp_pf)->green_shift
3473 , PF(&cmp_pf)->blue_shift
3474 , PF(&cmp_pf)->alpha_shift
3475 , PF(&cmp_pf)->red_mask
3476 , PF(&cmp_pf)->green_mask
3477 , PF(&cmp_pf)->blue_mask
3478 , PF(&cmp_pf)->alpha_mask
3479 , PF(&cmp_pf)->bytes_per_pixel
3480 , PF(&cmp_pf)->size
3481 , PF(&cmp_pf)->depth
3482 , PF(&cmp_pf)->stdpixfmt));
3484 ObtainSemaphore(&data->pfsema);
3485 AddTail((struct List *)&data->pflist, (struct Node *)&retpf->node);
3486 ReleaseSemaphore(&data->pfsema);
3490 DPF(bug("New refcount is %u\n", retpf->refcount));
3491 return (OOP_Object *)retpf;
3494 /****************************************************************************************/
3496 /* This method doesn't need object pointer, it's static. */
3498 VOID GFXHIDD__Hidd_Gfx__ReleasePixFmt(OOP_Class *cl, OOP_Object *pf)
3500 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3501 struct class_static_data *data;
3502 struct pixfmt_data *pixfmt = (struct pixfmt_data *)pf;
3504 DPF(bug("release_pixfmt 0x%p\n", pixfmt));
3506 data = CSD(cl);
3508 ObtainSemaphore(&data->pfsema);
3510 /* If refcount is already 0, this object was never registered in the database,
3511 don't touch it */
3512 DPF(bug("Old reference count is %u\n", pixfmt->refcount));
3513 if (pixfmt->refcount) {
3514 if (--pixfmt->refcount == 0) {
3515 Remove((struct Node *)&pixfmt->node);
3516 OOP_DisposeObject((OOP_Object *)pixfmt);
3520 ReleaseSemaphore(&data->pfsema);
3523 /*****************************************************************************************
3525 NAME
3526 moHidd_Gfx_CheckMode
3528 SYNOPSIS
3529 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CheckMode *msg);
3531 BOOL HIDD_Gfx_CheckMode(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
3532 OOP_Object *sync, OOP_Object *pixFmt);
3534 LOCATION
3535 hidd.gfx.driver
3537 FUNCTION
3538 Check if given display mode is supported by the driver.
3540 Normally any resolution (sync) can be used together with any pixelformat. However
3541 on some hardware there may be exceptions from this rule. In such a case this
3542 method should be implemented, and check should be performed.
3544 The information provided by this method is used in order to exclude unsupported
3545 modes from the database
3547 Default implementation in the base class just returns TRUE for all supplied values.
3549 Note that this method can not be used in order to chech that the given mode is
3550 really present in the database and it really refers to the given sync and
3551 pixelformat objects. Use HIDD_Gfx_GetMode() for mode ID validation.
3553 INPUTS
3554 gfxHidd - A display driver object
3555 modeID - A display mode ID
3556 sync - A pointer to a sync object associated with this mode
3557 pixFmt - A pointer to a pixelformat object associated with this mode
3559 RESULT
3560 TRUE if this mode is supported and FALSE if it's not.
3562 NOTES
3564 EXAMPLE
3566 BUGS
3567 Currently base class does not call this method after driver object creation.
3568 This needs to be fixed.
3570 SEE ALSO
3571 moHidd_Gfx_GetMode
3573 INTERNALS
3575 *****************************************************************************************/
3577 BOOL GFXHIDD__Hidd_Gfx__CheckMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CheckMode *msg)
3579 /* As a default we allways return TRUE, ie. the mode is OK */
3580 return TRUE;
3583 /*****************************************************************************************
3585 NAME
3586 moHidd_Gfx_GetPixFmt
3588 SYNOPSIS
3589 OOP_Object *OOP_DoMethod(OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg);
3591 OOP_Object *HIDD_Gfx_GetPixFmt(OOP_Object *gfxHidd, HIDDT_StdPixFmt pixFmt);
3593 LOCATION
3594 hidd.gfx.driver
3596 FUNCTION
3597 Get a standard pixelformat descriptor from internal pixelformats database.
3599 INPUTS
3600 gfxHidd - A display driver object
3601 pixFmt - An index of pixelformat (one of vHIDD_StdPixFmt_... values)
3603 RESULT
3604 A pointer to a pixelformat object or NULL if lookup failed
3606 NOTES
3607 Pixelformat objects are stored in a global system-wide database. They are not
3608 linked with a particular driver in any way and completely sharable between all
3609 drivers.
3611 EXAMPLE
3613 BUGS
3615 SEE ALSO
3617 INTERNALS
3618 This operation can never fail because all standard pixelformats are registered
3619 during early system initialization.
3621 *****************************************************************************************/
3623 OOP_Object *GFXHIDD__Hidd_Gfx__GetPixFmt(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg)
3625 OOP_Object *fmt;
3627 if (!IS_REAL_STDPIXFMT(msg->stdPixFmt))
3629 D(bug("!!! Illegal pixel format passed to Gfx::GetPixFmt(): %d\n", msg->stdPixFmt));
3630 return NULL;
3632 else
3634 fmt = (OOP_Object *)CSD(cl)->std_pixfmts[REAL_STDPIXFMT_IDX(msg->stdPixFmt)];
3637 return fmt;
3640 /*****************************************************************************************
3642 NAME
3643 moHidd_Gfx_GetSync
3645 SYNOPSIS
3646 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetSync *msg);
3648 OOP_Object *HIDD_Gfx_GetSync(OOP_Object *gfxHidd, ULONG num);
3650 LOCATION
3651 hidd.gfx.driver
3653 FUNCTION
3654 Get a sync object from internal display mode database by index
3656 INPUTS
3657 gfxHidd - A display driver object to query
3658 num - An index of sync object starting from 0
3660 RESULT
3661 A pointer to a sync object or NULL if there's no sync with such index
3663 NOTES
3665 EXAMPLE
3667 BUGS
3669 SEE ALSO
3671 INTERNALS
3673 *****************************************************************************************/
3675 OOP_Object *GFXHIDD__Hidd_Gfx__GetSync(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetSync *msg)
3677 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
3679 if (msg->num < data->mdb.num_syncs)
3680 return data->mdb.syncs[msg->num];
3681 else {
3682 D(bug("!!! Illegal sync index passed to Gfx::GetSync(): %d\n", msg->num));
3683 return NULL;
3687 /*****************************************************************************************
3689 NAME
3690 moHidd_Gfx_ModeProperties
3692 SYNOPSIS
3693 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ModeProperties *msg);
3695 ULONG HIDD_Gfx_ModeProperties(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
3696 struct HIDD_ModeProperties *props, ULONG propsLen);
3698 LOCATION
3699 hidd.gfx.driver
3701 FUNCTION
3702 Obtain an information about the video mode.
3704 Video mode description structure may grow in future, so be careful and always check
3705 propsLen parameter value. A system may ask you for less data than you can provide.
3706 Always return an actual value. Do not just zero out fields you don't know about,
3707 this is not expected to be backwards compatible.
3709 INPUTS
3710 gfxHidd - a pointer to a display driver object whose display mode you want to query
3711 modeID - a mode ID to query
3712 props - a pointer to a storage area where HIDD_ModeProperties structure will be put
3713 propsLen - length of the supplied buffer in bytes.
3715 RESULT
3716 Actual length of obtained structure
3718 NOTES
3719 Returned data must reflect only real hardware capabilities. For example, do not
3720 count emulated sprites. The system takes care about emulated features itself.
3722 EXAMPLE
3724 BUGS
3726 SEE ALSO
3727 aoHidd_Gfx_HWSpriteTypes, aoHidd_Gfx_SupportsHWCursor
3729 INTERNALS
3730 Default implementation in the base class relies on aHidd_Gfx_HWSpriteTypes attribute,
3731 not vice versa. If you override this method, do not forget to override this attribute too.
3733 *****************************************************************************************/
3735 ULONG GFXHIDD__Hidd_Gfx__ModeProperties(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ModeProperties *msg)
3737 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3738 struct HIDD_ModeProperties props = {0, 0, 0};
3739 IPTR has_hw_cursor = 0;
3740 ULONG len = msg->propsLen;
3742 D(bug("[GFXHIDD] Hidd::Gfx::ModeProperties(0x%08lX, 0x%p, %u)\n", msg->modeID, msg->props, msg->propsLen));
3743 OOP_GetAttr(o, aHidd_Gfx_HWSpriteTypes, &has_hw_cursor);
3744 if (has_hw_cursor) {
3745 D(bug("[GFXHIDD] Driver has hardware mouse cursor implementation\n"));
3746 props.DisplayInfoFlags = DIPF_IS_SPRITES;
3747 props.NumHWSprites = 1;
3750 if (len > sizeof(props))
3751 len = sizeof(props);
3752 D(bug("[GFXHIDD] Copying %u bytes\n", len));
3753 CopyMem(&props, msg->props, len);
3755 return len;
3758 /*****************************************************************************************
3760 NAME
3761 moHidd_Gfx_GetGamma
3763 SYNOPSIS
3764 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Gamma *msg);
3766 BOOL HIDD_Gfx_GetGamma(OOP_Object *gfxHidd, UBYTE *Red, UBYTE *Green, UBYTE *Blue);
3768 LOCATION
3769 hidd.gfx.driver
3771 FUNCTION
3772 Get current gamma table for the display.
3774 This method was neither ever implemented nor used. Currently obsolete and
3775 considered reserved.
3777 INPUTS
3779 RESULT
3781 NOTES
3783 EXAMPLE
3785 BUGS
3787 SEE ALSO
3788 moHidd_Gfx_SetGamma
3790 INTERNALS
3792 *****************************************************************************************/
3794 BOOL GFXHIDD__Hidd_Gfx__GetGamma(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Gamma *msg)
3796 return FALSE;
3799 /*****************************************************************************************
3801 NAME
3802 moHidd_Gfx_SetGamma
3804 SYNOPSIS
3805 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Gamma *msg);
3807 BOOL HIDD_Gfx_SetGamma(OOP_Object *gfxHidd, UBYTE *Red, UBYTE *Green, UBYTE *Blue);
3809 LOCATION
3810 hidd.gfx.driver
3812 FUNCTION
3813 Set current gamma table for the display.
3815 A gamma table consists of three 256-byte tables: one for red component, one for
3816 green and one for blue.
3818 INPUTS
3819 gfxHidd - A display driver object
3820 Red - A pointer to a 256-byte array for red component
3821 Green - A pointer to a 256-byte array for green component
3822 Blue - A pointer to a 256-byte array for blue component
3824 RESULT
3825 FALSE if the driver doesn't support gamma correction, otherwise TRUE
3827 NOTES
3829 EXAMPLE
3831 BUGS
3833 SEE ALSO
3835 INTERNALS
3837 *****************************************************************************************/
3839 BOOL GFXHIDD__Hidd_Gfx__SetGamma(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Gamma *msg)
3841 return FALSE;
3844 /*****************************************************************************************
3846 NAME
3847 moHidd_Gfx_QueryHardware3D
3849 SYNOPSIS
3850 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_QueryHardware3D *msg);
3852 BOOL HIDD_Gfx_QueryHardware3D(OOP_Object *gfxHidd, OOP_Object *pixFmt);
3854 LOCATION
3855 hidd.gfx.driver
3857 FUNCTION
3858 Query if the driver supports hardware-accelerated 3D graphics for the given
3859 pixelformat.
3861 INPUTS
3862 gfxHidd - A display driver object
3863 pixFmt - A pointer to a pixelformat descriptor object
3865 RESULT
3866 TRUE if the driver supports hardware-accelerated 3D for the given pixelformat,
3867 FALSE otherwise.
3869 NOTES
3871 EXAMPLE
3873 BUGS
3875 SEE ALSO
3877 INTERNALS
3879 *****************************************************************************************/
3881 BOOL GFXHIDD__Hidd_Gfx__QueryHardware3D(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_QueryHardware3D *msg)
3883 return FALSE;
3886 /*****************************************************************************************
3888 NAME
3889 moHidd_Gfx_GetMaxSpriteSize
3891 SYNOPSIS
3892 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetMaxSpriteSize *msg);
3894 BOOL HIDD_Gfx_GetMaxSpriteSize(OOP_Object *gfxHidd, ULONG Type, UWORD *Width, UWORD *Height);
3896 LOCATION
3897 hidd.gfx.driver
3899 FUNCTION
3900 Query maximum allowed size for the given sprite type.
3902 INPUTS
3903 gfxHidd - A display driver object
3904 Type - Type of the sprite image (one of vHidd_SpriteType_... values)
3905 Width - A pointer to UWORD where width will be placed.
3906 Height - A pointer to UWORD where height will be placed.
3908 RESULT
3909 FALSE is the given sprite type is not supported, otherwise TRUE.
3911 NOTES
3912 Default implementation in the base class just return some small values
3913 which it hopes can be supported by every driver if the driver supports given
3914 sprite type. It is strongly suggested to reimplement this method in the display
3915 driver.
3917 Width and Height are considered undefined if the method returns FALSE.
3919 EXAMPLE
3921 BUGS
3923 SEE ALSO
3925 INTERNALS
3927 *****************************************************************************************/
3929 BOOL GFXHIDD__Hidd_Gfx__GetMaxSpriteSize(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMaxSpriteSize *msg)
3931 IPTR types;
3932 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3934 OOP_GetAttr(o, aHidd_Gfx_HWSpriteTypes, &types);
3936 if (types & msg->Type) {
3937 *msg->Width = 16;
3938 *msg->Height = 32;
3939 return TRUE;
3940 } else
3941 return FALSE;
3944 /*****************************************************************************************
3946 NAME
3947 moHidd_Gfx_NewOverlay
3949 SYNOPSIS
3950 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NewOverlay *msg);
3952 OOP_Object *HIDD_Gfx_NewOverlay(OOP_Object *gfxHidd, struct TagItem *tagList);
3954 LOCATION
3955 hidd.gfx.driver
3957 FUNCTION
3958 Create a video overlay object.
3960 INPUTS
3961 gfxHidd - A graphics driver object on whose display you want to create an overlay.
3962 tagList - A list of overlay attributes. See overlay class documentation for
3963 their description.
3965 RESULT
3966 Pointer to the newly created overlay object or NULL in case of failure.
3968 NOTES
3969 Default implementation in the base class always sets VOERR_INVSCRMODE error and
3970 returns NULL meaning that hardware overlays are not supported. There's no sense
3971 in software implementation because the software is supposed to handle software
3972 rendering itself.
3974 EXAMPLE
3976 BUGS
3978 SEE ALSO
3979 moHidd_Gfx_DisposeOverlay
3981 INTERNALS
3983 *****************************************************************************************/
3985 OOP_Object *GFXHIDD__Hidd_Gfx__NewOverlay(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewOverlay *msg)
3987 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
3988 ULONG *err = (ULONG *)GetTagData(aHidd_Overlay_Error, 0, msg->attrList);
3990 if (err)
3991 *err = VOERR_INVSCRMODE;
3993 return NULL;
3996 /*****************************************************************************************
3998 NAME
3999 moHidd_Gfx_DisposeOverlay
4001 SYNOPSIS
4002 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_DisposeOverlay *msg);
4004 VOID HIDD_Gfx_DisposeOverlay(OOP_Object *gfxHidd, OOP_Object *Overlay)
4006 LOCATION
4007 hidd.gfx.driver
4009 FUNCTION
4010 Deletes an overlay previously created by moHidd_Gfx_NewOverlay.
4012 Subclasses do not have to override this method
4013 unless they allocate anything additional to an overlay object in
4014 their HIDD_Gfx_NewOverlay() implementation.
4016 INPUTS
4017 gfxHidd - A driver object which was used for creating a GC.
4018 Overlay - Pointer to an overlay object to delete.
4020 RESULT
4021 None.
4023 NOTES
4025 EXAMPLE
4027 BUGS
4029 SEE ALSO
4030 moHidd_Gfx_NewGC
4032 INTERNALS
4033 Basically just does OOP_DisposeObject(Overlay);
4035 *****************************************************************************************/
4037 VOID GFXHIDD__Hidd_Gfx__DisposeOverlay(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_DisposeOverlay *msg)
4039 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
4040 OOP_DisposeObject(msg->Overlay);
4043 /*****************************************************************************************
4045 NAME
4046 moHidd_Gfx_MakeViewPort
4048 SYNOPSIS
4049 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_MakeViewPort *msg);
4051 ULONG HIDD_Gfx_MakeViewPort(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data)
4053 LOCATION
4054 hidd.gfx.driver
4056 FUNCTION
4057 Performs driver-specific setup on a given ViewPort.
4059 INPUTS
4060 gfxHidd - A display driver object.
4061 data - a pointer to a HIDD_ViewPortData structure.
4063 RESULT
4064 The same code as used as return value for graphics.library/MakeVPort().
4066 NOTES
4067 When graphics.library calls this method, a complete view is not built yet.
4068 This means that data->Next pointer contains invalid data and needs to be
4069 ignored.
4071 It is valid to keep private data pointer in data->UserData accross calls.
4072 Newly created HIDD_ViewPortData is guraranteed to have NULL there.
4074 EXAMPLE
4076 BUGS
4078 SEE ALSO
4079 moHidd_Gfx_CleanViewPort
4081 INTERNALS
4082 Base class implementation just does nothing. This function is mainly intended
4083 to provide support for copperlist maintenance by Amiga(tm) chipset driver.
4085 *****************************************************************************************/
4087 ULONG GFXHIDD__Hidd_Gfx__MakeViewPort(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_MakeViewPort *msg)
4089 D(bug("Gfx::MakeViewPort: object 0x%p, data 0x%p\n", o, msg->Data));
4091 return MVP_OK;
4094 /*****************************************************************************************
4096 NAME
4097 moHidd_Gfx_CleanViewPort
4099 SYNOPSIS
4100 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CleanViewPort *msg);
4102 ULONG HIDD_Gfx_CleanViewPort(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data)
4104 LOCATION
4105 hidd.gfx.driver
4107 FUNCTION
4108 Performs driver-specific cleanup on a given ViewPort.
4110 INPUTS
4111 gfxHidd - A display driver object.
4112 data - a pointer to a HIDD_ViewPortDats structure.
4114 RESULT
4115 The same code as used as return value for graphics.library/MakeVPort().
4117 NOTES
4118 When graphics.library calls this method, the ViewPort is already unlinked
4119 from its view, and the bitmap can already be deallocated.
4120 This means that both data->Next and data->Bitmap pointers can contain invalid
4121 values.
4123 EXAMPLE
4125 BUGS
4127 SEE ALSO
4128 moHidd_Gfx_MakeViewPort
4130 INTERNALS
4131 Base class implementation just does nothing. This function is mainly intended
4132 to provide support for copperlist disposal by Amiga(tm) chipset driver.
4134 *****************************************************************************************/
4136 void GFXHIDD__Hidd_Gfx__CleanViewPort(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CleanViewPort *msg)
4138 D(bug("Gfx::CleanViewPort: object 0x%p, data 0x%p\n", o, msg->Data));
4141 /*****************************************************************************************
4143 NAME
4144 moHidd_Gfx_PrepareViewPorts
4146 SYNOPSIS
4147 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_PrepareViewPorts *msg);
4149 ULONG HIDD_Gfx_PrepareViewPorts(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data, struct View *view)
4151 LOCATION
4152 hidd.gfx.driver
4154 FUNCTION
4155 Performs driver-specific setup on a given view.
4157 INPUTS
4158 gfxHidd - A display driver object.
4159 data - a pointer to a chain of HIDD_ViewPortData structures.
4160 view - A pointer to graphics.library View structure being prepared.
4162 RESULT
4163 MCOP_OK if there was no error or MCOP_NO_MEM otherwise.
4164 MCOP_NOP is not allowed as a return value of this method.
4166 NOTES
4167 graphics.library calls this method in MrgCop() after the complete view
4168 is built. data->Next pointer contains valid data.
4170 This function can be repeatedly called several times, and there is no
4171 cleanup counterpart for it. This should be taken into account in method
4172 implementation.
4174 EXAMPLE
4176 BUGS
4178 SEE ALSO
4180 INTERNALS
4181 Base class implementation just does nothing. This function is mainly intended
4182 to provide support for copperlist maintenance by Amiga(tm) chipset driver.
4184 *****************************************************************************************/
4186 ULONG GFXHIDD__Hidd_Gfx__PrepareViewPorts(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ShowViewPorts *msg)
4188 return MCOP_OK;
4191 /****************************************************************************************/
4193 /* This is a private nonvirtual method */
4194 void GFXHIDD__Hidd_Gfx__UpdateBitMap(OOP_Class *cl, OOP_Object *o, OOP_Object *bm,
4195 struct pHidd_BitMap_UpdateRect *msg, struct Rectangle *display)
4197 struct HiddGfxData *data = OOP_INST_DATA(cl, o);
4200 * We check data->shownbm twice in order to avoid unnecessary locking
4201 * when our bitmap is not on display (it may be not displayable at all).
4202 * However the second check is still needed in order to make sure that
4203 * this bitmap is still on display, because we could be preempted between
4204 * the test and ObtainSemaphore() by concurrently running Show() call.
4205 * We use shared lock because it's safe to have two concurrently running
4206 * updates even on the same region.
4208 if ((data->fbmode == vHidd_FrameBuffer_Mirrored) && (bm == data->shownbm))
4210 ObtainSemaphoreShared(&data->fbsem);
4212 if (bm == data->shownbm)
4215 * Complete update rectangle.
4216 * Display rectangle is already in bitmap's coordinates.
4218 UWORD srcX = msg->x;
4219 UWORD srcY = msg->y;
4220 UWORD xLimit = srcX + msg->width;
4221 UWORD yLimit = srcY + msg->height;
4223 /* Intersect rectangles */
4224 if (display->MinX > srcX)
4225 srcX = display->MinX;
4226 if (display->MinY > srcY)
4227 srcY = display->MinY;
4228 if (display->MaxX < xLimit)
4229 xLimit = display->MaxX;
4230 if (display->MaxY < yLimit)
4231 yLimit = display->MaxY;
4233 if ((xLimit > srcX) && (yLimit > srcY))
4235 HIDD_Gfx_CopyBox(o, bm, srcX, srcY,
4236 data->framebuffer, srcX - display->MinX, srcY - display->MinY,
4237 xLimit - srcX, yLimit - srcY, data->gc);
4241 ReleaseSemaphore(&data->fbsem);
4245 /****************************************************************************************/
4247 #undef csd
4249 static inline BOOL cmp_pfs(HIDDT_PixelFormat *tmppf, HIDDT_PixelFormat *dbpf)
4251 /* Just compare everything except stdpixfmt */
4252 /* Compare flags first (because it's a fast check) */
4253 if (tmppf->flags != dbpf->flags)
4254 return FALSE;
4255 /* If they match, compare the rest of things */
4256 return !memcmp(tmppf, dbpf, offsetof(HIDDT_PixelFormat, stdpixfmt));
4259 static struct pixfmt_data *find_pixfmt(HIDDT_PixelFormat *tofind, struct class_static_data *csd)
4261 struct pixfmt_data *retpf = NULL;
4262 HIDDT_PixelFormat *db_pf;
4263 struct Node *n;
4265 /* Go through the pixel format list to see if a similar pf allready exists */
4266 ObtainSemaphoreShared(&csd->pfsema);
4268 ForeachNode(&csd->pflist, n)
4270 db_pf = PIXFMT_OBJ(n);
4271 DPF(bug("find_pixfmt(): Trying pixelformat 0x%p\n", db_pf));
4272 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n",
4273 db_pf->red_shift, db_pf->green_shift, db_pf->blue_shift, db_pf->alpha_shift,
4274 db_pf->red_mask, db_pf->green_mask, db_pf->blue_mask, db_pf->alpha_mask,
4275 db_pf->bytes_per_pixel, db_pf->size, db_pf->depth, db_pf->stdpixfmt));
4276 if (cmp_pfs(tofind, db_pf))
4278 DPF(bug("Match!\n"));
4279 retpf = (struct pixfmt_data *)db_pf;
4280 break;
4284 ReleaseSemaphore(&csd->pfsema);
4285 return retpf;