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>
18 #include "graphics_intern.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 the following private parameters:
85 DimensionInfo.reserved[0] - driver user data (intuition's monitorclass object)
86 DimensionInfo.reserved[1] - pixelformat object
87 Do not rely on this in end user software! This is private to AROS and
88 subject to change at any time!
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 IPTR redmask
, greenmask
, bluemask
;
158 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
160 di
= (struct DisplayInfo
*)qh
;
162 /* All modes returned from the HIDD are available */
163 di
->NotAvailable
= FALSE
;
166 * Set the propertyflags. We always set DIPF_IS_SPRITES because we always emulate
167 * one sprite for mouse pointer.
169 di
->PropertyFlags
= DIPF_IS_SPRITES
| HIDDProps
.DisplayInfoFlags
;
173 * All non-planar modes are considered Workbench-compatible. This is done
174 * for compatibility with existing RTG drivers which never set this flag themselves.
175 * This can be considered historical, in initial API design HIDD_Gfx_ModeProperties()
176 * did not exist at all and this flag was simply always set.
177 * In fact all modes can be considered Workbench-compatible. This flag is
178 * known to be used by original AmigaOS screenmode prefs program to filter out
179 * some modes. This program has many replacement which do not obey this flag,
180 * enabling opening Workbench on HAM screen for example.
181 * But we delegate setting this flag to the driver for planar modes. We do it
182 * for 100% compatibility of chipset driver. What if some m68k program has its own
183 * weird assumptions about this bit ?
184 * One more thing to note: we don't set DIPF_IS_FOREIGN bit. It is actually used
185 * only by Picasso96 and only for modes that are not graphics.library compatible.
186 * Many m68k RTG games rely on this flag not being set.
188 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &val
);
189 if (val
!= vHidd_StdPixFmt_Plane
)
190 di
->PropertyFlags
|= DIPF_IS_WB
;
192 /* Compute red green and blue bits */
193 OOP_GetAttr(pf
, aHidd_PixFmt_RedMask
, &redmask
);
194 OOP_GetAttr(pf
, aHidd_PixFmt_GreenMask
, &greenmask
);
195 OOP_GetAttr(pf
, aHidd_PixFmt_BlueMask
, &bluemask
);
197 /* Use gcc builtin function */
198 /* weissms: do not use, can cause undefined symbol _GLOBAL_OFFSET_TABLE_
199 * should work if we use a real cross compiler with static libgcc
200 di->RedBits = __builtin_popcount(redmask);
201 di->GreenBits = __builtin_popcount(greenmask);
202 di->BlueBits = __builtin_popcount(bluemask);
205 di
->RedBits
= popcount(redmask
);
206 di
->GreenBits
= popcount(greenmask
);
207 di
->BlueBits
= popcount(bluemask
);
210 * If number of colors is too large, PaletteRange is set to 65535.
211 * This is the behavior of original AmigaOS(tm).
213 val
= di
->RedBits
* di
->GreenBits
* di
->BlueBits
;
214 di
->PaletteRange
= (val
> 65535) ? 65535 : val
;
216 OOP_GetAttr(sync
, aHidd_Sync_PixelClock
, &val
);
219 * FIXME: don't know what to put here
220 * These seems to be some made-up units reflecting pixel ratio.
221 * In original AmigaOS(tm) they are hardcoded in monitor driver for
223 * They have something to do with ratioh and ratiov fields in struct MonitorSpec.
225 di
->Resolution
.x
= 22;
226 di
->Resolution
.y
= 22;
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;
298 di
->reserved
[0] = (IPTR
)DIH(handle
)->drv
->userdata
;
299 di
->reserved
[1] = (IPTR
)pf
;
306 struct MonitorInfo
*mi
;
308 HIDD_Gfx_ModeProperties(gfxhidd
, hiddmode
, &HIDDProps
, sizeof(HIDDProps
));
310 mi
= (struct MonitorInfo
*)qh
;
312 OOP_GetAttr(sync
, aHidd_Sync_MonitorSpec
, (IPTR
*)&mi
->Mspc
);
315 mi->ViewPosition.X = ?;
316 mi->ViewPosition.Y = ?;
317 mi->ViewResolution.X = ?;
318 mi->ViewResolution.Y = ?;
320 mi->MouseTicks.X = ?;
321 mi->MouseTicks.Y = ?;
322 mi->DefaultViewPosition.X = ?;
323 mi->DefaultViewPosition.Y = ?;
327 mi
->TotalRows
= mi
->Mspc
->total_rows
;
328 mi
->TotalColorClocks
= mi
->Mspc
->total_colorclocks
;
329 mi
->ViewPositionRange
= mi
->Mspc
->ms_LegalView
;
332 mi
->PreferredModeID
= ID
;
333 mi
->Compatibility
= HIDDProps
.CompositionFlags
? MCOMPAT_SELF
: MCOMPAT_NOBODY
;
341 IPTR depth
, stdpixfmt
;
342 STRPTR sync_description
;
344 OOP_GetAttr(pf
, aHidd_PixFmt_Depth
, &depth
);
345 OOP_GetAttr(pf
, aHidd_PixFmt_StdPixFmt
, &stdpixfmt
);
347 OOP_GetAttr(sync
, aHidd_Sync_Description
, (IPTR
*)&sync_description
);
348 ni
= (struct NameInfo
*)qh
;
350 if (sync_description
&& sync_description
[0] &&
351 (IS_REAL_STDPIXFMT(stdpixfmt
) || (stdpixfmt
== vHidd_StdPixFmt_Unknown
)))
353 STRPTR pixfmt_name
= "";
357 case vHidd_StdPixFmt_RGB16
:
358 case vHidd_StdPixFmt_RGB15
:
359 case vHidd_StdPixFmt_RGB24
:
363 case vHidd_StdPixFmt_RGB16_LE
:
364 case vHidd_StdPixFmt_RGB15_LE
:
365 pixfmt_name
= "RGB PC";
368 case vHidd_StdPixFmt_BGR24
:
369 case vHidd_StdPixFmt_BGR16
:
370 case vHidd_StdPixFmt_BGR15
:
374 case vHidd_StdPixFmt_BGR16_LE
:
375 case vHidd_StdPixFmt_BGR15_LE
:
376 pixfmt_name
= "BGR PC";
379 case vHidd_StdPixFmt_ARGB32
:
380 pixfmt_name
= "ARGB";
383 case vHidd_StdPixFmt_BGRA32
:
384 pixfmt_name
= "BGRA";
387 case vHidd_StdPixFmt_RGBA32
:
388 pixfmt_name
= "RGBA";
391 case vHidd_StdPixFmt_0RGB32
:
392 pixfmt_name
= "0RGB";
395 case vHidd_StdPixFmt_BGR032
:
396 pixfmt_name
= "BGR0";
399 case vHidd_StdPixFmt_RGB032
:
400 pixfmt_name
= "RGB0";
404 if (stdpixfmt
!= vHidd_StdPixFmt_Plane
)
405 snprintf(ni
->Name
, DISPLAYNAMELEN
, "%s %2dbit %s",
406 sync_description
, (int)depth
, pixfmt_name
);
408 strncpy(ni
->Name
, sync_description
, DISPLAYNAMELEN
);
415 OOP_GetAttr(sync
, aHidd_Sync_HDisp
, &width
);
416 OOP_GetAttr(sync
, aHidd_Sync_VDisp
, &height
);
417 snprintf(ni
->Name
, DISPLAYNAMELEN
, "AROS: %ldx%ldx%ld", width
, height
, depth
);
423 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
427 D(bug("GDID: %d\n", structsize
));
429 if (size
> structsize
)
431 CopyMem(qh
, buf
, size
);
432 FreeMem(qh
, structsize
);
433 /* NULL-terminate the name in case if it was trimmed */
434 if (tagID
== DTAG_NAME
)
441 } /* GetDisplayInfoData */
443 /****************************************************************************************/
445 static ULONG
check_sizes(ULONG tagID
, ULONG size
)
449 idx
= DTAG_TO_IDX(tagID
);
453 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
457 return size_checks
[idx
];
460 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
461 static UBYTE
popcount(IPTR x
) {
463 for (count
=0; x
; count
++)