2 * EGL Configuration (pixel format) functions.
10 #include "egldisplay.h"
11 #include "eglcurrent.h"
15 #define MIN2(A, B) (((A) < (B)) ? (A) : (B))
19 * Init the given _EGLconfig to default values.
20 * \param id the configuration's ID.
22 * Note that id must be positive for the config to be valid.
23 * It is also recommended that when there are N configs, their
24 * IDs are from 1 to N respectively.
27 _eglInitConfig(_EGLConfig
*conf
, _EGLDisplay
*dpy
, EGLint id
)
29 memset(conf
, 0, sizeof(*conf
));
33 /* some attributes take non-zero default values */
35 conf
->ConfigCaveat
= EGL_NONE
;
36 conf
->TransparentType
= EGL_NONE
;
37 conf
->NativeVisualType
= EGL_NONE
;
38 conf
->ColorBufferType
= EGL_RGB_BUFFER
;
43 * Link a config to a display and return the handle of the link.
44 * The handle can be passed to client directly.
46 * Note that we just save the ptr to the config (we don't copy the config).
49 _eglAddConfig(_EGLDisplay
*dpy
, _EGLConfig
*conf
)
52 assert(conf
->ConfigID
> 0);
55 dpy
->Configs
= _eglCreateArray("Config", 16);
57 return (EGLConfig
) NULL
;
61 _eglAppendArray(dpy
->Configs
, (void *) conf
);
63 return (EGLConfig
) conf
;
68 _eglCheckConfigHandle(EGLConfig config
, _EGLDisplay
*dpy
)
72 conf
= (_EGLConfig
*) _eglFindArray(dpy
->Configs
, (void *) config
);
74 assert(conf
->Display
== dpy
);
76 return (conf
!= NULL
);
86 ATTRIB_TYPE_PSEUDO
, /* non-queryable */
87 ATTRIB_TYPE_PLATFORM
, /* platform-dependent */
89 ATTRIB_CRITERION_EXACT
,
90 ATTRIB_CRITERION_ATLEAST
,
91 ATTRIB_CRITERION_MASK
,
92 ATTRIB_CRITERION_SPECIAL
,
93 ATTRIB_CRITERION_IGNORE
97 /* EGL spec Table 3.1 and 3.4 */
102 EGLint default_value
;
103 } _eglValidationTable
[] =
106 { EGL_BUFFER_SIZE
, ATTRIB_TYPE_INTEGER
,
107 ATTRIB_CRITERION_ATLEAST
,
109 { EGL_RED_SIZE
, ATTRIB_TYPE_INTEGER
,
110 ATTRIB_CRITERION_ATLEAST
,
112 { EGL_GREEN_SIZE
, ATTRIB_TYPE_INTEGER
,
113 ATTRIB_CRITERION_ATLEAST
,
115 { EGL_BLUE_SIZE
, ATTRIB_TYPE_INTEGER
,
116 ATTRIB_CRITERION_ATLEAST
,
118 { EGL_LUMINANCE_SIZE
, ATTRIB_TYPE_INTEGER
,
119 ATTRIB_CRITERION_ATLEAST
,
121 { EGL_ALPHA_SIZE
, ATTRIB_TYPE_INTEGER
,
122 ATTRIB_CRITERION_ATLEAST
,
124 { EGL_ALPHA_MASK_SIZE
, ATTRIB_TYPE_INTEGER
,
125 ATTRIB_CRITERION_ATLEAST
,
127 { EGL_BIND_TO_TEXTURE_RGB
, ATTRIB_TYPE_BOOLEAN
,
128 ATTRIB_CRITERION_EXACT
,
130 { EGL_BIND_TO_TEXTURE_RGBA
, ATTRIB_TYPE_BOOLEAN
,
131 ATTRIB_CRITERION_EXACT
,
133 { EGL_COLOR_BUFFER_TYPE
, ATTRIB_TYPE_ENUM
,
134 ATTRIB_CRITERION_EXACT
,
136 { EGL_CONFIG_CAVEAT
, ATTRIB_TYPE_ENUM
,
137 ATTRIB_CRITERION_EXACT
,
139 { EGL_CONFIG_ID
, ATTRIB_TYPE_INTEGER
,
140 ATTRIB_CRITERION_EXACT
,
142 { EGL_CONFORMANT
, ATTRIB_TYPE_BITMASK
,
143 ATTRIB_CRITERION_MASK
,
145 { EGL_DEPTH_SIZE
, ATTRIB_TYPE_INTEGER
,
146 ATTRIB_CRITERION_ATLEAST
,
148 { EGL_LEVEL
, ATTRIB_TYPE_PLATFORM
,
149 ATTRIB_CRITERION_EXACT
,
151 { EGL_MAX_PBUFFER_WIDTH
, ATTRIB_TYPE_INTEGER
,
152 ATTRIB_CRITERION_IGNORE
,
154 { EGL_MAX_PBUFFER_HEIGHT
, ATTRIB_TYPE_INTEGER
,
155 ATTRIB_CRITERION_IGNORE
,
157 { EGL_MAX_PBUFFER_PIXELS
, ATTRIB_TYPE_INTEGER
,
158 ATTRIB_CRITERION_IGNORE
,
160 { EGL_MAX_SWAP_INTERVAL
, ATTRIB_TYPE_INTEGER
,
161 ATTRIB_CRITERION_EXACT
,
163 { EGL_MIN_SWAP_INTERVAL
, ATTRIB_TYPE_INTEGER
,
164 ATTRIB_CRITERION_EXACT
,
166 { EGL_NATIVE_RENDERABLE
, ATTRIB_TYPE_BOOLEAN
,
167 ATTRIB_CRITERION_EXACT
,
169 { EGL_NATIVE_VISUAL_ID
, ATTRIB_TYPE_PLATFORM
,
170 ATTRIB_CRITERION_IGNORE
,
172 { EGL_NATIVE_VISUAL_TYPE
, ATTRIB_TYPE_PLATFORM
,
173 ATTRIB_CRITERION_EXACT
,
175 { EGL_RENDERABLE_TYPE
, ATTRIB_TYPE_BITMASK
,
176 ATTRIB_CRITERION_MASK
,
178 { EGL_SAMPLE_BUFFERS
, ATTRIB_TYPE_INTEGER
,
179 ATTRIB_CRITERION_ATLEAST
,
181 { EGL_SAMPLES
, ATTRIB_TYPE_INTEGER
,
182 ATTRIB_CRITERION_ATLEAST
,
184 { EGL_STENCIL_SIZE
, ATTRIB_TYPE_INTEGER
,
185 ATTRIB_CRITERION_ATLEAST
,
187 { EGL_SURFACE_TYPE
, ATTRIB_TYPE_BITMASK
,
188 ATTRIB_CRITERION_MASK
,
190 { EGL_TRANSPARENT_TYPE
, ATTRIB_TYPE_ENUM
,
191 ATTRIB_CRITERION_EXACT
,
193 { EGL_TRANSPARENT_RED_VALUE
, ATTRIB_TYPE_INTEGER
,
194 ATTRIB_CRITERION_EXACT
,
196 { EGL_TRANSPARENT_GREEN_VALUE
, ATTRIB_TYPE_INTEGER
,
197 ATTRIB_CRITERION_EXACT
,
199 { EGL_TRANSPARENT_BLUE_VALUE
, ATTRIB_TYPE_INTEGER
,
200 ATTRIB_CRITERION_EXACT
,
202 { EGL_MATCH_NATIVE_PIXMAP
, ATTRIB_TYPE_PSEUDO
,
203 ATTRIB_CRITERION_SPECIAL
,
206 { EGL_Y_INVERTED_NOK
, ATTRIB_TYPE_BOOLEAN
,
207 ATTRIB_CRITERION_EXACT
,
213 * Return true if a config is valid. When for_matching is true,
214 * EGL_DONT_CARE is accepted as a valid attribute value, and checks
215 * for conflicting attribute values are skipped.
217 * Note that some attributes are platform-dependent and are not
221 _eglValidateConfig(const _EGLConfig
*conf
, EGLBoolean for_matching
)
224 EGLBoolean valid
= EGL_TRUE
;
226 /* check attributes by their types */
227 for (i
= 0; i
< ARRAY_SIZE(_eglValidationTable
); i
++) {
230 attr
= _eglValidationTable
[i
].attr
;
231 val
= _eglGetConfigKey(conf
, attr
);
233 switch (_eglValidationTable
[i
].type
) {
234 case ATTRIB_TYPE_INTEGER
:
237 /* config id must be positive */
241 case EGL_SAMPLE_BUFFERS
:
242 /* there can be at most 1 sample buffer */
243 if (val
> 1 || val
< 0)
252 case ATTRIB_TYPE_BOOLEAN
:
253 if (val
!= EGL_TRUE
&& val
!= EGL_FALSE
)
256 case ATTRIB_TYPE_ENUM
:
258 case EGL_CONFIG_CAVEAT
:
259 if (val
!= EGL_NONE
&& val
!= EGL_SLOW_CONFIG
&&
260 val
!= EGL_NON_CONFORMANT_CONFIG
)
263 case EGL_TRANSPARENT_TYPE
:
264 if (val
!= EGL_NONE
&& val
!= EGL_TRANSPARENT_RGB
)
267 case EGL_COLOR_BUFFER_TYPE
:
268 if (val
!= EGL_RGB_BUFFER
&& val
!= EGL_LUMINANCE_BUFFER
)
276 case ATTRIB_TYPE_BITMASK
:
278 case EGL_SURFACE_TYPE
:
279 mask
= EGL_PBUFFER_BIT
|
282 EGL_VG_COLORSPACE_LINEAR_BIT
|
283 EGL_VG_ALPHA_FORMAT_PRE_BIT
|
284 EGL_MULTISAMPLE_RESOLVE_BOX_BIT
|
285 EGL_SWAP_BEHAVIOR_PRESERVED_BIT
;
286 #ifdef EGL_MESA_screen_surface
287 if (conf
->Display
->Extensions
.MESA_screen_surface
)
288 mask
|= EGL_SCREEN_BIT_MESA
;
291 case EGL_RENDERABLE_TYPE
:
293 mask
= EGL_OPENGL_ES_BIT
|
305 case ATTRIB_TYPE_PLATFORM
:
306 /* unable to check platform-dependent attributes here */
308 case ATTRIB_TYPE_PSEUDO
:
309 /* pseudo attributes should not be set */
318 if (!valid
&& for_matching
) {
319 /* accept EGL_DONT_CARE as a valid value */
320 if (val
== EGL_DONT_CARE
)
322 if (_eglValidationTable
[i
].criterion
== ATTRIB_CRITERION_SPECIAL
)
327 "attribute 0x%04x has an invalid value 0x%x", attr
, val
);
332 /* any invalid attribute value should have been catched */
333 if (!valid
|| for_matching
)
336 /* now check for conflicting attribute values */
338 switch (conf
->ColorBufferType
) {
340 if (conf
->LuminanceSize
)
342 if (conf
->RedSize
+ conf
->GreenSize
+
343 conf
->BlueSize
+ conf
->AlphaSize
!= conf
->BufferSize
)
346 case EGL_LUMINANCE_BUFFER
:
347 if (conf
->RedSize
|| conf
->GreenSize
|| conf
->BlueSize
)
349 if (conf
->LuminanceSize
+ conf
->AlphaSize
!= conf
->BufferSize
)
354 _eglLog(_EGL_DEBUG
, "conflicting color buffer type and channel sizes");
358 if (!conf
->SampleBuffers
&& conf
->Samples
)
361 _eglLog(_EGL_DEBUG
, "conflicting samples and sample buffers");
365 if (!(conf
->SurfaceType
& EGL_WINDOW_BIT
)) {
366 if (conf
->NativeVisualID
!= 0 || conf
->NativeVisualType
!= EGL_NONE
)
369 if (!(conf
->SurfaceType
& EGL_PBUFFER_BIT
)) {
370 if (conf
->BindToTextureRGB
|| conf
->BindToTextureRGBA
)
374 _eglLog(_EGL_DEBUG
, "conflicting surface type and native visual/texture binding");
383 * Return true if a config matches the criteria. This and
384 * _eglParseConfigAttribList together implement the algorithm
385 * described in "Selection of EGLConfigs".
387 * Note that attributes that are special (currently, only
388 * EGL_MATCH_NATIVE_PIXMAP) are ignored.
391 _eglMatchConfig(const _EGLConfig
*conf
, const _EGLConfig
*criteria
)
394 EGLBoolean matched
= EGL_TRUE
;
396 for (i
= 0; i
< ARRAY_SIZE(_eglValidationTable
); i
++) {
398 if (_eglValidationTable
[i
].criterion
== ATTRIB_CRITERION_IGNORE
)
401 attr
= _eglValidationTable
[i
].attr
;
402 cmp
= _eglGetConfigKey(criteria
, attr
);
403 if (cmp
== EGL_DONT_CARE
)
406 val
= _eglGetConfigKey(conf
, attr
);
407 switch (_eglValidationTable
[i
].criterion
) {
408 case ATTRIB_CRITERION_EXACT
:
412 case ATTRIB_CRITERION_ATLEAST
:
416 case ATTRIB_CRITERION_MASK
:
417 if ((val
& cmp
) != cmp
)
420 case ATTRIB_CRITERION_SPECIAL
:
430 /* only print the common errors when DEBUG is not defined */
431 if (attr
!= EGL_RENDERABLE_TYPE
)
435 "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
444 static INLINE EGLBoolean
445 _eglIsConfigAttribValid(_EGLConfig
*conf
, EGLint attr
)
447 if (_eglOffsetOfConfig(attr
) < 0)
451 case EGL_MATCH_NATIVE_PIXMAP
:
453 case EGL_Y_INVERTED_NOK
:
454 return conf
->Display
->Extensions
.NOK_texture_from_pixmap
;
463 * Initialize a criteria config from the given attribute list.
464 * Return EGL_FALSE if any of the attribute is invalid.
467 _eglParseConfigAttribList(_EGLConfig
*conf
, const EGLint
*attrib_list
)
471 /* reset to default values */
472 for (i
= 0; i
< ARRAY_SIZE(_eglValidationTable
); i
++) {
473 attr
= _eglValidationTable
[i
].attr
;
474 val
= _eglValidationTable
[i
].default_value
;
475 _eglSetConfigKey(conf
, attr
, val
);
479 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
+= 2) {
480 attr
= attrib_list
[i
];
481 val
= attrib_list
[i
+ 1];
483 if (!_eglIsConfigAttribValid(conf
, attr
))
486 _eglSetConfigKey(conf
, attr
, val
);
489 if (!_eglValidateConfig(conf
, EGL_TRUE
))
492 /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */
493 if (conf
->Level
== EGL_DONT_CARE
)
496 /* ignore other attributes when EGL_CONFIG_ID is given */
497 if (conf
->ConfigID
> 0) {
498 for (i
= 0; i
< ARRAY_SIZE(_eglValidationTable
); i
++) {
499 attr
= _eglValidationTable
[i
].attr
;
500 if (attr
!= EGL_CONFIG_ID
)
501 _eglSetConfigKey(conf
, attr
, EGL_DONT_CARE
);
505 if (!(conf
->SurfaceType
& EGL_WINDOW_BIT
))
506 conf
->NativeVisualType
= EGL_DONT_CARE
;
508 if (conf
->TransparentType
== EGL_NONE
) {
509 conf
->TransparentRedValue
= EGL_DONT_CARE
;
510 conf
->TransparentGreenValue
= EGL_DONT_CARE
;
511 conf
->TransparentBlueValue
= EGL_DONT_CARE
;
520 * Decide the ordering of conf1 and conf2, under the given criteria.
521 * When compare_id is true, this implements the algorithm described
522 * in "Sorting of EGLConfigs". When compare_id is false,
523 * EGL_CONFIG_ID is not compared.
525 * It returns a negative integer if conf1 is considered to come
526 * before conf2; a positive integer if conf2 is considered to come
527 * before conf1; zero if the ordering cannot be decided.
529 * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
533 _eglCompareConfigs(const _EGLConfig
*conf1
, const _EGLConfig
*conf2
,
534 const _EGLConfig
*criteria
, EGLBoolean compare_id
)
536 const EGLint compare_attribs
[] = {
550 /* the enum values have the desired ordering */
551 assert(EGL_NONE
< EGL_SLOW_CONFIG
);
552 assert(EGL_SLOW_CONFIG
< EGL_NON_CONFORMANT_CONFIG
);
553 val1
= conf1
->ConfigCaveat
- conf2
->ConfigCaveat
;
557 /* the enum values have the desired ordering */
558 assert(EGL_RGB_BUFFER
< EGL_LUMINANCE_BUFFER
);
559 val1
= conf1
->ColorBufferType
- conf2
->ColorBufferType
;
565 if (conf1
->ColorBufferType
== EGL_RGB_BUFFER
) {
566 if (criteria
->RedSize
> 0) {
567 val1
+= conf1
->RedSize
;
568 val2
+= conf2
->RedSize
;
570 if (criteria
->GreenSize
> 0) {
571 val1
+= conf1
->GreenSize
;
572 val2
+= conf2
->GreenSize
;
574 if (criteria
->BlueSize
> 0) {
575 val1
+= conf1
->BlueSize
;
576 val2
+= conf2
->BlueSize
;
580 if (criteria
->LuminanceSize
> 0) {
581 val1
+= conf1
->LuminanceSize
;
582 val2
+= conf2
->LuminanceSize
;
585 if (criteria
->AlphaSize
> 0) {
586 val1
+= conf1
->AlphaSize
;
587 val2
+= conf2
->AlphaSize
;
591 /* assume the default criteria, which gives no specific ordering */
595 /* for color bits, larger one is preferred */
597 return (val2
- val1
);
599 for (i
= 0; i
< ARRAY_SIZE(compare_attribs
); i
++) {
600 val1
= _eglGetConfigKey(conf1
, compare_attribs
[i
]);
601 val2
= _eglGetConfigKey(conf2
, compare_attribs
[i
]);
603 return (val1
- val2
);
606 /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
608 return (compare_id
) ? (conf1
->ConfigID
- conf2
->ConfigID
) : 0;
613 void _eglSwapConfigs(const _EGLConfig
**conf1
, const _EGLConfig
**conf2
)
615 const _EGLConfig
*tmp
= *conf1
;
622 * Quick sort an array of configs. This differs from the standard
623 * qsort() in that the compare function accepts an additional
627 _eglSortConfigs(const _EGLConfig
**configs
, EGLint count
,
628 EGLint (*compare
)(const _EGLConfig
*, const _EGLConfig
*,
632 const EGLint pivot
= 0;
638 _eglSwapConfigs(&configs
[pivot
], &configs
[count
/ 2]);
642 while (i
< count
&& compare(configs
[i
], configs
[pivot
], priv_data
) < 0)
644 while (compare(configs
[j
], configs
[pivot
], priv_data
) > 0)
647 _eglSwapConfigs(&configs
[i
], &configs
[j
]);
657 _eglSwapConfigs(&configs
[pivot
], &configs
[j
]);
659 _eglSortConfigs(configs
, j
, compare
, priv_data
);
660 _eglSortConfigs(configs
+ i
, count
- i
, compare
, priv_data
);
665 _eglFallbackCompare(const _EGLConfig
*conf1
, const _EGLConfig
*conf2
,
668 const _EGLConfig
*criteria
= (const _EGLConfig
*) priv_data
;
669 return _eglCompareConfigs(conf1
, conf2
, criteria
, EGL_TRUE
);
674 * Typical fallback routine for eglChooseConfig
677 _eglChooseConfig(_EGLDriver
*drv
, _EGLDisplay
*disp
, const EGLint
*attrib_list
,
678 EGLConfig
*configs
, EGLint config_size
, EGLint
*num_configs
)
680 _EGLConfig
**configList
, criteria
;
684 return _eglError(EGL_BAD_PARAMETER
, "eglChooseConfigs");
686 _eglInitConfig(&criteria
, disp
, 0);
687 if (!_eglParseConfigAttribList(&criteria
, attrib_list
))
688 return _eglError(EGL_BAD_ATTRIBUTE
, "eglChooseConfig");
690 configList
= (_EGLConfig
**) _eglFilterArray(disp
->Configs
, &count
,
691 (_EGLArrayForEach
) _eglMatchConfig
, (void *) &criteria
);
693 return _eglError(EGL_BAD_ALLOC
, "eglChooseConfig(out of memory)");
695 /* perform sorting of configs */
696 if (configs
&& count
) {
697 _eglSortConfigs((const _EGLConfig
**) configList
, count
,
698 _eglFallbackCompare
, (void *) &criteria
);
699 count
= MIN2(count
, config_size
);
700 for (i
= 0; i
< count
; i
++)
701 configs
[i
] = _eglGetConfigHandle(configList
[i
]);
706 *num_configs
= count
;
713 * Fallback for eglGetConfigAttrib.
716 _eglGetConfigAttrib(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
717 EGLint attribute
, EGLint
*value
)
719 if (!_eglIsConfigAttribValid(conf
, attribute
))
720 return _eglError(EGL_BAD_ATTRIBUTE
, "eglGetConfigAttrib");
722 return _eglError(EGL_BAD_PARAMETER
, "eglGetConfigAttrib");
724 *value
= _eglGetConfigKey(conf
, attribute
);
730 _eglFlattenConfig(void *elem
, void *buffer
)
732 _EGLConfig
*conf
= (_EGLConfig
*) elem
;
733 EGLConfig
*handle
= (EGLConfig
*) buffer
;
734 *handle
= _eglGetConfigHandle(conf
);
739 * Fallback for eglGetConfigs.
742 _eglGetConfigs(_EGLDriver
*drv
, _EGLDisplay
*disp
, EGLConfig
*configs
,
743 EGLint config_size
, EGLint
*num_config
)
746 return _eglError(EGL_BAD_PARAMETER
, "eglGetConfigs");
748 *num_config
= _eglFlattenArray(disp
->Configs
, (void *) configs
,
749 sizeof(configs
[0]), config_size
, _eglFlattenConfig
);