Autodoc formatting fixed.
[AROS.git] / rom / graphics / getdisplayinfodata.c
blob8f3b28679b71cabc99130d4d9e96df6a2877ce05
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics function GetDisplayInfoData()
6 Lang: english
7 */
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>
14 #include <stdio.h>
15 #include <string.h>
17 #include "graphics_intern.h"
18 #include "compositing_driver.h"
19 #include "dispinfo.h"
21 /****************************************************************************************/
23 static const ULONG size_checks[] =
25 sizeof(struct DisplayInfo),
26 sizeof(struct DimensionInfo),
27 sizeof(struct MonitorInfo),
28 sizeof(struct NameInfo),
31 #define KNOWN_IDS 4
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 /*****************************************************************************
41 NAME */
42 #include <proto/graphics.h>
44 AROS_LH5(ULONG, GetDisplayInfoData,
46 /* SYNOPSIS */
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),
53 /* LOCATION */
54 struct GfxBase *, GfxBase, 126, Graphics)
56 /* FUNCTION
57 Fills buffer with information about displayinfo handle.
59 INPUTS
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)
67 DTAG_NAME (NameInfo)
68 ID - displayinfo identifier, optionally used if handle is NULL
70 RESULT
71 result - if positive, number of bytes actually transferred
72 if zero, no information for ID was available
74 NOTES
76 EXAMPLE
78 BUGS
80 SEE ALSO
81 FindDisplayInfo(), NextDisplayInfo(), graphics/displayinfo.h
83 INTERNALS
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
86 changing the code.
88 HISTORY
90 ******************************************************************************/
92 AROS_LIBFUNC_INIT
94 struct QueryHeader *qh;
95 ULONG structsize;
96 OOP_Object *gfxhidd, *sync, *pf;
97 HIDDT_ModeID hiddmode;
98 struct HIDD_ModeProperties HIDDProps = {0};
100 if (NULL == handle)
102 /* FindDisplayInfo() handles INVALID_ID itself */
103 handle = FindDisplayInfo(ID);
105 else
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;
114 if (NULL == handle)
116 D(bug("!!! COULD NOT GET HANDLE IN GetDisplayInfoData()\n"));
117 return 0;
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"));
127 return 0;
130 D(bug("GetDisplayInfoData(handle=%d, tagID=%x)\n"
131 , (ULONG)handle, tagID));
133 /* Build the queryheader */
134 structsize = check_sizes(tagID, size);
135 if (!structsize)
136 return 0;
137 qh = AllocMem(structsize, MEMF_CLEAR);
138 if (!qh)
139 return 0;
141 /* Fill in the queryheader */
142 qh->StructID = tagID;
143 qh->DisplayID = ID;
144 qh->SkipID = TAG_SKIP;
146 qh->Length = (structsize + (DLONGSZ - 1)) / DLONGSZ;
148 switch (tagID)
150 case DTAG_DISP:
152 struct DisplayInfo *di;
153 const struct MonitorSpec *ms;
154 IPTR redmask, greenmask, bluemask;
155 IPTR width, height;
156 IPTR val = 0;
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;
175 * Some more tweaks.
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;
228 if (val)
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
234 * the mouse pointer.
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;
241 break;
244 case DTAG_DIMS:
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]);
308 else
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;
317 break;
320 case DTAG_MNTR:
322 struct MonitorInfo *mi = (struct MonitorInfo *)qh;
323 IPTR width, height;
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 = ?;
334 mi->MinRow = ?;
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;
346 if (mi->Mspc)
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
368 * syncs.
370 mi->Compatibility = MCOMPAT_MIXED;
372 else
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;
379 else
380 mi->Compatibility = MCOMPAT_NOBODY;
383 break;
386 case DTAG_NAME:
388 struct NameInfo *ni;
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 = "";
403 switch(stdpixfmt)
405 case vHidd_StdPixFmt_RGB16:
406 case vHidd_StdPixFmt_RGB15:
407 case vHidd_StdPixFmt_RGB24:
408 pixfmt_name = "RGB";
409 break;
411 case vHidd_StdPixFmt_RGB16_LE:
412 case vHidd_StdPixFmt_RGB15_LE:
413 pixfmt_name = "RGB PC";
414 break;
416 case vHidd_StdPixFmt_BGR24:
417 case vHidd_StdPixFmt_BGR16:
418 case vHidd_StdPixFmt_BGR15:
419 pixfmt_name = "BGR";
420 break;
422 case vHidd_StdPixFmt_BGR16_LE:
423 case vHidd_StdPixFmt_BGR15_LE:
424 pixfmt_name = "BGR PC";
425 break;
427 case vHidd_StdPixFmt_ARGB32:
428 pixfmt_name = "ARGB";
429 break;
431 case vHidd_StdPixFmt_BGRA32:
432 pixfmt_name = "BGRA";
433 break;
435 case vHidd_StdPixFmt_RGBA32:
436 pixfmt_name = "RGBA";
437 break;
439 case vHidd_StdPixFmt_0RGB32:
440 pixfmt_name = "0RGB";
441 break;
443 case vHidd_StdPixFmt_BGR032:
444 pixfmt_name = "BGR0";
445 break;
447 case vHidd_StdPixFmt_RGB032:
448 pixfmt_name = "RGB0";
449 break;
452 if (stdpixfmt != vHidd_StdPixFmt_Plane)
453 snprintf(ni->Name, DISPLAYNAMELEN, "%s %2dbit %s",
454 sync_description, (int)depth, pixfmt_name);
455 else
456 strncpy(ni->Name, sync_description, DISPLAYNAMELEN);
458 else
460 IPTR width = 0;
461 IPTR height = 0;
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);
467 break;
470 default:
471 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
472 break;
475 D(bug("GDID: %d\n", structsize));
477 if (size > structsize)
478 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)
483 buf[size - 1] = 0;
485 return size;
487 AROS_LIBFUNC_EXIT
489 } /* GetDisplayInfoData */
491 /****************************************************************************************/
493 static ULONG check_sizes(ULONG tagID, ULONG size)
495 ULONG idx;
497 idx = DTAG_TO_IDX(tagID);
499 if (idx > KNOWN_IDS)
501 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
502 return 0;
505 return size_checks[idx];
508 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
509 static UBYTE popcount(IPTR x) {
510 UBYTE count;
511 for (count=0; x; count++)
512 x &= x-1;
513 return count;