codeset
[AROS.git] / rom / graphics / bestmodeida.c
blob712633b89f886f4b652e67d125be5c283787384c
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Graphics function BestModeIDA()
6 Lang: english
7 */
9 #include <aros/debug.h>
10 #include <cybergraphx/cybergraphics.h>
11 #include <graphics/modeid.h>
12 #include <hidd/graphics.h>
13 #include <proto/graphics.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
17 #include "graphics_intern.h"
18 #include "dispinfo.h"
20 /*****************************************************************************
22 NAME */
23 #include <proto/graphics.h>
25 AROS_LH1(ULONG, BestModeIDA,
27 /* SYNOPSIS */
28 AROS_LHA(struct TagItem *, TagItems, A0),
30 /* LOCATION */
31 struct GfxBase *, GfxBase, 175, Graphics)
33 /* FUNCTION
35 INPUTS
36 TagItems - pointer to an array of TagItems
38 TAGS
39 BIDTAG_ViewPort (struct ViewPort *) - Viewport for which a mode is searched. Default: NULL
40 BIDTAG_MonitorID (ULONG) - Returned ID must use this monitor
41 BIDTAG_SourceID (ULONG) - Use this ModeID instead of a ViewPort.
42 DIPFMustHave mask is made up of the
43 ((DisplayInfo->PropertyFlags of this ID & SPECIAL_FLAGS) |
44 DIPFMustHave flags).
45 Default:
46 if BIDTAG_ViewPort was passed: VPModeID(vp), else the
47 DIPFMustHave and DIPFMustNotHave are unchanged.
48 BIDTAG_Depth (UBYTE) - Minimal depth. Default:
49 if BIDTAG_ViewPort is passed: vp->RasInfo->BitMap->Depth,
50 else 1.
51 BIDTAG_NominalWidth (UWORD),
52 BIDTAG_NominalHeight (UWORD) - Aspect radio. Default:
53 if BIDTAG_SourceID: SourceID NominalDimensionInfo
54 if BIDTAG_ViewPort: vp->DWidth and vp->DHeight
55 or 640 x 200.
56 BIDTAG_DesiredWidth (UWORD) - Width. Default: DIBTAG_NominalWidth.
57 BIDTAG_DesiredHeight (UWORD) - Height. Default: BIDTAG_NominalHeight.
58 BIDTAG_RedBits (UBYTE),
59 BIDTAG_GreenBits (UBYTE),
60 BIDTAG_BlueBits (UBYTE) - Bits per gun the mode must support. Default: 4
61 BIDTAG_DIPFMustHave (ULONG) - DIPF flags the resulting mode must have
62 BIDTAG_DIPFMustNotHave (ULONG) - DIPF flags the resulting mode must not have
64 RESULT
65 ID - ID of the best mode to use, or INVALID_ID if a match
66 could not be found
68 NOTES
70 EXAMPLE
72 BUGS
74 SEE ALSO
75 graphics/modeid.h, graphics/displayinfo.h
77 INTERNALS
78 This function also processes CYBRBIDTG_BoardName tag. This is private
79 to AROS, do not rely on it!
81 HISTORY
83 ******************************************************************************/
85 AROS_LIBFUNC_INIT
87 struct ViewPort *vp;
88 UWORD nominal_width, nominal_height;
89 UWORD desired_width, desired_height;
90 UBYTE depth;
91 ULONG sourceid, monitorid;
92 UBYTE redbits, greenbits, bluebits;
93 ULONG dipf_musthave, dipf_mustnothave;
94 ULONG modeid;
95 STRPTR boardname;
96 struct DisplayInfoHandle *dinfo;
97 struct DisplayInfo disp;
98 struct DimensionInfo dims;
99 ULONG found_id = INVALID_ID;
100 UWORD found_depth = -1;
101 UWORD found_width = -1;
102 UWORD found_height = -1;
104 /* Get defaults which can be overriden */
105 dipf_musthave = GetTagData(BIDTAG_DIPFMustHave , 0 , TagItems);
106 dipf_mustnothave = GetTagData(BIDTAG_DIPFMustNotHave, SPECIAL_FLAGS , TagItems);
107 monitorid = GetTagData(BIDTAG_MonitorID , INVALID_ID , TagItems);
108 redbits = GetTagData(BIDTAG_RedBits , 4 , TagItems);
109 greenbits = GetTagData(BIDTAG_GreenBits , 4 , TagItems);
110 bluebits = GetTagData(BIDTAG_BlueBits , 4 , TagItems);
112 /* Try to get viewport */
113 vp = (struct ViewPort *)GetTagData(BIDTAG_ViewPort, 0, TagItems);
114 if (vp) {
115 nominal_width = vp->DWidth;
116 nominal_height = vp->DHeight;
117 sourceid = GetVPModeID(vp);
118 depth = vp->RasInfo->BitMap->Depth;
119 } else {
120 sourceid = INVALID_ID;
121 nominal_width = 640;
122 nominal_height = 200;
123 depth = 1;
126 /* Then process SourceID, it overrides ViewPort size and mode */
127 sourceid = GetTagData(BIDTAG_SourceID, sourceid, TagItems);
128 if (sourceid != INVALID_ID) {
129 if (GetDisplayInfoData(NULL, (UBYTE *)&disp, sizeof(disp), DTAG_DISP, sourceid) >= offsetof(struct DisplayInfo, Resolution))
130 dipf_musthave |= (disp.PropertyFlags & SPECIAL_FLAGS);
132 if (GetDisplayInfoData(NULL, (UBYTE *)&dims, sizeof(dims), DTAG_DIMS, sourceid) >= offsetof(struct DimensionInfo, MaxOScan)) {
133 nominal_width = dims.Nominal.MaxX - dims.Nominal.MinX + 1;
134 nominal_height = dims.Nominal.MaxY - dims.Nominal.MinY + 1;
138 /* Get high-priority parameters */
139 nominal_width = GetTagData(BIDTAG_NominalWidth , nominal_width , TagItems);
140 nominal_height = GetTagData(BIDTAG_NominalHeight, nominal_height, TagItems);
141 desired_width = GetTagData(BIDTAG_DesiredWidth , nominal_width , TagItems);
142 desired_height = GetTagData(BIDTAG_DesiredHeight, nominal_height, TagItems);
143 depth = GetTagData(BIDTAG_Depth , depth , TagItems);
145 boardname = (STRPTR)GetTagData(CYBRBIDTG_BoardName, 0, TagItems);
147 /* Exclude flags in MustHave from MustNotHave (CHECKME: if this correct?) */
148 dipf_mustnothave &= ~dipf_musthave;
149 /* Mask out bit 12 in monitorid because the user may (and will) pass in IDs defined in include/graphics/modeid.h
150 (like PAL_MONITOR_ID, VGA_MONITOR_ID, etc) which have bit 12 set) */
151 if (monitorid != INVALID_ID)
152 monitorid &= AROS_MONITOR_ID_MASK;
154 D(bug("[BestModeIDA] Desired mode: %dx%dx%d, MonitorID 0x%08lX, MustHave 0x%08lX, MustNotHave 0x%08lX\n",
155 desired_width, desired_height, depth, monitorid, dipf_musthave, dipf_mustnothave));
157 /* OK, now we try to search for a mode that has the supplied charateristics */
158 for (modeid = INVALID_ID;;)
160 UWORD gm_width, gm_height;
162 modeid = NextDisplayInfo(modeid);
163 if (modeid == INVALID_ID)
164 break;
166 D(bug("[BestModeIDA] Checking ModeID 0x%08lX... ", modeid));
168 if ((monitorid != INVALID_ID) && ((modeid & AROS_MONITOR_ID_MASK) != monitorid)) {
169 D(bug("MonitorID does not match\n"));
170 continue;
173 dinfo = FindDisplayInfo(modeid);
174 if (!dinfo) {
175 D(bug("No DisplayInfoHandle!\n"));
176 continue;
179 if (boardname) {
180 STRPTR name;
182 OOP_GetAttr(dinfo->drv->gfxhidd, aHidd_Gfx_DriverName, (IPTR *)&name);
183 if (strcmp(boardname, name))
184 continue;
187 if (GetDisplayInfoData(dinfo, (UBYTE *)&disp, sizeof(disp), DTAG_DISP, modeid) < offsetof(struct DisplayInfo, pad2)) {
188 D(bug("No DisplayInfo!\n"));
189 continue;
191 if (disp.NotAvailable) { /* Filter out not available modes */
192 D(bug("Not available: %u\n", disp.NotAvailable));
193 continue;
195 if (disp.PropertyFlags & dipf_mustnothave) { /* Filter out modes which do not meet out special needs */
196 D(bug("Has MustNotHave flags: 0x%08lX\n", disp.PropertyFlags));
197 continue;
199 if ((disp.PropertyFlags & dipf_musthave) != dipf_musthave) {
200 D(bug("Does not have MustHave flags: 0x%08lX\n", disp.PropertyFlags));
201 continue;
204 if (GetDisplayInfoData(dinfo, (UBYTE *)&dims, sizeof(dims), DTAG_DIMS, modeid) < offsetof(struct DimensionInfo, MaxOScan)) {
205 D(bug("No DimensionInfo!\n"));
206 continue;
208 gm_width = dims.Nominal.MaxX - dims.Nominal.MinX + 1;
209 gm_height = dims.Nominal.MaxY - dims.Nominal.MinY + 1;
210 D(bug("%ux%ux%u", gm_width, gm_height, dims.MaxDepth));
212 /* FIXME: Take aspect ratio into account (nominal_width : nominal_height) */
214 /* Check if mode is not worse than requested */
215 if ( disp.RedBits >= redbits
216 && disp.GreenBits >= greenbits
217 && disp.BlueBits >= bluebits
218 && dims.MaxDepth >= depth
219 && gm_width >= desired_width
220 && gm_height >= desired_height)
222 /* Check if this mode matches closer than the one we already found */
223 if ((dims.MaxDepth <= found_depth) &&
224 (gm_width <= found_width) && (gm_height <= found_height)) {
225 found_id = modeid;
226 found_depth = dims.MaxDepth;
227 found_width = gm_width;
228 found_height = gm_height;
229 D(bug(" Match!\n"));
232 D(bug("\n"));
234 } /* for (each modeid) */
236 D(bug("[BestModeIDA] Returning mode ID 0x%08lX\n", found_id));
237 return found_id;
239 AROS_LIBFUNC_EXIT
240 } /* BestModeIDA */