2 Copyright © 1995-2013, 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 "compositor_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)
40 * Resolution calculation rules.
43 * ratioh, ratiov - ratio between size of a 1084S and the current monitor
44 * (larger fractions are larger monitors, smaller are smaller)
47 * Since this is related to mouse ticks, it would make sense for this
48 * calculation to be a inverse relationship to overall DPI, instead of
49 * to the number of pixels in the display.
51 * Therefore, Screen Resolution would be calculated as:
53 * res.x = (1280 * 11 * ratioh / pixel_width) >> RATIO_FIXEDPART
54 * res.y = (1024 * 11 * ratiov / pixel_height) >> RATIO_FIXEDPART
56 * Screen DPI can be directly calculated from DrawInfo Resolution as:
58 * #define C_1084_WIDTH_CIN 104 // 10.4 " in centi-inches
59 * #define C_1084_HEIGHT_CIN 78 // 7.8 " in centi-inches
61 * dpi.x = (11 * 1280 * 10) / C_1084_WIDTH_CIN / res.x
62 * dpi.y = (11 * 1024 * 10) / C_1084_HEIGHT_CIN / res.y
64 * Screen DPC (dots per centimeter) is calculated as:
66 * #define C_1084_WIDTH_MM 264 // 10.4 " in mm
67 * #define C_1084_HEIGHT_MM 198 // 7.8 " in mm
69 * dpc.x = 11 * 1280 * 10 / C_1084_WIDTH_MM / res.x
70 * dpc.y = 11 * 1024 * 10 / C_1084_HEIGHT_MM / res.y
72 * Jason S. McMullan <jason.mcmullan@gmail.com>
74 static inline void CalcScreenResolution(Point
*res
, const struct MonitorSpec
*mspc
,
75 OOP_Object
*sync
, struct GfxBase
*GfxBase
)
79 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
80 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
82 res
->x
= (1280 * 11 * mspc
->ratioh
/ width
) >> RATIO_FIXEDPART
;
83 res
->y
= (1024 * 11 * mspc
->ratiov
/ height
) >> RATIO_FIXEDPART
;
86 /*****************************************************************************
89 #include <proto/graphics.h>
91 AROS_LH5(ULONG
, GetDisplayInfoData
,
94 AROS_LHA(DisplayInfoHandle
, handle
, A0
),
95 AROS_LHA(UBYTE
*, buf
, A1
),
96 AROS_LHA(ULONG
, size
, D0
),
97 AROS_LHA(ULONG
, tagID
, D1
),
98 AROS_LHA(ULONG
, ID
, D2
),
101 struct GfxBase
*, GfxBase
, 126, Graphics
)
104 Fills buffer with information about displayinfo handle.
107 handle - displayinfo handle
108 buf - pointer to destination buffer
109 size - buffer size in bytes
110 tagID - data chunk type
111 DTAG_DISP (DisplayInfo)
112 DTAG_DIMS (DimensionInfo)
113 DTAG_MNTR (MonitorInfo)
115 ID - displayinfo identifier, optionally used if handle is NULL
118 result - if positive, number of bytes actually transferred
119 if zero, no information for ID was available
128 FindDisplayInfo(), NextDisplayInfo(), graphics/displayinfo.h
131 This function provides private data in reserved fields of DimensionInfo.
132 It is required by other AROS components. Please keep this in sync when
137 ******************************************************************************/
141 struct QueryHeader
*qh
;
143 OOP_Object
*gfxhidd
, *sync
, *pf
;
144 HIDDT_ModeID hiddmode
;
145 struct HIDD_ModeProperties HIDDProps
= {0};
149 /* FindDisplayInfo() handles INVALID_ID itself */
150 handle
= FindDisplayInfo(ID
);
155 * ID is likely INVALID_ID, but we need its value.
156 * Get it from the handle.
158 ID
= DIH(handle
)->id
| DIH(handle
)->drv
->id
;
163 D(bug("!!! COULD NOT GET HANDLE IN GetDisplayInfoData()\n"));
167 gfxhidd
= DIH(handle
)->drv
->gfxhidd
;
168 hiddmode
= DIH(handle
)->id
;
170 /* Get mode info from the HIDD */
171 if (!HIDD_Gfx_GetMode(gfxhidd
, hiddmode
, &sync
, &pf
))
173 D(bug("NO VALID MODE PASSED TO GetDisplayInfoData() !!!\n"));
177 D(bug("GetDisplayInfoData(handle=%d, tagID=%x)\n"
178 , (ULONG
)handle
, tagID
));
180 /* Build the queryheader */
181 structsize
= check_sizes(tagID
, size
);
184 qh
= AllocMem(structsize
, MEMF_CLEAR
);
188 /* Fill in the queryheader */
189 qh
->StructID
= tagID
;
191 qh
->SkipID
= TAG_SKIP
;
193 qh
->Length
= (structsize
+ (DLONGSZ
- 1)) / DLONGSZ
;
199 struct DisplayInfo
*di
;
200 const struct MonitorSpec
*ms
;
201 IPTR redmask
, greenmask
, bluemask
;
204 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
206 di
= (struct DisplayInfo
*)qh
;
208 /* All modes returned from the HIDD are available */
209 di
->NotAvailable
= FALSE
;
212 * Set the propertyflags. We always set DIPF_IS_SPRITES because we always emulate
213 * one sprite for mouse pointer.
215 di
->PropertyFlags
= DIPF_IS_SPRITES
| HIDDProps
.DisplayInfoFlags
;
219 * All non-planar modes are considered Workbench-compatible. This is done
220 * for compatibility with existing RTG drivers which never set this flag themselves.
221 * This can be considered historical, in initial API design HIDD_Gfx_ModeProperties()
222 * did not exist at all and this flag was simply always set.
223 * In fact all modes can be considered Workbench-compatible. This flag is
224 * known to be used by original AmigaOS screenmode prefs program to filter out
225 * some modes. This program has many replacement which do not obey this flag,
226 * enabling opening Workbench on HAM screen for example.
227 * But we delegate setting this flag to the driver for planar modes. We do it
228 * for 100% compatibility of chipset driver. What if some m68k program has its own
229 * weird assumptions about this bit ?
230 * One more thing to note: we don't set DIPF_IS_FOREIGN bit. It is actually used
231 * only by Picasso96 and only for modes that are not graphics.library compatible.
232 * Many m68k RTG games rely on this flag not being set.
234 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &val
);
235 if (val
!= vHidd_StdPixFmt_Plane
)
236 di
->PropertyFlags
|= DIPF_IS_WB
;
238 /* Compute red green and blue bits */
239 OOP_GetAttr(pf
, aHidd_PixFmt_RedMask
, &redmask
);
240 OOP_GetAttr(pf
, aHidd_PixFmt_GreenMask
, &greenmask
);
241 OOP_GetAttr(pf
, aHidd_PixFmt_BlueMask
, &bluemask
);
243 /* Use gcc builtin function */
244 /* weissms: do not use, can cause undefined symbol _GLOBAL_OFFSET_TABLE_
245 * should work if we use a real cross compiler with static libgcc
246 di->RedBits = __builtin_popcount(redmask);
247 di->GreenBits = __builtin_popcount(greenmask);
248 di->BlueBits = __builtin_popcount(bluemask);
251 di
->RedBits
= popcount(redmask
);
252 di
->GreenBits
= popcount(greenmask
);
253 di
->BlueBits
= popcount(bluemask
);
256 * If number of colors is too large, PaletteRange is set to 65535.
257 * This is the behavior of original AmigaOS(tm).
259 val
= 1 << (di
->RedBits
+ di
->GreenBits
+ di
->BlueBits
);
260 di
->PaletteRange
= (val
> 65535) ? 65535 : val
;
262 /* Display resolution in ticks */
263 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&ms
);
264 CalcScreenResolution(&di
->Resolution
, ms
, sync
, GfxBase
);
266 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &val
);
268 di
->PixelSpeed
= 1000000000 / val
;
271 * If the driver says it does not support sprites, we return one sprite.
272 * We emulate it by software in such a case because it's necessary for
275 di
->NumStdSprites
= (HIDDProps
.DisplayInfoFlags
& DIPF_IS_SPRITES
) ? HIDDProps
.NumHWSprites
: 1;
277 /* At the moment sprites always have the same resolution as display */
278 di
->SpriteResolution
= di
->Resolution
;
281 AROS extensions to allow querying if a hidd bitmap can be displayed
282 via the display compositor, and to enable it.
283 e.g openscreen uses these to determine if a custombitmap may be displayed.
285 di
->reserved
[0] = (IPTR
)compositor_IsBMCompositable
;
286 di
->reserved
[1] = (IPTR
)compositor_SetBMCompositable
;
293 struct DimensionInfo
*di
;
294 IPTR depth
, width
, height
;
295 IPTR minwidth
, minheight
;
296 IPTR maxwidth
, maxheight
;
298 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
299 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
300 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
301 OOP_GetAttr(sync
, aHidd_Sync_HMin
, &minwidth
);
302 OOP_GetAttr(sync
, aHidd_Sync_VMin
, &minheight
);
303 OOP_GetAttr(sync
, aHidd_Sync_HMax
, &maxwidth
);
304 OOP_GetAttr(sync
, aHidd_Sync_VMax
, &maxheight
);
306 di
= (struct DimensionInfo
*)qh
;
307 di
->MaxDepth
= depth
;
309 di
->MinRasterWidth
= minwidth
;
310 di
->MinRasterHeight
= minheight
;
311 di
->MaxRasterWidth
= maxwidth
;
312 di
->MaxRasterHeight
= maxheight
;
314 di
->Nominal
.MinX
= 0;
315 di
->Nominal
.MinY
= 0;
316 di
->Nominal
.MaxX
= width
- 1;
317 di
->Nominal
.MaxY
= height
- 1;
319 di
->MaxOScan
= di
->Nominal
;
320 di
->VideoOScan
= di
->Nominal
;
321 di
->TxtOScan
= di
->Nominal
;
322 di
->StdOScan
= di
->Nominal
;
324 * FIXME: our graphics subsystem does not have overscan API.
325 di->MaxOScan.MinX = di->Nominal.MinX;
326 di->MaxOScan.MinY = di->Nominal.MinY;
327 di->MaxOScan.MaxX = di->Nominal.MaxX;
328 di->MaxOScan.MaxY = di->Nominal.MaxY;
330 di->VideoOScan.MinX = di->Nominal.MinX;
331 di->VideoOScan.MinY = di->Nominal.MinY;
332 di->VideoOScan.MaxX = di->Nominal.MaxX;
333 di->VideoOScan.MaxY = di->Nominal.MaxY;
335 di->TxtOScan.MinX = di->Nominal.MinX;
336 di->TxtOScan.MinY = di->Nominal.MinY;
337 di->TxtOScan.MaxX = di->Nominal.MaxX;
338 di->TxtOScan.MaxY = di->Nominal.MaxY;
340 di->StdOScan.MinX = di->Nominal.MinX;
341 di->StdOScan.MinY = di->Nominal.MinY;
342 di->StdOScan.MaxX = di->Nominal.MaxX;
343 di->StdOScan.MaxY = di->Nominal.MaxY;
347 * reserved[0] is HIDD composition flags for intuition.library/OpenScreen().
348 * It can't be done in another way because only we (graphics.library) know about existence
349 * of software screen composition.
351 if (DIH(handle
)->drv
->compositor
)
353 IPTR capabilities
, state
;
354 OOP_GetAttr(DIH(handle
)->drv
->compositor
, aHidd_Compositor_Capabilities
, &capabilities
);
355 OOP_GetAttr(DIH(handle
)->drv
->compositor
, aHidd_Compositor_State
, &state
);
356 di
->reserved
[0] = (capabilities
<< 16) | state
;
360 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
361 di
->reserved
[0] = (HIDDProps
.CompositionFlags
<< 16) | HIDDProps
.CompositionFlags
;
364 /* This is for cybergraphics.library */
365 di
->reserved
[1] = (IPTR
)pf
;
372 struct MonitorInfo
*mi
= (struct MonitorInfo
*)qh
;
374 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&mi
->Mspc
);
377 mi->ViewPosition.X = ?;
378 mi->ViewPosition.Y = ?;
380 mi->MouseTicks.X = ?;
381 mi->MouseTicks.Y = ?;
382 mi->DefaultViewPosition.X = ?;
383 mi->DefaultViewPosition.Y = ?;
386 /* Resolution in ticks */
387 CalcScreenResolution(&mi
->ViewResolution
, mi
->Mspc
, sync
, GfxBase
);
389 mi
->TotalRows
= mi
->Mspc
->total_rows
;
390 mi
->TotalColorClocks
= mi
->Mspc
->total_colorclocks
;
391 mi
->ViewPositionRange
= mi
->Mspc
->ms_LegalView
;
394 * FIXME: For now we don't have a concept of preferred ModeID.
395 * However, see graphics_driver.c/driver_Setup(), it can be useful.
397 mi
->PreferredModeID
= ID
;
399 if (DIH(handle
)->drv
->compositor
)
402 * If we have software screen composition, we know we can compose.
403 * We use MCOMPAT_MIXED here because of changed understanding of what is "monitor".
404 * In AmigaOS(tm) a "monitor" is actually a sync (video mode). Different "monitors"
405 * are actually different modes of the same display (PAL, NTSC, VGA, etc).
406 * In AROS a "monitor" is a single physical display device. Of course we can do
407 * composition only on a single display, but we can compose together different
410 mi
->Compatibility
= MCOMPAT_MIXED
;
414 /* Otherwise query the driver */
415 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
417 if (HIDDProps
.CompositionFlags
)
418 mi
->Compatibility
= (HIDDProps
.CompositionFlags
& COMPF_SAME
) ? MCOMPAT_SELF
: MCOMPAT_MIXED
;
420 mi
->Compatibility
= MCOMPAT_NOBODY
;
429 IPTR depth
, stdpixfmt
;
430 STRPTR sync_description
;
432 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
433 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &stdpixfmt
);
435 OOP_GetAttr(sync
, aHidd_Sync_Description
, (IPTR
*)&sync_description
);
436 ni
= (struct NameInfo
*)qh
;
438 if (sync_description
&& sync_description
[0] &&
439 (IS_REAL_STDPIXFMT(stdpixfmt
) || (stdpixfmt
== vHidd_StdPixFmt_Unknown
)))
441 STRPTR pixfmt_name
= "";
445 case vHidd_StdPixFmt_RGB16
:
446 case vHidd_StdPixFmt_RGB15
:
447 case vHidd_StdPixFmt_RGB24
:
451 case vHidd_StdPixFmt_RGB16_LE
:
452 case vHidd_StdPixFmt_RGB15_LE
:
453 pixfmt_name
= "RGB PC";
456 case vHidd_StdPixFmt_BGR24
:
457 case vHidd_StdPixFmt_BGR16
:
458 case vHidd_StdPixFmt_BGR15
:
462 case vHidd_StdPixFmt_BGR16_LE
:
463 case vHidd_StdPixFmt_BGR15_LE
:
464 pixfmt_name
= "BGR PC";
467 case vHidd_StdPixFmt_ARGB32
:
468 pixfmt_name
= "ARGB";
471 case vHidd_StdPixFmt_BGRA32
:
472 pixfmt_name
= "BGRA";
475 case vHidd_StdPixFmt_RGBA32
:
476 pixfmt_name
= "RGBA";
479 case vHidd_StdPixFmt_0RGB32
:
480 pixfmt_name
= "0RGB";
483 case vHidd_StdPixFmt_BGR032
:
484 pixfmt_name
= "BGR0";
487 case vHidd_StdPixFmt_RGB032
:
488 pixfmt_name
= "RGB0";
492 if (stdpixfmt
!= vHidd_StdPixFmt_Plane
)
493 snprintf(ni
->Name
, DISPLAYNAMELEN
, "%s %2dbit %s",
494 sync_description
, (int)depth
, pixfmt_name
);
496 strncpy(ni
->Name
, sync_description
, DISPLAYNAMELEN
);
503 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
504 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
505 snprintf(ni
->Name
, DISPLAYNAMELEN
, "AROS: %ldx%ldx%ld", width
, height
, depth
);
511 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
515 D(bug("GDID: %d\n", structsize
));
517 if (size
> structsize
)
519 CopyMem(qh
, buf
, size
);
520 FreeMem(qh
, structsize
);
521 /* NULL-terminate the name in case if it was trimmed */
522 if (tagID
== DTAG_NAME
)
529 } /* GetDisplayInfoData */
531 /****************************************************************************************/
533 static ULONG
check_sizes(ULONG tagID
, ULONG size
)
537 idx
= DTAG_TO_IDX(tagID
);
541 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
545 return size_checks
[idx
];
548 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
549 static UBYTE
popcount(IPTR x
) {
551 for (count
=0; x
; count
++)