1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010 LunarG, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
35 #include "egldisplay.h"
37 #include "eglcurrent.h"
38 #include "eglscreen.h"
41 #ifdef EGL_MESA_screen_surface
44 #define MIN2(A, B) (((A) < (B)) ? (A) : (B))
48 * Given an EGLModeMESA handle, return the corresponding _EGLMode object
49 * or null if non-existant.
52 _eglLookupMode(EGLModeMESA mode
, _EGLDisplay
*disp
)
56 if (!disp
|| !disp
->Screens
)
59 /* loop over all screens on the display */
60 for (scrnum
= 0; scrnum
< disp
->Screens
->Size
; scrnum
++) {
61 const _EGLScreen
*scrn
= disp
->Screens
->Elements
[scrnum
];
65 * the mode ids of a screen ranges from scrn->Handle to scrn->Handle +
68 if (mode
>= scrn
->Handle
&&
69 mode
< scrn
->Handle
+ _EGL_SCREEN_MAX_MODES
) {
70 idx
= mode
- scrn
->Handle
;
72 assert(idx
< scrn
->NumModes
&& scrn
->Modes
[idx
].Handle
== mode
);
74 return &scrn
->Modes
[idx
];
83 * Parse the attrib_list to fill in the fields of the given _eglMode
84 * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
87 _eglParseModeAttribs(_EGLMode
*mode
, const EGLint
*attrib_list
)
91 /* init all attribs to EGL_DONT_CARE */
92 mode
->Handle
= EGL_DONT_CARE
;
93 mode
->Width
= EGL_DONT_CARE
;
94 mode
->Height
= EGL_DONT_CARE
;
95 mode
->RefreshRate
= EGL_DONT_CARE
;
96 mode
->Optimal
= EGL_DONT_CARE
;
97 mode
->Interlaced
= EGL_DONT_CARE
;
100 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
101 switch (attrib_list
[i
]) {
102 case EGL_MODE_ID_MESA
:
103 mode
->Handle
= attrib_list
[++i
];
104 if (mode
->Handle
<= 0) {
105 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(handle)");
110 mode
->Width
= attrib_list
[++i
];
111 if (mode
->Width
<= 0) {
112 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(width)");
117 mode
->Height
= attrib_list
[++i
];
118 if (mode
->Height
<= 0) {
119 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(height)");
123 case EGL_REFRESH_RATE_MESA
:
124 mode
->RefreshRate
= attrib_list
[++i
];
125 if (mode
->RefreshRate
<= 0) {
126 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(refresh rate)");
130 case EGL_INTERLACED_MESA
:
131 mode
->Interlaced
= attrib_list
[++i
];
132 if (mode
->Interlaced
!= EGL_TRUE
&& mode
->Interlaced
!= EGL_FALSE
) {
133 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(interlaced)");
137 case EGL_OPTIMAL_MESA
:
138 mode
->Optimal
= attrib_list
[++i
];
139 if (mode
->Optimal
!= EGL_TRUE
&& mode
->Optimal
!= EGL_FALSE
) {
140 _eglError(EGL_BAD_PARAMETER
, "eglChooseModeMESA(optimal)");
145 _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseModeMESA");
154 * Determine if the candidate mode's attributes are at least as good
155 * as the minimal mode's.
156 * \return EGL_TRUE if qualifies, EGL_FALSE otherwise
159 _eglModeQualifies(const _EGLMode
*c
, const _EGLMode
*min
)
161 if (min
->Handle
!= EGL_DONT_CARE
&& c
->Handle
!= min
->Handle
)
163 if (min
->Width
!= EGL_DONT_CARE
&& c
->Width
< min
->Width
)
165 if (min
->Height
!= EGL_DONT_CARE
&& c
->Height
< min
->Height
)
167 if (min
->RefreshRate
!= EGL_DONT_CARE
&& c
->RefreshRate
< min
->RefreshRate
)
169 if (min
->Optimal
!= EGL_DONT_CARE
&& c
->Optimal
!= min
->Optimal
)
171 if (min
->Interlaced
!= EGL_DONT_CARE
&& c
->Interlaced
!= min
->Interlaced
)
179 * Return value of given mode attribute, or -1 if bad attrib.
182 getModeAttrib(const _EGLMode
*m
, EGLint attrib
)
185 case EGL_MODE_ID_MESA
:
191 case EGL_REFRESH_RATE_MESA
:
192 return m
->RefreshRate
;
193 case EGL_OPTIMAL_MESA
:
195 case EGL_INTERLACED_MESA
:
196 return m
->Interlaced
;
208 EGLint Order
; /* SMALLER or LARGER */
211 /* the order of these entries is the priority */
212 static struct sort_info SortInfo
[] = {
213 { EGL_OPTIMAL_MESA
, LARGER
},
214 { EGL_INTERLACED_MESA
, SMALLER
},
215 { EGL_WIDTH
, LARGER
},
216 { EGL_HEIGHT
, LARGER
},
217 { EGL_REFRESH_RATE_MESA
, LARGER
},
218 { EGL_MODE_ID_MESA
, SMALLER
},
224 * Compare modes 'a' and 'b' and return -1 if a belongs before b, or 1 if a
225 * belongs after b, or 0 if they're equal.
229 _eglCompareModes(const void *a
, const void *b
)
231 const _EGLMode
*aMode
= *((const _EGLMode
**) a
);
232 const _EGLMode
*bMode
= *((const _EGLMode
**) b
);
235 for (i
= 0; SortInfo
[i
].Attrib
; i
++) {
236 const EGLint aVal
= getModeAttrib(aMode
, SortInfo
[i
].Attrib
);
237 const EGLint bVal
= getModeAttrib(bMode
, SortInfo
[i
].Attrib
);
242 else if (SortInfo
[i
].Order
== SMALLER
) {
243 return (aVal
< bVal
) ? -1 : 1;
245 else if (SortInfo
[i
].Order
== LARGER
) {
246 return (aVal
> bVal
) ? -1 : 1;
250 /* all attributes identical */
256 * Search for EGLModes which match the given attribute list.
257 * Called via eglChooseModeMESA API function.
260 _eglChooseModeMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLScreen
*scrn
,
261 const EGLint
*attrib_list
, EGLModeMESA
*modes
,
262 EGLint modes_size
, EGLint
*num_modes
)
264 _EGLMode
**modeList
, min
;
267 if (!_eglParseModeAttribs(&min
, attrib_list
)) {
268 /* error code will have been recorded */
272 /* allocate array of mode pointers */
273 modeList
= (_EGLMode
**) malloc(modes_size
* sizeof(_EGLMode
*));
275 _eglError(EGL_BAD_MODE_MESA
, "eglChooseModeMESA(out of memory)");
279 /* make array of pointers to qualifying modes */
280 for (i
= count
= 0; i
< scrn
->NumModes
&& count
< modes_size
; i
++) {
281 if (_eglModeQualifies(scrn
->Modes
+ i
, &min
)) {
282 modeList
[count
++] = scrn
->Modes
+ i
;
286 /* sort array of pointers */
287 qsort(modeList
, count
, sizeof(_EGLMode
*), _eglCompareModes
);
289 /* copy mode handles to output array */
290 for (i
= 0; i
< count
; i
++) {
291 modes
[i
] = modeList
[i
]->Handle
;
304 * Return all possible modes for the given screen. No sorting of results.
305 * Called via eglGetModesMESA() API function.
308 _eglGetModesMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLScreen
*scrn
,
309 EGLModeMESA
*modes
, EGLint modes_size
, EGLint
*num_modes
)
313 *num_modes
= MIN2(scrn
->NumModes
, modes_size
);
314 for (i
= 0; i
< *num_modes
; i
++) {
315 modes
[i
] = scrn
->Modes
[i
].Handle
;
319 /* just return total number of supported modes */
320 *num_modes
= scrn
->NumModes
;
328 * Query an attribute of a mode.
331 _eglGetModeAttribMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
332 _EGLMode
*m
, EGLint attribute
, EGLint
*value
)
336 v
= getModeAttrib(m
, attribute
);
338 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetModeAttribMESA");
347 * Return human-readable string for given mode.
348 * This is the default function called by eglQueryModeStringMESA().
351 _eglQueryModeStringMESA(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLMode
*m
)
357 #endif /* EGL_MESA_screen_surface */