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