2 * EGL Configuration (pixel format) functions.
10 #include "eglconfig.h"
11 #include "egldisplay.h"
12 #include "egldriver.h"
13 #include "eglglobals.h"
17 #define MIN2(A, B) (((A) < (B)) ? (A) : (B))
21 _eglSetConfigAttrib(_EGLConfig
*config
, EGLint attr
, EGLint val
)
23 assert(attr
>= FIRST_ATTRIB
);
24 assert(attr
< FIRST_ATTRIB
+ MAX_ATTRIBS
);
25 config
->Attrib
[attr
- FIRST_ATTRIB
] = val
;
30 * Init the given _EGLconfig to default values.
31 * \param id the configuration's ID.
34 _eglInitConfig(_EGLConfig
*config
, EGLint id
)
36 memset(config
, 0, sizeof(*config
));
37 config
->Handle
= (EGLConfig
) id
;
38 _eglSetConfigAttrib(config
, EGL_CONFIG_ID
, id
);
39 _eglSetConfigAttrib(config
, EGL_BIND_TO_TEXTURE_RGB
, EGL_DONT_CARE
);
40 _eglSetConfigAttrib(config
, EGL_BIND_TO_TEXTURE_RGBA
, EGL_DONT_CARE
);
41 _eglSetConfigAttrib(config
, EGL_CONFIG_CAVEAT
, EGL_DONT_CARE
);
42 _eglSetConfigAttrib(config
, EGL_NATIVE_RENDERABLE
, EGL_DONT_CARE
);
43 _eglSetConfigAttrib(config
, EGL_NATIVE_VISUAL_TYPE
, EGL_DONT_CARE
);
44 _eglSetConfigAttrib(config
, EGL_MIN_SWAP_INTERVAL
, EGL_DONT_CARE
);
45 _eglSetConfigAttrib(config
, EGL_MAX_SWAP_INTERVAL
, EGL_DONT_CARE
);
46 _eglSetConfigAttrib(config
, EGL_SURFACE_TYPE
, EGL_WINDOW_BIT
);
47 _eglSetConfigAttrib(config
, EGL_TRANSPARENT_TYPE
, EGL_NONE
);
48 _eglSetConfigAttrib(config
, EGL_TRANSPARENT_RED_VALUE
, EGL_DONT_CARE
);
49 _eglSetConfigAttrib(config
, EGL_TRANSPARENT_GREEN_VALUE
, EGL_DONT_CARE
);
50 _eglSetConfigAttrib(config
, EGL_TRANSPARENT_BLUE_VALUE
, EGL_DONT_CARE
);
51 #ifdef EGL_VERSION_1_2
52 _eglSetConfigAttrib(config
, EGL_COLOR_BUFFER_TYPE
, EGL_RGB_BUFFER
);
53 _eglSetConfigAttrib(config
, EGL_RENDERABLE_TYPE
, EGL_OPENGL_ES_BIT
);
54 #endif /* EGL_VERSION_1_2 */
59 * Return the public handle for an internal _EGLConfig.
60 * This is the inverse of _eglLookupConfig().
63 _eglGetConfigHandle(_EGLConfig
*config
)
65 return config
? config
->Handle
: 0;
70 * Given an EGLConfig handle, return the corresponding _EGLConfig object.
71 * This is the inverse of _eglGetConfigHandle().
74 _eglLookupConfig(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
)
77 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
78 for (i
= 0; i
< disp
->NumConfigs
; i
++) {
79 if (disp
->Configs
[i
]->Handle
== config
) {
80 return disp
->Configs
[i
];
88 * Add the given _EGLConfig to the given display.
89 * Note that we just save the ptr to the config (we don't copy the config).
92 _eglAddConfig(_EGLDisplay
*display
, _EGLConfig
*config
)
94 _EGLConfig
**newConfigs
;
97 /* do some sanity checks on the config's attribs */
98 assert(GET_CONFIG_ATTRIB(config
, EGL_CONFIG_ID
) > 0);
99 assert(GET_CONFIG_ATTRIB(config
, EGL_RENDERABLE_TYPE
) != 0x0);
100 assert(GET_CONFIG_ATTRIB(config
, EGL_SURFACE_TYPE
) != 0x0);
101 assert(GET_CONFIG_ATTRIB(config
, EGL_RED_SIZE
) > 0);
102 assert(GET_CONFIG_ATTRIB(config
, EGL_GREEN_SIZE
) > 0);
103 assert(GET_CONFIG_ATTRIB(config
, EGL_BLUE_SIZE
) > 0);
105 n
= display
->NumConfigs
;
107 /* realloc array of ptrs */
108 newConfigs
= (_EGLConfig
**) realloc(display
->Configs
,
109 (n
+ 1) * sizeof(_EGLConfig
*));
111 display
->Configs
= newConfigs
;
112 display
->Configs
[n
] = config
;
113 display
->NumConfigs
++;
123 * Parse the attrib_list to fill in the fields of the given _eglConfig
124 * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
127 _eglParseConfigAttribs(_EGLConfig
*config
, const EGLint
*attrib_list
)
131 /* set all config attribs to EGL_DONT_CARE */
132 for (i
= 0; i
< MAX_ATTRIBS
; i
++) {
133 config
->Attrib
[i
] = EGL_DONT_CARE
;
136 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
137 const EGLint attr
= attrib_list
[i
];
138 if (attr
>= EGL_BUFFER_SIZE
&&
139 attr
<= EGL_MAX_SWAP_INTERVAL
) {
140 EGLint k
= attr
- FIRST_ATTRIB
;
142 assert(k
< MAX_ATTRIBS
);
143 config
->Attrib
[k
] = attrib_list
[++i
];
145 #ifdef EGL_VERSION_1_2
146 else if (attr
== EGL_COLOR_BUFFER_TYPE
) {
147 EGLint bufType
= attrib_list
[++i
];
148 if (bufType
!= EGL_RGB_BUFFER
&& bufType
!= EGL_LUMINANCE_BUFFER
) {
149 _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseConfig");
152 _eglSetConfigAttrib(config
, EGL_COLOR_BUFFER_TYPE
, bufType
);
154 else if (attr
== EGL_RENDERABLE_TYPE
) {
155 EGLint renType
= attrib_list
[++i
];
156 if (renType
& ~(EGL_OPENGL_ES_BIT
| EGL_OPENGL_ES2_BIT
| EGL_OPENVG_BIT
)) {
157 _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseConfig");
160 _eglSetConfigAttrib(config
, EGL_RENDERABLE_TYPE
, renType
);
162 else if (attr
== EGL_ALPHA_MASK_SIZE
||
163 attr
== EGL_LUMINANCE_SIZE
) {
164 EGLint value
= attrib_list
[++i
];
165 _eglSetConfigAttrib(config
, attr
, value
);
167 #endif /* EGL_VERSION_1_2 */
169 _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseConfig");
186 EGLint MatchCriteria
;
190 /* This encodes the info from Table 3.5 of the EGL spec, ordered by
193 * XXX To do: EGL 1.2 attribs
195 static struct sort_info SortInfo
[] = {
196 { EGL_CONFIG_CAVEAT
, EXACT
, SPECIAL
},
197 { EGL_RED_SIZE
, ATLEAST
, SPECIAL
},
198 { EGL_GREEN_SIZE
, ATLEAST
, SPECIAL
},
199 { EGL_BLUE_SIZE
, ATLEAST
, SPECIAL
},
200 { EGL_ALPHA_SIZE
, ATLEAST
, SPECIAL
},
201 { EGL_BUFFER_SIZE
, ATLEAST
, SMALLER
},
202 { EGL_SAMPLE_BUFFERS
, ATLEAST
, SMALLER
},
203 { EGL_SAMPLES
, ATLEAST
, SMALLER
},
204 { EGL_DEPTH_SIZE
, ATLEAST
, SMALLER
},
205 { EGL_STENCIL_SIZE
, ATLEAST
, SMALLER
},
206 { EGL_NATIVE_VISUAL_TYPE
, EXACT
, SPECIAL
},
207 { EGL_CONFIG_ID
, EXACT
, SMALLER
},
208 { EGL_BIND_TO_TEXTURE_RGB
, EXACT
, NONE
},
209 { EGL_BIND_TO_TEXTURE_RGBA
, EXACT
, NONE
},
210 { EGL_LEVEL
, EXACT
, NONE
},
211 { EGL_NATIVE_RENDERABLE
, EXACT
, NONE
},
212 { EGL_MAX_SWAP_INTERVAL
, EXACT
, NONE
},
213 { EGL_MIN_SWAP_INTERVAL
, EXACT
, NONE
},
214 { EGL_SURFACE_TYPE
, MASK
, NONE
},
215 { EGL_TRANSPARENT_TYPE
, EXACT
, NONE
},
216 { EGL_TRANSPARENT_RED_VALUE
, EXACT
, NONE
},
217 { EGL_TRANSPARENT_GREEN_VALUE
, EXACT
, NONE
},
218 { EGL_TRANSPARENT_BLUE_VALUE
, EXACT
, NONE
},
224 * Return EGL_TRUE if the attributes of c meet or exceed the minimums
228 _eglConfigQualifies(const _EGLConfig
*c
, const _EGLConfig
*min
)
231 for (i
= 0; SortInfo
[i
].Attribute
!= 0; i
++) {
232 const EGLint mv
= GET_CONFIG_ATTRIB(min
, SortInfo
[i
].Attribute
);
233 if (mv
!= EGL_DONT_CARE
) {
234 const EGLint cv
= GET_CONFIG_ATTRIB(c
, SortInfo
[i
].Attribute
);
235 if (SortInfo
[i
].MatchCriteria
== EXACT
) {
240 else if (SortInfo
[i
].MatchCriteria
== ATLEAST
) {
246 assert(SortInfo
[i
].MatchCriteria
== MASK
);
247 if ((mv
& cv
) != mv
) {
258 * Compare configs 'a' and 'b' and return -1 if a belongs before b,
259 * 1 if a belongs after b, or 0 if they're equal.
263 _eglCompareConfigs(const void *a
, const void *b
)
265 const _EGLConfig
*aConfig
= (const _EGLConfig
*) a
;
266 const _EGLConfig
*bConfig
= (const _EGLConfig
*) b
;
269 for (i
= 0; SortInfo
[i
].Attribute
!= 0; i
++) {
270 const EGLint aVal
= GET_CONFIG_ATTRIB(aConfig
, SortInfo
[i
].Attribute
);
271 const EGLint bVal
= GET_CONFIG_ATTRIB(bConfig
, SortInfo
[i
].Attribute
);
272 if (SortInfo
[i
].SortOrder
== SMALLER
) {
275 else if (aVal
> bVal
)
277 /* else, continue examining attribute values */
279 else if (SortInfo
[i
].SortOrder
== SPECIAL
) {
280 if (SortInfo
[i
].Attribute
== EGL_CONFIG_CAVEAT
) {
281 /* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */
284 else if (aVal
> bVal
)
287 else if (SortInfo
[i
].Attribute
== EGL_RED_SIZE
||
288 SortInfo
[i
].Attribute
== EGL_GREEN_SIZE
||
289 SortInfo
[i
].Attribute
== EGL_BLUE_SIZE
||
290 SortInfo
[i
].Attribute
== EGL_ALPHA_SIZE
) {
293 else if (aVal
< bVal
)
297 assert(SortInfo
[i
].Attribute
== EGL_NATIVE_VISUAL_TYPE
);
300 else if (aVal
> bVal
)
305 assert(SortInfo
[i
].SortOrder
== NONE
);
306 /* continue examining attribute values */
310 /* all attributes identical */
316 * Typical fallback routine for eglChooseConfig
319 _eglChooseConfig(_EGLDriver
*drv
, EGLDisplay dpy
, const EGLint
*attrib_list
,
320 EGLConfig
*configs
, EGLint config_size
, EGLint
*num_configs
)
322 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
323 _EGLConfig
**configList
, criteria
;
326 /* parse the attrib_list to initialize criteria */
327 if (!_eglParseConfigAttribs(&criteria
, attrib_list
)) {
331 /* allocate array of config pointers */
332 configList
= (_EGLConfig
**) malloc(config_size
* sizeof(_EGLConfig
*));
334 _eglError(EGL_BAD_CONFIG
, "eglChooseConfig(out of memory)");
338 /* make array of pointers to qualifying configs */
339 for (i
= count
= 0; i
< disp
->NumConfigs
&& count
< config_size
; i
++) {
340 if (_eglConfigQualifies(disp
->Configs
[i
], &criteria
)) {
341 configList
[count
++] = disp
->Configs
[i
];
345 /* sort array of pointers */
346 qsort(configList
, count
, sizeof(_EGLConfig
*), _eglCompareConfigs
);
348 /* copy config handles to output array */
350 for (i
= 0; i
< count
; i
++) {
351 configs
[i
] = configList
[i
]->Handle
;
357 *num_configs
= count
;
364 * Fallback for eglGetConfigAttrib.
367 _eglGetConfigAttrib(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
368 EGLint attribute
, EGLint
*value
)
370 const _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
371 const EGLint k
= attribute
- FIRST_ATTRIB
;
372 if (k
>= 0 && k
< MAX_ATTRIBS
) {
373 *value
= conf
->Attrib
[k
];
377 _eglError(EGL_BAD_ATTRIBUTE
, "eglGetConfigAttrib");
384 * Fallback for eglGetConfigs.
387 _eglGetConfigs(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig
*configs
,
388 EGLint config_size
, EGLint
*num_config
)
390 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
392 if (!drv
->Initialized
) {
393 _eglError(EGL_NOT_INITIALIZED
, "eglGetConfigs");
399 *num_config
= MIN2(disp
->NumConfigs
, config_size
);
400 for (i
= 0; i
< *num_config
; i
++) {
401 configs
[i
] = disp
->Configs
[i
]->Handle
;
405 /* just return total number of supported configs */
406 *num_config
= disp
->NumConfigs
;