rename the directory
[AROS.git] / rom / hidds / graphics / GraphicsClass.c
blob1014ba0a64a76a9f00a0d279d61979c3ddf807c1
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics hidd class implementation.
6 Lang: english
7 */
9 /****************************************************************************************/
11 #define DEBUG 0
12 #define SDEBUG 0
13 #define DPF(x)
14 #define DCOPYBOX(x)
16 #include <aros/atomic.h>
17 #include <aros/debug.h>
18 #include <aros/symbolsets.h>
19 #include <aros/config.h>
20 #include <cybergraphx/cgxvideo.h>
21 #include <exec/lists.h>
22 #include <oop/static_mid.h>
23 #include <graphics/displayinfo.h>
24 #include <graphics/view.h>
26 #include "graphics_intern.h"
28 #include <string.h>
29 #include <stddef.h>
31 #include <proto/exec.h>
32 #include <proto/utility.h>
33 #include <proto/oop.h>
34 #include <exec/libraries.h>
35 #include <exec/memory.h>
37 #include <utility/tagitem.h>
39 #include LC_LIBDEFS_FILE
41 #include <hidd/graphics.h>
43 /*****************************************************************************************
45 NAME
46 --background_graphics--
48 LOCATION
49 hidd.graphics.graphics
51 NOTES
52 When working with graphics drivers this is the first object you get.
53 It allows you to create BitMap and GC (graphics context)
54 object. The class' methods must be overidden by hardware-specific
55 subclasses where documented to do so.
57 *****************************************************************************************/
59 /*****************************************************************************************
61 NAME
62 --display_modes--
64 LOCATION
65 hidd.graphics.graphics
67 NOTES
68 Each display driver object internally stores a database of supported display mode
69 IDs. This database is normally managed by base class, the driver does not need to
70 reimplement respective methods.
72 A display mode ID in AROS is a 32-bit integer value, the same as on AmigaOS(tm).
73 However mode ID layout introduced by Commodore does not fit well for RTG systems.
74 In order to overcome its limitations, display ID on AROS may have two forms:
76 1. A chipset mode ID. These are standard IDs defined by Commodore. You may find
77 their definitions in graphics/modeid.h.
79 2. AROS RTG mode ID.
81 An RTG mode ID is composed of three parts in the form:
83 nnnn xx yy
85 nnnn - monitor ID. This number is maintained by system libraries. IDs are
86 assigned in the order in which drivers are loaded and display hardware is
87 found. Drivers do not have to care about this part, and should normally
88 mask it out if they for some reason look at mode ID. In order to
89 distinguish between chipset mode IDs and RTG mode IDs, order number starts
90 not from zero, reserving some space for C= chipset mode IDs (which appear
91 to have order numbers from 0x0000 to 0x000A). Currently RTG monitor IDs
92 start from 0x0010, however with time this value may change. So don't rely
93 on some particular values in RTG IDs. Use cybergraphics.library/IsCyberModeID()
94 function if you want to know for sure if the given mode ID belongs to an
95 RTG driver.
97 xx - A sync object index in driver's mode database.
98 yy - A pixelformat object in driver's mode database.
100 Normally the driver does not have to care about mode ID decoding. The mode
101 database is maintained by base class. The only useful things for the driver are
102 sync and pixelformat objects, from which it's possible to get different
103 information about the mode. They can be obtained from the base class using
104 HIDD_Gfx_GetMode().
106 Note that the driver object by itself does not know its monitor ID. Different
107 displays are served by different objects, any of which may belong to any class.
108 So all driver methods which return mode IDs will set monitor ID to zero. All
109 methods that take mode ID as argument are expected to ignore the monitor ID part
110 and do not make any assumptions about its value.
112 *****************************************************************************************/
114 static BOOL create_std_pixfmts(struct class_static_data *_csd);
115 static VOID delete_pixfmts(struct class_static_data *_csd);
116 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags);
118 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl);
119 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl);
120 static OOP_Object *create_and_init_object(OOP_Class *cl, UBYTE *data, ULONG datasize,
121 struct class_static_data *_csd);
123 static struct pixfmt_data *find_pixfmt(HIDDT_PixelFormat *tofind
124 , struct class_static_data *_csd);
126 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm
127 , OOP_Object *dst_bm, UWORD width, UWORD height);
129 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf, ULONG attrcheck, struct class_static_data *_csd);
131 /****************************************************************************************/
133 #define COMPUTE_HIDD_MODEID(sync, pf) \
134 ( ((sync) << 8) | (pf) )
136 #define MODEID_TO_SYNCIDX(id) (((id) & 0X0000FF00) >> 8)
137 #define MODEID_TO_PFIDX(id) ( (id) & 0x000000FF)
139 /****************************************************************************************/
141 OOP_Object *GFX__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
143 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
144 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
145 struct TagItem gctags[] =
147 {aHidd_GC_Foreground, 0},
148 {TAG_DONE , 0}
151 D(bug("Entering gfx.hidd::New\n"));
153 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
154 D(bug("Got object o=%x\n", o));
156 if (o)
158 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
159 struct TagItem *tstate = msg->attrList;
160 struct TagItem *modetags = NULL;
161 struct TagItem *tag;
162 BOOL ok;
164 InitSemaphore(&data->mdb.sema);
165 InitSemaphore(&data->fbsem);
166 data->fbmode = -1;
168 D(bug("[GFX] attrList 0x%p\n", msg->attrList));
170 while ((tag = NextTagItem(&tstate)))
172 ULONG idx;
174 Hidd_Gfx_Switch(tag->ti_Tag, idx)
176 case aoHidd_Gfx_ModeTags:
177 modetags = (struct TagItem *)tag->ti_Data;
178 break;
180 case aoHidd_Gfx_FrameBufferType:
181 data->fbmode = tag->ti_Data;
182 break;
186 /* Register modes only after other attributes are initialized */
187 ok = modetags ? register_modes(cl, o, modetags) : TRUE;
189 /* Create a gc that we can use for some rendering */
190 if (ok)
192 data->gc = OOP_NewObject(CSD(cl)->gcclass, NULL, gctags);
193 if (NULL == data->gc)
195 D(bug("Could not get gc\n"));
196 ok = FALSE;
200 if (!ok)
202 OOP_MethodID dispose_mid = msg->mID - moRoot_New + moRoot_Dispose;
204 D(bug("Not OK\n"));
205 OOP_CoerceMethod(cl, o, &dispose_mid);
206 return NULL;
210 D(bug("Leaving gfx.hidd::New o=%x\n", o));
211 return o;
214 /****************************************************************************************/
216 VOID GFX__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
218 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
219 struct HIDDGraphicsData *data;
221 data = OOP_INST_DATA(cl, o);
223 /* free the mode db stuff */
224 free_mode_db(&data->mdb, cl);
226 /* Here we should unregister pixelformats registered in our New().
227 However gfx drivers aren't supposed to be removed, so it's okay
228 not to do it at all for now. */
230 if (NULL != data->gc)
231 OOP_DisposeObject(data->gc);
233 OOP_DoSuperMethod(cl, o, msg);
236 /*****************************************************************************************
238 NAME
239 aoHidd_Gfx_IsWindowed
241 SYNOPSIS
242 [..G], BOOL
244 LOCATION
245 hidd.graphics.graphics
247 FUNCTION
248 Tells if the display driver is using hosted display in host OS' window, and mouse
249 input is handled by host OS.
251 Windowed displays may send activation events to AROS. This is needed in order to
252 correctly handle display switch in a multi-display configuration (which means that
253 the user has multiple windows on host OS desktop and can freely switch between them).
255 NOTES
256 Even in fullscreen mode drivers should still return TRUE if the host OS manages mouse
257 input (for example, X11 driver). If mouse input is not managed by the host OS
258 (for example, with Linux framebuffer driver), return FALSE.
260 EXAMPLE
262 BUGS
264 SEE ALSO
265 aoHidd_Gfx_ActiveCallBack, aoHidd_Gfx_ActiveCallBackData
267 INTERNALS
268 Base class always provides FALSE value
270 *****************************************************************************************/
272 /*****************************************************************************************
274 NAME
275 aoHidd_Gfx_DMPSLevel
277 SYNOPSIS
278 [ISG], HIDDT_DPMSLevel
280 LOCATION
281 hidd.graphics.graphics
283 FUNCTION
284 Gets or sets current DPMS level for driver's display.
285 A value can be one of:
286 vHidd_Gfx_DPMSLevel_On,
287 vHidd_Gfx_DPMSLevel_Standby,
288 vHidd_Gfx_DPMSLevel_Suspend,
289 vHidd_Gfx_DPMSLevel_Off
291 If the driver does not support some state, it's up to the driver what to do.
292 Usually it is expected to ignore the request.
294 Getting this attribute should return real current state.
296 NOTES
298 EXAMPLE
300 BUGS
302 SEE ALSO
304 INTERNALS
305 Base class always provides vHidd_Gfx_DPMSLevel_On value (comes from rootclass'
306 Get() which sets the value to 0).
308 *****************************************************************************************/
310 /*****************************************************************************************
312 NAME
313 aoHidd_Gfx_ModeTags
315 SYNOPSIS
316 [I..], struct TagItem *
318 LOCATION
319 hidd.graphics.graphics
321 FUNCTION
322 Specify a pointer to a taglist which contains description of display modes
323 supported by the driver.
325 This attribute is usually appended in moRoot_New method of the display driver
326 class.
328 This attribute is mandatory for the base class, otherwise driver object creation
329 fails.
331 Mode description taglist may contain the following tags:
332 - Any sync attributes - these attributes will specify values common for all sync
333 modes
334 - Any pixelformat attributes - these attributes will specify values common for
335 all pixelformat modes
336 - aoHidd_Gfx_SyncTags - specifies a pointer to another separate taglist containing
337 attributes for one sync (display) mode. If this tag
338 is not supplied at all, a set of default modes will be
339 generated for the driver.
340 - aoHidd_Gfx_PixFmtTags - specifies a pointer to another separate taglist containing
341 attributes for one pixelformat. This tag must be supplied
342 at least once, otherwise driver object will fail to create.
344 aoHidd_Gfx_SyncTags and aoHidd_Gfx_PixFmtTags can be specified multiple times in
345 order to associate more than one display mode with the driver. Note that common
346 values for sync and pixelformat objects need to be placed in the taglist before
347 aoHidd_Gfx_SyncTags and aoHidd_Gfx_PixFmtTags. You may specify them again between
348 these tags in order to alter common values.
350 NOTES
352 EXAMPLE
353 Partial example code of display driver supporting a truecolor display with three
354 resolutions:
356 // Our pixelformat (24-bit 0BGR)
357 struct TagItem pftags[] =
359 { aHidd_PixFmt_RedShift , 24 },
360 { aHidd_PixFmt_GreenShift , 16 },
361 { aHidd_PixFmt_BlueShift , 8 },
362 { aHidd_PixFmt_AlphaShift , 0 },
363 { aHidd_PixFmt_RedMask , 0x000000FF },
364 { aHidd_PixFmt_GreenMask , 0x0000FF00 },
365 { aHidd_PixFmt_BlueMask , 0x00FF0000 },
366 { aHidd_PixFmt_AlphaMask , 0x00000000 },
367 { aHidd_PixFmt_ColorModel , vHidd_ColorModel_TrueColor },
368 { aHidd_PixFmt_Depth , 24 },
369 { aHidd_PixFmt_BytesPerPixel, 4 },
370 { aHidd_PixFmt_BitsPerPixel , 24 },
371 { aHidd_PixFmt_StdPixFmt , vHidd_StdPixFmt_Native },
372 { aHidd_PixFmt_BitMapType , vHidd_BitMapType_Chunky },
373 { TAG_DONE , 0UL }
376 // 640x480 resolution
377 struct TagItem tags_800_600[] =
379 { aHidd_Sync_HDisp , 640 },
380 { aHidd_Sync_VDisp , 480 },
381 { TAG_DONE , 0UL }
384 // 800x600 resolution
385 struct TagItem tags_800_600[] =
387 { aHidd_Sync_HDisp , 800 },
388 { aHidd_Sync_VDisp , 600 },
389 { TAG_DONE , 0UL }
392 // 1024x768 resolution
393 struct TagItem tags_1024_768[] =
395 { aHidd_Sync_HDisp , 1024 },
396 { aHidd_Sync_VDisp , 768 },
397 { TAG_DONE , 0UL }
400 // Mode description taglist itself
401 struct TagItem mode_tags[] =
403 // Our driver supports a single pixelformat
404 { aHidd_Gfx_PixFmtTags , (IPTR)pftags },
406 // Here go sync values common for all sync modes
407 { aHidd_Sync_HMin , 112 },
408 { aHidd_Sync_VMin , 112 },
409 { aHidd_Sync_HMax , 16384 },
410 { aHidd_Sync_VMax , 16384 },
411 { aHidd_Sync_Description, (IPTR)"Example: %hx%v" },
413 // First resolution
414 { aHidd_Gfx_SyncTags , (IPTR)tags_800_600 },
416 // Next two syncs will have HMax = 32768, as an example
417 { aHidd_Sync_HMax , 32768 },
419 // Two more resolutions
420 { aHidd_Gfx_SyncTags , (IPTR)tags_800_600 },
421 { aHidd_Gfx_SyncTags , (IPTR)tags_1024_768 },
422 { TAG_DONE , 0UL }
425 // This is the attribute list which is given to New method
426 // of the base class
427 struct TagItem mytags[] =
429 { aHidd_Gfx_ModeTags , (IPTR)mode_tags },
430 { TAG_DONE , NULL }
433 BUGS
435 SEE ALSO
437 INTERNALS
439 *****************************************************************************************/
441 /*****************************************************************************************
443 NAME
444 aoHidd_Gfx_NumSyncs
446 SYNOPSIS
447 [..G], ULONG
449 LOCATION
450 hidd.graphics.graphics
452 FUNCTION
453 Gets total number of sync objects in the internal display mode database.
455 NOTES
457 EXAMPLE
459 BUGS
461 SEE ALSO
462 moHidd_Gfx_GetSync
464 INTERNALS
466 *****************************************************************************************/
468 /*****************************************************************************************
470 NAME
471 aoHidd_Gfx_SupportsHWCursor
473 SYNOPSIS
474 [..G], BOOL
476 LOCATION
477 hidd.graphics.graphics
479 FUNCTION
480 Tells whether the driver supports hardware mouse pointer sprite.
482 If the driver provides TRUE value for this attribute, it is expected to implement
483 HIDD_Gfx_SetCursorPos(), HIDD_Gfx_SetCursorShape() and HIDD_Gfx_SetCursorVisible()
484 methods.
486 Mouse pointer counts for one hardware sprite, so if the driver implements also
487 HIDD_Gfx_ModeProperties(), it should set NumHWSprites to 1 in order to provide
488 valid information about display modes.
490 The driver must implement this attribute if it implements HIDD_Gfx_ModeProperties().
491 Otherwise it will provide false information in graphics.library/GetDisplayInfoData().
492 Base class can determine NumHWSprites based on this attribute value but not vice
493 versa.
495 NOTES
496 Default implementation in the base class returns FALSE. This causes the system to
497 use software sprite emulation.
499 This attribute is obsolete and is used only by AROS graphics.library up to v41.2. In
500 new drivers consider implementing aoHidd_Gfx_HWSpriteTypes attribute.
502 EXAMPLE
504 BUGS
506 SEE ALSO
507 aoHidd_Gfx_HWSpriteTypes, moHidd_Gfx_ModeProperties
509 INTERNALS
511 *****************************************************************************************/
513 /*****************************************************************************************
515 NAME
516 aoHidd_Gfx_NoFrameBuffer
518 SYNOPSIS
519 [..G], BOOL
521 LOCATION
522 hidd.graphics.graphics
524 FUNCTION
525 Tells whether the driver does not need a framebuffer.
527 Since v1.2 this attribute is obsolete. Please use aoHidd_Gfx_FrameBufferType
528 in new code.
530 NOTES
531 Provides FALSE if not implemented in the driver.
533 EXAMPLE
535 BUGS
537 SEE ALSO
538 aoHidd_Gfx_FrameBufferType, moHidd_Gfx_Show
540 INTERNALS
542 *****************************************************************************************/
544 /*****************************************************************************************
546 NAME
547 aoHidd_Gfx_HWSpriteTypes
549 SYNOPSIS
550 [..G], BOOL
552 LOCATION
553 hidd.graphics.graphics
555 FUNCTION
556 Return hardware sprite image types supported by the driver.
558 The returned value is a combination of the following bit flags:
559 vHidd_SpriteType_3Plus1 - color 0 is transparent, 1-3 visible
560 (Amiga(tm) chipset sprite format)
561 vHidd_SpriteType_2Plus1 - color 0 is transparent, color 1 is undefined
562 (can be whatever, for example clear or inverse),
563 colors 2-3 visible.
564 vHidd_SpriteType_DirectColor - Hi- or truecolor image, or LUT image with own
565 palette, perhaps with alpha channel
567 NOTES
568 This attribute should return 0 if the driver does not support hardware mouse sprite
569 at all. Software sprite emulation is done by graphics.library.
571 Default implementation in the base class is based on aoHidd_Gfx_SupportsHWCursor
572 value. This is done for backwards compatibility.
574 EXAMPLE
576 BUGS
578 SEE ALSO
579 aoHidd_Gfx_SupportsHWCursor
581 INTERNALS
582 Default implementation in the base class queries aoHidd_Gfx_SupportsHWCursor
583 and provides (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor) in case
584 if it returns TRUE. Otherwise it returns zero. This is done for backwards
585 compatibility with old drivers.
587 *****************************************************************************************/
589 /*****************************************************************************************
591 NAME
592 aoHidd_Gfx_MemorySize
594 SYNOPSIS
595 [..G], ULONG
597 LOCATION
598 hidd.graphics.graphics
600 FUNCTION
601 Query total size of video card memory in bytes.
603 NOTES
605 EXAMPLE
607 BUGS
609 SEE ALSO
610 aoHidd_Gfx_MemoryClock
612 INTERNALS
614 *****************************************************************************************/
616 /*****************************************************************************************
618 NAME
619 aoHidd_Gfx_MemoryClock
621 SYNOPSIS
622 [..G], ULONG
624 LOCATION
625 hidd.graphics.graphics
627 FUNCTION
628 Query video card's memory clock in Hz. 0 is a valid value meaning 'unknown'.
630 NOTES
632 EXAMPLE
634 BUGS
636 SEE ALSO
637 aoHidd_Gfx_MemorySize
639 INTERNALS
641 *****************************************************************************************/
643 /*****************************************************************************************
645 NAME
646 aoHidd_Gfx_DriverName
648 SYNOPSIS
649 [..G], STRPTR
651 LOCATION
652 hidd.graphics.graphics
654 FUNCTION
655 Query CyberGraphX driver name. It is the same name which can be given to
656 cybergraphics.library/BestCModeIDTagList() as CYBRBIDTG_BoardName value.
658 NOTES
659 By default base class returns class name as value of this attribute.
660 However this can (and must for some drivers listed in BestCModeIDTagList()
661 documentation) be overriden.
663 EXAMPLE
665 BUGS
667 SEE ALSO
669 INTERNALS
671 *****************************************************************************************/
673 /*****************************************************************************************
675 NAME
676 aoHidd_Gfx_ActiveCallBack
678 SYNOPSIS
679 [.S.], void (*)(APTR userdata, OOP_Object *bitmap)
681 LOCATION
682 hidd.graphics.graphics
684 FUNCTION
685 Set display activation interrupt handler.
687 This handler needs to be called by hosted display driver, if host OS
688 windowing system is used for the display and mouse input is handled by the
689 host OS.
691 This way the driver can tell AROS when a display window has been activated so that
692 AROS will be able to switch current display correctly when working in a multi-display
693 configuration.
695 The function uses C calling convention and needs to be declared as follows:
697 void ActivationHandler(APTR userdata, OOP_Object *bitmap);
699 Parameters of this function will be:
700 userdata - Whatever is specified by aoHidd_Gfx_ActiveCallBackData attribute.
701 bitmap - Currently reserved. Drivers need to set it to NULL.
703 The function can be called from within an interrupt, so usual restrictions apply
704 to it.
706 Set this attribute to NULL in order to disable activation handling.
708 NOTES
709 When setting the activation callback function, be sure that you set correct
710 userdata before you actually set the callback pointer. Otherwise your callback
711 can be called with wrong data pointer.
713 Only one activation handler can be installed. Installing a new handler replaces
714 the previous one.
716 Native displays do not need to implement this attribute because there can be
717 no external activation events.
719 EXAMPLE
721 BUGS
723 SEE ALSO
724 aoHidd_Gfx_ActiveCallBackData, aoHidd_Gfx_IsWindowed
726 INTERNALS
727 This attribute needs to be implemented by the display driver. Base class contains
728 no implementation.
730 *****************************************************************************************/
732 /*****************************************************************************************
734 NAME
735 aoHidd_Gfx_ActiveCallBackData
737 SYNOPSIS
738 [.S.], APTR
740 LOCATION
741 hidd.graphics.graphics
743 FUNCTION
744 Set user-defined data pointer for display activation handler.
746 NOTES
748 EXAMPLE
750 BUGS
752 SEE ALSO
753 aoHidd_Gfx_ActiveCallBack
755 INTERNALS
756 This attribute needs to be implemented by the display driver. Base class contains
757 no implementation.
759 *****************************************************************************************/
761 /*****************************************************************************************
763 NAME
764 aoHidd_Gfx_DefaultGC
766 SYNOPSIS
767 [..G], OOP_Object *
769 LOCATION
770 hidd.graphics.graphics
772 FUNCTION
773 Get a pointer to shared default GC object.
775 NOTES
776 The returned GC is preset to the following:
778 DrawMode = Copy
779 FG = 0
780 BG = 0
781 LinePat = ~0
782 ColMask = ~0
784 You must not alter these settings even temporarily, because this GC is shared between
785 bitmaps and between different tasks which may perform the rendering into different
786 regions of the same bitmap (two windows on one screen, for example). This GC is intended
787 to be used for internal copying operations.
789 EXAMPLE
791 BUGS
793 SEE ALSO
794 aoHidd_Gfx_ActiveCallBack
796 INTERNALS
797 This attribute needs to be implemented by the display driver. Base class contains
798 no implementation.
800 *****************************************************************************************/
802 static UBYTE get_fbmode(OOP_Class *cl, OOP_Object *o)
804 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
806 if (data->fbmode == -1)
808 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
811 * This attribute has never been set.
812 * Fall back to obsolete NoFrameBuffer.
814 data->fbmode = OOP_GET(o, aHidd_Gfx_NoFrameBuffer) ? vHidd_FrameBuffer_None : vHidd_FrameBuffer_Direct;
817 return data->fbmode;
820 /*****************************************************************************************
822 NAME
823 aoHidd_Gfx_FrameBufferType
825 SYNOPSIS
826 [I.G], UBYTE
828 LOCATION
829 hidd.graphics.graphics
831 FUNCTION
832 Specifies fixed framebuffer type used by the driver. The value can be one of the following:
834 vHidd_FrameBuffer_None - the driver does not use framebuffer.
835 vHidd_FrameBuffer_Direct - the driver uses framefuffer which can be accessed
836 directly for both reads and writes.
837 vHidd_FrameBuffer_Mirrored - the driver uses write-only framebuffer.
839 This attribute has to be specified during driver object creation. If this is not done,
840 the OS will use value of old aoHidd_Gfx_NoFrameBuffer attribute in order to distinguish
841 between vHidd_FrameBuffer_Direct (for FALSE) and vHidd_FrameBuffer_None (for TRUE).
843 NOTES
844 A fixed framebuffer is a special bitmap in a fixed area of video RAM. If the
845 framebuffer is used, the driver is expected to copy a new bitmap into it in
846 HIDD_Gfx_Show() and optionally copy old bitmap back.
848 A framebuffer is needed if the hardware does not have enough VRAM to store many
849 bitmaps or does not have capabilities to switch the display between various VRAM
850 regions.
852 Some hardware suffers from slow VRAM reading. In this case you should use mirrored
853 mode. If you use it, the system will hold a bitmap in the memory buffer, and
854 update VRAM on demand (hence the name).
856 An example of driver using a framebuffer is hosted SDL driver. By design SDL works
857 only with single display window, which is considered a framebuffer.
859 EXAMPLE
861 BUGS
863 SEE ALSO
864 aoHidd_Gfx_NoFrameBuffer
866 INTERNALS
868 *****************************************************************************************/
870 /*****************************************************************************************
872 NAME
873 aoHidd_Gfx_SupportsGamma
875 SYNOPSIS
876 [..G], UBYTE
878 LOCATION
879 hidd.graphics.graphics
881 FUNCTION
882 Specifies if the driver supports gamma correction tables. Default implementation
883 in base class returns FALSE.
885 NOTES
887 EXAMPLE
889 BUGS
891 SEE ALSO
892 moHidd_Gfx_SetGamma
894 INTERNALS
896 *****************************************************************************************/
898 VOID GFX__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
900 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
901 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
902 ULONG idx;
904 Hidd_Gfx_Switch (msg->attrID, idx)
906 case aoHidd_Gfx_NumSyncs:
907 *msg->storage = data->mdb.num_syncs;
908 return;
910 case aoHidd_Gfx_IsWindowed:
911 case aoHidd_Gfx_SupportsHWCursor:
912 case aoHidd_Gfx_SupportsGamma:
913 *msg->storage = 0;
914 return;
916 case aoHidd_Gfx_HWSpriteTypes:
917 /* Fall back to obsolete SupportsHWCursor */
918 *msg->storage = OOP_GET(o, aHidd_Gfx_SupportsHWCursor) ? (vHidd_SpriteType_3Plus1|vHidd_SpriteType_DirectColor) : 0;
919 return;
921 case aoHidd_Gfx_DriverName:
922 *msg->storage = (IPTR)OOP_OCLASS(o)->ClassNode.ln_Name;
923 return;
925 case aoHidd_Gfx_DefaultGC:
926 *msg->storage = (IPTR)data->gc;
927 return;
929 case aoHidd_Gfx_FrameBufferType:
930 *msg->storage = get_fbmode(cl, o);
931 return;
934 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
937 /*****************************************************************************************
939 NAME
940 moHidd_Gfx_NominalDimensions
942 SYNOPSIS
943 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NominalDimensions *msg);
945 OOP_Object *HIDD_Gfx_NominalDimensions(OOP_Object *gfxHidd, UWORD *width, UWORD *height, UBYTE *depth);
947 LOCATION
948 hidd.graphics.graphics
950 FUNCTION
952 INPUTS
953 gfxHidd - The graphics driver used to create the object.
955 RESULT
957 NOTES
959 EXAMPLE
961 BUGS
963 SEE ALSO
965 INTERNALS
967 *****************************************************************************************/
968 VOID GFX__Hidd_Gfx__NominalDimensions(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NominalDimensions *msg)
970 EnterFunc(bug("HIDDGfx::NominalDimensions()\n"));
972 if (msg->width)
973 *(msg->width) = AROS_NOMINAL_WIDTH;
974 if (msg->height)
975 *(msg->height) = AROS_NOMINAL_HEIGHT;
976 if (msg->depth)
977 *(msg->depth) = AROS_NOMINAL_DEPTH;
980 /*****************************************************************************************
982 NAME
983 moHidd_Gfx_CreateObject
985 SYNOPSIS
986 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CreateObject *msg);
988 OOP_Object *HIDD_Gfx_CreateObject(OOP_Object *gfxHidd, OOP_Class *cl, struct TagItem *tagList);
990 LOCATION
991 hidd.graphics.graphics
993 FUNCTION
994 Create a driver specific Gfx Object of the type "classID"
996 INPUTS
997 gfxHidd - The graphics driver used to create the object.
998 cl - The base OOP_Class of the object to be created.
999 tagList - Object specific attributes.
1001 RESULT
1002 pointer to the newly created OOP_Object, or NULL on failure.
1004 NOTES
1005 Drivers should query the gfx.hidd, or support class for the base class Ptr that
1006 the driver objects should use. The gfx hidd itself defines the following -:
1009 A GC object is just used for data storage. It is possible to subclass, however
1010 it is not recommended since it may not be future-proof due to the fact
1011 GC subclasses can not be interchanged between different drivers.
1012 Avoid using custom GCs.
1014 BitMap
1016 Each graphics driver exposes at least one displayable bitmap class.
1017 More may be exposed at the drivers discretion to represent nondisplayable bitmaps
1018 or other driver specific bitmap types.
1020 Generally bitmap objects are never created directly. Instead they are created
1021 using the HIDD_Gfx_CreateObject() call. An implementation of this method in the
1022 driver should examine bitmap attributes supplied and make a decision if the bitmap
1023 should be created using the driver's own class or one of the system classes.
1025 A typical implementation should pay attention to the following bitmap attributes:
1027 aHIDD_BitMap_ModeID - If this attribute is supplied, the bitmap needs to be
1028 either displayable by this driver, or be a friend of a
1029 displayable bitmap. A friend bitmap usually repeats the
1030 internal layout of its friend so that the driver may
1031 perform blitting operations quickly.
1033 aHIDD_BitMap_Displayable - If this attribute is supplied, the bitmap NEEDS to be
1034 displayable by this driver. Usually this means that
1035 the bitmap object will contain video hardware state
1036 information. This attribute will always be accompanied
1037 by aHIDD_BitMap_ModeID.
1039 aHIDD_BitMap_FrameBuffer - The bitmap needs to be a framebuffer bitmap. A
1040 framebuffer bitmap is necessary for some kinds of
1041 hardware which have a small fixed amount of video
1042 RAM which can hold only one screen at a time. Setting
1043 this attribute requires that a valid ModeID be also set.
1045 aHIDD_BitMap_Friend - If there's no ModeID supplied, you may wish to check class
1046 of friend bitmap. This can be useful if your driver uses
1047 different classes for displayable and non-displayable bitmaps.
1048 By default base class will pick up friend's class and use it
1049 for new bitmap if nothing is specified, here you may override
1050 this behavior.
1052 If a driver wants to specify a custom class for the bitmap being created,
1053 it should pass the aoHidd_BitMap_ClassPtr attribute to the base class.
1054 Bitmap objects should not be directly created, otherwise necessary information
1055 provided by the base class will be missing.
1057 This method must be implemented by the subclass. aHIDD_BitMap_ClassPtr or
1058 aHIDD_BitMap_ClassID must be provided to the base class for a displayable bitmap.
1060 EXAMPLE
1062 BUGS
1064 SEE ALSO
1066 INTERNALS
1067 The base class implementation currently does the folliwing in order to determine
1068 a class for a nondisplayable bitmap (in the listed order):
1070 1. Check aHIDD_BitMap_ClassPtr and aHIDD_BitMap_ClassID. If one of them is supplied,
1071 the class is already set by a subclass.
1072 2. Check aHIDD_BitMap_StdPixFmt. If this attribute is supplied, figure out type of
1073 the pixelformat (chunky or planar), and use one of two system's default classes.
1074 3. Check aHIDD_BitMap_Friend. If friend bitmap is supplied, obtain its class from
1075 aHIDD_BitMap_ClassPtr value of friend bitmap.
1076 4. If everything fails, bitmap creation fails too.
1078 This behavior is subject to change, but will maintain backwards compatibility.
1080 *****************************************************************************************/
1081 OOP_Object *GFX__Hidd_Gfx__CreateObject(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CreateObject *msg)
1083 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1084 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
1085 OOP_Object *object = NULL;
1087 EnterFunc(bug("HIDDGfx::CreateObject()\n"));
1089 if (msg->cl == CSD(cl)->gcclass)
1091 object = OOP_NewObject(NULL, CLID_Hidd_GC, msg->attrList);
1093 else if (msg->cl == CSD(cl)->bitmapclass)
1095 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1097 struct TagItem bmtags[] =
1099 {aHidd_BitMap_GfxHidd, 0}, /* 0 */
1100 {aHidd_BitMap_PixFmt , 0}, /* 1 */
1101 {TAG_IGNORE , 0}, /* 2 */
1102 {TAG_IGNORE , 0}, /* 3 */
1103 {TAG_IGNORE , 0}, /* 4 */
1104 {TAG_IGNORE , 0}, /* 5 */
1105 {TAG_MORE , 0}, /* 6 */
1107 struct TagItem *tag, *tstate = msg->attrList;
1108 ULONG idx;
1110 STRPTR classid = NULL;
1111 OOP_Class *classptr = NULL;
1112 BOOL displayable = FALSE;
1113 BOOL framebuffer = FALSE;
1114 HIDDT_StdPixFmt pixfmt = vHidd_StdPixFmt_Unknown;
1115 OOP_Object *friend_bm = NULL;
1116 OOP_Object *sync = NULL;
1117 OOP_Object *pf = NULL;
1119 BOOL gotclass = FALSE;
1120 BOOL got_width = FALSE;
1121 BOOL got_height = FALSE;
1122 BOOL got_depth = FALSE;
1124 #define BMAO(x) aoHidd_BitMap_ ## x
1125 #define BMAF(x) (1L << aoHidd_BitMap_ ## x)
1127 #define BM_DIMS_AF (BMAF(Width) | BMAF(Height))
1129 #define SET_TAG(tags, idx, tag, val) \
1130 tags[idx].ti_Tag = tag ; tags[idx].ti_Data = (IPTR)val;
1132 #define SET_BM_TAG(tags, idx, tag, val) \
1133 SET_TAG(tags, idx, aHidd_BitMap_ ## tag, val)
1135 #define COPY_BM_TAG(tags, idx, tag, obj) \
1136 tags[idx].ti_Tag = aHidd_BitMap_ ## tag; \
1137 OOP_GetAttr(obj, aHidd_BitMap_ ## tag , &tags[idx].ti_Data)
1139 while ((tag = NextTagItem(&tstate)))
1141 if (IS_BITMAP_ATTR(tag->ti_Tag, idx))
1143 switch (idx)
1145 case aoHidd_BitMap_Displayable:
1146 displayable = tag->ti_Data;
1147 break;
1149 case aoHidd_BitMap_FrameBuffer:
1150 framebuffer = tag->ti_Data;
1151 break;
1153 case aoHidd_BitMap_Width:
1154 got_width = TRUE;
1155 break;
1157 case aoHidd_BitMap_Height:
1158 got_height = TRUE;
1159 break;
1161 case aoHidd_BitMap_Depth:
1162 got_depth = TRUE;
1163 break;
1165 case aoHidd_BitMap_ModeID:
1166 /* Make sure it is a valid mode, and retrieve sync/pixelformat data */
1167 if (!HIDD_Gfx_GetMode(o, tag->ti_Data, &sync, &pf))
1169 D(bug("!!! Gfx::CreateObject: USER PASSED INVALID MODEID !!!\n"));
1170 return NULL;
1172 break;
1174 case aoHidd_BitMap_Friend:
1175 friend_bm = (OOP_Object *)tag->ti_Data;
1176 break;
1178 case aoHidd_BitMap_PixFmt:
1179 D(bug("!!! Gfx::CreateObject: USER IS NOT ALLOWED TO PASS aHidd_BitMap_PixFmt !!!\n"));
1180 return NULL;
1182 case aoHidd_BitMap_StdPixFmt:
1183 pixfmt = tag->ti_Data;
1184 break;
1186 case aoHidd_BitMap_ClassPtr:
1187 classptr = (OOP_Class *)tag->ti_Data;
1188 gotclass = TRUE;
1189 break;
1191 case aoHidd_BitMap_ClassID:
1192 classid = (STRPTR)tag->ti_Data;
1193 gotclass = TRUE;
1194 break;
1199 /* If we have a friend bitmap, we can inherit some attributes from it */
1200 if (friend_bm)
1202 if (!got_width)
1204 COPY_BM_TAG(bmtags, 2, Width, friend_bm);
1205 got_width = TRUE;
1208 if (!got_height)
1210 COPY_BM_TAG(bmtags, 3, Height, friend_bm);
1211 got_height = TRUE;
1214 if (!got_depth)
1216 COPY_BM_TAG(bmtags, 4, Depth, friend_bm);
1220 if (framebuffer)
1222 /* FrameBuffer implies Displayable */
1223 SET_BM_TAG(bmtags, 5, Displayable, TRUE);
1224 displayable = TRUE;
1226 else if (displayable)
1229 * Displayable, but not framebuffer (user's screen).
1230 * If we are working in framebuffer mode, we treat all such
1231 * bitmaps as framebuffer's friends and can inherit its class.
1233 if ((!gotclass) && data->framebuffer && (get_fbmode(cl, o) != vHidd_FrameBuffer_None))
1235 classptr = OOP_OCLASS(data->framebuffer);
1236 gotclass = TRUE;
1238 D(bug("[GFX] Using class 0x%p (%s) for displayable bitmap\n", classptr, classptr->ClassNode.ln_Name));
1242 if (displayable)
1244 /* Displayable bitmap. Here we must have ModeID and class. */
1245 if (!sync)
1247 D(bug("!!! Gfx::CreateObject: USER HAS NOT PASSED MODEID FOR DISPLAYABLE BITMAP !!!\n"));
1248 return NULL;
1251 if (!gotclass)
1253 D(bug("!!! Gfx::CreateObject: SUBCLASS DID NOT PASS CLASS FOR DISPLAYABLE BITMAP !!!\n"));
1254 return NULL;
1257 else /* if (!displayable) */
1260 * This is an offscreen bitmap and we need to guess its pixelformat.
1261 * In order to do this we need one of (in the order of preference):
1262 * - ModeID
1263 * - StdPixFmt
1264 * - Friend
1267 if (sync)
1270 * We have alredy got sync for the modeid case.
1271 * Obtain missing size information from it.
1273 if (!got_width)
1275 bmtags[2].ti_Tag = aHidd_BitMap_Width;
1276 OOP_GetAttr(sync, aHidd_Sync_HDisp, &bmtags[2].ti_Data);
1279 if (!got_height)
1281 bmtags[3].ti_Tag = aHidd_BitMap_Height;
1282 OOP_GetAttr(sync, aHidd_Sync_VDisp, &bmtags[3].ti_Data);
1285 else if (pixfmt != vHidd_StdPixFmt_Unknown)
1287 /* Next to look for is StdPixFmt */
1288 pf = HIDD_Gfx_GetPixFmt(o, pixfmt);
1289 if (NULL == pf)
1291 D(bug("!!! Gfx::CreateObject(): USER PASSED BOGUS StdPixFmt !!!\n"));
1292 return NULL;
1295 else if (friend_bm)
1297 /* Last alternative is that the user passed a friend bitmap */
1299 OOP_GetAttr(friend_bm, aHidd_BitMap_PixFmt, (IPTR *)&pf);
1302 * Inherit the class from friend bitmap (if not already specified).
1303 * We do it because friend bitmap may be a display HIDD bitmap
1305 if (!gotclass)
1307 classptr = OOP_OCLASS(friend_bm);
1308 gotclass = TRUE;
1310 D(bug("[GFX] Friend bitmap is 0x%p has class 0x%p (%s)\n", friend_bm, classptr, classptr->ClassNode.ln_Name));
1313 else
1315 D(bug("!!! Gfx::CreateObject: INSUFFICIENT ATTRS TO CREATE OFFSCREEN BITMAP !!!\n"));
1316 return NULL;
1319 /* Did the subclass provide an offbitmap class for us? */
1320 if (!gotclass)
1322 /* Have to find a suitable class ourselves from the pixelformat */
1323 HIDDT_BitMapType bmtype;
1325 OOP_GetAttr(pf, aHidd_PixFmt_BitMapType, &bmtype);
1326 switch (bmtype)
1328 case vHidd_BitMapType_Chunky:
1329 classptr = CSD(cl)->chunkybmclass;
1330 break;
1332 case vHidd_BitMapType_Planar:
1333 classptr = CSD(cl)->planarbmclass;
1334 break;
1336 default:
1337 D(bug("!!! Gfx::CreateObject: UNKNOWN BITMAPTYPE %d !!!\n", bmtype));
1338 return NULL;
1340 D(bug("[GFX] Bitmap type is %u, using class 0x%p\n", bmtype, classptr));
1342 } /* if (!gotclass) */
1344 } /* if (!displayable) */
1346 /* Set the tags we want to pass to the selected bitmap class */
1347 bmtags[0].ti_Data = (IPTR)o;
1348 bmtags[1].ti_Data = (IPTR)pf;
1349 bmtags[6].ti_Data = (IPTR)msg->attrList;
1351 object = OOP_NewObject(classptr, classid, bmtags);
1353 /* Remember the framebuffer. It can be needed for default Show() implementation. */
1354 if (framebuffer)
1355 data->framebuffer = object;
1358 ReturnPtr("HIDDGfx::CreateObject", OOP_Object *, object);
1361 /****************************************************************************************/
1363 #define SD(x) ((struct sync_data *)x)
1364 #define PF(x) ((HIDDT_PixelFormat *)x)
1366 #define XCOORD_TO_BYTEIDX(x) ( (x) >> 3)
1367 #define COORD_TO_BYTEIDX(x, y, bpr) ( ( (y) * bpr ) + XCOORD_TO_BYTEIDX(x) )
1368 #define XCOORD_TO_MASK(x) (1L << (7 - ((x) & 0x07) ))
1369 #define WIDTH_TO_BYTES(width) ( (( (width) - 1) >> 3) + 1)
1371 /****************************************************************************************/
1373 /* modebm functions pfidx is x and syncidx is y coord in the bitmap */
1375 /****************************************************************************************/
1377 static inline BOOL alloc_mode_bm(struct mode_bm *bm, ULONG numsyncs, ULONG numpfs,
1378 OOP_Class *cl)
1380 bm->bpr = WIDTH_TO_BYTES(numpfs);
1382 bm->bm = AllocVec(bm->bpr * numsyncs, MEMF_CLEAR);
1383 if (NULL == bm->bm)
1384 return FALSE;
1386 /* We initialize the mode bitmap to all modes valid */
1387 memset(bm->bm, 0xFF, bm->bpr * numsyncs);
1389 return TRUE;
1392 /****************************************************************************************/
1394 static inline VOID free_mode_bm(struct mode_bm *bm, OOP_Class *cl)
1396 FreeVec(bm->bm);
1397 bm->bm = NULL;
1398 bm->bpr = 0;
1401 /****************************************************************************************/
1403 static inline BOOL is_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx)
1405 if (0 != (XCOORD_TO_MASK(pfidx) & bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)]))
1406 return TRUE;
1408 return FALSE;
1411 /****************************************************************************************/
1413 static inline VOID set_valid_mode(struct mode_bm *bm, ULONG syncidx, ULONG pfidx,
1414 BOOL valid)
1416 if (valid)
1417 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] |= XCOORD_TO_MASK(pfidx);
1418 else
1419 bm->bm[COORD_TO_BYTEIDX(pfidx, syncidx, bm->bpr)] &= ~XCOORD_TO_MASK(pfidx);
1421 return;
1424 /****************************************************************************************/
1426 static BOOL alloc_mode_db(struct mode_db *mdb, ULONG numsyncs, ULONG numpfs, OOP_Class *cl)
1428 BOOL ok = FALSE;
1430 if (0 == numsyncs || 0 == numpfs)
1431 return FALSE;
1433 ObtainSemaphore(&mdb->sema);
1434 /* free_mode_bm() needs this */
1435 mdb->num_pixfmts = numpfs;
1436 mdb->num_syncs = numsyncs;
1438 mdb->syncs = AllocMem(sizeof (OOP_Object *) * numsyncs, MEMF_CLEAR);
1440 if (NULL != mdb->syncs)
1442 mdb->pixfmts = AllocMem(sizeof (OOP_Object *) * numpfs, MEMF_CLEAR);
1444 if (NULL != mdb->pixfmts)
1446 if (alloc_mode_bm(&mdb->orig_mode_bm, numsyncs, numpfs, cl))
1448 if (alloc_mode_bm(&mdb->checked_mode_bm, numsyncs, numpfs, cl))
1450 ok = TRUE;
1456 if (!ok)
1457 free_mode_db(mdb, cl);
1459 ReleaseSemaphore(&mdb->sema);
1461 return ok;
1464 /****************************************************************************************/
1466 static VOID free_mode_db(struct mode_db *mdb, OOP_Class *cl)
1468 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1469 ULONG i;
1471 ObtainSemaphore(&mdb->sema);
1473 if (NULL != mdb->pixfmts)
1476 /* Pixelformats are shared objects and never freed */
1477 FreeMem(mdb->pixfmts, sizeof (OOP_Object *) * mdb->num_pixfmts);
1478 mdb->pixfmts = NULL; mdb->num_pixfmts = 0;
1481 if (NULL != mdb->syncs)
1483 for (i = 0; i < mdb->num_syncs; i ++)
1485 if (NULL != mdb->syncs[i])
1488 OOP_DisposeObject(mdb->syncs[i]);
1489 mdb->syncs[i] = NULL;
1493 FreeMem(mdb->syncs, sizeof (OOP_Object *) * mdb->num_syncs);
1494 mdb->syncs = NULL; mdb->num_syncs = 0;
1497 if (NULL != mdb->orig_mode_bm.bm)
1499 free_mode_bm(&mdb->orig_mode_bm, cl);
1502 if (NULL != mdb->checked_mode_bm.bm)
1504 free_mode_bm(&mdb->checked_mode_bm, cl);
1507 ReleaseSemaphore(&mdb->sema);
1509 return;
1512 /****************************************************************************************/
1514 /* Initializes default tagarray. in numtags the TAG_MORE is not accounted for,
1515 so the array must be of size NUM_TAGS + 1
1518 /****************************************************************************************/
1520 static VOID init_def_tags(struct TagItem *tags, ULONG numtags)
1522 ULONG i;
1524 for (i = 0; i < numtags; i ++)
1526 tags[i].ti_Tag = TAG_IGNORE;
1527 tags[i].ti_Data = 0UL;
1530 tags[i].ti_Tag = TAG_MORE;
1531 tags[i].ti_Data = 0UL;
1533 return;
1536 /****************************************************************************************/
1538 #define MAKE_SYNC(name,clock,hdisp,hstart,hend,htotal,vdisp,vstart,vend,vtotal,descr) \
1539 struct TagItem sync_ ## name[]={ \
1540 { aHidd_Sync_PixelClock, clock*1000 }, \
1541 { aHidd_Sync_HDisp, hdisp }, \
1542 { aHidd_Sync_HSyncStart, hstart }, \
1543 { aHidd_Sync_HSyncEnd, hend }, \
1544 { aHidd_Sync_HTotal, htotal }, \
1545 { aHidd_Sync_VDisp, vdisp }, \
1546 { aHidd_Sync_VSyncStart, vstart }, \
1547 { aHidd_Sync_VSyncEnd, vend }, \
1548 { aHidd_Sync_VTotal, vtotal }, \
1549 { aHidd_Sync_Description, (IPTR)descr}, \
1550 { TAG_DONE, 0UL }}
1552 static BOOL register_modes(OOP_Class *cl, OOP_Object *o, struct TagItem *modetags)
1554 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1555 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
1556 struct TagItem *tag, *tstate;
1557 struct HIDDGraphicsData *data;
1559 MAKE_SYNC(640x480_60, 25174,
1560 640, 656, 752, 800,
1561 480, 490, 492, 525,
1562 "Default:640x480");
1564 MAKE_SYNC(800x600_56, 36000, // 36000
1565 800, 824, 896, 1024,
1566 600, 601, 603, 625,
1567 "Default:800x600");
1569 MAKE_SYNC(1024x768_60, 65000, //78654=60kHz, 75Hz. 65000=50kHz,62Hz
1570 1024, 1048, 1184, 1344,
1571 768, 771, 777, 806,
1572 "Default:1024x768");
1574 MAKE_SYNC(1152x864_60, 80000,
1575 1152, 1216, 1328, 1456,
1576 864, 870, 875, 916,
1577 "Default:1152x864");
1579 MAKE_SYNC(1280x1024_60, 108880,
1580 1280, 1360, 1496, 1712,
1581 1024, 1025, 1028, 1060,
1582 "Default:1280x1024");
1584 MAKE_SYNC(1600x1200_60, 155982,
1585 1600, 1632, 1792, 2048,
1586 1200, 1210, 1218, 1270,
1587 "Default:1600x1200");
1589 /* "new" 16:10 modes */
1591 MAKE_SYNC(1280x800_60, 83530,
1592 1280, 1344, 1480, 1680,
1593 800, 801, 804, 828,
1594 "Default:1280x800");
1596 MAKE_SYNC(1440x900_60, 106470,
1597 1440, 1520, 1672, 1904,
1598 900, 901, 904, 932,
1599 "Default:1440x900");
1601 MAKE_SYNC(1680x1050_60, 147140,
1602 1680, 1784, 1968, 2256,
1603 1050, 1051, 1054, 1087,
1604 "Default:1680x1050");
1606 MAKE_SYNC(1920x1080_60, 173000,
1607 1920, 2048, 2248, 2576,
1608 1080, 1083, 1088, 1120,
1609 "Default:1920x1080");
1611 MAKE_SYNC(1920x1200_60, 154000,
1612 1920, 1968, 2000, 2080,
1613 1200, 1203, 1209, 1235,
1614 "Default:1920x1200");
1616 struct mode_db *mdb;
1618 HIDDT_PixelFormat pixfmt_data;
1620 struct TagItem def_sync_tags[num_Hidd_Sync_Attrs + 1];
1621 struct TagItem def_pixfmt_tags[num_Hidd_PixFmt_Attrs + 1];
1623 ULONG numpfs = 0,numsyncs = 0;
1624 ULONG pfidx = 0, syncidx = 0;
1626 struct TagItem temporary_tags[] = {
1627 { aHidd_Gfx_SyncTags, (IPTR)sync_640x480_60 },
1628 { aHidd_Gfx_SyncTags, (IPTR)sync_800x600_56 },
1629 { aHidd_Gfx_SyncTags, (IPTR)sync_1024x768_60 },
1630 { aHidd_Gfx_SyncTags, (IPTR)sync_1152x864_60 },
1631 { aHidd_Gfx_SyncTags, (IPTR)sync_1280x1024_60 },
1632 { aHidd_Gfx_SyncTags, (IPTR)sync_1600x1200_60 },
1633 { aHidd_Gfx_SyncTags, (IPTR)sync_1280x800_60 },
1634 { aHidd_Gfx_SyncTags, (IPTR)sync_1440x900_60 },
1635 { aHidd_Gfx_SyncTags, (IPTR)sync_1680x1050_60 },
1636 { aHidd_Gfx_SyncTags, (IPTR)sync_1920x1080_60 },
1637 { aHidd_Gfx_SyncTags, (IPTR)sync_1920x1200_60 },
1638 { TAG_MORE, 0UL }
1641 data = OOP_INST_DATA(cl, o);
1642 mdb = &data->mdb;
1643 InitSemaphore(&mdb->sema);
1645 memset(&pixfmt_data, 0, sizeof (pixfmt_data));
1647 init_def_tags(def_sync_tags, num_Hidd_Sync_Attrs);
1648 init_def_tags(def_pixfmt_tags, num_Hidd_PixFmt_Attrs);
1650 def_sync_tags[aoHidd_Sync_GfxHidd].ti_Tag = aHidd_Sync_GfxHidd;
1651 def_sync_tags[aoHidd_Sync_GfxHidd].ti_Data = (IPTR)o;
1653 /* First we need to calculate how much memory we are to allocate by counting supplied
1654 pixel formats and syncs */
1656 for (tstate = modetags; (tag = NextTagItem(&tstate));)
1658 ULONG idx;
1660 if (IS_GFX_ATTR(tag->ti_Tag, idx))
1662 switch (idx)
1664 case aoHidd_Gfx_PixFmtTags:
1665 numpfs++;
1666 break;
1668 case aoHidd_Gfx_SyncTags:
1669 numsyncs ++;
1670 break;
1672 default:
1673 break;
1678 if (0 == numpfs)
1680 D(bug("!!! WE MUST AT LEAST HAVE ONE PIXFMT IN Gfx::RegisterModes() !!!\n"));
1683 if (0 == numsyncs)
1685 D(bug("!!! NO SYNC IN Gfx::RegisterModes() !!!\n!!! USING DEFAULT MODES !!!\n"));
1686 temporary_tags[11].ti_Tag = TAG_MORE;
1687 temporary_tags[11].ti_Data = (IPTR)modetags;
1688 modetags = &temporary_tags[0];
1689 numsyncs = 11;
1692 ObtainSemaphore(&mdb->sema);
1694 /* Allocate memory for mode db */
1695 if (!alloc_mode_db(&data->mdb, numsyncs, numpfs, cl))
1696 goto failure;
1699 for (tstate = modetags; (tag = NextTagItem(&tstate));)
1701 /* Look for Gfx, PixFmt and Sync tags */
1702 ULONG idx;
1704 if (IS_GFX_ATTR(tag->ti_Tag, idx))
1706 switch (idx)
1708 case aoHidd_Gfx_PixFmtTags:
1709 def_pixfmt_tags[num_Hidd_PixFmt_Attrs].ti_Data = tag->ti_Data;
1710 mdb->pixfmts[pfidx] = GFX__Hidd_Gfx__RegisterPixFmt(cl, def_pixfmt_tags);
1712 if (NULL == mdb->pixfmts[pfidx])
1714 D(bug("!!! UNABLE TO CREATE PIXFMT OBJECT IN Gfx::RegisterModes() !!!\n"));
1715 goto failure;
1718 pfidx ++;
1719 break;
1721 case aoHidd_Gfx_SyncTags:
1722 def_sync_tags[num_Hidd_Sync_Attrs].ti_Data = tag->ti_Data;
1724 mdb->syncs[syncidx] = OOP_NewObject(CSD(cl)->syncclass, NULL, def_sync_tags);
1725 if (!mdb->syncs[syncidx]) {
1726 D(bug("!!! UNABLE TO CREATE SYNC OBJECT IN Gfx::RegisterModes() !!!\n"));
1727 goto failure;
1730 syncidx ++;
1731 break;
1735 else if (IS_SYNC_ATTR(tag->ti_Tag, idx))
1737 if (idx >= num_Hidd_Sync_Attrs)
1739 D(bug("!!! UNKNOWN SYNC ATTR IN Gfx::New(): %d !!!\n", idx));
1741 else
1743 def_sync_tags[idx].ti_Tag = tag->ti_Tag;
1744 def_sync_tags[idx].ti_Data = tag->ti_Data;
1748 else if (IS_PIXFMT_ATTR(tag->ti_Tag, idx))
1750 if (idx >= num_Hidd_PixFmt_Attrs)
1752 D(bug("!!! UNKNOWN PIXFMT ATTR IN Gfx::New(): %d !!!\n", idx));
1754 else
1756 def_pixfmt_tags[idx].ti_Tag = tag->ti_Tag;
1757 def_pixfmt_tags[idx].ti_Data = tag->ti_Data;
1762 ReleaseSemaphore(&mdb->sema);
1764 return TRUE;
1766 failure:
1768 /* mode db is freed in dispose */
1769 ReleaseSemaphore(&mdb->sema);
1771 return FALSE;
1774 /****************************************************************************************/
1776 struct modequery
1778 struct mode_db *mdb;
1779 ULONG minwidth;
1780 ULONG maxwidth;
1781 ULONG minheight;
1782 ULONG maxheight;
1783 HIDDT_StdPixFmt *stdpfs;
1784 ULONG numfound;
1785 ULONG pfidx;
1786 ULONG syncidx;
1787 BOOL dims_ok;
1788 BOOL stdpfs_ok;
1789 BOOL check_ok;
1790 OOP_Class *cl;
1793 /****************************************************************************************/
1795 /* This is a recursive function that looks for valid modes */
1797 /****************************************************************************************/
1799 static HIDDT_ModeID *querymode(struct modequery *mq)
1801 HIDDT_ModeID *modeids;
1802 register OOP_Object *pf;
1803 register OOP_Object *sync;
1804 BOOL mode_ok = FALSE;
1805 ULONG syncidx, pfidx;
1807 mq->dims_ok = FALSE;
1808 mq->stdpfs_ok = FALSE;
1809 mq->check_ok = FALSE;
1811 /* Look at the supplied idx */
1812 if (mq->pfidx >= mq->mdb->num_pixfmts)
1814 mq->pfidx = 0;
1815 mq->syncidx ++;
1818 if (mq->syncidx >= mq->mdb->num_syncs)
1820 /* We have reached the end of the recursion. Allocate memory and go back
1823 modeids = AllocVec(sizeof (HIDDT_ModeID) * (mq->numfound + 1), MEMF_ANY);
1824 /* Get the end of the array */
1825 modeids += mq->numfound;
1826 *modeids = vHidd_ModeID_Invalid;
1828 return modeids;
1831 syncidx = mq->syncidx;
1832 pfidx = mq->pfidx;
1833 /* Get the pf and sync objects */
1834 pf = mq->mdb->pixfmts[syncidx];
1835 sync = mq->mdb->syncs[pfidx];
1838 /* Check that the mode is really usable */
1839 if (is_valid_mode(&mq->mdb->checked_mode_bm, syncidx, pfidx))
1841 mq->check_ok = TRUE;
1844 /* See if this mode matches the criterias set */
1846 if ( SD(sync)->hdisp >= mq->minwidth
1847 && SD(sync)->hdisp <= mq->maxwidth
1848 && SD(sync)->vdisp >= mq->minheight
1849 && SD(sync)->vdisp <= mq->maxheight )
1853 mq->dims_ok = TRUE;
1855 if (NULL != mq->stdpfs)
1857 register HIDDT_StdPixFmt *stdpf = mq->stdpfs;
1858 while (*stdpf)
1860 if (*stdpf == PF(pf)->stdpixfmt)
1862 mq->stdpfs_ok = TRUE;
1864 stdpf ++;
1867 else
1869 mq->stdpfs_ok = TRUE;
1875 if (mq->dims_ok && mq->stdpfs_ok && mq->check_ok)
1877 mode_ok = TRUE;
1878 mq->numfound ++;
1881 mq->pfidx ++;
1883 modeids = querymode(mq);
1885 if (NULL == modeids)
1886 return NULL;
1888 if (mode_ok)
1890 /* The mode is OK. Add it to the list */
1891 modeids --;
1892 *modeids = COMPUTE_HIDD_MODEID(syncidx, pfidx);
1895 return modeids;
1899 /*****************************************************************************************
1901 NAME
1902 moHidd_Gfx_QueryModeIDs
1904 SYNOPSIS
1905 HIDDT_ModeID *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_QueryModeIDs *msg);
1907 HIDDT_ModeID *HIDD_Gfx_QueryModeIDs(OOP_Object *gfxHidd, struct TagItem *queryTags);
1909 LOCATION
1910 hidd.graphics.graphics
1912 FUNCTION
1913 Obtain a table of all supported display mode IDs
1915 The returned address points to an array of HIDDT_ModeID containing all ModeIDs
1916 supported by this driver. The array is terminated with vHidd_ModeID_Invalid.
1918 INPUTS
1919 gfxHidd - A driver object which to query.
1920 querytags - An optional taglist containing query options. Can be NULL.
1921 The following tags are supported:
1923 tHidd_GfxMode_MinWidth (ULONG) - A minimum width of modes you are
1924 interested in
1925 tHidd_GfxMode_MaxWidth (ULONG) - A maximum width of modes you are
1926 interested in
1927 tHidd_GfxMode_MinHeight (ULONG) - A minimum height of modes you are
1928 interested in
1929 tHidd_GfxMode_MaxHeight (ULONG) - A maximum height of modes you are
1930 interested in
1931 tHidd_GfxMode_PixFmts (HIDDT_StdPifXmt *) - A pointer to an array
1932 of standard pixelformat indexes. If supplied, only mode IDs whose
1933 pixelformat numbers match any of given ones will be returned.
1935 RESULT
1936 A pointer to an array of ModeIDs or NULL in case of failure
1938 NOTES
1940 EXAMPLE
1942 BUGS
1944 SEE ALSO
1945 moHidd_Gfx_ReleaseModeIDs, moHidd_Gfx_NextModeID
1947 INTERNALS
1949 *****************************************************************************************/
1951 HIDDT_ModeID *GFX__Hidd_Gfx__QueryModeIDs(OOP_Class *cl, OOP_Object *o,
1952 struct pHidd_Gfx_QueryModeIDs *msg)
1954 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
1955 struct TagItem *tag, *tstate;
1957 HIDDT_ModeID *modeids;
1958 struct HIDDGraphicsData *data;
1959 struct mode_db *mdb;
1961 struct modequery mq =
1963 NULL, /* mode db (set later) */
1964 0, 0xFFFFFFFF, /* minwidth, maxwidth */
1965 0, 0xFFFFFFFF, /* minheight, maxheight */
1966 NULL, /* stdpfs */
1967 0, /* numfound */
1968 0, 0, /* pfidx, syncidx */
1969 FALSE, FALSE, /* dims_ok, stdpfs_ok */
1970 FALSE, /* check_ok */
1971 NULL /* class (set later) */
1976 data = OOP_INST_DATA(cl, o);
1977 mdb = &data->mdb;
1978 mq.mdb = mdb;
1979 mq.cl = cl;
1981 for (tstate = msg->queryTags; (tag = NextTagItem(&tstate)); )
1983 switch (tag->ti_Tag)
1985 case tHidd_GfxMode_MinWidth:
1986 mq.minwidth = (ULONG)tag->ti_Tag;
1987 break;
1989 case tHidd_GfxMode_MaxWidth:
1990 mq.maxwidth = (ULONG)tag->ti_Tag;
1991 break;
1993 case tHidd_GfxMode_MinHeight:
1994 mq.minheight = (ULONG)tag->ti_Tag;
1995 break;
1997 case tHidd_GfxMode_MaxHeight:
1998 mq.maxheight = (ULONG)tag->ti_Tag;
1999 break;
2001 case tHidd_GfxMode_PixFmts:
2002 mq.stdpfs = (HIDDT_StdPixFmt *)tag->ti_Data;
2003 break;
2008 ObtainSemaphoreShared(&mdb->sema);
2010 /* Recursively check all modes */
2011 modeids = querymode(&mq);
2013 ReleaseSemaphore(&mdb->sema);
2015 return modeids;
2019 /*****************************************************************************************
2021 NAME
2022 moHidd_Gfx_ReleaseModeIDs
2024 SYNOPSIS
2025 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ReleaseModeIDs *msg);
2027 VOID HIDD_Gfx_ReleaseModeIDs(OOP_Object *gfxHidd, HIDDT_ModeID *modeIDs);
2029 LOCATION
2030 hidd.graphics.graphics
2032 FUNCTION
2033 Free array of display mode IDs returned by HIDD_Gfx_QueryModeIDs()
2035 INPUTS
2036 gfxHidd - A driver object used to obtain the array
2037 modeIDs - A pointer to an array
2039 RESULT
2040 None.
2042 NOTES
2044 EXAMPLE
2046 BUGS
2048 SEE ALSO
2049 moHidd_Gfx_QueryModeIDs
2051 INTERNALS
2053 *****************************************************************************************/
2055 VOID GFX__Hidd_Gfx__ReleaseModeIDs(OOP_Class *cl, OOP_Object *o,
2056 struct pHidd_Gfx_ReleaseModeIDs *msg)
2058 FreeVec(msg->modeIDs);
2061 /*****************************************************************************************
2063 NAME
2064 moHidd_Gfx_NextModeID
2066 SYNOPSIS
2067 HIDDT_ModeID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NextModeID *msg);
2069 HIDDT_ModeID HIDD_Gfx_NextModeID(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
2070 OOP_Object **syncPtr, OOP_Object **pixFmtPtr);
2072 LOCATION
2073 hidd.graphics.graphics
2075 FUNCTION
2076 Iterate driver's internal display mode database.
2078 INPUTS
2079 gfxHidd - A driver object to query
2080 modeID - A previous mode ID or vHidd_ModeID_Invalid for start of the iteration
2081 syncPtr - A pointer to a storage where pointer to sync object will be placed
2082 pixFmtPtr - A pointer to a storage where pointer to pixelformat object will be placed
2084 RESULT
2085 Next available mode ID or vHidd_ModeID_Invalid if there are no more display modes.
2086 If the function returns vHidd_ModeID_Invalid, sync and pixelformat pointers will
2087 be set to NULL.
2089 NOTES
2091 EXAMPLE
2093 BUGS
2095 SEE ALSO
2096 moHidd_Gfx_GetMode
2098 INTERNALS
2100 *****************************************************************************************/
2102 HIDDT_ModeID GFX__Hidd_Gfx__NextModeID(OOP_Class *cl, OOP_Object *o,
2103 struct pHidd_Gfx_NextModeID *msg)
2105 struct HIDDGraphicsData *data;
2106 struct mode_db *mdb;
2107 ULONG syncidx, pfidx;
2108 HIDDT_ModeID return_id = vHidd_ModeID_Invalid;
2109 BOOL found = FALSE;
2111 data = OOP_INST_DATA(cl, o);
2112 mdb = &data->mdb;
2114 ObtainSemaphoreShared(&mdb->sema);
2115 if (vHidd_ModeID_Invalid == msg->modeID)
2117 pfidx = 0;
2118 syncidx = 0;
2120 else
2122 pfidx = MODEID_TO_PFIDX( msg->modeID );
2123 syncidx = MODEID_TO_SYNCIDX( msg->modeID );
2125 /* Increament one from the last call */
2126 pfidx ++;
2127 if (pfidx >= mdb->num_pixfmts)
2129 pfidx = 0;
2130 syncidx ++;
2134 /* Search for a new mode. We only accept valid modes */
2135 for (; syncidx < mdb->num_syncs; syncidx ++)
2137 /* We only return valid modes */
2138 for (; pfidx < mdb->num_pixfmts; pfidx ++)
2140 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
2142 found = TRUE;
2143 break;
2146 if (found)
2147 break;
2150 if (found)
2152 return_id = COMPUTE_HIDD_MODEID(syncidx, pfidx);
2153 *msg->syncPtr = mdb->syncs[syncidx];
2154 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
2156 else
2158 *msg->syncPtr = *msg->pixFmtPtr = NULL;
2161 ReleaseSemaphore(&mdb->sema);
2163 return return_id;
2166 /*****************************************************************************************
2168 NAME
2169 moHidd_Gfx_GetMode
2171 SYNOPSIS
2172 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetMode *msg);
2174 BOOL HIDD_Gfx_GetMode(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
2175 OOP_Object **syncPtr, OOP_Object **pixFmtPtr);
2177 LOCATION
2178 hidd.graphics.graphics
2180 FUNCTION
2181 Get sync and pixelformat objects for a particular display ModeID.
2183 INPUTS
2184 gfxHidd - pointer to a driver object which this ModeID belongs to
2185 syncPtr - pointer to a storage where sync object pointer will be placed
2186 pixFmtPtr - pointer to a storage where pixelformat object pointer will be placed
2188 RESULT
2189 TRUE upon success, FALSE in case of failure (e.g. given mode does not exist in
2190 driver's internal database). If the function returns FALSE, sync and pixelformat
2191 pointers will be set to NULL.
2193 NOTES
2194 Every display mode is associated with some sync and pixelformat object. If the
2195 method returns TRUE, object pointers are guaranteed to be valid.
2197 EXAMPLE
2199 BUGS
2201 SEE ALSO
2202 moHidd_Gfx_NextModeID
2204 INTERNALS
2206 *****************************************************************************************/
2208 BOOL GFX__Hidd_Gfx__GetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMode *msg)
2210 ULONG pfidx, syncidx;
2211 struct HIDDGraphicsData *data;
2212 struct mode_db *mdb;
2213 BOOL ok = FALSE;
2215 data = OOP_INST_DATA(cl, o);
2216 mdb = &data->mdb;
2218 pfidx = MODEID_TO_PFIDX(msg->modeID);
2219 syncidx = MODEID_TO_SYNCIDX(msg->modeID);
2221 ObtainSemaphoreShared(&mdb->sema);
2223 if (! (pfidx >= mdb->num_pixfmts || syncidx >= mdb->num_syncs) )
2225 if (is_valid_mode(&mdb->checked_mode_bm, syncidx, pfidx))
2227 ok = TRUE;
2228 *msg->syncPtr = mdb->syncs[syncidx];
2229 *msg->pixFmtPtr = mdb->pixfmts[pfidx];
2233 ReleaseSemaphore(&mdb->sema);
2235 if (!ok)
2237 *msg->syncPtr = *msg->pixFmtPtr = NULL;
2240 return ok;
2243 /*****************************************************************************************
2245 NAME
2246 moHidd_Gfx_SetMode
2248 SYNOPSIS
2249 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetMode *msg);
2251 BOOL HIDD_Gfx_SetMode(OOP_Object *gfxHidd, OOP_Object *sync);
2253 LOCATION
2254 hidd.graphics.graphics
2256 FUNCTION
2257 Update display mode according to changed sync object
2259 INPUTS
2260 gfxHidd - A display driver to operate on
2261 sync - A modified sync object pointer
2263 RESULT
2264 TRUE if everything went OK and FALSE in case of some error
2266 NOTES
2267 This method is used to inform the driver that some external program has changed
2268 sync data and wants to update the display if needed. It's up to the implementation to
2269 check that current display is really using this sync (frontmost screen uses this mode).
2271 EXAMPLE
2273 BUGS
2275 SEE ALSO
2277 INTERNALS
2278 Base class implementation just returns FALSE indicating that this method is
2279 not supported.
2281 *****************************************************************************************/
2283 BOOL GFX__Hidd_Gfx__SetMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetMode *msg)
2285 return FALSE;
2288 /****************************************************************************************/
2290 static VOID copy_bm_and_colmap(OOP_Class *cl, OOP_Object *o, OOP_Object *src_bm,
2291 OOP_Object *dst_bm, UWORD width, UWORD height)
2293 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2294 struct HIDDGraphicsData *data;
2295 ULONG i;
2296 IPTR numentries;
2297 OOP_Object *src_colmap;
2298 APTR psrc_colmap = &src_colmap;
2300 data = OOP_INST_DATA(cl, o);
2302 /* We have to copy the colormap into the framebuffer bitmap */
2303 OOP_GetAttr(src_bm, aHidd_BitMap_ColorMap, (IPTR *)psrc_colmap);
2304 OOP_GetAttr(src_colmap, aHidd_ColorMap_NumEntries, &numentries);
2306 for (i = 0; i < numentries; i ++)
2308 HIDDT_Color col;
2310 HIDD_CM_GetColor(src_colmap, i, &col);
2311 HIDD_BM_SetColors(dst_bm, &col, i, 1);
2314 if (data->fbmode == vHidd_FrameBuffer_Mirrored)
2317 * Mirror mode, just turn on visibility.
2318 * The data will be copied to the framebuffer later,
2319 * when graphics.library calls UpdateRect() after Show().
2321 BM__Hidd_BitMap__SetVisible(CSD(cl)->bitmapclass, src_bm, TRUE);
2323 else
2326 * Direct framebuffer mode.
2327 * graphics.library will call UpdateRect() on the framebuffer object.
2328 * So we need to copy the data now.
2329 * We don't support scrolling for this mode, so we simply do the
2330 * bulk copy and ignore all offsets.
2332 HIDD_Gfx_CopyBox(o, src_bm, 0, 0,
2333 dst_bm, 0, 0, width, height, data->gc);
2337 /*****************************************************************************************
2339 NAME
2340 moHidd_Gfx_Show
2342 SYNOPSIS
2343 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Show *msg);
2345 OOP_Object *HIDD_Gfx_Show(OOP_Object *gfxHidd, OOP_Object *bitMap, ULONG flags);
2347 LOCATION
2348 hidd.graphics.graphics
2350 FUNCTION
2351 Change currently displayed bitmap on the screen.
2353 The bitmap object supplied must have been created with aHidd_BitMap_Displayable
2354 attribute set to TRUE.
2356 The function's behavior differs a lot depending on whether the driver uses a
2357 framebuffer or video hardware is able to switch screens itself.
2359 If the driver uses a framebuffer bitmap, it is supposed to copy the supplied bitmap
2360 into the framebuffer and return a framebuffer pointer. It also can be asked to
2361 copy back old framebuffer contents into previous bitmap object. It is driver's
2362 job to keep track of which bitmap object was displayed last time. This is what
2363 default implementation does. Note that it is very basic, and even does not support
2364 changing display resolution. It's not recommended to rely on it in production
2365 drivers (unless your video hardware supports only one mode).
2367 If the driver does not use a framebuffer, it is supposed to reprogram the hardware
2368 here to display an appropriate region of video RAM. Do not call the base class
2369 in this case, its implementation relies on framebuffer existance and will always
2370 return NULL which indicates an error.
2372 It is valid to get NULL value in bitMap parameter. This means that there is
2373 nothing to display and the screen needs to be blanked out. It is valid for
2374 non-framebuffer-based driver to return NULL as a reply then. In all other cases
2375 NULL return value means an error.
2377 Please avoid returning errors at all. graphics.library/LoadView() has no error
2378 indication. An error during showing a bitmap would leave the display in
2379 unpredictable state.
2381 If the driver does not use a framebuffer, consider using HIDD_Gfx_ShowViewPorts().
2382 It's more straightforward, flexible and offers support for screen composition.
2384 INPUTS
2385 gfxHidd - a display driver object, whose display you wish to change.
2386 bitMap - a pointer to a bitmap object which needs to be shown or NULL.
2387 flags - currently only one flag is defined:
2389 fHidd_Gfx_Show_CopyBack - Copy back the image data from framebuffer bitmap
2390 to old displayed bitmap. Used only if the driver
2391 needs a framebuffer.
2393 RESULT
2394 A pointer to a currently displayed bitmap object or NULL (read FUNCTION paragraph for
2395 detailed description)
2397 NOTES
2398 Drivers which use mirrored video data buffer do not have to update the display
2399 immediately in this method. moHidd_BitMap_UpdateRect will be sent to the returned
2400 bitmap if it's not NULL. Of course display blanking (if NULL bitmap was received)
2401 needs to be performed immediately.
2403 EXAMPLE
2405 BUGS
2407 SEE ALSO
2408 moHidd_Gfx_ShowViewPorts, graphics.library/LoadView()
2410 INTERNALS
2412 *****************************************************************************************/
2414 OOP_Object *GFX__Hidd_Gfx__Show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
2416 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2417 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
2418 OOP_Object *bm = msg->bitMap;
2419 IPTR oldwidth = 0;
2420 IPTR oldheight = 0;
2421 IPTR newwidth = 0;
2422 IPTR newheight = 0;
2424 if (NULL == data->framebuffer)
2426 /* We require framebuffer. Don't call us otherwise. */
2427 return NULL;
2430 ObtainSemaphore(&data->fbsem);
2432 if (data->shownbm)
2434 /* Get size of old bitmap */
2435 OOP_GetAttr(data->shownbm, aHidd_BitMap_Width, &oldwidth);
2436 OOP_GetAttr(data->shownbm, aHidd_BitMap_Height, &oldheight);
2438 if (data->fbmode == vHidd_FrameBuffer_Mirrored)
2440 BM__Hidd_BitMap__SetVisible(CSD(cl)->bitmapclass, data->shownbm, FALSE);
2442 else if (msg->flags & fHidd_Gfx_Show_CopyBack)
2444 /* Copy the framebuffer data back into the old shown bitmap */
2445 copy_bm_and_colmap(cl, o, data->framebuffer, data->shownbm, oldwidth, oldheight);
2449 if (bm == data->framebuffer)
2451 /* If showing the framebuffer itself, just detach from old bitmap and that's all. */
2452 data->shownbm = NULL;
2453 ReleaseSemaphore(&data->fbsem);
2455 return data->framebuffer;
2458 if (bm)
2460 IPTR modeid;
2463 * Switch framebuffer display mode.
2464 * This operation can fail if the bitmap has inappropriate mode.
2466 OOP_GetAttr(bm, aHidd_BitMap_ModeID, &modeid);
2467 if (!OOP_SetAttrsTags(data->framebuffer, aHidd_BitMap_ModeID, modeid, TAG_DONE))
2468 return NULL;
2470 /* Get size of new bitmap */
2471 OOP_GetAttr(bm, aHidd_BitMap_Width, &newwidth);
2472 OOP_GetAttr(bm, aHidd_BitMap_Height, &newheight);
2474 /* Copy it into the framebuffer */
2475 copy_bm_and_colmap(cl, o, bm, data->framebuffer, newwidth, newheight);
2479 * Clear remaining parts of the framebuffer (if previous bitmap was larger than new one)
2480 * Note that if the new bitmap is NULL, newwidth and newheight will both be zero.
2481 * This will cause clearing the whole display.
2483 if (oldheight) /* width and height can be zero only together, check one of them */
2485 if (newwidth < oldwidth)
2486 HIDD_BM_FillRect(data->framebuffer, data->gc, newwidth, 0, oldwidth - 1, oldheight - 1);
2487 if ((newheight < oldheight) && newwidth)
2488 HIDD_BM_FillRect(data->framebuffer, data->gc, 0, newheight, newwidth - 1, oldheight);
2491 /* Remember new displayed bitmap */
2492 data->shownbm = bm;
2494 ReleaseSemaphore(&data->fbsem);
2496 /* Return the actual bitmap to perform further operations on */
2497 return (data->fbmode == vHidd_FrameBuffer_Mirrored) ? bm : data->framebuffer;
2500 /*****************************************************************************************
2502 NAME
2503 moHidd_Gfx_ShowViewPorts
2505 SYNOPSIS
2506 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ShowViewPorts *msg);
2508 ULONG HIDD_Gfx_ShowViewPorts(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data, struct View *view);
2510 LOCATION
2511 hidd.graphics.graphics
2513 FUNCTION
2514 Show one or more bitmaps on the screen.
2516 It is completely up to the driver how to implement this function. The driver may
2517 or may not support hardware-assisted screens composition. Bitmaps are sorted
2518 in the list in descending z-order. The driver is expected to put at least frontmost
2519 bitmap on display.
2521 It is valid to get NULL pointer as data parameter. This means that there's
2522 nothing to show and the screen should go blank.
2524 Bitmaps display offsets are stored in their aHidd_BitMap_LeftEdge and
2525 aHidd_BitMap_TopEdge attributes. This function is not expected to modify their
2526 values somehow. They are assumed to be preserved between calls unless changed
2527 explicitly by the system.
2529 If you implement this method, you don't have to implement HIDD_Gfx_Show() because
2530 it will never be called.
2532 Note that there is no more error indication - the driver is expected to be
2533 error-free here.
2535 INPUTS
2536 gfxHidd - a display driver object, whose display you wish to change.
2537 data - a singly linked list of bitmap objects to show
2539 RESULT
2540 TRUE if this method is supported by the driver, FALSE otherwise
2542 NOTES
2544 EXAMPLE
2546 BUGS
2548 SEE ALSO
2549 moHidd_Gfx_Show
2551 INTERNALS
2552 Default base class implementation simply returns FALSE. This causes
2553 the system to use HIDD_Gfx_Show() instead.
2555 *****************************************************************************************/
2557 ULONG GFX__Hidd_Gfx__ShowViewPorts(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ShowViewPorts *msg)
2559 /* By default we don't support screen composition (and this method too) */
2560 return FALSE;
2563 /*****************************************************************************************
2565 NAME
2566 moHidd_Gfx_SetCursorShape
2568 SYNOPSIS
2569 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorShape *msg);
2571 BOOL HIDD_Gfx_SetCursorShape(OOP_Object *gfxHidd, OOP_Object *shape,
2572 WORD xoffset, WORD yoffset);
2574 LOCATION
2575 hidd.graphics.graphics
2577 FUNCTION
2578 Set mouse pointer shape.
2580 A pointer image is contained in the specified bitmap object. The bitmap object
2581 may contain a colormap if the system wants to specify own colors for the pointer.
2582 The supplied colormap will also contain alpha channel values.
2584 It is up to driver what to do if, for example, alpha channel is not supported by
2585 the hardware. Or if given bitmap type is not supported (for example truecolor
2586 bitmap on LUT-only hardware). It is expected that the driver converts bitmap
2587 data to a more appropriate form in such a case.
2589 A hotspot is given as an offset from the actual hotspot to the top-left corner
2590 of the pointer image. It is generally needed only for hosted display drivers
2591 which utilize host's support for mouse pointer.
2593 The default implementation in the base class just does nothing. A software mouse
2594 pointer is implemented in a special layer called fakegfx.hidd inside
2595 graphics.library. If a software pointer emulation is used, this method will
2596 never be called.
2598 INPUTS
2599 gfxHidd - a display driver object, for whose display you wish to change the pointer
2600 shape - a pointer to a bitmap object, containing pointer bitmap
2601 xoffset - a horizontal hotspot offset
2602 yoffset - a vertical hotspot offset
2604 RESULT
2605 TRUE on success, FALSE on failure
2607 NOTES
2609 EXAMPLE
2611 BUGS
2613 SEE ALSO
2614 moHidd_Gfx_SetCursorPos, moHidd_Gfx_SetCursorVisible
2616 INTERNALS
2618 *****************************************************************************************/
2620 BOOL GFX__Hidd_Gfx__SetCursorShape(OOP_Class *cl, OOP_Object *o,
2621 struct pHidd_Gfx_SetCursorShape *msg)
2623 /* We have no clue how to render the cursor */
2624 return TRUE;
2627 /*****************************************************************************************
2629 NAME
2630 moHidd_Gfx_SetCursorVisible
2632 SYNOPSIS
2633 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorVisible *msg);
2635 VOID HIDD_Gfx_SetCursorVisible(OOP_Object *gfxHidd, BOOL visible);
2637 LOCATION
2638 hidd.graphics.graphics
2640 FUNCTION
2641 Control mouse pointer visiblity.
2643 The default implementation in the base class does nothing. If a software pointer
2644 emulation is used, this method will never be called.
2646 INPUTS
2647 gfxHidd - a display driver object, on whose display you wish to turn
2648 pointer on or off
2649 visible - TRUE to enable pointer display, FALSE to disable it
2651 RESULT
2652 None.
2654 NOTES
2656 EXAMPLE
2658 BUGS
2660 SEE ALSO
2661 moHidd_Gfx_SetCursorPos, moHidd_Gfx_SetCursorVisible
2663 INTERNALS
2665 *****************************************************************************************/
2667 VOID GFX__Hidd_Gfx__SetCursorVisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
2672 /*****************************************************************************************
2674 NAME
2675 moHidd_Gfx_SetCursorPos
2677 SYNOPSIS
2678 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_SetCursorPos *msg);
2680 BOOL HIDD_Gfx_SetCursorPos(OOP_Object *gfxHidd, WORD x, WORD y);
2682 LOCATION
2683 hidd.graphics.graphics
2685 FUNCTION
2686 Set current mouse pointer position.
2688 This is a real position on top-left image corner relative to top-left corner of
2689 the physical display. Neither logical screen origin nor hotspot are taken into
2690 account here.
2692 The default implementation in the base class does nothing and just returns TRUE.
2693 If a software pointer emulation is used, this method will never be called.
2695 INPUTS
2696 gfxHidd - a display driver object, on whose display you wish to position the pointer
2697 x - An x coordinate of the pointer (relative to the physical screen origin)
2698 y - A y coordinate of the pointer (relative to the physical screen origin)
2700 RESULT
2701 Always TRUE. Reserved for future, do not use it.
2703 NOTES
2704 This method is called by graphics.library/MoveSprite() which has no return value.
2705 However, for historical reasons, this method has a return value. Drivers should
2706 always return TRUE in order to ensure future compatibility.
2708 EXAMPLE
2710 BUGS
2712 SEE ALSO
2713 moHidd_Gfx_SetCursorShape, moHidd_Gfx_SetCursorVisible, graphics.library/MoveSprite()
2715 INTERNALS
2717 *****************************************************************************************/
2719 BOOL GFX__Hidd_Gfx__SetCursorPos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
2721 return TRUE;
2724 /*****************************************************************************************
2726 NAME
2727 moHidd_Gfx_CopyBox
2729 SYNOPSIS
2730 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg);
2732 VOID HIDD_Gfx_CopyBox(OOP_Object *gfxHidd, OOP_Object *src, WORD srcX, WORD srcY,
2733 OOP_Object *dest, WORD destX, WORD destY, UWORD width, UWORD height,
2734 OOP_Object *gc);
2736 LOCATION
2737 hidd.graphics.graphics
2739 FUNCTION
2740 Perform rectangle copy (blit) operation from one bitmap to another.
2742 Given bitmaps may belong to different display drivers. The driver may attempt to
2743 use hardware for acceleration (if available), and if it's impossible, pass the
2744 operation on to the base class.
2746 Always check class of the supplied bitmap before attempting to look at its
2747 private data.
2749 A GC is used in order to specify raster operation performed between the source
2750 and destination according to its aHidd_GC_DrawMode attribute value.
2752 INPUTS
2753 gfxHidd - a display driver object that you are going to use for copying
2754 src - a pointer to source bitmap object
2755 srcX - an X coordinate of the source rectangle
2756 srcY - a Y coordinate of the source rectangle
2757 dest - a pointer to destination bitmap object
2758 destX - an X coordinate of the destination rectangle
2759 destY - a Y coordinate of the destination rectangle
2760 width - width of the rectangle to copy
2761 height - height of the rectangle to copy
2762 gc - graphics context holding draw mode on the destination
2764 RESULT
2765 None.
2767 NOTES
2768 You must specify valid coordinates (non-negative and inside the actual bitmap
2769 area), no checks are done.
2771 It is valid to specify two overlapped areas of the same bitmap as source
2772 and destination.
2774 EXAMPLE
2776 BUGS
2778 SEE ALSO
2780 INTERNALS
2782 *****************************************************************************************/
2784 VOID GFX__Hidd_Gfx__CopyBox(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBox *msg)
2786 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
2787 WORD x, y;
2788 WORD srcX = msg->srcX, destX = msg->destX;
2789 WORD srcY = msg->srcY, destY = msg->destY;
2790 WORD startX, endX, deltaX, startY, endY, deltaY;
2791 ULONG memFG;
2792 HIDDT_PixelFormat *srcpf, *dstpf;
2793 OOP_Object *dest, *src;
2794 OOP_Object *gc;
2795 APTR srcPixels = NULL;
2796 APTR destPixels = NULL;
2798 dest = msg->dest;
2799 src = msg->src;
2801 /* If source/dest overlap, direction of operation is important */
2803 if (srcX < destX)
2805 startX = msg->width - 1; endX = -1; deltaX = -1;
2807 else
2809 startX = 0; endX = msg->width; deltaX = 1;
2812 if (srcY < destY)
2814 startY = msg->height - 1; endY = -1; deltaY = -1;
2816 else
2818 startY = 0; endY = msg->height; deltaY = 1;
2821 /* Get the source pixel format */
2822 srcpf = (HIDDT_PixelFormat *)HBM(src)->prot.pixfmt;
2824 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,
2825 msg->src, srcX, srcY, msg->dest, destX, destY, msg->width, msg->height));
2826 DCOPYBOX(bug("COPYBOX: GC=0x%p, DrawMode %ld, ColMask 0x%08X\n", msg->gc, GC_DRMD(msg->gc), GC_COLMASK(msg->gc)));
2828 #ifdef COPYBOX_DUMP_DIMS
2830 IPTR sw, sh, dw, dh;
2832 OOP_GetAttr(obj, aHidd_BitMap_Width, &sw);
2833 OOP_GetAttr(obj, aHidd_BitMap_Height, &sh);
2834 OOP_GetAttr(msg->dest, aHidd_BitMap_Width, &dw);
2835 OOP_GetAttr(msg->dest, aHidd_BitMap_Height, &dh);
2837 bug("src dims: %dx%d dest dims: %dx%d\n", sw, sh, dw, dh);
2839 #endif
2841 dstpf = (HIDDT_PixelFormat *)HBM(dest)->prot.pixfmt;
2843 OOP_GetAttr(msg->src, aHidd_ChunkyBM_Buffer, (APTR)&srcPixels);
2844 OOP_GetAttr(msg->dest, aHidd_ChunkyBM_Buffer, (APTR)&destPixels);
2846 if (srcPixels && destPixels)
2849 * Both bitmaps are chunky ones and they have directly accessible buffer.
2850 * We can use optimized routines to do the copy.
2852 IPTR src_bytesperline, dest_bytesperline;
2854 OOP_GetAttr(msg->src, aHidd_BitMap_BytesPerRow, &src_bytesperline);
2855 OOP_GetAttr(msg->dest, aHidd_BitMap_BytesPerRow, &dest_bytesperline);
2857 switch(GC_DRMD(msg->gc))
2859 case vHidd_GC_DrawMode_Copy:
2860 /* At the moment we optimize only bulk copy */
2862 if (srcpf == dstpf)
2865 * The same pixelformat. Extremely great!
2867 * FIXME: Bulk copy to the same pixelformat is also handled in ConvertPixels very well
2868 * (optimized to either per-line or bulk memcpy()). But it can't handle
2869 * overlapping regions (which seems to be a requirement for CopyBox).
2870 * If this is fixed, we can even throw away HIDD_BM_CopyMemBoxXX at all, reducing
2871 * kickstart size.
2873 switch(srcpf->bytes_per_pixel)
2875 case 1:
2877 * In fact all these methods are static, they ignore object pointer, and it's
2878 * needed only for OOP_DoMethod() to fetch class information.
2879 * We use destination bitmap pointer, we can also source one.
2881 HIDD_BM_CopyMemBox8(msg->dest,
2882 srcPixels, msg->srcX, msg->srcY,
2883 destPixels, msg->destX, msg->destY,
2884 msg->width, msg->height,
2885 src_bytesperline, dest_bytesperline);
2886 return;
2888 case 2:
2889 HIDD_BM_CopyMemBox16(msg->dest,
2890 srcPixels, msg->srcX, msg->srcY,
2891 destPixels, msg->destX, msg->destY,
2892 msg->width, msg->height,
2893 src_bytesperline, dest_bytesperline);
2894 return;
2896 case 3:
2897 HIDD_BM_CopyMemBox24(msg->dest,
2898 srcPixels, msg->srcX, msg->srcY,
2899 destPixels, msg->destX, msg->destY,
2900 msg->width, msg->height,
2901 src_bytesperline, dest_bytesperline);
2902 return;
2904 case 4:
2905 HIDD_BM_CopyMemBox32(msg->dest,
2906 srcPixels, msg->srcX, msg->srcY,
2907 destPixels, msg->destX, msg->destY,
2908 msg->width, msg->height,
2909 src_bytesperline, dest_bytesperline);
2910 return;
2912 } /* switch(srcpf->bytes_per_pixel) */
2913 } /* srcpf == dstpf */
2914 else
2917 * Pixelformats are different. This can't be the same bitmap,
2918 * and it's safe to use ConvertPixels method (see FIXME above).
2920 srcPixels += (msg->srcY * src_bytesperline ) + (msg->srcX * srcpf->bytes_per_pixel);
2921 destPixels += (msg->destY * dest_bytesperline) + (msg->destX * dstpf->bytes_per_pixel);
2924 * Supply NULL pixlut. In this case bitmap's own colormap will be used
2925 * for color lookup (if needed).
2927 HIDD_BM_ConvertPixels(msg->dest,
2928 &srcPixels, srcpf, src_bytesperline,
2929 &destPixels, dstpf, dest_bytesperline,
2930 msg->width, msg->height, NULL);
2932 return;
2935 break;
2937 /* TODO: Optimize other DrawModes here */
2939 } /* switch(mode) */
2941 } /* srcPixels && destPixels */
2943 gc = msg->gc;
2945 memFG = GC_FG(msg->gc);
2947 /* All else have failed, copy pixel by pixel */
2948 if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf))
2950 if (IS_TRUECOLOR(srcpf))
2952 DCOPYBOX(bug("COPY FROM TRUECOLOR TO TRUECOLOR\n"));
2954 for(y = startY; y != endY; y += deltaY)
2956 HIDDT_Color col;
2958 /* if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
2959 bug("[%d,%d] ", memSrcX, memDestX);
2961 for(x = startX; x != endX; x += deltaX)
2963 HIDDT_Pixel pix = GETPIXEL(cl, src, srcX + x, srcY + y);
2965 #if COPYBOX_CHECK_FOR_ALIKE_PIXFMT
2966 if (srcpf == dstpf)
2968 GC_FG(gc) = pix;
2970 else
2971 #endif
2973 HIDD_BM_UnmapPixel(src, pix, &col);
2974 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, &col);
2977 DRAWPIXEL(cl, dest, gc, destX + x, destY + y);
2979 /*if (0 == strcmp("CON: Window", FindTask(NULL)->tc_Node.ln_Name))
2980 bug("[%d,%d] ", srcY, destY);
2984 } /* if (IS_TRUECOLOR(srcpf)) */
2985 else
2987 /* Two palette bitmaps.
2988 For this case we do NOT convert through RGB,
2989 but copy the pixel indexes directly
2991 DCOPYBOX(bug("COPY FROM PALETTE TO PALETTE\n"));
2993 /* FIXME: This might not work very well with two StaticPalette bitmaps */
2995 for(y = startY; y != endY; y += deltaY)
2997 for(x = startX; x != endX; x += deltaX)
2999 GC_FG(gc) = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3001 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
3006 } /* if (IS_TRUECOLOR(srcpf)) else ... */
3008 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) */
3009 else
3011 /* Two unlike bitmaps */
3012 if (IS_TRUECOLOR(srcpf))
3014 for(y = startY; y != endY; y += deltaY)
3016 for(x = startX; x != endX; x += deltaX)
3018 HIDDT_Pixel pix;
3019 HIDDT_Color col;
3021 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3022 HIDD_BM_UnmapPixel(src, pix, &col);
3024 HIDD_BM_PutPixel(dest, destX + x, destY + y,
3025 HIDD_BM_MapColor(dest, &col));
3029 else if (IS_TRUECOLOR(dstpf))
3031 /* Get the colortab */
3032 HIDDT_Color *ctab = ((HIDDT_ColorLUT *)HBM(src)->colmap)->colors;
3034 DCOPYBOX(bug("COPY FROM PALETTE TO TRUECOLOR, DRAWMODE %d, CTAB %p\n", GC_DRMD(gc), ctab));
3036 for(y = startY; y != endY; y += deltaY)
3038 for(x = startX; x != endX; x += deltaX)
3040 register HIDDT_Pixel pix;
3041 HIDDT_Color col;
3043 pix = HIDD_BM_GetPixel(src, srcX + x, srcY + y);
3044 col = ctab[pix];
3047 * !!!! HIDD_BM_MapColor() pokes pixval of the passed HIDDT_Color,
3048 * so if the address of the entry in the colormap is passed, the colormap
3049 * itself will be modified, if we pass "&ctab[pix]" to HIDD_BM_MapColor() !!!!
3052 GC_FG(gc) = HIDD_BM_MapColor(msg->dest, &col);
3053 HIDD_BM_DrawPixel(msg->dest, gc, destX + x, destY + y);
3059 } /* if (HIDD_PF_COLMODEL(srcpf) == HIDD_PF_COLMODEL(dstpf)) else ... */
3061 GC_FG(gc) = memFG;
3064 /*****************************************************************************************
3066 NAME
3067 moHidd_Gfx_CopyBoxMasked
3069 SYNOPSIS
3070 IPTR OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CopyBoxMasked *msg);
3072 IPTR HIDD_Gfx_CopyBoxMasked(OOP_Object *gfxHidd, OOP_Object *src, WORD srcX, WORD srcY,
3073 OOP_Object *dest, WORD destX, WORD destY, UWORD width, UWORD height,
3074 PLANEPTR mask, OOP_Object *gc);
3076 LOCATION
3077 hidd.graphics.graphics
3079 FUNCTION
3080 Perform rectangle copy (blit) operation from one bitmap to another,
3081 using a cookie cutter mask.
3083 Given bitmaps must be on the same display driver.
3085 A GC is used in order to specify raster operation performed between the source
3086 and destination according to its aHidd_GC_DrawMode attribute value.
3088 INPUTS
3089 gfxHidd - a display driver object that you are going to use for copying
3090 src - a pointer to source bitmap object
3091 srcX - an X coordinate of the source rectangle
3092 srcY - a Y coordinate of the source rectangle
3093 dest - a pointer to destination bitmap object
3094 destX - an X coordinate of the destination rectangle
3095 destY - a Y coordinate of the destination rectangle
3096 width - width of the rectangle to copy
3097 height - height of the rectangle to copy
3098 mask - single bitplane mask
3099 gc - graphics context holding draw mode on the destination
3101 RESULT
3102 TRUE is the operation succeeded and FALSE in case of some error, for example
3103 if the system was too low on memory.
3105 NOTES
3106 You must specify valid coordinates (non-negative and inside the actual bitmap
3107 area), no checks are done.
3109 It is valid to specify two overlapped areas of the same bitmap as source
3110 and destination.
3112 Mask size must correspond to full source bitmap size (including alignment).
3114 EXAMPLE
3116 BUGS
3118 SEE ALSO
3120 INTERNALS
3122 *****************************************************************************************/
3124 /* Nominal size of the pixel conversion buffer */
3125 #ifdef __mc68000
3126 #define NUMPIX 4096 /* Not that much room to spare */
3127 #else
3128 #define NUMPIX 100000
3129 #endif
3131 IPTR GFX__Hidd_Gfx__CopyBoxMasked(OOP_Class *cl, OOP_Object *obj, struct pHidd_Gfx_CopyBoxMasked *msg)
3133 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3134 ULONG pixfmt = vHidd_StdPixFmt_Native32;
3135 OOP_Object *src_pf, *dest_pf;
3136 HIDDT_ColorModel src_colmod, dest_colmod;
3137 HIDDT_Color *ctab = NULL;
3138 ULONG bytes_per_line, lines_per_step, doing_lines, lines_done;
3139 IPTR mask_align, mask_bpr;
3140 UBYTE *srcbuf;
3142 OOP_GetAttr(msg->src , aHidd_BitMap_PixFmt, (IPTR *)&src_pf);
3143 OOP_GetAttr(msg->dest, aHidd_BitMap_PixFmt, (IPTR *)&dest_pf);
3145 OOP_GetAttr(src_pf, aHidd_PixFmt_ColorModel, &src_colmod);
3146 OOP_GetAttr(dest_pf, aHidd_PixFmt_ColorModel, &dest_colmod);
3148 if ((src_colmod == vHidd_ColorModel_Palette) && (dest_colmod == vHidd_ColorModel_TrueColor))
3151 * LUT->truecolor conversion. We need a colormap (palette).
3152 * If the source is displayable (screen) bitmap, it will have own palette. In this case
3153 * we should use it.
3154 * If it's just a bitmap in memory, it won't have a palette (colmap will be NULL). In this
3155 * case destination bitmap needs to have a palette. This will happen if it's either a displayable
3156 * bitmap, or is a friend of displayable bitmap (will share friend's palette then).
3158 HIDDT_ColorLUT *colmap = (HIDDT_ColorLUT *)HBM(msg->src)->colmap;
3160 if (!colmap)
3161 colmap = (HIDDT_ColorLUT *)HBM(msg->dest)->colmap;
3163 if (!colmap)
3165 D(bug("BltMaskBitMapRastPort could not retrieve pixel table for blit from palette to truecolor bitmap"));
3166 return FALSE;
3169 ctab = colmap->colors;
3171 else if ((src_colmod == vHidd_ColorModel_TrueColor) && (dest_colmod == vHidd_ColorModel_TrueColor))
3173 if (src_pf != dest_pf)
3176 * Pixelformats are different, conversion needed.
3177 * First, we use two operations on destination bitmap (get and put), and only one
3178 * operation on source bitmap (get).
3179 * Second, we map LUT source pixels on destination bitmap's pixelformat.
3180 * Resume: we use destination's pixelformat for the whole operation. Conversion
3181 * happens during GetImage on the source bitmap.
3183 OOP_GetAttr(dest_pf, aHidd_PixFmt_StdPixFmt, (IPTR *)&pixfmt);
3186 else if ((src_colmod == vHidd_ColorModel_TrueColor) && (dest_colmod == vHidd_ColorModel_Palette))
3188 D(bug("BltMaskBitMapRastPort from truecolor bitmap to palette bitmap not supported!"));
3189 return FALSE;
3192 /* Mask width in pixels corresponds to full bitmap width (including alignment) */
3193 OOP_GetAttr(msg->src, aHidd_BitMap_Width, &mask_bpr);
3194 OOP_GetAttr(msg->src, aHidd_BitMap_Align, &mask_align);
3196 mask_align--;
3197 mask_bpr = ((mask_bpr + mask_align) & ~mask_align) >> 3;
3200 * TODO: Here we use a temporary buffer to perform the operation. This is slow and
3201 * actually unnecessary is many cases. If one of source or destination bitmaps is
3202 * directly accessible, we should use their own buffers. This will increase the speed
3203 * and decrease memory usage, because of omitted copy operations.
3206 /* Based on the NUMPIX advice, figure out how many
3207 * lines per step we can allocate
3209 bytes_per_line = msg->width * sizeof(HIDDT_Pixel);
3210 lines_per_step = NUMPIX / bytes_per_line;
3211 if (lines_per_step == 0)
3212 lines_per_step = 1;
3214 /* Allocate a temporary buffer */
3215 srcbuf = AllocMem(2 * lines_per_step * bytes_per_line, MEMF_ANY);
3217 /* Try line-at-a-time if we can't allocate a big buffer */
3218 if (!srcbuf && lines_per_step > 1)
3220 lines_per_step = 1;
3221 srcbuf = AllocMem(2 * lines_per_step * bytes_per_line, MEMF_ANY);
3224 if (srcbuf)
3226 UBYTE *destbuf = srcbuf + lines_per_step * bytes_per_line;
3227 HIDDT_DrawMode drawmode = GC_DRMD(msg->gc);
3229 /* PutImage needs to be called in Copy mode for proper operation */
3230 GC_DRMD(msg->gc) = vHidd_GC_DrawMode_Copy;
3232 for (lines_done = 0; lines_done != msg->height; lines_done += doing_lines)
3234 HIDDT_Pixel *srcpixelbuf;
3235 HIDDT_Pixel *destpixelbuf;
3236 UBYTE *mask;
3237 UWORD x, y;
3239 doing_lines = lines_per_step;
3240 if (lines_done + doing_lines > msg->height)
3241 doing_lines = msg->height - lines_done;
3243 HIDD_BM_GetImage(msg->src, srcbuf, bytes_per_line,
3244 msg->srcX, msg->srcY + lines_done,
3245 msg->width, doing_lines, pixfmt);
3247 HIDD_BM_GetImage(msg->dest, destbuf, bytes_per_line,
3248 msg->destX, msg->destY + lines_done,
3249 msg->width, doing_lines, pixfmt);
3251 mask = &msg->mask[COORD_TO_BYTEIDX(0, msg->srcY + lines_done, mask_bpr)];
3253 srcpixelbuf = (HIDDT_Pixel *)srcbuf;
3254 destpixelbuf = (HIDDT_Pixel *)destbuf;
3256 switch (drawmode)
3258 case vHidd_GC_DrawMode_Or: /* (ABC|ABNC|ANBC) if copy source and blit thru mask */
3259 case vHidd_GC_DrawMode_Copy: /* (ABC|ABNC = 0xC0) - compatibility with AOS3 */
3260 for (y = 0; y < doing_lines; y++)
3262 for (x = 0; x < msg->width; x++)
3264 if (mask[XCOORD_TO_BYTEIDX(msg->srcX + x)] & XCOORD_TO_MASK(msg->srcX + x))
3266 HIDDT_Pixel pix = *srcpixelbuf;
3268 if (ctab)
3271 * TODO:
3272 * Here and in several other places we use colormap data for palette->truecolor conversion.
3273 * The algorithm is as follows: take LUT pixel value (which is effectively color index), find RGB
3274 * entry in the LUT, then compose a pixel from RGB triplet using MapColor method on the destination
3275 * bitmap.
3276 * This two-step operation is slow. graphics.library internally uses cached version of the palette
3277 * (HIDDT_PixLut), where all colors are already decoded into pixel values.
3278 * Since HIDD subsystem also needs this, this pixlut (called pixtab - pixel table in graphics.library),
3279 * should be moved here. In fact a good place for it is a bitmap object (since pixlut = colormap + pixfmt,
3280 * and pixfmt is a bitmap's property.
3281 * graphics.library has pixlut attached to a BitMap structure (using HIDD_BM_PIXTAB() macro).
3285 * !!!! HIDD_BM_MapColor() pokes pixval of the passed HIDDT_Color,
3286 * so if the address of the entry in the colormap is passed, the colormap
3287 * itself will be modified, if we pass "&ctab[pix]" to HIDD_BM_MapColor() !!!!
3290 HIDDT_Color col = ctab[pix];
3292 pix = HIDD_BM_MapColor(msg->dest, &col);
3295 *destpixelbuf = pix;
3297 srcpixelbuf++;
3298 destpixelbuf++;
3300 mask += mask_bpr;
3302 break;
3304 case vHidd_GC_DrawMode_AndInverted: /* (ANBC) if invert source and blit thru mask */
3305 D(bug("CopyBoxMasked does not support ANBC minterm yet"));
3306 break;
3308 default:
3309 D(bug("CopyBoxMasked: DrawMode 0x%x not handled.\n", drawmode));
3310 break;
3313 HIDD_BM_PutImage(msg->dest, msg->gc, destbuf, bytes_per_line,
3314 msg->destX, msg->destY + lines_done,
3315 msg->width, doing_lines, pixfmt);
3317 } /* for(lines_done = 0; lines_done != height; lines_done += doing_lines) */
3319 /* Restore GC state */
3320 GC_DRMD(msg->gc) = drawmode;
3322 /* Free our temporary buffer */
3323 FreeMem(srcbuf, 2 * lines_per_step * bytes_per_line);
3325 return TRUE;
3326 } /* if (lines_per_step) */
3327 else
3329 /* urk :-( pixelbuffer too small to hold two lines) */
3330 D(bug("BltMaskBitMapRastPort found pixelbuffer to be too small"));
3331 return FALSE;
3336 /*****************************************************************************************
3338 NAME
3339 moHidd_Gfx_ShowImminentReset
3341 SYNOPSIS
3342 VOID OOP_DoMethod(OOP_Object *obj, OOP_Msg msg);
3344 LOCATION
3345 hidd.graphics.graphics
3347 FUNCTION
3348 Indicate upcoming machine reset. Obsolete.
3350 Since graphics.library v41.4 this method is not used any more. Considered
3351 reserved. Do not use it in any way.
3353 INPUTS
3354 None.
3356 RESULT
3357 None.
3359 NOTES
3361 EXAMPLE
3363 BUGS
3365 SEE ALSO
3367 INTERNALS
3369 *****************************************************************************************/
3371 VOID GFX__Hidd_Gfx__ShowImminentReset(OOP_Class *cl, OOP_Object *obj, OOP_Msg msg)
3375 /****************************************************************************************/
3378 * The following two methods are private, static, and not virtual.
3379 * They operate only on static data and don't need object pointer.
3382 OOP_Object *GFX__Hidd_Gfx__RegisterPixFmt(OOP_Class *cl, struct TagItem *pixFmtTags)
3384 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3385 HIDDT_PixelFormat cmp_pf;
3386 struct class_static_data *data;
3387 struct pixfmt_data *retpf = NULL;
3389 memset(&cmp_pf, 0, sizeof(cmp_pf));
3391 data = CSD(cl);
3392 if (!parse_pixfmt_tags(pixFmtTags, &cmp_pf, 0, CSD(cl)))
3394 D(bug("!!! FAILED PARSING TAGS IN Gfx::RegisterPixFmt() !!!\n"));
3395 return FALSE;
3399 * Our alpha-less R8G8B8 pixelformats are defined as having depth
3400 * and size = 24, not 32 bits. Nevertheless, many hardware reports
3401 * 32 bits in such cases.
3402 * In order to avoid confusion we attempt to detect this situation and
3403 * fix up pixelformat definition. If we don't do it, we get nonstandard
3404 * pixelformat with no corresponding CGX code, which can misbehave.
3406 if ((cmp_pf.flags == PF_GRAPHTYPE(TrueColor, Chunky)) &&
3407 (cmp_pf.bytes_per_pixel == 4) && (cmp_pf.alpha_mask == 0) &&
3408 (cmp_pf.red_mask << cmp_pf.red_shift == 0xFF000000) &&
3409 (cmp_pf.green_mask << cmp_pf.green_shift == 0xFF000000) &&
3410 (cmp_pf.blue_mask << cmp_pf.blue_shift == 0xFF000000))
3412 DPF(bug("Gfx::RegisterPixFmt(): 4-byte R8G8B8 detected\n"));
3414 if (cmp_pf.depth > 24)
3416 DPF(bug("Gfx::RegisterPixFmt(): Fixing up depth %d > 24\n", cmp_pf.depth));
3417 cmp_pf.depth = 24;
3420 if (cmp_pf.size > 24)
3422 DPF(bug("Gfx::RegisterPixFmt(): Fixing up size %d > 24\n", cmp_pf.size));
3423 cmp_pf.size = 24;
3427 DPF(bug("Gfx::RegisterPixFmt(): Registering pixelformat:\n"));
3428 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
3429 , PF(&cmp_pf)->red_shift
3430 , PF(&cmp_pf)->green_shift
3431 , PF(&cmp_pf)->blue_shift
3432 , PF(&cmp_pf)->alpha_shift
3433 , PF(&cmp_pf)->red_mask
3434 , PF(&cmp_pf)->green_mask
3435 , PF(&cmp_pf)->blue_mask
3436 , PF(&cmp_pf)->alpha_mask
3437 , PF(&cmp_pf)->bytes_per_pixel
3438 , PF(&cmp_pf)->size
3439 , PF(&cmp_pf)->depth
3440 , PF(&cmp_pf)->stdpixfmt));
3442 retpf = find_pixfmt(&cmp_pf, CSD(cl));
3444 DPF(bug("Found matching pixelformat: 0x%p\n", retpf));
3445 if (retpf)
3446 /* Increase pf refcount */
3447 AROS_ATOMIC_INC(retpf->refcount);
3448 else
3450 /* Could not find an alike pf, Create a new pfdb node */
3451 /* Since we pass NULL as the taglist below, the PixFmt class will just create a dummy pixfmt */
3452 retpf = OOP_NewObject(CSD(cl)->pixfmtclass, NULL, NULL);
3453 if (retpf) {
3454 /* We have one user */
3455 retpf->refcount = 1;
3457 /* Initialize the pixfmt object the "ugly" way */
3458 memcpy(retpf, &cmp_pf, sizeof (HIDDT_PixelFormat));
3460 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n"
3461 , PF(&cmp_pf)->red_shift
3462 , PF(&cmp_pf)->green_shift
3463 , PF(&cmp_pf)->blue_shift
3464 , PF(&cmp_pf)->alpha_shift
3465 , PF(&cmp_pf)->red_mask
3466 , PF(&cmp_pf)->green_mask
3467 , PF(&cmp_pf)->blue_mask
3468 , PF(&cmp_pf)->alpha_mask
3469 , PF(&cmp_pf)->bytes_per_pixel
3470 , PF(&cmp_pf)->size
3471 , PF(&cmp_pf)->depth
3472 , PF(&cmp_pf)->stdpixfmt));
3474 ObtainSemaphore(&data->pfsema);
3475 AddTail((struct List *)&data->pflist, (struct Node *)&retpf->node);
3476 ReleaseSemaphore(&data->pfsema);
3480 DPF(bug("New refcount is %u\n", retpf->refcount));
3481 return (OOP_Object *)retpf;
3484 /****************************************************************************************/
3486 /* This method doesn't need object pointer, it's static. */
3488 VOID GFX__Hidd_Gfx__ReleasePixFmt(OOP_Class *cl, OOP_Object *pf)
3490 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3491 struct class_static_data *data;
3492 struct pixfmt_data *pixfmt = (struct pixfmt_data *)pf;
3494 DPF(bug("release_pixfmt 0x%p\n", pixfmt));
3496 data = CSD(cl);
3498 ObtainSemaphore(&data->pfsema);
3500 /* If refcount is already 0, this object was never registered in the database,
3501 don't touch it */
3502 DPF(bug("Old reference count is %u\n", pixfmt->refcount));
3503 if (pixfmt->refcount) {
3504 if (--pixfmt->refcount == 0) {
3505 Remove((struct Node *)&pixfmt->node);
3506 OOP_DisposeObject((OOP_Object *)pixfmt);
3510 ReleaseSemaphore(&data->pfsema);
3513 /*****************************************************************************************
3515 NAME
3516 moHidd_Gfx_CheckMode
3518 SYNOPSIS
3519 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CheckMode *msg);
3521 BOOL HIDD_Gfx_CheckMode(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
3522 OOP_Object *sync, OOP_Object *pixFmt);
3524 LOCATION
3525 hidd.graphics.graphics
3527 FUNCTION
3528 Check if given display mode is supported by the driver.
3530 Normally any resolution (sync) can be used together with any pixelformat. However
3531 on some hardware there may be exceptions from this rule. In such a case this
3532 method should be implemented, and check should be performed.
3534 The information provided by this method is used in order to exclude unsupported
3535 modes from the database
3537 Default implementation in the base class just returns TRUE for all supplied values.
3539 Note that this method can not be used in order to chech that the given mode is
3540 really present in the database and it really refers to the given sync and
3541 pixelformat objects. Use HIDD_Gfx_GetMode() for mode ID validation.
3543 INPUTS
3544 gfxHidd - A display driver object
3545 modeID - A display mode ID
3546 sync - A pointer to a sync object associated with this mode
3547 pixFmt - A pointer to a pixelformat object associated with this mode
3549 RESULT
3550 TRUE if this mode is supported and FALSE if it's not.
3552 NOTES
3554 EXAMPLE
3556 BUGS
3557 Currently base class does not call this method after driver object creation.
3558 This needs to be fixed.
3560 SEE ALSO
3561 moHidd_Gfx_GetMode
3563 INTERNALS
3565 *****************************************************************************************/
3567 BOOL GFX__Hidd_Gfx__CheckMode(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CheckMode *msg)
3569 /* As a default we allways return TRUE, ie. the mode is OK */
3570 return TRUE;
3573 /*****************************************************************************************
3575 NAME
3576 moHidd_Gfx_GetPixFmt
3578 SYNOPSIS
3579 OOP_Object *OOP_DoMethod(OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg);
3581 OOP_Object *HIDD_Gfx_GetPixFmt(OOP_Object *gfxHidd, HIDDT_StdPixFmt pixFmt);
3583 LOCATION
3584 hidd.graphics.graphics
3586 FUNCTION
3587 Get a standard pixelformat descriptor from internal pixelformats database.
3589 INPUTS
3590 gfxHidd - A display driver object
3591 pixFmt - An index of pixelformat (one of vHIDD_StdPixFmt_... values)
3593 RESULT
3594 A pointer to a pixelformat object or NULL if lookup failed
3596 NOTES
3597 Pixelformat objects are stored in a global system-wide database. They are not
3598 linked with a particular driver in any way and completely sharable between all
3599 drivers.
3601 EXAMPLE
3603 BUGS
3605 SEE ALSO
3607 INTERNALS
3608 This operation can never fail because all standard pixelformats are registered
3609 during early system initialization.
3611 *****************************************************************************************/
3613 OOP_Object *GFX__Hidd_Gfx__GetPixFmt(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetPixFmt *msg)
3615 OOP_Object *fmt;
3617 if (!IS_REAL_STDPIXFMT(msg->stdPixFmt))
3619 D(bug("!!! Illegal pixel format passed to Gfx::GetPixFmt(): %d\n", msg->stdPixFmt));
3620 return NULL;
3622 else
3624 fmt = (OOP_Object *)CSD(cl)->std_pixfmts[REAL_STDPIXFMT_IDX(msg->stdPixFmt)];
3627 return fmt;
3630 /*****************************************************************************************
3632 NAME
3633 moHidd_Gfx_GetSync
3635 SYNOPSIS
3636 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetSync *msg);
3638 OOP_Object *HIDD_Gfx_GetSync(OOP_Object *gfxHidd, ULONG num);
3640 LOCATION
3641 hidd.graphics.graphics
3643 FUNCTION
3644 Get a sync object from internal display mode database by index
3646 INPUTS
3647 gfxHidd - A display driver object to query
3648 num - An index of sync object starting from 0
3650 RESULT
3651 A pointer to a sync object or NULL if there's no sync with such index
3653 NOTES
3655 EXAMPLE
3657 BUGS
3659 SEE ALSO
3661 INTERNALS
3663 *****************************************************************************************/
3665 OOP_Object *GFX__Hidd_Gfx__GetSync(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetSync *msg)
3667 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
3669 if (msg->num < data->mdb.num_syncs)
3670 return data->mdb.syncs[msg->num];
3671 else {
3672 D(bug("!!! Illegal sync index passed to Gfx::GetSync(): %d\n", msg->num));
3673 return NULL;
3677 /*****************************************************************************************
3679 NAME
3680 moHidd_Gfx_ModeProperties
3682 SYNOPSIS
3683 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_ModeProperties *msg);
3685 ULONG HIDD_Gfx_ModeProperties(OOP_Object *gfxHidd, HIDDT_ModeID modeID,
3686 struct HIDD_ModeProperties *props, ULONG propsLen);
3688 LOCATION
3689 hidd.graphics.graphics
3691 FUNCTION
3692 Obtain an information about the video mode.
3694 Video mode description structure may grow in future, so be careful and always check
3695 propsLen parameter value. A system may ask you for less data than you can provide.
3696 Always return an actual value. Do not just zero out fields you don't know about,
3697 this is not expected to be backwards compatible.
3699 INPUTS
3700 gfxHidd - a pointer to a display driver object whose display mode you want to query
3701 modeID - a mode ID to query
3702 props - a pointer to a storage area where HIDD_ModeProperties structure will be put
3703 propsLen - length of the supplied buffer in bytes.
3705 RESULT
3706 Actual length of obtained structure
3708 NOTES
3709 Returned data must reflect only real hardware capabilities. For example, do not
3710 count emulated sprites. The system takes care about emulated features itself.
3712 EXAMPLE
3714 BUGS
3716 SEE ALSO
3717 aoHidd_Gfx_HWSpriteTypes, aoHidd_Gfx_SupportsHWCursor
3719 INTERNALS
3720 Default implementation in the base class relies on aHidd_Gfx_HWSpriteTypes attribute,
3721 not vice versa. If you override this method, do not forget to override this attribute too.
3723 *****************************************************************************************/
3725 ULONG GFX__Hidd_Gfx__ModeProperties(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ModeProperties *msg)
3727 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3728 struct HIDD_ModeProperties props = {0, 0, 0};
3729 IPTR has_hw_cursor = 0;
3730 ULONG len = msg->propsLen;
3732 D(bug("[GFXHIDD] Hidd::Gfx::ModeProperties(0x%08lX, 0x%p, %u)\n", msg->modeID, msg->props, msg->propsLen));
3733 OOP_GetAttr(o, aHidd_Gfx_HWSpriteTypes, &has_hw_cursor);
3734 if (has_hw_cursor) {
3735 D(bug("[GFXHIDD] Driver has hardware mouse cursor implementation\n"));
3736 props.DisplayInfoFlags = DIPF_IS_SPRITES;
3737 props.NumHWSprites = 1;
3740 if (len > sizeof(props))
3741 len = sizeof(props);
3742 D(bug("[GFXHIDD] Copying %u bytes\n", len));
3743 CopyMem(&props, msg->props, len);
3745 return len;
3748 /*****************************************************************************************
3750 NAME
3751 moHidd_Gfx_GetGamma
3753 SYNOPSIS
3754 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Gamma *msg);
3756 BOOL HIDD_Gfx_GetGamma(OOP_Object *gfxHidd, UBYTE *Red, UBYTE *Green, UBYTE *Blue);
3758 LOCATION
3759 hidd.graphics.graphics
3761 FUNCTION
3762 Get current gamma table for the display.
3764 This method was neither ever implemented nor used. Currently obsolete and
3765 considered reserved.
3767 INPUTS
3769 RESULT
3771 NOTES
3773 EXAMPLE
3775 BUGS
3777 SEE ALSO
3778 moHidd_Gfx_SetGamma
3780 INTERNALS
3782 *****************************************************************************************/
3784 BOOL GFX__Hidd_Gfx__GetGamma(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Gamma *msg)
3786 return FALSE;
3789 /*****************************************************************************************
3791 NAME
3792 moHidd_Gfx_SetGamma
3794 SYNOPSIS
3795 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_Gamma *msg);
3797 BOOL HIDD_Gfx_SetGamma(OOP_Object *gfxHidd, UBYTE *Red, UBYTE *Green, UBYTE *Blue);
3799 LOCATION
3800 hidd.graphics.graphics
3802 FUNCTION
3803 Set current gamma table for the display.
3805 A gamma table consists of three 256-byte tables: one for red component, one for
3806 green and one for blue.
3808 INPUTS
3809 gfxHidd - A display driver object
3810 Red - A pointer to a 256-byte array for red component
3811 Green - A pointer to a 256-byte array for green component
3812 Blue - A pointer to a 256-byte array for blue component
3814 RESULT
3815 FALSE if the driver doesn't support gamma correction, otherwise TRUE
3817 NOTES
3819 EXAMPLE
3821 BUGS
3823 SEE ALSO
3825 INTERNALS
3827 *****************************************************************************************/
3829 BOOL GFX__Hidd_Gfx__SetGamma(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Gamma *msg)
3831 return FALSE;
3834 /*****************************************************************************************
3836 NAME
3837 moHidd_Gfx_QueryHardware3D
3839 SYNOPSIS
3840 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_QueryHardware3D *msg);
3842 BOOL HIDD_Gfx_QueryHardware3D(OOP_Object *gfxHidd, OOP_Object *pixFmt);
3844 LOCATION
3845 hidd.graphics.graphics
3847 FUNCTION
3848 Query if the driver supports hardware-accelerated 3D graphics for the given
3849 pixelformat.
3851 INPUTS
3852 gfxHidd - A display driver object
3853 pixFmt - A pointer to a pixelformat descriptor object
3855 RESULT
3856 TRUE if the driver supports hardware-accelerated 3D for the given pixelformat,
3857 FALSE otherwise.
3859 NOTES
3861 EXAMPLE
3863 BUGS
3865 SEE ALSO
3867 INTERNALS
3869 *****************************************************************************************/
3871 BOOL GFX__Hidd_Gfx__QueryHardware3D(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_QueryHardware3D *msg)
3873 return FALSE;
3876 /*****************************************************************************************
3878 NAME
3879 moHidd_Gfx_GetMaxSpriteSize
3881 SYNOPSIS
3882 BOOL OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_GetMaxSpriteSize *msg);
3884 BOOL HIDD_Gfx_GetMaxSpriteSize(OOP_Object *gfxHidd, ULONG Type, UWORD *Width, UWORD *Height);
3886 LOCATION
3887 hidd.graphics.graphics
3889 FUNCTION
3890 Query maximum allowed size for the given sprite type.
3892 INPUTS
3893 gfxHidd - A display driver object
3894 Type - Type of the sprite image (one of vHidd_SpriteType_... values)
3895 Width - A pointer to UWORD where width will be placed.
3896 Height - A pointer to UWORD where height will be placed.
3898 RESULT
3899 FALSE is the given sprite type is not supported, otherwise TRUE.
3901 NOTES
3902 Default implementation in the base class just return some small values
3903 which it hopes can be supported by every driver if the driver supports given
3904 sprite type. It is strongly suggested to reimplement this method in the display
3905 driver.
3907 Width and Height are considered undefined if the method returns FALSE.
3909 EXAMPLE
3911 BUGS
3913 SEE ALSO
3915 INTERNALS
3917 *****************************************************************************************/
3919 BOOL GFX__Hidd_Gfx__GetMaxSpriteSize(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_GetMaxSpriteSize *msg)
3921 IPTR types;
3922 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
3924 OOP_GetAttr(o, aHidd_Gfx_HWSpriteTypes, &types);
3926 if (types & msg->Type) {
3927 *msg->Width = 16;
3928 *msg->Height = 32;
3929 return TRUE;
3930 } else
3931 return FALSE;
3934 /*****************************************************************************************
3936 NAME
3937 moHidd_Gfx_NewOverlay
3939 SYNOPSIS
3940 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_NewOverlay *msg);
3942 OOP_Object *HIDD_Gfx_NewOverlay(OOP_Object *gfxHidd, struct TagItem *tagList);
3944 LOCATION
3945 hidd.graphics.graphics
3947 FUNCTION
3948 Create a video overlay object.
3950 INPUTS
3951 gfxHidd - A graphics driver object on whose display you want to create an overlay.
3952 tagList - A list of overlay attributes. See overlay class documentation for
3953 their description.
3955 RESULT
3956 Pointer to the newly created overlay object or NULL in case of failure.
3958 NOTES
3959 Default implementation in the base class always sets VOERR_INVSCRMODE error and
3960 returns NULL meaning that hardware overlays are not supported. There's no sense
3961 in software implementation because the software is supposed to handle software
3962 rendering itself.
3964 EXAMPLE
3966 BUGS
3968 SEE ALSO
3969 moHidd_Gfx_DisposeOverlay
3971 INTERNALS
3973 *****************************************************************************************/
3975 OOP_Object *GFX__Hidd_Gfx__NewOverlay(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_NewOverlay *msg)
3977 struct Library *UtilityBase = CSD(cl)->cs_UtilityBase;
3978 ULONG *err = (ULONG *)GetTagData(aHidd_Overlay_Error, 0, msg->attrList);
3980 if (err)
3981 *err = VOERR_INVSCRMODE;
3983 return NULL;
3986 /*****************************************************************************************
3988 NAME
3989 moHidd_Gfx_DisposeOverlay
3991 SYNOPSIS
3992 VOID OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_DisposeOverlay *msg);
3994 VOID HIDD_Gfx_DisposeOverlay(OOP_Object *gfxHidd, OOP_Object *Overlay)
3996 LOCATION
3997 hidd.graphics.graphics
3999 FUNCTION
4000 Deletes an overlay previously created by moHidd_Gfx_NewOverlay.
4002 Subclasses do not have to override this method
4003 unless they allocate anything additional to an overlay object in
4004 their HIDD_Gfx_NewOverlay() implementation.
4006 INPUTS
4007 gfxHidd - A driver object which was used for creating a GC.
4008 Overlay - Pointer to an overlay object to delete.
4010 RESULT
4011 None.
4013 NOTES
4015 EXAMPLE
4017 BUGS
4019 SEE ALSO
4020 moHidd_Gfx_NewGC
4022 INTERNALS
4023 Basically just does OOP_DisposeObject(Overlay);
4025 *****************************************************************************************/
4027 VOID GFX__Hidd_Gfx__DisposeOverlay(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_DisposeOverlay *msg)
4029 struct Library *OOPBase = CSD(cl)->cs_OOPBase;
4030 OOP_DisposeObject(msg->Overlay);
4033 /*****************************************************************************************
4035 NAME
4036 moHidd_Gfx_MakeViewPort
4038 SYNOPSIS
4039 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_MakeViewPort *msg);
4041 ULONG HIDD_Gfx_MakeViewPort(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data)
4043 LOCATION
4044 hidd.graphics.graphics
4046 FUNCTION
4047 Performs driver-specific setup on a given ViewPort.
4049 INPUTS
4050 gfxHidd - A display driver object.
4051 data - a pointer to a HIDD_ViewPortData structure.
4053 RESULT
4054 The same code as used as return value for graphics.library/MakeVPort().
4056 NOTES
4057 When graphics.library calls this method, a complete view is not built yet.
4058 This means that data->Next pointer contains invalid data and needs to be
4059 ignored.
4061 It is valid to keep private data pointer in data->UserData accross calls.
4062 Newly created HIDD_ViewPortData is guraranteed to have NULL there.
4064 EXAMPLE
4066 BUGS
4068 SEE ALSO
4069 moHidd_Gfx_CleanViewPort
4071 INTERNALS
4072 Base class implementation just does nothing. This function is mainly intended
4073 to provide support for copperlist maintenance by Amiga(tm) chipset driver.
4075 *****************************************************************************************/
4077 ULONG GFX__Hidd_Gfx__MakeViewPort(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_MakeViewPort *msg)
4079 D(bug("Gfx::MakeViewPort: object 0x%p, data 0x%p\n", o, msg->Data));
4081 return MVP_OK;
4084 /*****************************************************************************************
4086 NAME
4087 moHidd_Gfx_CleanViewPort
4089 SYNOPSIS
4090 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_CleanViewPort *msg);
4092 ULONG HIDD_Gfx_CleanViewPort(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data)
4094 LOCATION
4095 hidd.graphics.graphics
4097 FUNCTION
4098 Performs driver-specific cleanup on a given ViewPort.
4100 INPUTS
4101 gfxHidd - A display driver object.
4102 data - a pointer to a HIDD_ViewPortDats structure.
4104 RESULT
4105 The same code as used as return value for graphics.library/MakeVPort().
4107 NOTES
4108 When graphics.library calls this method, the ViewPort is already unlinked
4109 from its view, and the bitmap can already be deallocated.
4110 This means that both data->Next and data->Bitmap pointers can contain invalid
4111 values.
4113 EXAMPLE
4115 BUGS
4117 SEE ALSO
4118 moHidd_Gfx_MakeViewPort
4120 INTERNALS
4121 Base class implementation just does nothing. This function is mainly intended
4122 to provide support for copperlist disposal by Amiga(tm) chipset driver.
4124 *****************************************************************************************/
4126 void GFX__Hidd_Gfx__CleanViewPort(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CleanViewPort *msg)
4128 D(bug("Gfx::CleanViewPort: object 0x%p, data 0x%p\n", o, msg->Data));
4131 /*****************************************************************************************
4133 NAME
4134 moHidd_Gfx_PrepareViewPorts
4136 SYNOPSIS
4137 ULONG OOP_DoMethod(OOP_Object *obj, struct pHidd_Gfx_PrepareViewPorts *msg);
4139 ULONG HIDD_Gfx_PrepareViewPorts(OOP_Object *gfxHidd, struct HIDD_ViewPortData *data, struct View *view)
4141 LOCATION
4142 hidd.graphics.graphics
4144 FUNCTION
4145 Performs driver-specific setup on a given view.
4147 INPUTS
4148 gfxHidd - A display driver object.
4149 data - a pointer to a chain of HIDD_ViewPortData structures.
4150 view - A pointer to graphics.library View structure being prepared.
4152 RESULT
4153 MCOP_OK if there was no error or MCOP_NO_MEM otherwise.
4154 MCOP_NOP is not allowed as a return value of this method.
4156 NOTES
4157 graphics.library calls this method in MrgCop() after the complete view
4158 is built. data->Next pointer contains valid data.
4160 This function can be repeatedly called several times, and there is no
4161 cleanup counterpart for it. This should be taken into account in method
4162 implementation.
4164 EXAMPLE
4166 BUGS
4168 SEE ALSO
4170 INTERNALS
4171 Base class implementation just does nothing. This function is mainly intended
4172 to provide support for copperlist maintenance by Amiga(tm) chipset driver.
4174 *****************************************************************************************/
4176 ULONG GFX__Hidd_Gfx__PrepareViewPorts(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_ShowViewPorts *msg)
4178 return MCOP_OK;
4181 /****************************************************************************************/
4183 /* This is a private nonvirtual method */
4184 void GFX__Hidd_Gfx__UpdateBitMap(OOP_Class *cl, OOP_Object *o, OOP_Object *bm,
4185 struct pHidd_BitMap_UpdateRect *msg, struct Rectangle *display)
4187 struct HIDDGraphicsData *data = OOP_INST_DATA(cl, o);
4190 * We check data->shownbm twice in order to avoid unnecessary locking
4191 * when our bitmap is not on display (it may be not displayable at all).
4192 * However the second check is still needed in order to make sure that
4193 * this bitmap is still on display, because we could be preempted between
4194 * the test and ObtainSemaphore() by concurrently running Show() call.
4195 * We use shared lock because it's safe to have two concurrently running
4196 * updates even on the same region.
4198 if ((data->fbmode == vHidd_FrameBuffer_Mirrored) && (bm == data->shownbm))
4200 ObtainSemaphoreShared(&data->fbsem);
4202 if (bm == data->shownbm)
4205 * Complete update rectangle.
4206 * Display rectangle is already in bitmap's coordinates.
4208 UWORD srcX = msg->x;
4209 UWORD srcY = msg->y;
4210 UWORD xLimit = srcX + msg->width;
4211 UWORD yLimit = srcY + msg->height;
4213 /* Intersect rectangles */
4214 if (display->MinX > srcX)
4215 srcX = display->MinX;
4216 if (display->MinY > srcY)
4217 srcY = display->MinY;
4218 if (display->MaxX < xLimit)
4219 xLimit = display->MaxX;
4220 if (display->MaxY < yLimit)
4221 yLimit = display->MaxY;
4223 if ((xLimit > srcX) && (yLimit > srcY))
4225 HIDD_Gfx_CopyBox(o, bm, srcX, srcY,
4226 data->framebuffer, srcX - display->MinX, srcY - display->MinY,
4227 xLimit - srcX, yLimit - srcY, data->gc);
4231 ReleaseSemaphore(&data->fbsem);
4235 #undef csd
4237 /****************************************************************************************/
4239 static ULONG ObtainAttrBases(OOP_AttrBase *bases, CONST_STRPTR const *interfaces, ULONG count, struct Library *OOPBase)
4241 ULONG i;
4242 ULONG failed = 0;
4244 for (i = 0; i < count; i++)
4246 bases[i] = OOP_ObtainAttrBase(interfaces[i]);
4247 if (!bases[i])
4248 failed++;
4251 return failed;
4254 static void ReleaseAttrBases(OOP_AttrBase *bases, CONST_STRPTR const *interfaces, ULONG count, struct Library *OOPBase)
4256 ULONG i;
4258 for (i = 0; i < count; i++)
4260 if (bases[i])
4261 OOP_ReleaseAttrBase(interfaces[i]);
4265 static ULONG GetMethodBases(OOP_MethodID *bases, CONST_STRPTR const *interfaces, ULONG count, struct Library *OOPBase)
4267 ULONG i;
4268 ULONG failed = 0;
4270 for (i = 0; i < count; i++)
4272 bases[i] = OOP_GetMethodID(interfaces[i], 0);
4273 if (bases[i] == -1)
4274 failed++;
4277 return failed;
4280 static const CONST_STRPTR interfaces[NUM_ATTRBASES] =
4282 IID_Hidd_BitMap,
4283 IID_Hidd_Gfx,
4284 IID_Hidd_GC,
4285 IID_Hidd_ColorMap,
4286 IID_Hidd_Overlay,
4287 IID_Hidd_Sync,
4288 IID_Hidd_PixFmt,
4289 IID_Hidd_PlanarBM,
4290 IID_Hidd_ChunkyBM,
4293 static int GFX_ClassInit(LIBBASETYPEPTR LIBBASE)
4295 struct class_static_data *csd = &LIBBASE->hdg_csd;
4296 struct Library *OOPBase = csd->cs_OOPBase;
4298 if (!(csd->cs_UtilityBase = TaggedOpenLibrary(TAGGEDOPEN_UTILITY)))
4300 ReturnInt("init_gfxhiddclass", ULONG, FALSE);
4303 if (ObtainAttrBases(csd->attrBases, interfaces, NUM_ATTRBASES, OOPBase))
4305 ReturnInt("init_gfxhiddclass", ULONG, FALSE);
4308 if (GetMethodBases(csd->methodBases, interfaces, NUM_METHODBASES, OOPBase))
4310 ReturnInt("init_gfxhiddclass", ULONG, FALSE);
4313 D(bug("Creating std pixelfmts\n"));
4314 ReturnInt("init_gfxhiddclass", ULONG, create_std_pixfmts(csd));
4317 /****************************************************************************************/
4319 static int GFX_ClassFree(LIBBASETYPEPTR LIBBASE)
4321 struct class_static_data *csd = &LIBBASE->hdg_csd;
4322 struct Library *OOPBase = csd->cs_OOPBase;
4324 EnterFunc(bug("free_gfxhiddclass(csd=%p)\n", csd));
4326 delete_pixfmts(csd);
4327 ReleaseAttrBases(csd->attrBases, interfaces, NUM_ATTRBASES, OOPBase);
4328 CloseLibrary(csd->cs_UtilityBase);
4330 ReturnInt("free_gfxhiddclass", BOOL, TRUE);
4333 /****************************************************************************************/
4335 ADD2INITLIB(GFX_ClassInit, 0)
4336 ADD2EXPUNGELIB(GFX_ClassFree, 0)
4338 /****************************************************************************************/
4340 /* Since the shift/mask values of a pixel format are designed for pixel
4341 access, not byte access, they are endianess dependant */
4343 #if AROS_BIG_ENDIAN
4344 #include "stdpixfmts_be.h"
4345 #else
4346 #include "stdpixfmts_le.h"
4347 #endif
4349 /****************************************************************************************/
4351 static BOOL create_std_pixfmts(struct class_static_data *csd)
4353 ULONG i;
4354 struct pixfmt_data *pf;
4356 memset(csd->std_pixfmts, 0, sizeof (OOP_Object *) * num_Hidd_StdPixFmt);
4358 for (i = 0; i < num_Hidd_StdPixFmt; i ++)
4360 pf = (struct pixfmt_data *)create_and_init_object(csd->pixfmtclass, (UBYTE *)&stdpfs[i], sizeof (stdpfs[i]), csd);
4362 if (!pf)
4364 D(bug("FAILED TO CREATE PIXEL FORMAT %d\n", i));
4365 delete_pixfmts(csd);
4366 ReturnBool("create_stdpixfmts", FALSE);
4369 csd->std_pixfmts[i] = &pf->pf;
4370 /* We don't use semaphore protection here because we do this only during class init stage */
4371 pf->refcount = 1;
4372 AddTail((struct List *)&csd->pflist, (struct Node *)&pf->node);
4374 ReturnBool("create_stdpixfmts", TRUE);
4377 /****************************************************************************************/
4379 static VOID delete_pixfmts(struct class_static_data *csd)
4381 struct Node *n, *safe;
4382 struct Library *OOPBase = csd->cs_OOPBase;
4384 ForeachNodeSafe(&csd->pflist, n, safe)
4385 OOP_DisposeObject((OOP_Object *)PIXFMT_OBJ(n));
4388 /****************************************************************************************/
4390 static inline BOOL cmp_pfs(HIDDT_PixelFormat *tmppf, HIDDT_PixelFormat *dbpf)
4392 /* Just compare everything except stdpixfmt */
4393 /* Compare flags first (because it's a fast check) */
4394 if (tmppf->flags != dbpf->flags)
4395 return FALSE;
4396 /* If they match, compare the rest of things */
4397 return !memcmp(tmppf, dbpf, offsetof(HIDDT_PixelFormat, stdpixfmt));
4400 /****************************************************************************************/
4403 Parses the tags supplied in 'tags' and puts the result into 'pf'.
4404 It also checks to see if all needed attrs are supplied.
4405 It uses 'attrcheck' for this, so you may find attrs outside
4406 of this function, and mark them as found before calling this function
4409 #define PFAF(x) (1L << aoHidd_PixFmt_ ## x)
4410 #define PF_COMMON_AF ( PFAF(Depth) | PFAF(BitsPerPixel) | PFAF(BytesPerPixel) \
4411 | PFAF(ColorModel) | PFAF(BitMapType) )
4413 #define PF_TRUECOLOR_AF ( PFAF(RedMask) | PFAF(GreenMask) | PFAF(BlueMask) | PFAF(AlphaMask) | \
4414 PFAF(RedShift) | PFAF(GreenShift) | PFAF(BlueShift) | PFAF(AlphaShift))
4416 #define PF_PALETTE_AF ( PFAF(CLUTMask) | PFAF(CLUTShift) | PFAF(RedMask) | PFAF(GreenMask) | \
4417 PFAF(BlueMask) )
4419 #define PFAO(x) (aoHidd_PixFmt_ ## x)
4421 /****************************************************************************************/
4423 BOOL parse_pixfmt_tags(struct TagItem *tags, HIDDT_PixelFormat *pf,
4424 ULONG ATTRCHECK(pixfmt), struct class_static_data *csd)
4426 IPTR attrs[num_Hidd_PixFmt_Attrs] = {0};
4427 struct Library *OOPBase = csd->cs_OOPBase;
4429 if (0 != OOP_ParseAttrs(tags, attrs, num_Hidd_PixFmt_Attrs,
4430 &ATTRCHECK(pixfmt), HiddPixFmtAttrBase))
4432 D(bug("!!! parse_pixfmt_tags: ERROR PARSING TAGS THROUGH OOP_ParseAttrs !!!\n"));
4433 return FALSE;
4436 if (PF_COMMON_AF != (PF_COMMON_AF & ATTRCHECK(pixfmt)))
4438 D(bug("!!! parse_pixfmt_tags: Missing PixFmt attributes passed to parse_pixfmt_tags(): %x !!!\n", ATTRCHECK(pixfmt)));
4439 return FALSE;
4442 /* Set the common attributes */
4443 pf->depth = attrs[PFAO(Depth)];
4444 pf->size = attrs[PFAO(BitsPerPixel)];
4445 pf->bytes_per_pixel = attrs[PFAO(BytesPerPixel)];
4446 /* Fill in only real StdPixFmt specification. Special values (Native and Native32)
4447 are not allowed here */
4448 if (attrs[PFAO(StdPixFmt)] >= num_Hidd_PseudoStdPixFmt)
4449 pf->stdpixfmt = attrs[PFAO(StdPixFmt)];
4451 SET_PF_COLMODEL( pf, attrs[PFAO(ColorModel)]);
4452 SET_PF_BITMAPTYPE(pf, attrs[PFAO(BitMapType)]);
4454 if (ATTRCHECK(pixfmt) & PFAF(SwapPixelBytes))
4456 SET_PF_SWAPPIXELBYTES_FLAG(pf, attrs[PFAO(SwapPixelBytes)]);
4459 /* Set the colormodel specific stuff */
4460 switch (HIDD_PF_COLMODEL(pf))
4462 case vHidd_ColorModel_TrueColor:
4463 /* Check that we got all the truecolor describing stuff */
4464 if (PF_TRUECOLOR_AF != (PF_TRUECOLOR_AF & ATTRCHECK(pixfmt)))
4466 D(bug("!!! Unsufficient true color format describing attrs to pixfmt in parse_pixfmt_tags() !!!\n"));
4467 return FALSE;
4470 /* Set the truecolor stuff */
4471 pf->red_mask = attrs[PFAO(RedMask)];
4472 pf->green_mask = attrs[PFAO(GreenMask)];
4473 pf->blue_mask = attrs[PFAO(BlueMask)];
4474 pf->alpha_mask = attrs[PFAO(AlphaMask)];
4476 pf->red_shift = attrs[PFAO(RedShift)];
4477 pf->green_shift = attrs[PFAO(GreenShift)];
4478 pf->blue_shift = attrs[PFAO(BlueShift)];
4479 pf->alpha_shift = attrs[PFAO(AlphaShift)];
4480 break;
4482 case vHidd_ColorModel_Palette:
4483 case vHidd_ColorModel_StaticPalette:
4484 if ( PF_PALETTE_AF != (PF_PALETTE_AF & ATTRCHECK(pixfmt)))
4486 D(bug("!!! Unsufficient palette format describing attrs to pixfmt in parse_pixfmt_tags() !!!\n"));
4487 return FALSE;
4490 /* set palette stuff */
4491 pf->clut_mask = attrs[PFAO(CLUTMask)];
4492 pf->clut_shift = attrs[PFAO(CLUTShift)];
4494 pf->red_mask = attrs[PFAO(RedMask)];
4495 pf->green_mask = attrs[PFAO(GreenMask)];
4496 pf->blue_mask = attrs[PFAO(BlueMask)];
4498 break;
4500 } /* shift (colormodel) */
4502 return TRUE;
4505 /****************************************************************************************/
4508 Create an empty object and initialize it the "ugly" way. This only works with
4509 CLID_Hidd_PixFmt and CLID_Hidd_Sync classes
4512 /****************************************************************************************/
4514 static OOP_Object *create_and_init_object(OOP_Class *cl, UBYTE *data, ULONG datasize,
4515 struct class_static_data *csd)
4517 OOP_Object *o;
4518 struct Library *OOPBase = csd->cs_OOPBase;
4520 o = OOP_NewObject(cl, NULL, NULL);
4521 if (NULL == o)
4523 D(bug("!!! UNABLE TO CREATE OBJECT IN create_and_init_object() !!!\n"));
4524 return NULL;
4527 memcpy(o, data, datasize);
4529 return o;
4532 /****************************************************************************************/
4534 static struct pixfmt_data *find_pixfmt(HIDDT_PixelFormat *tofind, struct class_static_data *csd)
4536 struct pixfmt_data *retpf = NULL;
4537 HIDDT_PixelFormat *db_pf;
4538 struct Node *n;
4540 /* Go through the pixel format list to see if a similar pf allready exists */
4541 ObtainSemaphoreShared(&csd->pfsema);
4543 ForeachNode(&csd->pflist, n)
4545 db_pf = PIXFMT_OBJ(n);
4546 DPF(bug("find_pixfmt(): Trying pixelformat 0x%p\n", db_pf));
4547 DPF(bug("(%d, %d, %d, %d), (%x, %x, %x, %x), %d, %d, %d, %d\n",
4548 db_pf->red_shift, db_pf->green_shift, db_pf->blue_shift, db_pf->alpha_shift,
4549 db_pf->red_mask, db_pf->green_mask, db_pf->blue_mask, db_pf->alpha_mask,
4550 db_pf->bytes_per_pixel, db_pf->size, db_pf->depth, db_pf->stdpixfmt));
4551 if (cmp_pfs(tofind, db_pf))
4553 DPF(bug("Match!\n"));
4554 retpf = (struct pixfmt_data *)db_pf;
4555 break;
4559 ReleaseSemaphore(&csd->pfsema);
4560 return retpf;