2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Graphics function GetDisplayInfoData()
9 #include <aros/debug.h>
10 #include <proto/graphics.h>
11 #include <graphics/displayinfo.h>
12 #include <hidd/graphics.h>
13 #include <proto/oop.h>
17 #include "graphics_intern.h"
18 #include "compositing_driver.h"
21 /****************************************************************************************/
23 static const ULONG size_checks
[] =
25 sizeof(struct DisplayInfo
),
26 sizeof(struct DimensionInfo
),
27 sizeof(struct MonitorInfo
),
28 sizeof(struct NameInfo
),
33 static ULONG
check_sizes(ULONG tagID
, ULONG size
);
34 static UBYTE
popcount(IPTR x
);
36 #define DLONGSZ (sizeof (ULONG) * 2)
37 #define DTAG_TO_IDX(dtag) (((dtag) & 0x7FFFF000) >> 12)
39 /*****************************************************************************
42 #include <proto/graphics.h>
44 AROS_LH5(ULONG
, GetDisplayInfoData
,
47 AROS_LHA(DisplayInfoHandle
, handle
, A0
),
48 AROS_LHA(UBYTE
*, buf
, A1
),
49 AROS_LHA(ULONG
, size
, D0
),
50 AROS_LHA(ULONG
, tagID
, D1
),
51 AROS_LHA(ULONG
, ID
, D2
),
54 struct GfxBase
*, GfxBase
, 126, Graphics
)
57 Fills buffer with information about displayinfo handle.
60 handle - displayinfo handle
61 buf - pointer to destination buffer
62 size - buffer size in bytes
63 tagID - data chunk type
64 DTAG_DISP (DisplayInfo)
65 DTAG_DIMS (DimensionInfo)
66 DTAG_MNTR (MonitorInfo)
68 ID - displayinfo identifier, optionally used if handle is NULL
71 result - if positive, number of bytes actually transferred
72 if zero, no information for ID was available
81 FindDisplayInfo(), NextDisplayInfo(), graphics/displayinfo.h
84 This function provides private data in reserved fields of DimensionInfo.
85 It is required by other AROS components. Please keep this in sync when
90 ******************************************************************************/
94 struct QueryHeader
*qh
;
96 OOP_Object
*gfxhidd
, *sync
, *pf
;
97 HIDDT_ModeID hiddmode
;
98 struct HIDD_ModeProperties HIDDProps
= {0};
102 /* FindDisplayInfo() handles INVALID_ID itself */
103 handle
= FindDisplayInfo(ID
);
108 * ID is likely INVALID_ID, but we need its value.
109 * Get it from the handle.
111 ID
= DIH(handle
)->id
| DIH(handle
)->drv
->id
;
116 D(bug("!!! COULD NOT GET HANDLE IN GetDisplayInfoData()\n"));
120 gfxhidd
= DIH(handle
)->drv
->gfxhidd
;
121 hiddmode
= DIH(handle
)->id
;
123 /* Get mode info from the HIDD */
124 if (!HIDD_Gfx_GetMode(gfxhidd
, hiddmode
, &sync
, &pf
))
126 D(bug("NO VALID MODE PASSED TO GetDisplayInfoData() !!!\n"));
130 D(bug("GetDisplayInfoData(handle=%d, tagID=%x)\n"
131 , (ULONG
)handle
, tagID
));
133 /* Build the queryheader */
134 structsize
= check_sizes(tagID
, size
);
137 qh
= AllocMem(structsize
, MEMF_CLEAR
);
141 /* Fill in the queryheader */
142 qh
->StructID
= tagID
;
144 qh
->SkipID
= TAG_SKIP
;
146 qh
->Length
= (structsize
+ (DLONGSZ
- 1)) / DLONGSZ
;
152 struct DisplayInfo
*di
;
153 const struct MonitorSpec
*ms
;
154 IPTR redmask
, greenmask
, bluemask
;
158 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&ms
);
159 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
160 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
161 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
163 di
= (struct DisplayInfo
*)qh
;
165 /* All modes returned from the HIDD are available */
166 di
->NotAvailable
= FALSE
;
169 * Set the propertyflags. We always set DIPF_IS_SPRITES because we always emulate
170 * one sprite for mouse pointer.
172 di
->PropertyFlags
= DIPF_IS_SPRITES
| HIDDProps
.DisplayInfoFlags
;
176 * All non-planar modes are considered Workbench-compatible. This is done
177 * for compatibility with existing RTG drivers which never set this flag themselves.
178 * This can be considered historical, in initial API design HIDD_Gfx_ModeProperties()
179 * did not exist at all and this flag was simply always set.
180 * In fact all modes can be considered Workbench-compatible. This flag is
181 * known to be used by original AmigaOS screenmode prefs program to filter out
182 * some modes. This program has many replacement which do not obey this flag,
183 * enabling opening Workbench on HAM screen for example.
184 * But we delegate setting this flag to the driver for planar modes. We do it
185 * for 100% compatibility of chipset driver. What if some m68k program has its own
186 * weird assumptions about this bit ?
187 * One more thing to note: we don't set DIPF_IS_FOREIGN bit. It is actually used
188 * only by Picasso96 and only for modes that are not graphics.library compatible.
189 * Many m68k RTG games rely on this flag not being set.
191 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &val
);
192 if (val
!= vHidd_StdPixFmt_Plane
)
193 di
->PropertyFlags
|= DIPF_IS_WB
;
195 /* Compute red green and blue bits */
196 OOP_GetAttr(pf
, aHidd_PixFmt_RedMask
, &redmask
);
197 OOP_GetAttr(pf
, aHidd_PixFmt_GreenMask
, &greenmask
);
198 OOP_GetAttr(pf
, aHidd_PixFmt_BlueMask
, &bluemask
);
200 /* Use gcc builtin function */
201 /* weissms: do not use, can cause undefined symbol _GLOBAL_OFFSET_TABLE_
202 * should work if we use a real cross compiler with static libgcc
203 di->RedBits = __builtin_popcount(redmask);
204 di->GreenBits = __builtin_popcount(greenmask);
205 di->BlueBits = __builtin_popcount(bluemask);
208 di
->RedBits
= popcount(redmask
);
209 di
->GreenBits
= popcount(greenmask
);
210 di
->BlueBits
= popcount(bluemask
);
213 * If number of colors is too large, PaletteRange is set to 65535.
214 * This is the behavior of original AmigaOS(tm).
216 val
= di
->RedBits
* di
->GreenBits
* di
->BlueBits
;
217 di
->PaletteRange
= (val
> 65535) ? 65535 : val
;
219 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &val
);
220 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &val
);
223 * Display resolution in ticks
225 di
->Resolution
.x
= (1280 * 11 * ms
->ratioh
/ width
) >> RATIO_FIXEDPART
;
226 di
->Resolution
.y
= (1024 * 11 * ms
->ratiov
/ height
) >> RATIO_FIXEDPART
;
229 di
->PixelSpeed
= 1000000000 / val
;
232 * If the driver says it does not support sprites, we return one sprite.
233 * We emulate it by software in such a case because it's necessary for
236 di
->NumStdSprites
= (HIDDProps
.DisplayInfoFlags
& DIPF_IS_SPRITES
) ? HIDDProps
.NumHWSprites
: 1;
238 /* At the moment sprites always have the same resolution as display */
239 di
->SpriteResolution
= di
->Resolution
;
246 struct DimensionInfo
*di
;
247 IPTR depth
, width
, height
;
248 IPTR minwidth
, minheight
;
249 IPTR maxwidth
, maxheight
;
251 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
252 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
253 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
254 OOP_GetAttr(sync
, aHidd_Sync_HMin
, &minwidth
);
255 OOP_GetAttr(sync
, aHidd_Sync_VMin
, &minheight
);
256 OOP_GetAttr(sync
, aHidd_Sync_HMax
, &maxwidth
);
257 OOP_GetAttr(sync
, aHidd_Sync_VMax
, &maxheight
);
259 di
= (struct DimensionInfo
*)qh
;
260 di
->MaxDepth
= depth
;
262 di
->MinRasterWidth
= minwidth
;
263 di
->MinRasterHeight
= minheight
;
264 di
->MaxRasterWidth
= maxwidth
;
265 di
->MaxRasterHeight
= maxheight
;
267 di
->Nominal
.MinX
= 0;
268 di
->Nominal
.MinY
= 0;
269 di
->Nominal
.MaxX
= width
- 1;
270 di
->Nominal
.MaxY
= height
- 1;
272 di
->MaxOScan
= di
->Nominal
;
273 di
->VideoOScan
= di
->Nominal
;
274 di
->TxtOScan
= di
->Nominal
;
275 di
->StdOScan
= di
->Nominal
;
277 * FIXME: our graphics subsystem does not have overscan API.
278 di->MaxOScan.MinX = di->Nominal.MinX;
279 di->MaxOScan.MinY = di->Nominal.MinY;
280 di->MaxOScan.MaxX = di->Nominal.MaxX;
281 di->MaxOScan.MaxY = di->Nominal.MaxY;
283 di->VideoOScan.MinX = di->Nominal.MinX;
284 di->VideoOScan.MinY = di->Nominal.MinY;
285 di->VideoOScan.MaxX = di->Nominal.MaxX;
286 di->VideoOScan.MaxY = di->Nominal.MaxY;
288 di->TxtOScan.MinX = di->Nominal.MinX;
289 di->TxtOScan.MinY = di->Nominal.MinY;
290 di->TxtOScan.MaxX = di->Nominal.MaxX;
291 di->TxtOScan.MaxY = di->Nominal.MaxY;
293 di->StdOScan.MinX = di->Nominal.MinX;
294 di->StdOScan.MinY = di->Nominal.MinY;
295 di->StdOScan.MaxX = di->Nominal.MaxX;
296 di->StdOScan.MaxY = di->Nominal.MaxY;
300 * reserved[0] is HIDD composition flags for intuition.library/OpenScreen().
301 * It can't be done in another way because only we (graphics.library) know about existence
302 * of software screen composition.
304 if (DIH(handle
)->drv
->composer
)
306 OOP_GetAttr(DIH(handle
)->drv
->composer
, aHidd_Compositing_Capabilities
, &di
->reserved
[0]);
310 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
311 di
->reserved
[0] = HIDDProps
.CompositionFlags
;
314 /* This is for cybergraphics.library */
315 di
->reserved
[1] = (IPTR
)pf
;
322 struct MonitorInfo
*mi
= (struct MonitorInfo
*)qh
;
325 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&mi
->Mspc
);
326 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
327 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
330 mi->ViewPosition.X = ?;
331 mi->ViewPosition.Y = ?;
332 mi->ViewResolution.X = ?;
333 mi->ViewResolution.Y = ?;
335 mi->MouseTicks.X = ?;
336 mi->MouseTicks.Y = ?;
337 mi->DefaultViewPosition.X = ?;
338 mi->DefaultViewPosition.Y = ?;
341 /* Resolution in ticks
343 mi
->ViewResolution
.x
= (1280 * 11 * mi
->Mspc
->ratioh
/ width
) >> RATIO_FIXEDPART
;
344 mi
->ViewResolution
.y
= (1024 * 11 * mi
->Mspc
->ratiov
/ height
) >> RATIO_FIXEDPART
;
348 mi
->TotalRows
= mi
->Mspc
->total_rows
;
349 mi
->TotalColorClocks
= mi
->Mspc
->total_colorclocks
;
350 mi
->ViewPositionRange
= mi
->Mspc
->ms_LegalView
;
354 * FIXME: For now we don't have a concept of preferred ModeID.
355 * However, see graphics_driver.c/driver_Setup(), it can be useful.
357 mi
->PreferredModeID
= ID
;
359 if (DIH(handle
)->drv
->composer
)
362 * If we have software screen composition, we know we can compose.
363 * We use MCOMPAT_MIXED here because of changed understanding of what is "monitor".
364 * In AmigaOS(tm) a "monitor" is actually a sync (video mode). Different "monitors"
365 * are actually different modes of the same display (PAL, NTSC, VGA, etc).
366 * In AROS a "monitor" is a single physical display device. Of course we can do
367 * composition only on a single display, but we can compose together different
370 mi
->Compatibility
= MCOMPAT_MIXED
;
374 /* Otherwise query the driver */
375 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
377 if (HIDDProps
.CompositionFlags
)
378 mi
->Compatibility
= (HIDDProps
.CompositionFlags
& COMPF_SAME
) ? MCOMPAT_SELF
: MCOMPAT_MIXED
;
380 mi
->Compatibility
= MCOMPAT_NOBODY
;
389 IPTR depth
, stdpixfmt
;
390 STRPTR sync_description
;
392 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
393 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &stdpixfmt
);
395 OOP_GetAttr(sync
, aHidd_Sync_Description
, (IPTR
*)&sync_description
);
396 ni
= (struct NameInfo
*)qh
;
398 if (sync_description
&& sync_description
[0] &&
399 (IS_REAL_STDPIXFMT(stdpixfmt
) || (stdpixfmt
== vHidd_StdPixFmt_Unknown
)))
401 STRPTR pixfmt_name
= "";
405 case vHidd_StdPixFmt_RGB16
:
406 case vHidd_StdPixFmt_RGB15
:
407 case vHidd_StdPixFmt_RGB24
:
411 case vHidd_StdPixFmt_RGB16_LE
:
412 case vHidd_StdPixFmt_RGB15_LE
:
413 pixfmt_name
= "RGB PC";
416 case vHidd_StdPixFmt_BGR24
:
417 case vHidd_StdPixFmt_BGR16
:
418 case vHidd_StdPixFmt_BGR15
:
422 case vHidd_StdPixFmt_BGR16_LE
:
423 case vHidd_StdPixFmt_BGR15_LE
:
424 pixfmt_name
= "BGR PC";
427 case vHidd_StdPixFmt_ARGB32
:
428 pixfmt_name
= "ARGB";
431 case vHidd_StdPixFmt_BGRA32
:
432 pixfmt_name
= "BGRA";
435 case vHidd_StdPixFmt_RGBA32
:
436 pixfmt_name
= "RGBA";
439 case vHidd_StdPixFmt_0RGB32
:
440 pixfmt_name
= "0RGB";
443 case vHidd_StdPixFmt_BGR032
:
444 pixfmt_name
= "BGR0";
447 case vHidd_StdPixFmt_RGB032
:
448 pixfmt_name
= "RGB0";
452 if (stdpixfmt
!= vHidd_StdPixFmt_Plane
)
453 snprintf(ni
->Name
, DISPLAYNAMELEN
, "%s %2dbit %s",
454 sync_description
, (int)depth
, pixfmt_name
);
456 strncpy(ni
->Name
, sync_description
, DISPLAYNAMELEN
);
463 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
464 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
465 snprintf(ni
->Name
, DISPLAYNAMELEN
, "AROS: %ldx%ldx%ld", width
, height
, depth
);
471 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
475 D(bug("GDID: %d\n", structsize
));
477 if (size
> structsize
)
479 CopyMem(qh
, buf
, size
);
480 FreeMem(qh
, structsize
);
481 /* NULL-terminate the name in case if it was trimmed */
482 if (tagID
== DTAG_NAME
)
489 } /* GetDisplayInfoData */
491 /****************************************************************************************/
493 static ULONG
check_sizes(ULONG tagID
, ULONG size
)
497 idx
= DTAG_TO_IDX(tagID
);
501 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
505 return size_checks
[idx
];
508 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
509 static UBYTE
popcount(IPTR x
) {
511 for (count
=0; x
; count
++)