2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Graphics function GetDisplayInfoData()
11 #include <aros/debug.h>
12 #include <proto/graphics.h>
13 #include <graphics/displayinfo.h>
14 #include <hidd/graphics.h>
15 #include <proto/oop.h>
19 #include "graphics_intern.h"
20 #include "compositing_driver.h"
23 /****************************************************************************************/
25 static const ULONG size_checks
[] =
27 sizeof(struct DisplayInfo
),
28 sizeof(struct DimensionInfo
),
29 sizeof(struct MonitorInfo
),
30 sizeof(struct NameInfo
),
35 static ULONG
check_sizes(ULONG tagID
, ULONG size
);
36 static UBYTE
popcount(IPTR x
);
38 #define DLONGSZ (sizeof (ULONG) * 2)
39 #define DTAG_TO_IDX(dtag) (((dtag) & 0x7FFFF000) >> 12)
41 /*****************************************************************************
44 #include <proto/graphics.h>
46 AROS_LH5(ULONG
, GetDisplayInfoData
,
49 AROS_LHA(DisplayInfoHandle
, handle
, A0
),
50 AROS_LHA(UBYTE
*, buf
, A1
),
51 AROS_LHA(ULONG
, size
, D0
),
52 AROS_LHA(ULONG
, tagID
, D1
),
53 AROS_LHA(ULONG
, ID
, D2
),
56 struct GfxBase
*, GfxBase
, 126, Graphics
)
59 Fills buffer with information about displayinfo handle.
62 handle - displayinfo handle
63 buf - pointer to destination buffer
64 size - buffer size in bytes
65 tagID - data chunk type
66 DTAG_DISP (DisplayInfo)
67 DTAG_DIMS (DimensionInfo)
68 DTAG_MNTR (MonitorInfo)
70 ID - displayinfo identifier, optionally used if handle is NULL
73 result - if positive, number of bytes actually transferred
74 if zero, no information for ID was available
83 FindDisplayInfo(), NextDisplayInfo(), graphics/displayinfo.h
86 This function provides private data in reserved fields of DimensionInfo.
87 It is required by other AROS components. Please keep this in sync when
92 ******************************************************************************/
96 struct QueryHeader
*qh
;
98 OOP_Object
*gfxhidd
, *sync
, *pf
;
99 HIDDT_ModeID hiddmode
;
100 struct HIDD_ModeProperties HIDDProps
= {0};
104 /* FindDisplayInfo() handles INVALID_ID itself */
105 handle
= FindDisplayInfo(ID
);
110 * ID is likely INVALID_ID, but we need its value.
111 * Get it from the handle.
113 ID
= DIH(handle
)->id
| DIH(handle
)->drv
->id
;
118 D(bug("!!! COULD NOT GET HANDLE IN GetDisplayInfoData()\n"));
122 gfxhidd
= DIH(handle
)->drv
->gfxhidd
;
123 hiddmode
= DIH(handle
)->id
;
125 /* Get mode info from the HIDD */
126 if (!HIDD_Gfx_GetMode(gfxhidd
, hiddmode
, &sync
, &pf
))
128 D(bug("NO VALID MODE PASSED TO GetDisplayInfoData() !!!\n"));
132 D(bug("GetDisplayInfoData(handle=%d, tagID=%x)\n"
133 , (ULONG
)handle
, tagID
));
135 /* Build the queryheader */
136 structsize
= check_sizes(tagID
, size
);
139 qh
= AllocMem(structsize
, MEMF_CLEAR
);
143 /* Fill in the queryheader */
144 qh
->StructID
= tagID
;
146 qh
->SkipID
= TAG_SKIP
;
148 qh
->Length
= (structsize
+ (DLONGSZ
- 1)) / DLONGSZ
;
154 struct DisplayInfo
*di
;
155 const struct MonitorSpec
*ms
;
156 IPTR redmask
, greenmask
, bluemask
;
160 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&ms
);
161 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
162 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
163 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
165 di
= (struct DisplayInfo
*)qh
;
167 /* All modes returned from the HIDD are available */
168 di
->NotAvailable
= FALSE
;
171 * Set the propertyflags. We always set DIPF_IS_SPRITES because we always emulate
172 * one sprite for mouse pointer.
174 di
->PropertyFlags
= DIPF_IS_SPRITES
| HIDDProps
.DisplayInfoFlags
;
178 * All non-planar modes are considered Workbench-compatible. This is done
179 * for compatibility with existing RTG drivers which never set this flag themselves.
180 * This can be considered historical, in initial API design HIDD_Gfx_ModeProperties()
181 * did not exist at all and this flag was simply always set.
182 * In fact all modes can be considered Workbench-compatible. This flag is
183 * known to be used by original AmigaOS screenmode prefs program to filter out
184 * some modes. This program has many replacement which do not obey this flag,
185 * enabling opening Workbench on HAM screen for example.
186 * But we delegate setting this flag to the driver for planar modes. We do it
187 * for 100% compatibility of chipset driver. What if some m68k program has its own
188 * weird assumptions about this bit ?
189 * One more thing to note: we don't set DIPF_IS_FOREIGN bit. It is actually used
190 * only by Picasso96 and only for modes that are not graphics.library compatible.
191 * Many m68k RTG games rely on this flag not being set.
193 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &val
);
194 if (val
!= vHidd_StdPixFmt_Plane
)
195 di
->PropertyFlags
|= DIPF_IS_WB
;
197 /* Compute red green and blue bits */
198 OOP_GetAttr(pf
, aHidd_PixFmt_RedMask
, &redmask
);
199 OOP_GetAttr(pf
, aHidd_PixFmt_GreenMask
, &greenmask
);
200 OOP_GetAttr(pf
, aHidd_PixFmt_BlueMask
, &bluemask
);
202 /* Use gcc builtin function */
203 /* weissms: do not use, can cause undefined symbol _GLOBAL_OFFSET_TABLE_
204 * should work if we use a real cross compiler with static libgcc
205 di->RedBits = __builtin_popcount(redmask);
206 di->GreenBits = __builtin_popcount(greenmask);
207 di->BlueBits = __builtin_popcount(bluemask);
210 di
->RedBits
= popcount(redmask
);
211 di
->GreenBits
= popcount(greenmask
);
212 di
->BlueBits
= popcount(bluemask
);
215 * If number of colors is too large, PaletteRange is set to 65535.
216 * This is the behavior of original AmigaOS(tm).
218 val
= di
->RedBits
* di
->GreenBits
* di
->BlueBits
;
219 di
->PaletteRange
= (val
> 65535) ? 65535 : val
;
221 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &val
);
222 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &val
);
225 * Display resolution in ticks
227 di
->Resolution
.x
= (1280 * 11 * ms
->ratioh
/ width
) >> RATIO_FIXEDPART
;
228 di
->Resolution
.y
= (1024 * 11 * ms
->ratiov
/ height
) >> RATIO_FIXEDPART
;
231 di
->PixelSpeed
= 1000000000 / val
;
234 * If the driver says it does not support sprites, we return one sprite.
235 * We emulate it by software in such a case because it's necessary for
238 di
->NumStdSprites
= (HIDDProps
.DisplayInfoFlags
& DIPF_IS_SPRITES
) ? HIDDProps
.NumHWSprites
: 1;
240 /* At the moment sprites always have the same resolution as display */
241 di
->SpriteResolution
= di
->Resolution
;
248 struct DimensionInfo
*di
;
249 IPTR depth
, width
, height
;
250 IPTR minwidth
, minheight
;
251 IPTR maxwidth
, maxheight
;
253 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
254 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
255 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
256 OOP_GetAttr(sync
, aHidd_Sync_HMin
, &minwidth
);
257 OOP_GetAttr(sync
, aHidd_Sync_VMin
, &minheight
);
258 OOP_GetAttr(sync
, aHidd_Sync_HMax
, &maxwidth
);
259 OOP_GetAttr(sync
, aHidd_Sync_VMax
, &maxheight
);
261 di
= (struct DimensionInfo
*)qh
;
262 di
->MaxDepth
= depth
;
264 di
->MinRasterWidth
= minwidth
;
265 di
->MinRasterHeight
= minheight
;
266 di
->MaxRasterWidth
= maxwidth
;
267 di
->MaxRasterHeight
= maxheight
;
269 di
->Nominal
.MinX
= 0;
270 di
->Nominal
.MinY
= 0;
271 di
->Nominal
.MaxX
= width
- 1;
272 di
->Nominal
.MaxY
= height
- 1;
274 di
->MaxOScan
= di
->Nominal
;
275 di
->VideoOScan
= di
->Nominal
;
276 di
->TxtOScan
= di
->Nominal
;
277 di
->StdOScan
= di
->Nominal
;
279 * FIXME: our graphics subsystem does not have overscan API.
280 di->MaxOScan.MinX = di->Nominal.MinX;
281 di->MaxOScan.MinY = di->Nominal.MinY;
282 di->MaxOScan.MaxX = di->Nominal.MaxX;
283 di->MaxOScan.MaxY = di->Nominal.MaxY;
285 di->VideoOScan.MinX = di->Nominal.MinX;
286 di->VideoOScan.MinY = di->Nominal.MinY;
287 di->VideoOScan.MaxX = di->Nominal.MaxX;
288 di->VideoOScan.MaxY = di->Nominal.MaxY;
290 di->TxtOScan.MinX = di->Nominal.MinX;
291 di->TxtOScan.MinY = di->Nominal.MinY;
292 di->TxtOScan.MaxX = di->Nominal.MaxX;
293 di->TxtOScan.MaxY = di->Nominal.MaxY;
295 di->StdOScan.MinX = di->Nominal.MinX;
296 di->StdOScan.MinY = di->Nominal.MinY;
297 di->StdOScan.MaxX = di->Nominal.MaxX;
298 di->StdOScan.MaxY = di->Nominal.MaxY;
302 * reserved[0] is HIDD composition flags for intuition.library/OpenScreen().
303 * It can't be done in another way because only we (graphics.library) know about existence
304 * of software screen composition.
306 if (DIH(handle
)->drv
->composer
)
308 OOP_GetAttr(DIH(handle
)->drv
->composer
, aHidd_Compositing_Capabilities
, &di
->reserved
[0]);
312 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
313 di
->reserved
[0] = HIDDProps
.CompositionFlags
;
316 /* This is for cybergraphics.library */
317 di
->reserved
[1] = (IPTR
)pf
;
324 struct MonitorInfo
*mi
= (struct MonitorInfo
*)qh
;
327 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&mi
->Mspc
);
328 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
329 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
332 mi->ViewPosition.X = ?;
333 mi->ViewPosition.Y = ?;
334 mi->ViewResolution.X = ?;
335 mi->ViewResolution.Y = ?;
337 mi->MouseTicks.X = ?;
338 mi->MouseTicks.Y = ?;
339 mi->DefaultViewPosition.X = ?;
340 mi->DefaultViewPosition.Y = ?;
343 /* Resolution in ticks
345 mi
->ViewResolution
.x
= (1280 * 11 * mi
->Mspc
->ratioh
/ width
) >> RATIO_FIXEDPART
;
346 mi
->ViewResolution
.y
= (1024 * 11 * mi
->Mspc
->ratiov
/ height
) >> RATIO_FIXEDPART
;
350 mi
->TotalRows
= mi
->Mspc
->total_rows
;
351 mi
->TotalColorClocks
= mi
->Mspc
->total_colorclocks
;
352 mi
->ViewPositionRange
= mi
->Mspc
->ms_LegalView
;
356 * FIXME: For now we don't have a concept of preferred ModeID.
357 * However, see graphics_driver.c/driver_Setup(), it can be useful.
359 mi
->PreferredModeID
= ID
;
361 if (DIH(handle
)->drv
->composer
)
364 * If we have software screen composition, we know we can compose.
365 * We use MCOMPAT_MIXED here because of changed understanding of what is "monitor".
366 * In AmigaOS(tm) a "monitor" is actually a sync (video mode). Different "monitors"
367 * are actually different modes of the same display (PAL, NTSC, VGA, etc).
368 * In AROS a "monitor" is a single physical display device. Of course we can do
369 * composition only on a single display, but we can compose together different
372 mi
->Compatibility
= MCOMPAT_MIXED
;
376 /* Otherwise query the driver */
377 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
379 if (HIDDProps
.CompositionFlags
)
380 mi
->Compatibility
= (HIDDProps
.CompositionFlags
& COMPF_SAME
) ? MCOMPAT_SELF
: MCOMPAT_MIXED
;
382 mi
->Compatibility
= MCOMPAT_NOBODY
;
391 IPTR depth
, stdpixfmt
;
392 STRPTR sync_description
;
394 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
395 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &stdpixfmt
);
397 OOP_GetAttr(sync
, aHidd_Sync_Description
, (IPTR
*)&sync_description
);
398 ni
= (struct NameInfo
*)qh
;
400 if (sync_description
&& sync_description
[0] &&
401 (IS_REAL_STDPIXFMT(stdpixfmt
) || (stdpixfmt
== vHidd_StdPixFmt_Unknown
)))
403 STRPTR pixfmt_name
= "";
407 case vHidd_StdPixFmt_RGB16
:
408 case vHidd_StdPixFmt_RGB15
:
409 case vHidd_StdPixFmt_RGB24
:
413 case vHidd_StdPixFmt_RGB16_LE
:
414 case vHidd_StdPixFmt_RGB15_LE
:
415 pixfmt_name
= "RGB PC";
418 case vHidd_StdPixFmt_BGR24
:
419 case vHidd_StdPixFmt_BGR16
:
420 case vHidd_StdPixFmt_BGR15
:
424 case vHidd_StdPixFmt_BGR16_LE
:
425 case vHidd_StdPixFmt_BGR15_LE
:
426 pixfmt_name
= "BGR PC";
429 case vHidd_StdPixFmt_ARGB32
:
430 pixfmt_name
= "ARGB";
433 case vHidd_StdPixFmt_BGRA32
:
434 pixfmt_name
= "BGRA";
437 case vHidd_StdPixFmt_RGBA32
:
438 pixfmt_name
= "RGBA";
441 case vHidd_StdPixFmt_0RGB32
:
442 pixfmt_name
= "0RGB";
445 case vHidd_StdPixFmt_BGR032
:
446 pixfmt_name
= "BGR0";
449 case vHidd_StdPixFmt_RGB032
:
450 pixfmt_name
= "RGB0";
454 if (stdpixfmt
!= vHidd_StdPixFmt_Plane
)
455 snprintf(ni
->Name
, DISPLAYNAMELEN
, "%s %2dbit %s",
456 sync_description
, (int)depth
, pixfmt_name
);
458 strncpy(ni
->Name
, sync_description
, DISPLAYNAMELEN
);
465 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
466 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
467 snprintf(ni
->Name
, DISPLAYNAMELEN
, "AROS: %ldx%ldx%ld", width
, height
, depth
);
473 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
477 D(bug("GDID: %d\n", structsize
));
479 if (size
> structsize
)
481 CopyMem(qh
, buf
, size
);
482 FreeMem(qh
, structsize
);
483 /* NULL-terminate the name in case if it was trimmed */
484 if (tagID
== DTAG_NAME
)
491 } /* GetDisplayInfoData */
493 /****************************************************************************************/
495 static ULONG
check_sizes(ULONG tagID
, ULONG size
)
499 idx
= DTAG_TO_IDX(tagID
);
503 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
507 return size_checks
[idx
];
510 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
511 static UBYTE
popcount(IPTR x
) {
513 for (count
=0; x
; count
++)