gcc-4.6.2: Update with patch for gengtype.c
[AROS.git] / rom / graphics / getdisplayinfodata.c
blobeee124df23b7382dc9b3b8d136854496cd80b890
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics function GetDisplayInfoData()
6 Lang: english
7 */
9 #define DEBUG 0
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>
16 #include <stdio.h>
17 #include <string.h>
19 #include "graphics_intern.h"
20 #include "compositing_driver.h"
21 #include "dispinfo.h"
23 /****************************************************************************************/
25 static const ULONG size_checks[] =
27 sizeof(struct DisplayInfo),
28 sizeof(struct DimensionInfo),
29 sizeof(struct MonitorInfo),
30 sizeof(struct NameInfo),
33 #define KNOWN_IDS 4
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 /*****************************************************************************
43 NAME */
44 #include <proto/graphics.h>
46 AROS_LH5(ULONG, GetDisplayInfoData,
48 /* SYNOPSIS */
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),
55 /* LOCATION */
56 struct GfxBase *, GfxBase, 126, Graphics)
58 /* FUNCTION
59 Fills buffer with information about displayinfo handle.
61 INPUTS
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)
69 DTAG_NAME (NameInfo)
70 ID - displayinfo identifier, optionally used if handle is NULL
72 RESULT
73 result - if positive, number of bytes actually transferred
74 if zero, no information for ID was available
76 NOTES
78 EXAMPLE
80 BUGS
82 SEE ALSO
83 FindDisplayInfo(), NextDisplayInfo(), graphics/displayinfo.h
85 INTERNALS
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
88 changing the code.
90 HISTORY
92 ******************************************************************************/
94 AROS_LIBFUNC_INIT
96 struct QueryHeader *qh;
97 ULONG structsize;
98 OOP_Object *gfxhidd, *sync, *pf;
99 HIDDT_ModeID hiddmode;
100 struct HIDD_ModeProperties HIDDProps = {0};
102 if (NULL == handle)
104 /* FindDisplayInfo() handles INVALID_ID itself */
105 handle = FindDisplayInfo(ID);
107 else
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;
116 if (NULL == handle)
118 D(bug("!!! COULD NOT GET HANDLE IN GetDisplayInfoData()\n"));
119 return 0;
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"));
129 return 0;
132 D(bug("GetDisplayInfoData(handle=%d, tagID=%x)\n"
133 , (ULONG)handle, tagID));
135 /* Build the queryheader */
136 structsize = check_sizes(tagID, size);
137 if (!structsize)
138 return 0;
139 qh = AllocMem(structsize, MEMF_CLEAR);
140 if (!qh)
141 return 0;
143 /* Fill in the queryheader */
144 qh->StructID = tagID;
145 qh->DisplayID = ID;
146 qh->SkipID = TAG_SKIP;
148 qh->Length = (structsize + (DLONGSZ - 1)) / DLONGSZ;
150 switch (tagID)
152 case DTAG_DISP:
154 struct DisplayInfo *di;
155 const struct MonitorSpec *ms;
156 IPTR redmask, greenmask, bluemask;
157 IPTR width, height;
158 IPTR val = 0;
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;
177 * Some more tweaks.
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;
230 if (val)
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
236 * the mouse pointer.
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;
243 break;
246 case DTAG_DIMS:
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]);
310 else
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;
319 break;
322 case DTAG_MNTR:
324 struct MonitorInfo *mi = (struct MonitorInfo *)qh;
325 IPTR width, height;
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 = ?;
336 mi->MinRow = ?;
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;
348 if (mi->Mspc)
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
370 * syncs.
372 mi->Compatibility = MCOMPAT_MIXED;
374 else
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;
381 else
382 mi->Compatibility = MCOMPAT_NOBODY;
385 break;
388 case DTAG_NAME:
390 struct NameInfo *ni;
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 = "";
405 switch(stdpixfmt)
407 case vHidd_StdPixFmt_RGB16:
408 case vHidd_StdPixFmt_RGB15:
409 case vHidd_StdPixFmt_RGB24:
410 pixfmt_name = "RGB";
411 break;
413 case vHidd_StdPixFmt_RGB16_LE:
414 case vHidd_StdPixFmt_RGB15_LE:
415 pixfmt_name = "RGB PC";
416 break;
418 case vHidd_StdPixFmt_BGR24:
419 case vHidd_StdPixFmt_BGR16:
420 case vHidd_StdPixFmt_BGR15:
421 pixfmt_name = "BGR";
422 break;
424 case vHidd_StdPixFmt_BGR16_LE:
425 case vHidd_StdPixFmt_BGR15_LE:
426 pixfmt_name = "BGR PC";
427 break;
429 case vHidd_StdPixFmt_ARGB32:
430 pixfmt_name = "ARGB";
431 break;
433 case vHidd_StdPixFmt_BGRA32:
434 pixfmt_name = "BGRA";
435 break;
437 case vHidd_StdPixFmt_RGBA32:
438 pixfmt_name = "RGBA";
439 break;
441 case vHidd_StdPixFmt_0RGB32:
442 pixfmt_name = "0RGB";
443 break;
445 case vHidd_StdPixFmt_BGR032:
446 pixfmt_name = "BGR0";
447 break;
449 case vHidd_StdPixFmt_RGB032:
450 pixfmt_name = "RGB0";
451 break;
454 if (stdpixfmt != vHidd_StdPixFmt_Plane)
455 snprintf(ni->Name, DISPLAYNAMELEN, "%s %2dbit %s",
456 sync_description, (int)depth, pixfmt_name);
457 else
458 strncpy(ni->Name, sync_description, DISPLAYNAMELEN);
460 else
462 IPTR width = 0;
463 IPTR height = 0;
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);
469 break;
472 default:
473 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
474 break;
477 D(bug("GDID: %d\n", structsize));
479 if (size > structsize)
480 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)
485 buf[size - 1] = 0;
487 return size;
489 AROS_LIBFUNC_EXIT
491 } /* GetDisplayInfoData */
493 /****************************************************************************************/
495 static ULONG check_sizes(ULONG tagID, ULONG size)
497 ULONG idx;
499 idx = DTAG_TO_IDX(tagID);
501 if (idx > KNOWN_IDS)
503 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
504 return 0;
507 return size_checks[idx];
510 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
511 static UBYTE popcount(IPTR x) {
512 UBYTE count;
513 for (count=0; x; count++)
514 x &= x-1;
515 return count;