Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/egl/main/eglconfig.c
4560 views
1
/**************************************************************************
2
*
3
* Copyright 2008 VMware, Inc.
4
* Copyright 2009-2010 Chia-I Wu <[email protected]>
5
* Copyright 2010-2011 LunarG, Inc.
6
* All Rights Reserved.
7
*
8
* Permission is hereby granted, free of charge, to any person obtaining a
9
* copy of this software and associated documentation files (the
10
* "Software"), to deal in the Software without restriction, including
11
* without limitation the rights to use, copy, modify, merge, publish,
12
* distribute, sub license, and/or sell copies of the Software, and to
13
* permit persons to whom the Software is furnished to do so, subject to
14
* the following conditions:
15
*
16
* The above copyright notice and this permission notice (including the
17
* next paragraph) shall be included in all copies or substantial portions
18
* of the Software.
19
*
20
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
* DEALINGS IN THE SOFTWARE.
27
*
28
**************************************************************************/
29
30
31
/**
32
* EGL Configuration (pixel format) functions.
33
*/
34
35
36
#include <stdlib.h>
37
#include <string.h>
38
#include <assert.h>
39
#include "c99_compat.h"
40
#include "util/macros.h"
41
42
#include "eglconfig.h"
43
#include "egldisplay.h"
44
#include "eglcurrent.h"
45
#include "egllog.h"
46
47
48
49
50
/**
51
* Init the given _EGLconfig to default values.
52
* \param id the configuration's ID.
53
*
54
* Note that id must be positive for the config to be valid.
55
* It is also recommended that when there are N configs, their
56
* IDs are from 1 to N respectively.
57
*/
58
void
59
_eglInitConfig(_EGLConfig *conf, _EGLDisplay *disp, EGLint id)
60
{
61
memset(conf, 0, sizeof(*conf));
62
63
conf->Display = disp;
64
65
/* some attributes take non-zero default values */
66
conf->ConfigID = id;
67
conf->ConfigCaveat = EGL_NONE;
68
conf->TransparentType = EGL_NONE;
69
conf->NativeVisualType = EGL_NONE;
70
conf->ColorBufferType = EGL_RGB_BUFFER;
71
conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
72
}
73
74
75
/**
76
* Link a config to its display and return the handle of the link.
77
* The handle can be passed to client directly.
78
*
79
* Note that we just save the ptr to the config (we don't copy the config).
80
*/
81
EGLConfig
82
_eglLinkConfig(_EGLConfig *conf)
83
{
84
_EGLDisplay *disp = conf->Display;
85
86
/* sanity check */
87
assert(disp);
88
assert(conf->ConfigID > 0);
89
90
if (!disp->Configs) {
91
disp->Configs = _eglCreateArray("Config", 16);
92
if (!disp->Configs)
93
return (EGLConfig) NULL;
94
}
95
96
_eglAppendArray(disp->Configs, (void *) conf);
97
98
return (EGLConfig) conf;
99
}
100
101
102
/**
103
* Lookup a handle to find the linked config.
104
* Return NULL if the handle has no corresponding linked config.
105
*/
106
_EGLConfig *
107
_eglLookupConfig(EGLConfig config, _EGLDisplay *disp)
108
{
109
_EGLConfig *conf;
110
111
if (!disp)
112
return NULL;
113
114
conf = (_EGLConfig *) _eglFindArray(disp->Configs, (void *) config);
115
if (conf)
116
assert(conf->Display == disp);
117
118
return conf;
119
}
120
121
122
enum type {
123
ATTRIB_TYPE_INTEGER,
124
ATTRIB_TYPE_BOOLEAN,
125
ATTRIB_TYPE_BITMASK,
126
ATTRIB_TYPE_ENUM,
127
ATTRIB_TYPE_PSEUDO, /* non-queryable */
128
ATTRIB_TYPE_PLATFORM, /* platform-dependent */
129
};
130
131
enum criterion {
132
ATTRIB_CRITERION_EXACT,
133
ATTRIB_CRITERION_ATLEAST,
134
ATTRIB_CRITERION_MASK,
135
ATTRIB_CRITERION_SPECIAL,
136
ATTRIB_CRITERION_IGNORE
137
};
138
139
140
/* EGL spec Table 3.1 and 3.4 */
141
static const struct {
142
EGLint attr;
143
enum type type;
144
enum criterion criterion;
145
EGLint default_value;
146
} _eglValidationTable[] =
147
{
148
/* core */
149
{ EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER,
150
ATTRIB_CRITERION_ATLEAST,
151
0 },
152
{ EGL_RED_SIZE, ATTRIB_TYPE_INTEGER,
153
ATTRIB_CRITERION_ATLEAST,
154
0 },
155
{ EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER,
156
ATTRIB_CRITERION_ATLEAST,
157
0 },
158
{ EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER,
159
ATTRIB_CRITERION_ATLEAST,
160
0 },
161
{ EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER,
162
ATTRIB_CRITERION_ATLEAST,
163
0 },
164
{ EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER,
165
ATTRIB_CRITERION_ATLEAST,
166
0 },
167
{ EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER,
168
ATTRIB_CRITERION_ATLEAST,
169
0 },
170
{ EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN,
171
ATTRIB_CRITERION_EXACT,
172
EGL_DONT_CARE },
173
{ EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN,
174
ATTRIB_CRITERION_EXACT,
175
EGL_DONT_CARE },
176
{ EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM,
177
ATTRIB_CRITERION_EXACT,
178
EGL_RGB_BUFFER },
179
{ EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM,
180
ATTRIB_CRITERION_EXACT,
181
EGL_DONT_CARE },
182
{ EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER,
183
ATTRIB_CRITERION_EXACT,
184
EGL_DONT_CARE },
185
{ EGL_CONFORMANT, ATTRIB_TYPE_BITMASK,
186
ATTRIB_CRITERION_MASK,
187
0 },
188
{ EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER,
189
ATTRIB_CRITERION_ATLEAST,
190
0 },
191
{ EGL_LEVEL, ATTRIB_TYPE_PLATFORM,
192
ATTRIB_CRITERION_EXACT,
193
0 },
194
{ EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER,
195
ATTRIB_CRITERION_IGNORE,
196
0 },
197
{ EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER,
198
ATTRIB_CRITERION_IGNORE,
199
0 },
200
{ EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER,
201
ATTRIB_CRITERION_IGNORE,
202
0 },
203
{ EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
204
ATTRIB_CRITERION_EXACT,
205
EGL_DONT_CARE },
206
{ EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
207
ATTRIB_CRITERION_EXACT,
208
EGL_DONT_CARE },
209
{ EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN,
210
ATTRIB_CRITERION_EXACT,
211
EGL_DONT_CARE },
212
{ EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM,
213
ATTRIB_CRITERION_IGNORE,
214
0 },
215
{ EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM,
216
ATTRIB_CRITERION_EXACT,
217
EGL_DONT_CARE },
218
{ EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK,
219
ATTRIB_CRITERION_MASK,
220
EGL_OPENGL_ES_BIT },
221
{ EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER,
222
ATTRIB_CRITERION_ATLEAST,
223
0 },
224
{ EGL_SAMPLES, ATTRIB_TYPE_INTEGER,
225
ATTRIB_CRITERION_ATLEAST,
226
0 },
227
{ EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER,
228
ATTRIB_CRITERION_ATLEAST,
229
0 },
230
{ EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK,
231
ATTRIB_CRITERION_MASK,
232
EGL_WINDOW_BIT },
233
{ EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM,
234
ATTRIB_CRITERION_EXACT,
235
EGL_NONE },
236
{ EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER,
237
ATTRIB_CRITERION_EXACT,
238
EGL_DONT_CARE },
239
{ EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER,
240
ATTRIB_CRITERION_EXACT,
241
EGL_DONT_CARE },
242
{ EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER,
243
ATTRIB_CRITERION_EXACT,
244
EGL_DONT_CARE },
245
{ EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO,
246
ATTRIB_CRITERION_SPECIAL,
247
EGL_NONE },
248
/* extensions */
249
{ EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN,
250
ATTRIB_CRITERION_EXACT,
251
EGL_DONT_CARE },
252
{ EGL_FRAMEBUFFER_TARGET_ANDROID, ATTRIB_TYPE_BOOLEAN,
253
ATTRIB_CRITERION_EXACT,
254
EGL_DONT_CARE },
255
{ EGL_RECORDABLE_ANDROID, ATTRIB_TYPE_BOOLEAN,
256
ATTRIB_CRITERION_EXACT,
257
EGL_DONT_CARE },
258
{ EGL_COLOR_COMPONENT_TYPE_EXT, ATTRIB_TYPE_ENUM,
259
ATTRIB_CRITERION_EXACT,
260
EGL_COLOR_COMPONENT_TYPE_FIXED_EXT },
261
};
262
263
264
/**
265
* Return true if a config is valid. When for_matching is true,
266
* EGL_DONT_CARE is accepted as a valid attribute value, and checks
267
* for conflicting attribute values are skipped.
268
*
269
* Note that some attributes are platform-dependent and are not
270
* checked.
271
*/
272
EGLBoolean
273
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
274
{
275
_EGLDisplay *disp = conf->Display;
276
EGLint i, attr, val;
277
EGLBoolean valid = EGL_TRUE;
278
279
/* check attributes by their types */
280
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
281
EGLint mask;
282
283
attr = _eglValidationTable[i].attr;
284
val = _eglGetConfigKey(conf, attr);
285
286
switch (_eglValidationTable[i].type) {
287
case ATTRIB_TYPE_INTEGER:
288
switch (attr) {
289
case EGL_CONFIG_ID:
290
/* config id must be positive */
291
if (val <= 0)
292
valid = EGL_FALSE;
293
break;
294
case EGL_SAMPLE_BUFFERS:
295
/* there can be at most 1 sample buffer */
296
if (val > 1 || val < 0)
297
valid = EGL_FALSE;
298
break;
299
default:
300
if (val < 0)
301
valid = EGL_FALSE;
302
break;
303
}
304
break;
305
case ATTRIB_TYPE_BOOLEAN:
306
if (val != EGL_TRUE && val != EGL_FALSE)
307
valid = EGL_FALSE;
308
break;
309
case ATTRIB_TYPE_ENUM:
310
switch (attr) {
311
case EGL_CONFIG_CAVEAT:
312
if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
313
val != EGL_NON_CONFORMANT_CONFIG)
314
valid = EGL_FALSE;
315
break;
316
case EGL_TRANSPARENT_TYPE:
317
if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
318
valid = EGL_FALSE;
319
break;
320
case EGL_COLOR_BUFFER_TYPE:
321
if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
322
valid = EGL_FALSE;
323
break;
324
case EGL_COLOR_COMPONENT_TYPE_EXT:
325
if (val != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT &&
326
val != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT)
327
valid = EGL_FALSE;
328
break;
329
default:
330
unreachable("check _eglValidationTable[]");
331
break;
332
}
333
break;
334
case ATTRIB_TYPE_BITMASK:
335
switch (attr) {
336
case EGL_SURFACE_TYPE:
337
mask = EGL_PBUFFER_BIT |
338
EGL_PIXMAP_BIT |
339
EGL_WINDOW_BIT |
340
EGL_VG_COLORSPACE_LINEAR_BIT |
341
EGL_VG_ALPHA_FORMAT_PRE_BIT |
342
EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
343
EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
344
if (disp->Extensions.KHR_mutable_render_buffer)
345
mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
346
break;
347
case EGL_RENDERABLE_TYPE:
348
case EGL_CONFORMANT:
349
mask = EGL_OPENGL_ES_BIT |
350
EGL_OPENVG_BIT |
351
EGL_OPENGL_ES2_BIT |
352
EGL_OPENGL_ES3_BIT_KHR |
353
EGL_OPENGL_BIT;
354
break;
355
default:
356
unreachable("check _eglValidationTable[]");
357
mask = 0;
358
break;
359
}
360
if (val & ~mask)
361
valid = EGL_FALSE;
362
break;
363
case ATTRIB_TYPE_PLATFORM:
364
/* unable to check platform-dependent attributes here */
365
break;
366
case ATTRIB_TYPE_PSEUDO:
367
/* pseudo attributes should not be set */
368
if (val != 0)
369
valid = EGL_FALSE;
370
break;
371
}
372
373
if (!valid && for_matching) {
374
/* accept EGL_DONT_CARE as a valid value */
375
if (val == EGL_DONT_CARE)
376
valid = EGL_TRUE;
377
if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
378
valid = EGL_TRUE;
379
}
380
if (!valid) {
381
_eglLog(_EGL_DEBUG,
382
"attribute 0x%04x has an invalid value 0x%x", attr, val);
383
break;
384
}
385
}
386
387
/* any invalid attribute value should have been catched */
388
if (!valid || for_matching)
389
return valid;
390
391
/* now check for conflicting attribute values */
392
393
switch (conf->ColorBufferType) {
394
case EGL_RGB_BUFFER:
395
if (conf->LuminanceSize)
396
valid = EGL_FALSE;
397
if (conf->RedSize + conf->GreenSize +
398
conf->BlueSize + conf->AlphaSize != conf->BufferSize)
399
valid = EGL_FALSE;
400
break;
401
case EGL_LUMINANCE_BUFFER:
402
if (conf->RedSize || conf->GreenSize || conf->BlueSize)
403
valid = EGL_FALSE;
404
if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
405
valid = EGL_FALSE;
406
break;
407
}
408
if (!valid) {
409
_eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
410
return EGL_FALSE;
411
}
412
413
if (!conf->SampleBuffers && conf->Samples)
414
valid = EGL_FALSE;
415
if (!valid) {
416
_eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
417
return EGL_FALSE;
418
}
419
420
if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
421
if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE)
422
valid = EGL_FALSE;
423
}
424
if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) {
425
if (conf->BindToTextureRGB || conf->BindToTextureRGBA)
426
valid = EGL_FALSE;
427
}
428
if (!valid) {
429
_eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
430
return EGL_FALSE;
431
}
432
433
return valid;
434
}
435
436
437
/**
438
* Return true if a config matches the criteria. This and
439
* _eglParseConfigAttribList together implement the algorithm
440
* described in "Selection of EGLConfigs".
441
*
442
* Note that attributes that are special (currently, only
443
* EGL_MATCH_NATIVE_PIXMAP) are ignored.
444
*/
445
EGLBoolean
446
_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
447
{
448
EGLint attr, val, i;
449
EGLBoolean matched = EGL_TRUE;
450
451
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
452
EGLint cmp;
453
if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
454
continue;
455
456
attr = _eglValidationTable[i].attr;
457
cmp = _eglGetConfigKey(criteria, attr);
458
if (cmp == EGL_DONT_CARE)
459
continue;
460
461
val = _eglGetConfigKey(conf, attr);
462
switch (_eglValidationTable[i].criterion) {
463
case ATTRIB_CRITERION_EXACT:
464
if (val != cmp)
465
matched = EGL_FALSE;
466
break;
467
case ATTRIB_CRITERION_ATLEAST:
468
if (val < cmp)
469
matched = EGL_FALSE;
470
break;
471
case ATTRIB_CRITERION_MASK:
472
if ((val & cmp) != cmp)
473
matched = EGL_FALSE;
474
break;
475
case ATTRIB_CRITERION_SPECIAL:
476
/* ignored here */
477
break;
478
case ATTRIB_CRITERION_IGNORE:
479
unreachable("already handled above");
480
break;
481
}
482
483
if (!matched) {
484
#ifndef DEBUG
485
/* only print the common errors when DEBUG is not defined */
486
if (attr != EGL_RENDERABLE_TYPE)
487
break;
488
#endif
489
_eglLog(_EGL_DEBUG,
490
"the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
491
val, attr, cmp);
492
break;
493
}
494
}
495
496
return matched;
497
}
498
499
static inline EGLBoolean
500
_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
501
{
502
if (_eglOffsetOfConfig(attr) < 0)
503
return EGL_FALSE;
504
505
switch (attr) {
506
case EGL_Y_INVERTED_NOK:
507
return conf->Display->Extensions.NOK_texture_from_pixmap;
508
case EGL_FRAMEBUFFER_TARGET_ANDROID:
509
return conf->Display->Extensions.ANDROID_framebuffer_target;
510
case EGL_RECORDABLE_ANDROID:
511
return conf->Display->Extensions.ANDROID_recordable;
512
default:
513
break;
514
}
515
516
return EGL_TRUE;
517
}
518
519
/**
520
* Initialize a criteria config from the given attribute list.
521
* Return EGL_FALSE if any of the attribute is invalid.
522
*/
523
EGLBoolean
524
_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *disp,
525
const EGLint *attrib_list)
526
{
527
EGLint attr, val, i;
528
529
_eglInitConfig(conf, disp, EGL_DONT_CARE);
530
531
/* reset to default values */
532
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
533
attr = _eglValidationTable[i].attr;
534
val = _eglValidationTable[i].default_value;
535
_eglSetConfigKey(conf, attr, val);
536
}
537
538
/* parse the list */
539
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
540
attr = attrib_list[i];
541
val = attrib_list[i + 1];
542
543
if (!_eglIsConfigAttribValid(conf, attr))
544
return EGL_FALSE;
545
546
_eglSetConfigKey(conf, attr, val);
547
}
548
549
if (!_eglValidateConfig(conf, EGL_TRUE))
550
return EGL_FALSE;
551
552
/* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */
553
if (conf->Level == EGL_DONT_CARE ||
554
conf->MatchNativePixmap == EGL_DONT_CARE)
555
return EGL_FALSE;
556
557
/* ignore other attributes when EGL_CONFIG_ID is given */
558
if (conf->ConfigID != EGL_DONT_CARE) {
559
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
560
attr = _eglValidationTable[i].attr;
561
if (attr != EGL_CONFIG_ID)
562
_eglSetConfigKey(conf, attr, EGL_DONT_CARE);
563
}
564
}
565
else {
566
if (!(conf->SurfaceType & EGL_WINDOW_BIT))
567
conf->NativeVisualType = EGL_DONT_CARE;
568
569
if (conf->TransparentType == EGL_NONE) {
570
conf->TransparentRedValue = EGL_DONT_CARE;
571
conf->TransparentGreenValue = EGL_DONT_CARE;
572
conf->TransparentBlueValue = EGL_DONT_CARE;
573
}
574
}
575
576
return EGL_TRUE;
577
}
578
579
580
/**
581
* Decide the ordering of conf1 and conf2, under the given criteria.
582
* When compare_id is true, this implements the algorithm described
583
* in "Sorting of EGLConfigs". When compare_id is false,
584
* EGL_CONFIG_ID is not compared.
585
*
586
* It returns a negative integer if conf1 is considered to come
587
* before conf2; a positive integer if conf2 is considered to come
588
* before conf1; zero if the ordering cannot be decided.
589
*
590
* Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
591
* ignored here.
592
*/
593
EGLint
594
_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
595
const _EGLConfig *criteria, EGLBoolean compare_id)
596
{
597
const EGLint compare_attribs[] = {
598
EGL_BUFFER_SIZE,
599
EGL_SAMPLE_BUFFERS,
600
EGL_SAMPLES,
601
EGL_DEPTH_SIZE,
602
EGL_STENCIL_SIZE,
603
EGL_ALPHA_MASK_SIZE,
604
};
605
EGLint val1, val2;
606
EGLint i;
607
608
if (conf1 == conf2)
609
return 0;
610
611
/* the enum values have the desired ordering */
612
STATIC_ASSERT(EGL_NONE < EGL_SLOW_CONFIG);
613
STATIC_ASSERT(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
614
val1 = conf1->ConfigCaveat - conf2->ConfigCaveat;
615
if (val1)
616
return val1;
617
618
/* the enum values have the desired ordering */
619
STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
620
val1 = conf1->ColorBufferType - conf2->ColorBufferType;
621
if (val1)
622
return val1;
623
624
if (criteria) {
625
val1 = val2 = 0;
626
if (conf1->ColorBufferType == EGL_RGB_BUFFER) {
627
if (criteria->RedSize > 0) {
628
val1 += conf1->RedSize;
629
val2 += conf2->RedSize;
630
}
631
if (criteria->GreenSize > 0) {
632
val1 += conf1->GreenSize;
633
val2 += conf2->GreenSize;
634
}
635
if (criteria->BlueSize > 0) {
636
val1 += conf1->BlueSize;
637
val2 += conf2->BlueSize;
638
}
639
}
640
else {
641
if (criteria->LuminanceSize > 0) {
642
val1 += conf1->LuminanceSize;
643
val2 += conf2->LuminanceSize;
644
}
645
}
646
if (criteria->AlphaSize > 0) {
647
val1 += conf1->AlphaSize;
648
val2 += conf2->AlphaSize;
649
}
650
}
651
else {
652
/* assume the default criteria, which gives no specific ordering */
653
val1 = val2 = 0;
654
}
655
656
/* for color bits, larger one is preferred */
657
if (val1 != val2)
658
return (val2 - val1);
659
660
for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
661
val1 = _eglGetConfigKey(conf1, compare_attribs[i]);
662
val2 = _eglGetConfigKey(conf2, compare_attribs[i]);
663
if (val1 != val2)
664
return (val1 - val2);
665
}
666
667
/* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
668
669
return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
670
}
671
672
673
static inline
674
void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
675
{
676
const _EGLConfig *tmp = *conf1;
677
*conf1 = *conf2;
678
*conf2 = tmp;
679
}
680
681
682
/**
683
* Quick sort an array of configs. This differs from the standard
684
* qsort() in that the compare function accepts an additional
685
* argument.
686
*/
687
static void
688
_eglSortConfigs(const _EGLConfig **configs, EGLint count,
689
EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
690
void *),
691
void *priv_data)
692
{
693
const EGLint pivot = 0;
694
EGLint i, j;
695
696
if (count <= 1)
697
return;
698
699
_eglSwapConfigs(&configs[pivot], &configs[count / 2]);
700
i = 1;
701
j = count - 1;
702
do {
703
while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
704
i++;
705
while (compare(configs[j], configs[pivot], priv_data) > 0)
706
j--;
707
if (i < j) {
708
_eglSwapConfigs(&configs[i], &configs[j]);
709
i++;
710
j--;
711
}
712
else if (i == j) {
713
i++;
714
j--;
715
break;
716
}
717
} while (i <= j);
718
_eglSwapConfigs(&configs[pivot], &configs[j]);
719
720
_eglSortConfigs(configs, j, compare, priv_data);
721
_eglSortConfigs(configs + i, count - i, compare, priv_data);
722
}
723
724
725
/**
726
* A helper function for implementing eglChooseConfig. See _eglFilterArray and
727
* _eglSortConfigs for the meanings of match and compare.
728
*/
729
EGLBoolean
730
_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs,
731
EGLint config_size, EGLint *num_configs,
732
EGLBoolean (*match)(const _EGLConfig *, void *),
733
EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
734
void *),
735
void *priv_data)
736
{
737
_EGLConfig **configList;
738
EGLint i, count;
739
740
/* get the number of matched configs */
741
count = _eglFilterArray(array, NULL, 0,
742
(_EGLArrayForEach) match, priv_data);
743
if (!count) {
744
*num_configs = count;
745
return EGL_TRUE;
746
}
747
748
configList = malloc(sizeof(*configList) * count);
749
if (!configList)
750
return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
751
752
/* get the matched configs */
753
_eglFilterArray(array, (void **) configList, count,
754
(_EGLArrayForEach) match, priv_data);
755
756
/* perform sorting of configs */
757
if (configs && count) {
758
_eglSortConfigs((const _EGLConfig **) configList, count,
759
compare, priv_data);
760
count = MIN2(count, config_size);
761
for (i = 0; i < count; i++)
762
configs[i] = _eglGetConfigHandle(configList[i]);
763
}
764
765
free(configList);
766
767
*num_configs = count;
768
769
return EGL_TRUE;
770
}
771
772
773
static EGLBoolean
774
_eglFallbackMatch(const _EGLConfig *conf, void *priv_data)
775
{
776
return _eglMatchConfig(conf, (const _EGLConfig *) priv_data);
777
}
778
779
780
static EGLint
781
_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
782
void *priv_data)
783
{
784
return _eglCompareConfigs(conf1, conf2,
785
(const _EGLConfig *) priv_data, EGL_TRUE);
786
}
787
788
789
/**
790
* Typical fallback routine for eglChooseConfig
791
*/
792
EGLBoolean
793
_eglChooseConfig(_EGLDisplay *disp, const EGLint *attrib_list,
794
EGLConfig *configs, EGLint config_size, EGLint *num_configs)
795
{
796
_EGLConfig criteria;
797
798
if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
799
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
800
801
return _eglFilterConfigArray(disp->Configs,
802
configs, config_size, num_configs,
803
_eglFallbackMatch, _eglFallbackCompare,
804
(void *) &criteria);
805
}
806
807
808
/**
809
* Fallback for eglGetConfigAttrib.
810
*/
811
EGLBoolean
812
_eglGetConfigAttrib(_EGLDisplay *disp, _EGLConfig *conf,
813
EGLint attribute, EGLint *value)
814
{
815
if (!_eglIsConfigAttribValid(conf, attribute))
816
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
817
818
/* nonqueryable attributes */
819
switch (attribute) {
820
case EGL_MATCH_NATIVE_PIXMAP:
821
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
822
break;
823
default:
824
break;
825
}
826
827
if (!value)
828
return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
829
830
*value = _eglGetConfigKey(conf, attribute);
831
return EGL_TRUE;
832
}
833
834
835
static EGLBoolean
836
_eglFlattenConfig(void *elem, void *buffer)
837
{
838
_EGLConfig *conf = (_EGLConfig *) elem;
839
EGLConfig *handle = (EGLConfig *) buffer;
840
*handle = _eglGetConfigHandle(conf);
841
return EGL_TRUE;
842
}
843
844
/**
845
* Fallback for eglGetConfigs.
846
*/
847
EGLBoolean
848
_eglGetConfigs(_EGLDisplay *disp, EGLConfig *configs,
849
EGLint config_size, EGLint *num_config)
850
{
851
*num_config = _eglFlattenArray(disp->Configs, (void *) configs,
852
sizeof(configs[0]), config_size, _eglFlattenConfig);
853
854
return EGL_TRUE;
855
}
856
857