5 #include "egldisplay.h"
8 #include "eglcurrent.h"
10 #include "eglstring.h"
13 #define MIN2(A, B) (((A) < (B)) ? (A) : (B))
17 * Given an EGLModeMESA handle, return the corresponding _EGLMode object
18 * or null if non-existant.
21 _eglLookupMode(EGLModeMESA mode
, _EGLDisplay
*disp
)
25 /* loop over all screens on the display */
26 for (scrnum
= 0; scrnum
< disp
->NumScreens
; scrnum
++) {
27 const _EGLScreen
*scrn
= disp
->Screens
[scrnum
];
29 /* search list of modes for handle */
30 for (i
= 0; i
< scrn
->NumModes
; i
++) {
31 if (scrn
->Modes
[i
].Handle
== mode
) {
32 return scrn
->Modes
+ i
;
42 * Add a new mode with the given attributes (width, height, depth, refreshRate)
43 * to the given screen.
44 * Assign a new mode ID/handle to the mode as well.
45 * \return pointer to the new _EGLMode
48 _eglAddNewMode(_EGLScreen
*screen
, EGLint width
, EGLint height
,
49 EGLint refreshRate
, const char *name
)
57 assert(refreshRate
> 0);
60 newModes
= (_EGLMode
*) realloc(screen
->Modes
, (n
+1) * sizeof(_EGLMode
));
62 screen
->Modes
= newModes
;
63 screen
->Modes
[n
].Handle
= n
+ 1;
64 screen
->Modes
[n
].Width
= width
;
65 screen
->Modes
[n
].Height
= height
;
66 screen
->Modes
[n
].RefreshRate
= refreshRate
;
67 screen
->Modes
[n
].Optimal
= EGL_FALSE
;
68 screen
->Modes
[n
].Interlaced
= EGL_FALSE
;
69 screen
->Modes
[n
].Name
= _eglstrdup(name
);
71 return screen
->Modes
+ n
;
81 * Parse the attrib_list to fill in the fields of the given _eglMode
82 * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
85 _eglParseModeAttribs(_EGLMode
*mode
, const EGLint
*attrib_list
)
89 /* init all attribs to EGL_DONT_CARE */
90 mode
->Handle
= EGL_DONT_CARE
;
91 mode
->Width
= EGL_DONT_CARE
;
92 mode
->Height
= EGL_DONT_CARE
;
93 mode
->RefreshRate
= EGL_DONT_CARE
;
94 mode
->Optimal
= EGL_DONT_CARE
;
95 mode
->Interlaced
= EGL_DONT_CARE
;
98 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
99 switch (attrib_list
[i
]) {
100 case EGL_MODE_ID_MESA
:
101 mode
->Handle
= attrib_list
[++i
];
102 if (mode
->Handle
<= 0) {
103 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(handle)");
108 mode
->Width
= attrib_list
[++i
];
109 if (mode
->Width
<= 0) {
110 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(width)");
115 mode
->Height
= attrib_list
[++i
];
116 if (mode
->Height
<= 0) {
117 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(height)");
121 case EGL_REFRESH_RATE_MESA
:
122 mode
->RefreshRate
= attrib_list
[++i
];
123 if (mode
->RefreshRate
<= 0) {
124 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(refresh rate)");
128 case EGL_INTERLACED_MESA
:
129 mode
->Interlaced
= attrib_list
[++i
];
130 if (mode
->Interlaced
!= EGL_TRUE
&& mode
->Interlaced
!= EGL_FALSE
) {
131 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(interlaced)");
135 case EGL_OPTIMAL_MESA
:
136 mode
->Optimal
= attrib_list
[++i
];
137 if (mode
->Optimal
!= EGL_TRUE
&& mode
->Optimal
!= EGL_FALSE
) {
138 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(optimal)");
143 _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseModeMESA");
152 * Determine if the candidate mode's attributes are at least as good
153 * as the minimal mode's.
154 * \return EGL_TRUE if qualifies, EGL_FALSE otherwise
157 _eglModeQualifies(const _EGLMode
*c
, const _EGLMode
*min
)
159 if (min
->Handle
!= EGL_DONT_CARE
&& c
->Handle
!= min
->Handle
)
161 if (min
->Width
!= EGL_DONT_CARE
&& c
->Width
< min
->Width
)
163 if (min
->Height
!= EGL_DONT_CARE
&& c
->Height
< min
->Height
)
165 if (min
->RefreshRate
!= EGL_DONT_CARE
&& c
->RefreshRate
< min
->RefreshRate
)
167 if (min
->Optimal
!= EGL_DONT_CARE
&& c
->Optimal
!= min
->Optimal
)
169 if (min
->Interlaced
!= EGL_DONT_CARE
&& c
->Interlaced
!= min
->Interlaced
)
177 * Return value of given mode attribute, or -1 if bad attrib.
180 getModeAttrib(const _EGLMode
*m
, EGLint attrib
)
183 case EGL_MODE_ID_MESA
:
189 case EGL_REFRESH_RATE_MESA
:
190 return m
->RefreshRate
;
191 case EGL_OPTIMAL_MESA
:
193 case EGL_INTERLACED_MESA
:
194 return m
->Interlaced
;
206 EGLint Order
; /* SMALLER or LARGER */
209 /* the order of these entries is the priority */
210 static struct sort_info SortInfo
[] = {
211 { EGL_OPTIMAL_MESA
, LARGER
},
212 { EGL_INTERLACED_MESA
, SMALLER
},
213 { EGL_WIDTH
, LARGER
},
214 { EGL_HEIGHT
, LARGER
},
215 { EGL_REFRESH_RATE_MESA
, LARGER
},
216 { EGL_MODE_ID_MESA
, SMALLER
},
222 * Compare modes 'a' and 'b' and return -1 if a belongs before b, or 1 if a
223 * belongs after b, or 0 if they're equal.
227 _eglCompareModes(const void *a
, const void *b
)
229 const _EGLMode
*aMode
= *((const _EGLMode
**) a
);
230 const _EGLMode
*bMode
= *((const _EGLMode
**) b
);
233 for (i
= 0; SortInfo
[i
].Attrib
; i
++) {
234 const EGLint aVal
= getModeAttrib(aMode
, SortInfo
[i
].Attrib
);
235 const EGLint bVal
= getModeAttrib(bMode
, SortInfo
[i
].Attrib
);
240 else if (SortInfo
[i
].Order
== SMALLER
) {
241 return (aVal
< bVal
) ? -1 : 1;
243 else if (SortInfo
[i
].Order
== LARGER
) {
244 return (aVal
> bVal
) ? -1 : 1;
248 /* all attributes identical */
254 * Search for EGLModes which match the given attribute list.
255 * Called via eglChooseModeMESA API function.
258 _eglChooseModeMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLScreen
*scrn
,
259 const EGLint
*attrib_list
, EGLModeMESA
*modes
,
260 EGLint modes_size
, EGLint
*num_modes
)
262 _EGLMode
**modeList
, min
;
265 if (!_eglParseModeAttribs(&min
, attrib_list
)) {
266 /* error code will have been recorded */
270 /* allocate array of mode pointers */
271 modeList
= (_EGLMode
**) malloc(modes_size
* sizeof(_EGLMode
*));
273 _eglError(EGL_BAD_MODE_MESA
, "eglChooseModeMESA(out of memory)");
277 /* make array of pointers to qualifying modes */
278 for (i
= count
= 0; i
< scrn
->NumModes
&& count
< modes_size
; i
++) {
279 if (_eglModeQualifies(scrn
->Modes
+ i
, &min
)) {
280 modeList
[count
++] = scrn
->Modes
+ i
;
284 /* sort array of pointers */
285 qsort(modeList
, count
, sizeof(_EGLMode
*), _eglCompareModes
);
287 /* copy mode handles to output array */
288 for (i
= 0; i
< count
; i
++) {
289 modes
[i
] = modeList
[i
]->Handle
;
302 * Return all possible modes for the given screen. No sorting of results.
303 * Called via eglGetModesMESA() API function.
306 _eglGetModesMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLScreen
*scrn
,
307 EGLModeMESA
*modes
, EGLint modes_size
, EGLint
*num_modes
)
311 *num_modes
= MIN2(scrn
->NumModes
, modes_size
);
312 for (i
= 0; i
< *num_modes
; i
++) {
313 modes
[i
] = scrn
->Modes
[i
].Handle
;
317 /* just return total number of supported modes */
318 *num_modes
= scrn
->NumModes
;
326 * Query an attribute of a mode.
329 _eglGetModeAttribMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
330 _EGLMode
*m
, EGLint attribute
, EGLint
*value
)
334 v
= getModeAttrib(m
, attribute
);
336 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetModeAttribMESA");
345 * Return human-readable string for given mode.
346 * This is the default function called by eglQueryModeStringMESA().
349 _eglQueryModeStringMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLMode
*m
)