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