6 #include "egldisplay.h"
9 #include "eglglobals.h"
10 #include "eglscreen.h"
13 #define MIN2(A, B) (((A) < (B)) ? (A) : (B))
17 my_strdup(const char *s
)
21 char *s2
= malloc(l
+ 1);
33 * Given an EGLModeMESA handle, return the corresponding _EGLMode object
34 * or null if non-existant.
37 _eglLookupMode(EGLDisplay dpy
, EGLModeMESA mode
)
39 const _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
42 /* loop over all screens on the display */
43 for (scrnum
= 0; scrnum
< disp
->NumScreens
; scrnum
++) {
44 const _EGLScreen
*scrn
= disp
->Screens
[scrnum
];
46 /* search list of modes for handle */
47 for (i
= 0; i
< scrn
->NumModes
; i
++) {
48 if (scrn
->Modes
[i
].Handle
== mode
) {
49 return scrn
->Modes
+ i
;
59 * Add a new mode with the given attributes (width, height, depth, refreshRate)
60 * to the given screen.
61 * Assign a new mode ID/handle to the mode as well.
62 * \return pointer to the new _EGLMode
65 _eglAddNewMode(_EGLScreen
*screen
, EGLint width
, EGLint height
,
66 EGLint refreshRate
, const char *name
)
74 assert(refreshRate
> 0);
77 newModes
= (_EGLMode
*) realloc(screen
->Modes
, (n
+1) * sizeof(_EGLMode
));
79 screen
->Modes
= newModes
;
80 screen
->Modes
[n
].Handle
= n
+ 1;
81 screen
->Modes
[n
].Width
= width
;
82 screen
->Modes
[n
].Height
= height
;
83 screen
->Modes
[n
].RefreshRate
= refreshRate
;
84 screen
->Modes
[n
].Optimal
= EGL_FALSE
;
85 screen
->Modes
[n
].Interlaced
= EGL_FALSE
;
86 screen
->Modes
[n
].Name
= my_strdup(name
);
88 return screen
->Modes
+ n
;
98 * Parse the attrib_list to fill in the fields of the given _eglMode
99 * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
102 _eglParseModeAttribs(_EGLMode
*mode
, const EGLint
*attrib_list
)
106 /* init all attribs to EGL_DONT_CARE */
107 mode
->Handle
= EGL_DONT_CARE
;
108 mode
->Width
= EGL_DONT_CARE
;
109 mode
->Height
= EGL_DONT_CARE
;
110 mode
->RefreshRate
= EGL_DONT_CARE
;
111 mode
->Optimal
= EGL_DONT_CARE
;
112 mode
->Interlaced
= EGL_DONT_CARE
;
115 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
116 switch (attrib_list
[i
]) {
117 case EGL_MODE_ID_MESA
:
118 mode
->Handle
= attrib_list
[++i
];
119 if (mode
->Handle
<= 0) {
120 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(handle)");
125 mode
->Width
= attrib_list
[++i
];
126 if (mode
->Width
<= 0) {
127 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(width)");
132 mode
->Height
= attrib_list
[++i
];
133 if (mode
->Height
<= 0) {
134 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(height)");
138 case EGL_REFRESH_RATE_MESA
:
139 mode
->RefreshRate
= attrib_list
[++i
];
140 if (mode
->RefreshRate
<= 0) {
141 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(refresh rate)");
145 case EGL_INTERLACED_MESA
:
146 mode
->Interlaced
= attrib_list
[++i
];
147 if (mode
->Interlaced
!= EGL_TRUE
&& mode
->Interlaced
!= EGL_FALSE
) {
148 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(interlaced)");
152 case EGL_OPTIMAL_MESA
:
153 mode
->Optimal
= attrib_list
[++i
];
154 if (mode
->Optimal
!= EGL_TRUE
&& mode
->Optimal
!= EGL_FALSE
) {
155 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(optimal)");
160 _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseModeMESA");
169 * Determine if the candidate mode's attributes are at least as good
170 * as the minimal mode's.
171 * \return EGL_TRUE if qualifies, EGL_FALSE otherwise
174 _eglModeQualifies(const _EGLMode
*c
, const _EGLMode
*min
)
176 if (min
->Handle
!= EGL_DONT_CARE
&& c
->Handle
!= min
->Handle
)
178 if (min
->Width
!= EGL_DONT_CARE
&& c
->Width
< min
->Width
)
180 if (min
->Height
!= EGL_DONT_CARE
&& c
->Height
< min
->Height
)
182 if (min
->RefreshRate
!= EGL_DONT_CARE
&& c
->RefreshRate
< min
->RefreshRate
)
184 if (min
->Optimal
!= EGL_DONT_CARE
&& c
->Optimal
!= min
->Optimal
)
186 if (min
->Interlaced
!= EGL_DONT_CARE
&& c
->Interlaced
!= min
->Interlaced
)
194 * Return value of given mode attribute, or -1 if bad attrib.
197 getModeAttrib(const _EGLMode
*m
, EGLint attrib
)
200 case EGL_MODE_ID_MESA
:
206 case EGL_REFRESH_RATE_MESA
:
207 return m
->RefreshRate
;
208 case EGL_OPTIMAL_MESA
:
210 case EGL_INTERLACED_MESA
:
211 return m
->Interlaced
;
223 EGLint Order
; /* SMALLER or LARGER */
226 /* the order of these entries is the priority */
227 static struct sort_info SortInfo
[] = {
228 { EGL_OPTIMAL_MESA
, LARGER
},
229 { EGL_INTERLACED_MESA
, SMALLER
},
230 { EGL_WIDTH
, LARGER
},
231 { EGL_HEIGHT
, LARGER
},
232 { EGL_REFRESH_RATE_MESA
, LARGER
},
233 { EGL_MODE_ID_MESA
, SMALLER
},
239 * Compare modes 'a' and 'b' and return -1 if a belongs before b, or 1 if a
240 * belongs after b, or 0 if they're equal.
244 _eglCompareModes(const void *a
, const void *b
)
246 const _EGLMode
*aMode
= *((const _EGLMode
**) a
);
247 const _EGLMode
*bMode
= *((const _EGLMode
**) b
);
250 for (i
= 0; SortInfo
[i
].Attrib
; i
++) {
251 const EGLint aVal
= getModeAttrib(aMode
, SortInfo
[i
].Attrib
);
252 const EGLint bVal
= getModeAttrib(bMode
, SortInfo
[i
].Attrib
);
257 else if (SortInfo
[i
].Order
== SMALLER
) {
258 return (aVal
< bVal
) ? -1 : 1;
260 else if (SortInfo
[i
].Order
== LARGER
) {
261 return (aVal
> bVal
) ? -1 : 1;
265 /* all attributes identical */
271 * Search for EGLModes which match the given attribute list.
272 * Called via eglChooseModeMESA API function.
275 _eglChooseModeMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
276 const EGLint
*attrib_list
, EGLModeMESA
*modes
,
277 EGLint modes_size
, EGLint
*num_modes
)
279 const _EGLScreen
*scrn
= _eglLookupScreen(dpy
, screen
);
280 _EGLMode
**modeList
, min
;
284 _eglError(EGL_BAD_SCREEN_MESA
, "eglChooseModeMESA");
288 if (!_eglParseModeAttribs(&min
, attrib_list
)) {
289 /* error code will have been recorded */
293 /* allocate array of mode pointers */
294 modeList
= (_EGLMode
**) malloc(modes_size
* sizeof(_EGLMode
*));
296 _eglError(EGL_BAD_MODE_MESA
, "eglChooseModeMESA(out of memory)");
300 /* make array of pointers to qualifying modes */
301 for (i
= count
= 0; i
< scrn
->NumModes
&& count
< modes_size
; i
++) {
302 if (_eglModeQualifies(scrn
->Modes
+ i
, &min
)) {
303 modeList
[count
++] = scrn
->Modes
+ i
;
307 /* sort array of pointers */
308 qsort(modeList
, count
, sizeof(_EGLMode
*), _eglCompareModes
);
310 /* copy mode handles to output array */
311 for (i
= 0; i
< count
; i
++) {
312 modes
[i
] = modeList
[i
]->Handle
;
325 * Return all possible modes for the given screen. No sorting of results.
326 * Called via eglGetModesMESA() API function.
329 _eglGetModesMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
330 EGLModeMESA
*modes
, EGLint modes_size
, EGLint
*num_modes
)
332 _EGLScreen
*scrn
= _eglLookupScreen(dpy
, screen
);
335 _eglError(EGL_BAD_SCREEN_MESA
, "eglGetModesMESA");
341 *num_modes
= MIN2(scrn
->NumModes
, modes_size
);
342 for (i
= 0; i
< *num_modes
; i
++) {
343 modes
[i
] = scrn
->Modes
[i
].Handle
;
347 /* just return total number of supported modes */
348 *num_modes
= scrn
->NumModes
;
356 * Query an attribute of a mode.
359 _eglGetModeAttribMESA(_EGLDriver
*drv
, EGLDisplay dpy
,
360 EGLModeMESA mode
, EGLint attribute
, EGLint
*value
)
362 _EGLMode
*m
= _eglLookupMode(dpy
, mode
);
366 _eglError(EGL_BAD_MODE_MESA
, "eglGetModeAttribMESA");
370 v
= getModeAttrib(m
, attribute
);
372 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetModeAttribMESA");
381 * Return human-readable string for given mode.
382 * This is the default function called by eglQueryModeStringMESA().
385 _eglQueryModeStringMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLModeMESA mode
)
387 _EGLMode
*m
= _eglLookupMode(dpy
, mode
);
389 _eglError(EGL_BAD_MODE_MESA
, "eglQueryModeStringMESA");
404 _eglTestModeModule(void)
407 _EGLMode
*modes
= (_EGLMode
*) malloc(count
* sizeof(_EGLMode
));
408 _EGLMode
**modeList
= (_EGLMode
**) malloc(count
* sizeof(_EGLMode
*));
411 for (i
= 0; i
< count
; i
++) {
412 modes
[i
].Handle
= _eglRand(20);
413 modes
[i
].Width
= 512 + 256 * _eglRand(2);
414 modes
[i
].Height
= 512 + 256 * _eglRand(2);
415 modes
[i
].RefreshRate
= 50 + 5 * _eglRand(3);
416 modes
[i
].Interlaced
= _eglRand(2);
417 modes
[i
].Optimal
= _eglRand(4) == 0;
418 modeList
[i
] = modes
+ i
;
421 /* sort array of pointers */
422 qsort(modeList
, count
, sizeof(_EGLMode
*), compareModes
);
424 for (i
= 0; i
< count
; i
++) {
425 _EGLMode
*m
= modeList
[i
];
426 printf("%2d: %3d %4d x %4d @ %3d opt %d int %d\n", i
,
427 m
->Handle
, m
->Width
, m
->Height
, m
->RefreshRate
,
428 m
->Optimal
, m
->Interlaced
);