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