Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / rom / graphics / getdisplayinfodata.c
blobd9baec2fadc81e0deb294a295666ee9f74066120
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>
18 #include "graphics_intern.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 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!
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 IPTR redmask, greenmask, bluemask;
156 IPTR val = 0;
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;
172 * Some more tweaks.
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
222 * every mode.
223 * They have something to do with ratioh and ratiov fields in struct MonitorSpec.
225 di->Resolution.x = 22;
226 di->Resolution.y = 22;
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;
298 di->reserved[0] = (IPTR)DIH(handle)->drv->userdata;
299 di->reserved[1] = (IPTR)pf;
301 break;
304 case DTAG_MNTR:
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 = ?;
319 mi->MinRow = ?;
320 mi->MouseTicks.X = ?;
321 mi->MouseTicks.Y = ?;
322 mi->DefaultViewPosition.X = ?;
323 mi->DefaultViewPosition.Y = ?;
326 if (mi->Mspc) {
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;
335 break;
338 case DTAG_NAME:
340 struct NameInfo *ni;
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 = "";
355 switch(stdpixfmt)
357 case vHidd_StdPixFmt_RGB16:
358 case vHidd_StdPixFmt_RGB15:
359 case vHidd_StdPixFmt_RGB24:
360 pixfmt_name = "RGB";
361 break;
363 case vHidd_StdPixFmt_RGB16_LE:
364 case vHidd_StdPixFmt_RGB15_LE:
365 pixfmt_name = "RGB PC";
366 break;
368 case vHidd_StdPixFmt_BGR24:
369 case vHidd_StdPixFmt_BGR16:
370 case vHidd_StdPixFmt_BGR15:
371 pixfmt_name = "BGR";
372 break;
374 case vHidd_StdPixFmt_BGR16_LE:
375 case vHidd_StdPixFmt_BGR15_LE:
376 pixfmt_name = "BGR PC";
377 break;
379 case vHidd_StdPixFmt_ARGB32:
380 pixfmt_name = "ARGB";
381 break;
383 case vHidd_StdPixFmt_BGRA32:
384 pixfmt_name = "BGRA";
385 break;
387 case vHidd_StdPixFmt_RGBA32:
388 pixfmt_name = "RGBA";
389 break;
391 case vHidd_StdPixFmt_0RGB32:
392 pixfmt_name = "0RGB";
393 break;
395 case vHidd_StdPixFmt_BGR032:
396 pixfmt_name = "BGR0";
397 break;
399 case vHidd_StdPixFmt_RGB032:
400 pixfmt_name = "RGB0";
401 break;
404 if (stdpixfmt != vHidd_StdPixFmt_Plane)
405 snprintf(ni->Name, DISPLAYNAMELEN, "%s %2dbit %s",
406 sync_description, (int)depth, pixfmt_name);
407 else
408 strncpy(ni->Name, sync_description, DISPLAYNAMELEN);
410 else
412 IPTR width = 0;
413 IPTR height = 0;
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);
419 break;
422 default:
423 D(bug("!!! UNKNOWN tagID IN CALL TO GetDisplayInfoData() !!!\n"));
424 break;
427 D(bug("GDID: %d\n", structsize));
429 if (size > structsize)
430 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)
435 buf[size - 1] = 0;
437 return size;
439 AROS_LIBFUNC_EXIT
441 } /* GetDisplayInfoData */
443 /****************************************************************************************/
445 static ULONG check_sizes(ULONG tagID, ULONG size)
447 ULONG idx;
449 idx = DTAG_TO_IDX(tagID);
451 if (idx > KNOWN_IDS)
453 D(bug("!!! INVALID tagID TO GetDisplayInfoData"));
454 return 0;
457 return size_checks[idx];
460 /* taken from http://en.wikipedia.org/wiki/Hamming_weight */
461 static UBYTE popcount(IPTR x) {
462 UBYTE count;
463 for (count=0; x; count++)
464 x &= x-1;
465 return count;