Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / egl / main / eglconfig.c
1 /**
2 * EGL Configuration (pixel format) functions.
3 */
4
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <assert.h>
9 #include "eglconfig.h"
10 #include "egldisplay.h"
11 #include "eglcurrent.h"
12 #include "egllog.h"
13
14
15 #define MIN2(A, B) (((A) < (B)) ? (A) : (B))
16
17
18 /**
19 * Init the given _EGLconfig to default values.
20 * \param id the configuration's ID.
21 *
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.
25 */
26 void
27 _eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id)
28 {
29 memset(conf, 0, sizeof(*conf));
30
31 conf->Display = dpy;
32
33 /* some attributes take non-zero default values */
34 conf->ConfigID = id;
35 conf->ConfigCaveat = EGL_NONE;
36 conf->TransparentType = EGL_NONE;
37 conf->NativeVisualType = EGL_NONE;
38 conf->ColorBufferType = EGL_RGB_BUFFER;
39 }
40
41
42 /**
43 * Link a config to a display and return the handle of the link.
44 * The handle can be passed to client directly.
45 *
46 * Note that we just save the ptr to the config (we don't copy the config).
47 */
48 EGLConfig
49 _eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
50 {
51 /* sanity check */
52 assert(conf->ConfigID > 0);
53
54 if (!dpy->Configs) {
55 dpy->Configs = _eglCreateArray("Config", 16);
56 if (!dpy->Configs)
57 return (EGLConfig) NULL;
58 }
59
60 conf->Display = dpy;
61 _eglAppendArray(dpy->Configs, (void *) conf);
62
63 return (EGLConfig) conf;
64 }
65
66
67 EGLBoolean
68 _eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
69 {
70 _EGLConfig *conf;
71
72 conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
73 if (conf)
74 assert(conf->Display == dpy);
75
76 return (conf != NULL);
77 }
78
79
80 enum {
81 /* types */
82 ATTRIB_TYPE_INTEGER,
83 ATTRIB_TYPE_BOOLEAN,
84 ATTRIB_TYPE_BITMASK,
85 ATTRIB_TYPE_ENUM,
86 ATTRIB_TYPE_PSEUDO, /* non-queryable */
87 ATTRIB_TYPE_PLATFORM, /* platform-dependent */
88 /* criteria */
89 ATTRIB_CRITERION_EXACT,
90 ATTRIB_CRITERION_ATLEAST,
91 ATTRIB_CRITERION_MASK,
92 ATTRIB_CRITERION_SPECIAL,
93 ATTRIB_CRITERION_IGNORE
94 };
95
96
97 /* EGL spec Table 3.1 and 3.4 */
98 static const struct {
99 EGLint attr;
100 EGLint type;
101 EGLint criterion;
102 EGLint default_value;
103 } _eglValidationTable[] =
104 {
105 /* core */
106 { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER,
107 ATTRIB_CRITERION_ATLEAST,
108 0 },
109 { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER,
110 ATTRIB_CRITERION_ATLEAST,
111 0 },
112 { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER,
113 ATTRIB_CRITERION_ATLEAST,
114 0 },
115 { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER,
116 ATTRIB_CRITERION_ATLEAST,
117 0 },
118 { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER,
119 ATTRIB_CRITERION_ATLEAST,
120 0 },
121 { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER,
122 ATTRIB_CRITERION_ATLEAST,
123 0 },
124 { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER,
125 ATTRIB_CRITERION_ATLEAST,
126 0 },
127 { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN,
128 ATTRIB_CRITERION_EXACT,
129 EGL_DONT_CARE },
130 { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN,
131 ATTRIB_CRITERION_EXACT,
132 EGL_DONT_CARE },
133 { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM,
134 ATTRIB_CRITERION_EXACT,
135 EGL_RGB_BUFFER },
136 { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM,
137 ATTRIB_CRITERION_EXACT,
138 EGL_DONT_CARE },
139 { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER,
140 ATTRIB_CRITERION_EXACT,
141 EGL_DONT_CARE },
142 { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK,
143 ATTRIB_CRITERION_MASK,
144 0 },
145 { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER,
146 ATTRIB_CRITERION_ATLEAST,
147 0 },
148 { EGL_LEVEL, ATTRIB_TYPE_PLATFORM,
149 ATTRIB_CRITERION_EXACT,
150 0 },
151 { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER,
152 ATTRIB_CRITERION_IGNORE,
153 0 },
154 { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER,
155 ATTRIB_CRITERION_IGNORE,
156 0 },
157 { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER,
158 ATTRIB_CRITERION_IGNORE,
159 0 },
160 { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
161 ATTRIB_CRITERION_EXACT,
162 EGL_DONT_CARE },
163 { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
164 ATTRIB_CRITERION_EXACT,
165 EGL_DONT_CARE },
166 { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN,
167 ATTRIB_CRITERION_EXACT,
168 EGL_DONT_CARE },
169 { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM,
170 ATTRIB_CRITERION_IGNORE,
171 0 },
172 { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM,
173 ATTRIB_CRITERION_EXACT,
174 EGL_DONT_CARE },
175 { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK,
176 ATTRIB_CRITERION_MASK,
177 EGL_OPENGL_ES_BIT },
178 { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER,
179 ATTRIB_CRITERION_ATLEAST,
180 0 },
181 { EGL_SAMPLES, ATTRIB_TYPE_INTEGER,
182 ATTRIB_CRITERION_ATLEAST,
183 0 },
184 { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER,
185 ATTRIB_CRITERION_ATLEAST,
186 0 },
187 { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK,
188 ATTRIB_CRITERION_MASK,
189 EGL_WINDOW_BIT },
190 { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM,
191 ATTRIB_CRITERION_EXACT,
192 EGL_NONE },
193 { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER,
194 ATTRIB_CRITERION_EXACT,
195 EGL_DONT_CARE },
196 { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER,
197 ATTRIB_CRITERION_EXACT,
198 EGL_DONT_CARE },
199 { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER,
200 ATTRIB_CRITERION_EXACT,
201 EGL_DONT_CARE },
202 { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO,
203 ATTRIB_CRITERION_SPECIAL,
204 EGL_NONE },
205 /* extensions */
206 { EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN,
207 ATTRIB_CRITERION_EXACT,
208 EGL_DONT_CARE }
209 };
210
211
212 /**
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.
216 *
217 * Note that some attributes are platform-dependent and are not
218 * checked.
219 */
220 EGLBoolean
221 _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
222 {
223 EGLint i, attr, val;
224 EGLBoolean valid = EGL_TRUE;
225
226 /* check attributes by their types */
227 for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
228 EGLint mask;
229
230 attr = _eglValidationTable[i].attr;
231 val = _eglGetConfigKey(conf, attr);
232
233 switch (_eglValidationTable[i].type) {
234 case ATTRIB_TYPE_INTEGER:
235 switch (attr) {
236 case EGL_CONFIG_ID:
237 /* config id must be positive */
238 if (val <= 0)
239 valid = EGL_FALSE;
240 break;
241 case EGL_SAMPLE_BUFFERS:
242 /* there can be at most 1 sample buffer */
243 if (val > 1 || val < 0)
244 valid = EGL_FALSE;
245 break;
246 default:
247 if (val < 0)
248 valid = EGL_FALSE;
249 break;
250 }
251 break;
252 case ATTRIB_TYPE_BOOLEAN:
253 if (val != EGL_TRUE && val != EGL_FALSE)
254 valid = EGL_FALSE;
255 break;
256 case ATTRIB_TYPE_ENUM:
257 switch (attr) {
258 case EGL_CONFIG_CAVEAT:
259 if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
260 val != EGL_NON_CONFORMANT_CONFIG)
261 valid = EGL_FALSE;
262 break;
263 case EGL_TRANSPARENT_TYPE:
264 if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
265 valid = EGL_FALSE;
266 break;
267 case EGL_COLOR_BUFFER_TYPE:
268 if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
269 valid = EGL_FALSE;
270 break;
271 default:
272 assert(0);
273 break;
274 }
275 break;
276 case ATTRIB_TYPE_BITMASK:
277 switch (attr) {
278 case EGL_SURFACE_TYPE:
279 mask = EGL_PBUFFER_BIT |
280 EGL_PIXMAP_BIT |
281 EGL_WINDOW_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;
289 #endif
290 break;
291 case EGL_RENDERABLE_TYPE:
292 case EGL_CONFORMANT:
293 mask = EGL_OPENGL_ES_BIT |
294 EGL_OPENVG_BIT |
295 EGL_OPENGL_ES2_BIT |
296 EGL_OPENGL_BIT;
297 break;
298 default:
299 assert(0);
300 break;
301 }
302 if (val & ~mask)
303 valid = EGL_FALSE;
304 break;
305 case ATTRIB_TYPE_PLATFORM:
306 /* unable to check platform-dependent attributes here */
307 break;
308 case ATTRIB_TYPE_PSEUDO:
309 /* pseudo attributes should not be set */
310 if (val != 0)
311 valid = EGL_FALSE;
312 break;
313 default:
314 assert(0);
315 break;
316 }
317
318 if (!valid && for_matching) {
319 /* accept EGL_DONT_CARE as a valid value */
320 if (val == EGL_DONT_CARE)
321 valid = EGL_TRUE;
322 if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
323 valid = EGL_TRUE;
324 }
325 if (!valid) {
326 _eglLog(_EGL_DEBUG,
327 "attribute 0x%04x has an invalid value 0x%x", attr, val);
328 break;
329 }
330 }
331
332 /* any invalid attribute value should have been catched */
333 if (!valid || for_matching)
334 return valid;
335
336 /* now check for conflicting attribute values */
337
338 switch (conf->ColorBufferType) {
339 case EGL_RGB_BUFFER:
340 if (conf->LuminanceSize)
341 valid = EGL_FALSE;
342 if (conf->RedSize + conf->GreenSize +
343 conf->BlueSize + conf->AlphaSize != conf->BufferSize)
344 valid = EGL_FALSE;
345 break;
346 case EGL_LUMINANCE_BUFFER:
347 if (conf->RedSize || conf->GreenSize || conf->BlueSize)
348 valid = EGL_FALSE;
349 if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
350 valid = EGL_FALSE;
351 break;
352 }
353 if (!valid) {
354 _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
355 return EGL_FALSE;
356 }
357
358 if (!conf->SampleBuffers && conf->Samples)
359 valid = EGL_FALSE;
360 if (!valid) {
361 _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
362 return EGL_FALSE;
363 }
364
365 if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
366 if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE)
367 valid = EGL_FALSE;
368 }
369 if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) {
370 if (conf->BindToTextureRGB || conf->BindToTextureRGBA)
371 valid = EGL_FALSE;
372 }
373 if (!valid) {
374 _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
375 return EGL_FALSE;
376 }
377
378 return valid;
379 }
380
381
382 /**
383 * Return true if a config matches the criteria. This and
384 * _eglParseConfigAttribList together implement the algorithm
385 * described in "Selection of EGLConfigs".
386 *
387 * Note that attributes that are special (currently, only
388 * EGL_MATCH_NATIVE_PIXMAP) are ignored.
389 */
390 EGLBoolean
391 _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
392 {
393 EGLint attr, val, i;
394 EGLBoolean matched = EGL_TRUE;
395
396 for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
397 EGLint cmp;
398 if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
399 continue;
400
401 attr = _eglValidationTable[i].attr;
402 cmp = _eglGetConfigKey(criteria, attr);
403 if (cmp == EGL_DONT_CARE)
404 continue;
405
406 val = _eglGetConfigKey(conf, attr);
407 switch (_eglValidationTable[i].criterion) {
408 case ATTRIB_CRITERION_EXACT:
409 if (val != cmp)
410 matched = EGL_FALSE;
411 break;
412 case ATTRIB_CRITERION_ATLEAST:
413 if (val < cmp)
414 matched = EGL_FALSE;
415 break;
416 case ATTRIB_CRITERION_MASK:
417 if ((val & cmp) != cmp)
418 matched = EGL_FALSE;
419 break;
420 case ATTRIB_CRITERION_SPECIAL:
421 /* ignored here */
422 break;
423 default:
424 assert(0);
425 break;
426 }
427
428 if (!matched) {
429 #ifndef DEBUG
430 /* only print the common errors when DEBUG is not defined */
431 if (attr != EGL_RENDERABLE_TYPE)
432 break;
433 #endif
434 _eglLog(_EGL_DEBUG,
435 "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
436 val, attr, cmp);
437 break;
438 }
439 }
440
441 return matched;
442 }
443
444 static INLINE EGLBoolean
445 _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
446 {
447 if (_eglOffsetOfConfig(attr) < 0)
448 return EGL_FALSE;
449
450 switch (attr) {
451 case EGL_MATCH_NATIVE_PIXMAP:
452 return EGL_FALSE;
453 case EGL_Y_INVERTED_NOK:
454 return conf->Display->Extensions.NOK_texture_from_pixmap;
455 default:
456 break;
457 }
458
459 return EGL_TRUE;
460 }
461
462 /**
463 * Initialize a criteria config from the given attribute list.
464 * Return EGL_FALSE if any of the attribute is invalid.
465 */
466 EGLBoolean
467 _eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list)
468 {
469 EGLint attr, val, i;
470
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);
476 }
477
478 /* parse the list */
479 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
480 attr = attrib_list[i];
481 val = attrib_list[i + 1];
482
483 if (!_eglIsConfigAttribValid(conf, attr))
484 return EGL_FALSE;
485
486 _eglSetConfigKey(conf, attr, val);
487 }
488
489 if (!_eglValidateConfig(conf, EGL_TRUE))
490 return EGL_FALSE;
491
492 /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */
493 if (conf->Level == EGL_DONT_CARE)
494 return EGL_FALSE;
495
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);
502 }
503 }
504 else {
505 if (!(conf->SurfaceType & EGL_WINDOW_BIT))
506 conf->NativeVisualType = EGL_DONT_CARE;
507
508 if (conf->TransparentType == EGL_NONE) {
509 conf->TransparentRedValue = EGL_DONT_CARE;
510 conf->TransparentGreenValue = EGL_DONT_CARE;
511 conf->TransparentBlueValue = EGL_DONT_CARE;
512 }
513 }
514
515 return EGL_TRUE;
516 }
517
518
519 /**
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.
524 *
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.
528 *
529 * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
530 * ignored here.
531 */
532 EGLint
533 _eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
534 const _EGLConfig *criteria, EGLBoolean compare_id)
535 {
536 const EGLint compare_attribs[] = {
537 EGL_BUFFER_SIZE,
538 EGL_SAMPLE_BUFFERS,
539 EGL_SAMPLES,
540 EGL_DEPTH_SIZE,
541 EGL_STENCIL_SIZE,
542 EGL_ALPHA_MASK_SIZE,
543 };
544 EGLint val1, val2;
545 EGLint i;
546
547 if (conf1 == conf2)
548 return 0;
549
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;
554 if (val1)
555 return val1;
556
557 /* the enum values have the desired ordering */
558 assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
559 val1 = conf1->ColorBufferType - conf2->ColorBufferType;
560 if (val1)
561 return val1;
562
563 if (criteria) {
564 val1 = val2 = 0;
565 if (conf1->ColorBufferType == EGL_RGB_BUFFER) {
566 if (criteria->RedSize > 0) {
567 val1 += conf1->RedSize;
568 val2 += conf2->RedSize;
569 }
570 if (criteria->GreenSize > 0) {
571 val1 += conf1->GreenSize;
572 val2 += conf2->GreenSize;
573 }
574 if (criteria->BlueSize > 0) {
575 val1 += conf1->BlueSize;
576 val2 += conf2->BlueSize;
577 }
578 }
579 else {
580 if (criteria->LuminanceSize > 0) {
581 val1 += conf1->LuminanceSize;
582 val2 += conf2->LuminanceSize;
583 }
584 }
585 if (criteria->AlphaSize > 0) {
586 val1 += conf1->AlphaSize;
587 val2 += conf2->AlphaSize;
588 }
589 }
590 else {
591 /* assume the default criteria, which gives no specific ordering */
592 val1 = val2 = 0;
593 }
594
595 /* for color bits, larger one is preferred */
596 if (val1 != val2)
597 return (val2 - val1);
598
599 for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
600 val1 = _eglGetConfigKey(conf1, compare_attribs[i]);
601 val2 = _eglGetConfigKey(conf2, compare_attribs[i]);
602 if (val1 != val2)
603 return (val1 - val2);
604 }
605
606 /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
607
608 return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
609 }
610
611
612 static INLINE
613 void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
614 {
615 const _EGLConfig *tmp = *conf1;
616 *conf1 = *conf2;
617 *conf2 = tmp;
618 }
619
620
621 /**
622 * Quick sort an array of configs. This differs from the standard
623 * qsort() in that the compare function accepts an additional
624 * argument.
625 */
626 void
627 _eglSortConfigs(const _EGLConfig **configs, EGLint count,
628 EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
629 void *),
630 void *priv_data)
631 {
632 const EGLint pivot = 0;
633 EGLint i, j;
634
635 if (count <= 1)
636 return;
637
638 _eglSwapConfigs(&configs[pivot], &configs[count / 2]);
639 i = 1;
640 j = count - 1;
641 do {
642 while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
643 i++;
644 while (compare(configs[j], configs[pivot], priv_data) > 0)
645 j--;
646 if (i < j) {
647 _eglSwapConfigs(&configs[i], &configs[j]);
648 i++;
649 j--;
650 }
651 else if (i == j) {
652 i++;
653 j--;
654 break;
655 }
656 } while (i <= j);
657 _eglSwapConfigs(&configs[pivot], &configs[j]);
658
659 _eglSortConfigs(configs, j, compare, priv_data);
660 _eglSortConfigs(configs + i, count - i, compare, priv_data);
661 }
662
663
664 static int
665 _eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
666 void *priv_data)
667 {
668 const _EGLConfig *criteria = (const _EGLConfig *) priv_data;
669 return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE);
670 }
671
672
673 /**
674 * Typical fallback routine for eglChooseConfig
675 */
676 EGLBoolean
677 _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
678 EGLConfig *configs, EGLint config_size, EGLint *num_configs)
679 {
680 _EGLConfig **configList, criteria;
681 EGLint i, count;
682
683 if (!num_configs)
684 return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
685
686 _eglInitConfig(&criteria, disp, 0);
687 if (!_eglParseConfigAttribList(&criteria, attrib_list))
688 return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
689
690 configList = (_EGLConfig **) _eglFilterArray(disp->Configs, &count,
691 (_EGLArrayForEach) _eglMatchConfig, (void *) &criteria);
692 if (!configList)
693 return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
694
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]);
702 }
703
704 free(configList);
705
706 *num_configs = count;
707
708 return EGL_TRUE;
709 }
710
711
712 /**
713 * Fallback for eglGetConfigAttrib.
714 */
715 EGLBoolean
716 _eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
717 EGLint attribute, EGLint *value)
718 {
719 if (!_eglIsConfigAttribValid(conf, attribute))
720 return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
721 if (!value)
722 return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
723
724 *value = _eglGetConfigKey(conf, attribute);
725 return EGL_TRUE;
726 }
727
728
729 static EGLBoolean
730 _eglFlattenConfig(void *elem, void *buffer)
731 {
732 _EGLConfig *conf = (_EGLConfig *) elem;
733 EGLConfig *handle = (EGLConfig *) buffer;
734 *handle = _eglGetConfigHandle(conf);
735 return EGL_TRUE;
736 }
737
738 /**
739 * Fallback for eglGetConfigs.
740 */
741 EGLBoolean
742 _eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
743 EGLint config_size, EGLint *num_config)
744 {
745 if (!num_config)
746 return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
747
748 *num_config = _eglFlattenArray(disp->Configs, (void *) configs,
749 sizeof(configs[0]), config_size, _eglFlattenConfig);
750
751 return EGL_TRUE;
752 }