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