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