1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28/*
29 A FEATURES_T is a structure represented by a bit pattern
30
31 Constructed with FEATURES_PACK(red, green, blue, alpha, depth, stencil, multi, mask, lockable)
32
33 Attributes are returned with
34 FEATURES_UNPACK_RED(c)
35 FEATURES_UNPACK_GREEN(c)
36 FEATURES_UNPACK_BLUE(c)
37 FEATURES_UNPACK_ALPHA(c)
38 FEATURES_UNPACK_DEPTH(c)
39 FEATURES_UNPACK_STENCIL(c)
40 FEATURES_UNPACK_MULTI(c)
41 FEATURES_UNPACK_MASK(c)
42 FEATURES_UNPACK_LOCKABLE(c)
43
44 Additionally,
45 FEATURES_UNPACK_COLOR(c) = red + green + blue + alpha
46
47 Attributes can take the following values:
48 0 <= red <= 15
49 0 <= green <= 15
50 0 <= blue <= 15
51 0 <= alpha <= 15
52 0 <= depth <= 255
53 0 <= stencil <= 15
54 multi in {0,1}
55 mask in {0,8}
56 lockable in {0,1}
57
58*/
59
60
61#define FEATURES_UNPACK_RED(c) ((EGLint)((c) >> 28 & 0xf))
62#define FEATURES_UNPACK_GREEN(c) ((EGLint)((c) >> 24 & 0xf))
63#define FEATURES_UNPACK_BLUE(c) ((EGLint)((c) >> 20 & 0xf))
64#define FEATURES_UNPACK_ALPHA(c) ((EGLint)((c) >> 16 & 0xf))
65#define FEATURES_UNPACK_DEPTH(c) ((EGLint)((c) >> 8 & 0xff))
66#define FEATURES_UNPACK_STENCIL(c) ((EGLint)((c) >> 4 & 0xf))
67#define FEATURES_UNPACK_MULTI(c) ((EGLint)((c) >> 3 & 0x1))
68#define FEATURES_UNPACK_MASK(c) ((EGLint)(((c) >> 2 & 0x1) << 3))
69#define FEATURES_UNPACK_LOCKABLE(c) ((c) >> 1 & 0x1)
70
71#define FEATURES_UNPACK_COLOR(c) (FEATURES_UNPACK_RED(c)+FEATURES_UNPACK_GREEN(c)+FEATURES_UNPACK_BLUE(c)+FEATURES_UNPACK_ALPHA(c))
72
73/*
74 bool egl_config_check_attribs(const EGLint *attrib_list, bool *use_red, bool *use_green, bool *use_blue, bool *use_alpha)
75
76 Checks whether all attributes and values are valid. Returns whether the list includes each of
77 EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, EGL_ALPHA_SIZE
78
79 We use the table in eglGetConfigAttrib to guide us as to which values are valid.
80
81 Implementation notes:
82
83 -
84
85 Preconditions:
86
87 use_red, use_green, use_blue, use_alpha are valid pointers
88 attrib_list is NULL or a pointer to an EGL_NONE-terminated list of attribute/value pairs
89
90 Postconditions:
91
92 If list is valid then we return true and:
93 use_red is set to true iff attrib_list includes EGL_RED_SIZE and the corresponding value is not 0 or EGL_DONT_CARE
94 use_green, use_blue, use_alpha similarly
95 all attributes in list are valid
96 Else we return false.
97
98 Invariants preserved:
99
100 -
101
102 Invariants used:
103
104 -
105*/
106
107bool egl_config_check_attribs(const EGLint *attrib_list, bool *use_red, bool *use_green, bool *use_blue, bool *use_alpha)
108{
109 if (!attrib_list)
110 return true;
111
112 while (*attrib_list != EGL_NONE) {
113 EGLint name = *attrib_list++;
114 EGLint value = *attrib_list++;
115
116 if (name == EGL_RED_SIZE && value != 0 && value != EGL_DONT_CARE)
117 *use_red = true;
118
119 if (name == EGL_GREEN_SIZE && value != 0 && value != EGL_DONT_CARE)
120 *use_green = true;
121
122 if (name == EGL_BLUE_SIZE && value != 0 && value != EGL_DONT_CARE)
123 *use_blue = true;
124
125 if (name == EGL_ALPHA_SIZE && value != 0 && value != EGL_DONT_CARE)
126 *use_alpha = true;
127
128 switch (name) {
129 case EGL_BUFFER_SIZE:
130 case EGL_RED_SIZE:
131 case EGL_GREEN_SIZE:
132 case EGL_BLUE_SIZE:
133 case EGL_LUMINANCE_SIZE:
134 case EGL_ALPHA_SIZE:
135 case EGL_ALPHA_MASK_SIZE:
136 if (value != EGL_DONT_CARE && value < 0) return false;
137 break;
138 case EGL_BIND_TO_TEXTURE_RGB:
139 case EGL_BIND_TO_TEXTURE_RGBA:
140 if (value != EGL_DONT_CARE && value != EGL_FALSE && value != EGL_TRUE)
141 return false;
142 break;
143 case EGL_COLOR_BUFFER_TYPE:
144 if (value != EGL_DONT_CARE && value != EGL_RGB_BUFFER && value != EGL_LUMINANCE_BUFFER)
145 return false;
146 break;
147 case EGL_CONFIG_CAVEAT:
148 if (value != EGL_DONT_CARE && value != EGL_NONE && value != EGL_SLOW_CONFIG && value != EGL_NON_CONFORMANT_CONFIG)
149 return false;
150 break;
151 case EGL_CONFIG_ID:
152 if (value != EGL_DONT_CARE && value < 1)
153 return false;
154 break;
155 case EGL_CONFORMANT:
156 if (value != EGL_DONT_CARE && (value & ~(EGL_OPENGL_BIT|EGL_OPENGL_ES_BIT|EGL_OPENGL_ES2_BIT|EGL_OPENVG_BIT)))
157 return false;
158 break;
159 case EGL_DEPTH_SIZE:
160 if (value != EGL_DONT_CARE && value < 0) return false;
161 break;
162 case EGL_LEVEL:
163 break;
164 case EGL_MATCH_NATIVE_PIXMAP:
165 /* 1.4 Spec is poor here - says that value has to be a valid handle, but also says that any attribute
166 * value (other than EGL_LEVEL) can be EGL_DONT_CARE. It also says that the default value is EGL_NONE,
167 * but that doesn't really make sense - sensible to assume that the default is EGL_DONT_CARE, and don't
168 * support EGL_NONE as an explicit parameter. (Could theoretically collide with a real handle...)
169 */
170 if (value != EGL_DONT_CARE) {
171 KHRN_IMAGE_WRAP_T image;
172 if (!platform_get_pixmap_info((EGLNativePixmapType)(intptr_t)value, &image))
173 return false;
174 khrn_platform_release_pixmap_info((EGLNativePixmapType)(intptr_t)value, &image);
175 }
176 break;
177 case EGL_MAX_PBUFFER_WIDTH:
178 case EGL_MAX_PBUFFER_HEIGHT:
179 case EGL_MAX_PBUFFER_PIXELS:
180 break;
181 case EGL_MAX_SWAP_INTERVAL:
182 case EGL_MIN_SWAP_INTERVAL:
183 if (value != EGL_DONT_CARE && value < 0) return false;
184 break;
185 case EGL_NATIVE_RENDERABLE:
186 if (value != EGL_DONT_CARE && value != EGL_FALSE && value != EGL_TRUE)
187 return false;
188 break;
189 case EGL_NATIVE_VISUAL_ID:
190 case EGL_NATIVE_VISUAL_TYPE:
191 break;
192 case EGL_RENDERABLE_TYPE:
193 if (value != EGL_DONT_CARE && (value & ~(EGL_OPENGL_BIT|EGL_OPENGL_ES_BIT|EGL_OPENGL_ES2_BIT|EGL_OPENVG_BIT)))
194 return false;
195 break;
196 case EGL_SAMPLE_BUFFERS:
197 case EGL_SAMPLES:
198 case EGL_STENCIL_SIZE:
199 if (value != EGL_DONT_CARE && value < 0) return false;
200 break;
201 case EGL_SURFACE_TYPE:
202 {
203 int valid_bits = EGL_WINDOW_BIT|EGL_PIXMAP_BIT|EGL_PBUFFER_BIT|
204 EGL_MULTISAMPLE_RESOLVE_BOX_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT|
205 EGL_VG_COLORSPACE_LINEAR_BIT|EGL_VG_ALPHA_FORMAT_PRE_BIT;
206#if EGL_KHR_lock_surface
207 valid_bits |= EGL_LOCK_SURFACE_BIT_KHR|EGL_OPTIMAL_FORMAT_BIT_KHR;
208#endif
209 if (value != EGL_DONT_CARE && (value & ~valid_bits))
210 return false;
211 break;
212 }
213 case EGL_TRANSPARENT_TYPE:
214 if (value != EGL_DONT_CARE && value != EGL_NONE && value != EGL_TRANSPARENT_RGB)
215 return false;
216 break;
217 case EGL_TRANSPARENT_RED_VALUE:
218 case EGL_TRANSPARENT_GREEN_VALUE:
219 case EGL_TRANSPARENT_BLUE_VALUE:
220 if (value != EGL_DONT_CARE && value < 0) return false;
221 break;
222#if EGL_KHR_lock_surface
223 case EGL_MATCH_FORMAT_KHR:
224 switch (value) {
225 case EGL_DONT_CARE:
226 case EGL_NONE:
227 case EGL_FORMAT_RGB_565_EXACT_KHR:
228 case EGL_FORMAT_RGB_565_KHR:
229 case EGL_FORMAT_RGBA_8888_EXACT_KHR:
230 case EGL_FORMAT_RGBA_8888_KHR:
231 break;
232 default:
233 return false;
234 }
235 break;
236#endif
237#if EGL_ANDROID_recordable
238 case EGL_RECORDABLE_ANDROID:
239 switch (value) {
240 case EGL_DONT_CARE:
241 case EGL_TRUE:
242 case EGL_FALSE:
243 break;
244 default:
245 return false;
246 }
247 break;
248#endif
249 default:
250 return false;
251 }
252 }
253
254 return true;
255}
256
257/*
258 bool less_than(int id0, int id1, bool use_red, bool use_green, bool use_blue, bool use_alpha)
259
260 total ordering on configs; sort in
261
262 - decreasing order of color buffer depth, ignoring components for which we have not expressed a preference
263 - increasing order of color buffer depth
264 - increasing order of multisample buffers
265 - increasing order of depth buffer depth
266 - increasing order of stencil buffer depth
267 - increasing order of mask buffer depth
268
269 Implementation notes:
270
271 We ignore:
272 EGL_CONFIG_CAVEAT (all EGL_NONE)
273 EGL_COLOR_BUFFER_TYPE (all EGL_RGB_BUFFER)
274 EGL_SAMPLES (if EGL_SAMPLES is 1 then all 4 else all 0)
275 EGL_NATIVE_VISUAL_TYPE (all EGL_NONE)
276 EGL_CONFIG_ID (already sorted in this order and sort algorithm is stable)
277
278 Khrnonos documentation:
279
280 Sorting of EGLConfigs
281 If more than one matching EGLConfig is found, then a list of EGLConfigs
282 is returned. The list is sorted by proceeding in ascending order of the ”Sort Priority”
283 column of table 3.4. That is, configurations that are not ordered by a lower
284 numbered rule are sorted by the next higher numbered rule.
285 Sorting for each rule is either numerically Smaller or Larger as described in the
286 ”Sort Order” column, or a Special sort order as described for each sort rule below:
287 1. Special: by EGL CONFIG CAVEAT where the precedence is EGL NONE,
288 EGL SLOW CONFIG, EGL NON CONFORMANT CONFIG.
289 2. Special:
290 by EGL COLOR BUFFER TYPE where the precedence is EGL RGB BUFFER,
291 EGL LUMINANCE BUFFER.
292 3. Special: by larger total number of color bits (for an RGB color buffer,
293 this is the sum of EGL RED SIZE, EGL GREEN SIZE, EGL BLUE SIZE,
294 and EGL ALPHA SIZE; for a luminance color buffer, the sum of
295 EGL LUMINANCE SIZE and EGL ALPHA SIZE) [3]. If the requested number
296 of bits in attrib list for a particular color component is 0 or EGL_DONT_CARE,
297 then the number of bits for that component is not considered.
298 4. Smaller EGL BUFFER SIZE.
299 5. Smaller EGL SAMPLE BUFFERS.
300 6. Smaller EGL SAMPLES.
301 7. Smaller EGL DEPTH SIZE.
302 8. Smaller EGL STENCIL SIZE.
303 9. Smaller EGL ALPHA MASK SIZE.
304 10. Special: by EGL NATIVE VISUAL TYPE (the actual sort order is
305 implementation-defined, depending on the meaning of native visual types).
306 11. Smaller EGL CONFIG ID (this is always the last sorting rule, and guarantees
307 a unique ordering).
308 EGLConfigs are not sorted with respect to the parameters
309 EGL BIND TO TEXTURE RGB, EGL BIND TO TEXTURE RGBA, EGL CONFORMANT,
310 EGL LEVEL, EGL NATIVE RENDERABLE, EGL MAX SWAP INTERVAL,
311 EGL MIN SWAP INTERVAL, EGL RENDERABLE TYPE, EGL SURFACE TYPE,
312 EGL TRANSPARENT TYPE, EGL TRANSPARENT RED VALUE,
313 EGL TRANSPARENT GREEN VALUE, and EGL TRANSPARENT BLUE VALUE.
314
315 3This rule places configs with deeper color buffers first in the list returned by eglChooseConfig.
316Applications may find this counterintuitive, and need to perform additional processing on the list of
317configs to find one best matching their requirements. For example, specifying RGBA depths of 5651
318could return a list whose first config has a depth of 8888.
319
320
321 Preconditions:
322
323 0 <= id0 < EGL_MAX_CONFIGS
324 0 <= id1 < EGL_MAX_CONFIGS
325
326 Postconditions:
327
328 -
329
330 Invariants preserved:
331
332 -
333
334 Invariants used:
335
336 -
337*/
338
339static bool less_than(int id0, int id1, bool use_red, bool use_green, bool use_blue, bool use_alpha)
340{
341 FEATURES_T features0 = formats[id0].features;
342 FEATURES_T features1 = formats[id1].features;
343
344 EGLint all0 = FEATURES_UNPACK_COLOR(features0);
345 EGLint all1 = FEATURES_UNPACK_COLOR(features1);
346
347 EGLint multi0 = FEATURES_UNPACK_MULTI(features0);
348 EGLint multi1 = FEATURES_UNPACK_MULTI(features1);
349
350 EGLint depth0 = FEATURES_UNPACK_DEPTH(features0);
351 EGLint depth1 = FEATURES_UNPACK_DEPTH(features1);
352
353 EGLint stencil0 = FEATURES_UNPACK_STENCIL(features0);
354 EGLint stencil1 = FEATURES_UNPACK_STENCIL(features1);
355
356 EGLint mask0 = FEATURES_UNPACK_MASK(features0);
357 EGLint mask1 = FEATURES_UNPACK_MASK(features1);
358
359 int used0 = 0;
360 int used1 = 0;
361
362 if (use_red) {
363 used0 += FEATURES_UNPACK_RED(features0);
364 used1 += FEATURES_UNPACK_RED(features1);
365 }
366 if (use_green) {
367 used0 += FEATURES_UNPACK_GREEN(features0);
368 used1 += FEATURES_UNPACK_GREEN(features1);
369 }
370 if (use_blue) {
371 used0 += FEATURES_UNPACK_BLUE(features0);
372 used1 += FEATURES_UNPACK_BLUE(features1);
373 }
374 if (use_alpha) {
375 used0 += FEATURES_UNPACK_ALPHA(features0);
376 used1 += FEATURES_UNPACK_ALPHA(features1);
377 }
378
379 return used0 > used1 || (used0 == used1 &&
380 (all0 < all1 || (all0 == all1 &&
381 (multi0 < multi1 || (multi0 == multi1 &&
382 (depth0 < depth1 || (depth0 == depth1 &&
383 (stencil0 < stencil1 || (stencil0 == stencil1 &&
384 (mask0 < mask1))))))))));
385}
386
387/*
388 void egl_config_sort(int *ids, EGLBoolean use_red, EGLBoolean use_green, EGLBoolean use_blue, EGLBoolean use_alpha)
389
390 Sorts a list of EGL_CONFIG_IDs
391
392 Implementation notes:
393
394 Uses bubble sort
395
396 Preconditions:
397
398 ids is a pointer to EGL_MAX_CONFIGS elements
399 0 <= ids[i] < EGL_MAX_CONFIG for 0 <= i < EGL_MAX_CONFIG
400
401 Postconditions:
402
403 ids is a permutation of the original
404
405 Invariants preserved:
406
407 -
408
409 Invariants used:
410
411 -
412*/
413
414void egl_config_sort(int *ids, bool use_red, bool use_green, bool use_blue, bool use_alpha)
415{
416 int i, j;
417
418 for (i = 1; i < EGL_MAX_CONFIGS; i++)
419 for (j = 0; j < EGL_MAX_CONFIGS - i; j++)
420 if (less_than(ids[j + 1], ids[j], use_red, use_green, use_blue, use_alpha)) {
421 int temp = ids[j];
422 ids[j] = ids[j + 1];
423 ids[j + 1] = temp;
424 }
425}
426
427/*
428 bool egl_config_get_attrib(int id, EGLint attrib, EGLint *value)
429
430 Returns the value of the given attribute of the given config. Returns false
431 if there is no such attribute.
432
433 Implementation notes:
434
435 We match EGL_MATCH_NATIVE_PIXMAP here
436 too, because it *is* a valid attribute according to eglGetConfigAttrib
437 (even though it doesn't return anything meaningful) and we need it for
438 egl_config_filter.
439
440 Preconditions:
441
442 0 <= id < EGL_MAX_CONFIGS
443 value is a valid pointer
444
445 Postconditions:
446
447 If attrib is a valid attribute then true is returned and *value is set
448 Else false is returned
449
450 Invariants preserved:
451
452 -
453
454 Invariants used:
455
456 -
457*/
458
459bool egl_config_get_attrib(int id, EGLint attrib, EGLint *value)
460{
461 FEATURES_T features = formats[id].features;
462
463 switch (attrib) {
464 case EGL_BUFFER_SIZE:
465 *value = FEATURES_UNPACK_COLOR(features);
466 return true;
467 case EGL_RED_SIZE:
468 *value = FEATURES_UNPACK_RED(features);
469 return true;
470 case EGL_GREEN_SIZE:
471 *value = FEATURES_UNPACK_GREEN(features);
472 return true;
473 case EGL_BLUE_SIZE:
474 *value = FEATURES_UNPACK_BLUE(features);
475 return true;
476 case EGL_LUMINANCE_SIZE:
477 *value = 0;
478 return true;
479 case EGL_ALPHA_SIZE:
480 *value = FEATURES_UNPACK_ALPHA(features);
481 return true;
482 case EGL_ALPHA_MASK_SIZE:
483 *value = FEATURES_UNPACK_MASK(features);
484 return true;
485 case EGL_BIND_TO_TEXTURE_RGB:
486 *value = bindable_rgb(features);
487 return true;
488 case EGL_BIND_TO_TEXTURE_RGBA:
489 *value = bindable_rgba(features);
490 return true;
491 case EGL_COLOR_BUFFER_TYPE:
492 *value = EGL_RGB_BUFFER;
493 return true;
494 case EGL_CONFIG_CAVEAT:
495 *value = EGL_NONE;
496 return true;
497 case EGL_CONFIG_ID:
498 *value = (EGLint)(uintptr_t)egl_config_from_id(id);
499 return true;
500 case EGL_CONFORMANT:
501 *value = egl_config_get_api_conformance(id);
502 return true;
503 case EGL_DEPTH_SIZE:
504 *value = FEATURES_UNPACK_DEPTH(features);
505 return true;
506 case EGL_LEVEL:
507 *value = 0;
508 return true;
509 case EGL_MATCH_NATIVE_PIXMAP:
510 *value = 0;
511 return true;
512 case EGL_MAX_PBUFFER_WIDTH:
513 *value = EGL_CONFIG_MAX_WIDTH;
514 return true;
515 case EGL_MAX_PBUFFER_HEIGHT:
516 *value = EGL_CONFIG_MAX_HEIGHT;
517 return true;
518 case EGL_MAX_PBUFFER_PIXELS:
519 *value = EGL_CONFIG_MAX_WIDTH * EGL_CONFIG_MAX_HEIGHT;
520 return true;
521 case EGL_MAX_SWAP_INTERVAL:
522 *value = EGL_CONFIG_MAX_SWAP_INTERVAL;
523 return true;
524 case EGL_MIN_SWAP_INTERVAL:
525 *value = EGL_CONFIG_MIN_SWAP_INTERVAL;
526 return true;
527 case EGL_NATIVE_RENDERABLE:
528 *value = EGL_TRUE;
529 return true;
530 case EGL_NATIVE_VISUAL_ID:
531 *value = platform_get_color_format(egl_config_get_color_format(id));
532 return true;
533 case EGL_NATIVE_VISUAL_TYPE:
534 *value = EGL_NONE;
535 return true;
536 case EGL_RENDERABLE_TYPE:
537 *value = egl_config_get_api_support(id);
538 return true;
539 case EGL_SAMPLE_BUFFERS:
540 *value = FEATURES_UNPACK_MULTI(features);
541 return true;
542 case EGL_SAMPLES:
543 *value = FEATURES_UNPACK_MULTI(features) * 4;
544 return true;
545 case EGL_STENCIL_SIZE:
546 *value = FEATURES_UNPACK_STENCIL(features);
547 return true;
548 case EGL_SURFACE_TYPE:
549 *value = (EGLint)(EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT | EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT | EGL_MULTISAMPLE_RESOLVE_BOX_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT);
550#if EGL_KHR_lock_surface
551 if (egl_config_is_lockable(id))
552 {
553 *value |= EGL_LOCK_SURFACE_BIT_KHR;
554 if (egl_config_get_mapped_format(id) == egl_config_get_color_format(id))
555 *value |= EGL_OPTIMAL_FORMAT_BIT_KHR; /* Considered optimal if no format conversion needs doing. Currently all lockable surfaces are optimal */
556 }
557#endif
558 return true;
559 case EGL_TRANSPARENT_TYPE:
560 *value = EGL_NONE;
561 return true;
562 case EGL_TRANSPARENT_RED_VALUE:
563 case EGL_TRANSPARENT_GREEN_VALUE:
564 case EGL_TRANSPARENT_BLUE_VALUE:
565 *value = 0;
566 return true;
567#if EGL_KHR_lock_surface
568 case EGL_MATCH_FORMAT_KHR:
569 if (!egl_config_is_lockable(id))
570 *value = EGL_NONE;
571 else {
572 switch (egl_config_get_mapped_format(id))
573 {
574 case RGB_565_RSO:
575 *value = EGL_FORMAT_RGB_565_EXACT_KHR;
576 break;
577 case ARGB_8888_RSO:
578 *value = EGL_FORMAT_RGBA_8888_EXACT_KHR;
579 break;
580 default:
581 UNREACHABLE();
582 }
583 }
584 return true;
585#endif
586#if EGL_ANDROID_recordable
587 case EGL_RECORDABLE_ANDROID:
588 *value = EGL_TRUE;
589 return true;
590#endif
591 default:
592 return false;
593 }
594}
595
596/*
597 bool egl_config_filter(int id, const EGLint *attrib_list)
598
599 Returns whether the given EGL config satisfies the supplied attrib_list.
600
601 Implementation notes:
602
603 The following attributes:
604 EGL_COLOR_BUFFER_TYPE
605 EGL_LEVEL
606 EGL_RENDERABLE_TYPE
607 EGL_SURFACE_TYPE
608 EGL_TRANSPARENT_TYPE
609 (possibly EGL_MATCH_NATIVE_PIXMAP - see comment)
610
611 have default values not equivalent to EGL_DONT_CARE. But all of our configs
612 match the default value in all of these cases so we can treat the default as
613 EGL_DONT_CARE for all attributes.
614
615 Preconditions:
616
617 attrib_list is NULL or a pointer to an EGL_NONE-terminated list of valid attribute/value pairs
618 0 <= id < EGL_MAX_CONFIGS
619
620 Postconditions:
621
622 -
623
624 Invariants preserved:
625
626 -
627
628 Invariants used:
629
630 -
631*/
632
633bool egl_config_filter(int id, const EGLint *attrib_list)
634{
635 if (!attrib_list)
636 return true;
637
638 while (*attrib_list != EGL_NONE) {
639 EGLint name = *attrib_list++;
640 EGLint value = *attrib_list++;
641 EGLint actual_value;
642
643 if (!egl_config_get_attrib(id, name, &actual_value) )
644 {
645 UNREACHABLE();
646 return false;
647 }
648
649 switch (name) {
650 /* Selection Criteria: AtLeast */
651 case EGL_BUFFER_SIZE:
652 case EGL_RED_SIZE:
653 case EGL_GREEN_SIZE:
654 case EGL_BLUE_SIZE:
655 case EGL_LUMINANCE_SIZE:
656 case EGL_ALPHA_SIZE:
657 case EGL_ALPHA_MASK_SIZE:
658 case EGL_DEPTH_SIZE:
659 case EGL_SAMPLE_BUFFERS:
660 case EGL_SAMPLES:
661 case EGL_STENCIL_SIZE:
662 if (value != EGL_DONT_CARE && value > actual_value)
663 return false;
664 break;
665
666 /* Selection Criteria: Exact */
667 /*
668 Excluding EGL_TRANSPARENT_x_VALUE and EGL_MATCH_FORMAT_KHR which are listed in
669 the table as Exact, but seem to have special rules attached to them.
670
671 Excluding EGL_NATIVE_VISUAL_TYPE which is in the ignore list
672 Excluding EGL_LEVEL because EGL_DONT_CARE is not allowed
673 */
674 case EGL_BIND_TO_TEXTURE_RGB:
675 case EGL_BIND_TO_TEXTURE_RGBA:
676 case EGL_COLOR_BUFFER_TYPE:
677 case EGL_CONFIG_CAVEAT:
678 case EGL_CONFIG_ID:
679 case EGL_MAX_SWAP_INTERVAL:
680 case EGL_MIN_SWAP_INTERVAL:
681 case EGL_NATIVE_RENDERABLE:
682 case EGL_TRANSPARENT_TYPE:
683#if EGL_ANDROID_recordable
684 case EGL_RECORDABLE_ANDROID:
685#endif
686 if (value != EGL_DONT_CARE && value != actual_value)
687 return false;
688 break;
689
690 case EGL_LEVEL:
691 if (value != actual_value)
692 return false;
693 break;
694
695 /* Selection Criteria: Mask */
696 case EGL_CONFORMANT:
697 case EGL_RENDERABLE_TYPE:
698 case EGL_SURFACE_TYPE:
699 if (value != EGL_DONT_CARE && (value & ~actual_value))
700 return false;
701 break;
702
703 /* Selection Criteria: Special */
704 case EGL_MATCH_NATIVE_PIXMAP:
705 if (value != EGL_DONT_CARE) { /* see comments in egl_config_check_attribs */
706 EGLNativePixmapType pixmap = (EGLNativePixmapType)(intptr_t)value;
707 KHRN_IMAGE_WRAP_T image;
708 if (!platform_get_pixmap_info(pixmap, &image)) {
709 /*
710 Not actually unreachable in theory!
711 We should have detected this in egl_config_check_attribs
712 It's possible that the validity of pixmap has changed since then however...
713 */
714 UNREACHABLE();
715 return false;
716 }
717 if (!egl_config_match_pixmap_info(id, &image) ||
718 !platform_match_pixmap_api_support(pixmap, egl_config_get_api_support(id)))
719 {
720 khrn_platform_release_pixmap_info(pixmap, &image);
721 return false;
722 }
723
724 khrn_platform_release_pixmap_info(pixmap, &image);
725 }
726 break;
727#if EGL_KHR_lock_surface
728 case EGL_MATCH_FORMAT_KHR:
729 if (!(value == EGL_DONT_CARE || value == actual_value
730 || (value == EGL_FORMAT_RGB_565_KHR && actual_value == EGL_FORMAT_RGB_565_EXACT_KHR)
731 || (value == EGL_FORMAT_RGBA_8888_KHR && actual_value == EGL_FORMAT_RGBA_8888_EXACT_KHR)))
732 {
733 return false;
734 }
735 break;
736#endif
737
738 /* Attributes we can completely ignore */
739 case EGL_MAX_PBUFFER_WIDTH:
740 case EGL_MAX_PBUFFER_HEIGHT:
741 case EGL_MAX_PBUFFER_PIXELS:
742 case EGL_NATIVE_VISUAL_ID:
743 /*
744 "If EGL_MAX_PBUFFER_WIDTH, EGL_MAX_PBUFFER_HEIGHT,
745 EGL_MAX_PBUFFER_PIXELS, or EGL_NATIVE_VISUAL_ID are specified in
746 attrib_list, then they are ignored"
747 */
748
749 case EGL_NATIVE_VISUAL_TYPE:
750 /*
751 "if there are no native visual types, then the EGL NATIVE VISUAL TYPE attribute is
752 ignored."
753 */
754
755 case EGL_TRANSPARENT_BLUE_VALUE:
756 case EGL_TRANSPARENT_GREEN_VALUE:
757 case EGL_TRANSPARENT_RED_VALUE:
758 /*
759 "If EGL_TRANSPARENT_TYPE is set to EGL_NONE in attrib_list, then
760 the EGL_TRANSPARENT_RED_VALUE, EGL_TRANSPARENT_GREEN_VALUE, and
761 EGL_TRANSPARENT_BLUE_VALUE attributes are ignored."
762
763 Possible spec deviation if EGL_TRANSPARENT_TYPE is specified as EGL_DONT_CARE
764 and EGL_TRANSPARENT_*_VALUE is also specified?
765 */
766
767 break;
768
769 default:
770 UNREACHABLE();
771 break;
772 }
773 }
774
775 return true;
776}
777