eglconfig.c revision 01e04c3f
13464ebd5Sriastradh/**************************************************************************
23464ebd5Sriastradh *
3af69d88dSmrg * Copyright 2008 VMware, Inc.
43464ebd5Sriastradh * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
53464ebd5Sriastradh * Copyright 2010-2011 LunarG, Inc.
63464ebd5Sriastradh * All Rights Reserved.
73464ebd5Sriastradh *
83464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
93464ebd5Sriastradh * copy of this software and associated documentation files (the
103464ebd5Sriastradh * "Software"), to deal in the Software without restriction, including
113464ebd5Sriastradh * without limitation the rights to use, copy, modify, merge, publish,
123464ebd5Sriastradh * distribute, sub license, and/or sell copies of the Software, and to
133464ebd5Sriastradh * permit persons to whom the Software is furnished to do so, subject to
143464ebd5Sriastradh * the following conditions:
153464ebd5Sriastradh *
163464ebd5Sriastradh * The above copyright notice and this permission notice (including the
173464ebd5Sriastradh * next paragraph) shall be included in all copies or substantial portions
183464ebd5Sriastradh * of the Software.
193464ebd5Sriastradh *
203464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
213464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
223464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
233464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
243464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
253464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
263464ebd5Sriastradh * DEALINGS IN THE SOFTWARE.
273464ebd5Sriastradh *
283464ebd5Sriastradh **************************************************************************/
293464ebd5Sriastradh
303464ebd5Sriastradh
314a49301eSmrg/**
324a49301eSmrg * EGL Configuration (pixel format) functions.
334a49301eSmrg */
344a49301eSmrg
354a49301eSmrg
364a49301eSmrg#include <stdlib.h>
374a49301eSmrg#include <string.h>
384a49301eSmrg#include <assert.h>
3901e04c3fSmrg#include "c99_compat.h"
4001e04c3fSmrg#include "util/macros.h"
4101e04c3fSmrg
424a49301eSmrg#include "eglconfig.h"
434a49301eSmrg#include "egldisplay.h"
44cdc920a0Smrg#include "eglcurrent.h"
454a49301eSmrg#include "egllog.h"
464a49301eSmrg
474a49301eSmrg
484a49301eSmrg
494a49301eSmrg
504a49301eSmrg/**
514a49301eSmrg * Init the given _EGLconfig to default values.
524a49301eSmrg * \param id  the configuration's ID.
534a49301eSmrg *
544a49301eSmrg * Note that id must be positive for the config to be valid.
554a49301eSmrg * It is also recommended that when there are N configs, their
564a49301eSmrg * IDs are from 1 to N respectively.
574a49301eSmrg */
584a49301eSmrgvoid
593464ebd5Sriastradh_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id)
604a49301eSmrg{
613464ebd5Sriastradh   memset(conf, 0, sizeof(*conf));
624a49301eSmrg
633464ebd5Sriastradh   conf->Display = dpy;
64cdc920a0Smrg
654a49301eSmrg   /* some attributes take non-zero default values */
663464ebd5Sriastradh   conf->ConfigID = id;
673464ebd5Sriastradh   conf->ConfigCaveat = EGL_NONE;
683464ebd5Sriastradh   conf->TransparentType = EGL_NONE;
693464ebd5Sriastradh   conf->NativeVisualType = EGL_NONE;
703464ebd5Sriastradh   conf->ColorBufferType = EGL_RGB_BUFFER;
7101e04c3fSmrg   conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
724a49301eSmrg}
734a49301eSmrg
744a49301eSmrg
754a49301eSmrg/**
763464ebd5Sriastradh * Link a config to its display and return the handle of the link.
774a49301eSmrg * The handle can be passed to client directly.
784a49301eSmrg *
794a49301eSmrg * Note that we just save the ptr to the config (we don't copy the config).
804a49301eSmrg */
8101e04c3fSmrgEGLConfig
823464ebd5Sriastradh_eglLinkConfig(_EGLConfig *conf)
834a49301eSmrg{
843464ebd5Sriastradh   _EGLDisplay *dpy = conf->Display;
854a49301eSmrg
864a49301eSmrg   /* sanity check */
8701e04c3fSmrg   assert(dpy);
8801e04c3fSmrg   assert(conf->ConfigID > 0);
894a49301eSmrg
903464ebd5Sriastradh   if (!dpy->Configs) {
913464ebd5Sriastradh      dpy->Configs = _eglCreateArray("Config", 16);
923464ebd5Sriastradh      if (!dpy->Configs)
934a49301eSmrg         return (EGLConfig) NULL;
944a49301eSmrg   }
954a49301eSmrg
963464ebd5Sriastradh   _eglAppendArray(dpy->Configs, (void *) conf);
974a49301eSmrg
984a49301eSmrg   return (EGLConfig) conf;
994a49301eSmrg}
1004a49301eSmrg
1014a49301eSmrg
1023464ebd5Sriastradh/**
1033464ebd5Sriastradh * Lookup a handle to find the linked config.
1043464ebd5Sriastradh * Return NULL if the handle has no corresponding linked config.
1053464ebd5Sriastradh */
1063464ebd5Sriastradh_EGLConfig *
1073464ebd5Sriastradh_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy)
1084a49301eSmrg{
1093464ebd5Sriastradh   _EGLConfig *conf;
1104a49301eSmrg
1113464ebd5Sriastradh   if (!dpy)
1123464ebd5Sriastradh      return NULL;
1133464ebd5Sriastradh
1143464ebd5Sriastradh   conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
1153464ebd5Sriastradh   if (conf)
1163464ebd5Sriastradh      assert(conf->Display == dpy);
1173464ebd5Sriastradh
1183464ebd5Sriastradh   return conf;
1194a49301eSmrg}
1204a49301eSmrg
1214a49301eSmrg
12201e04c3fSmrgenum type {
1234a49301eSmrg   ATTRIB_TYPE_INTEGER,
1244a49301eSmrg   ATTRIB_TYPE_BOOLEAN,
1254a49301eSmrg   ATTRIB_TYPE_BITMASK,
1264a49301eSmrg   ATTRIB_TYPE_ENUM,
1274a49301eSmrg   ATTRIB_TYPE_PSEUDO, /* non-queryable */
1284a49301eSmrg   ATTRIB_TYPE_PLATFORM, /* platform-dependent */
12901e04c3fSmrg};
13001e04c3fSmrg
13101e04c3fSmrgenum criterion {
1324a49301eSmrg   ATTRIB_CRITERION_EXACT,
1334a49301eSmrg   ATTRIB_CRITERION_ATLEAST,
1344a49301eSmrg   ATTRIB_CRITERION_MASK,
1354a49301eSmrg   ATTRIB_CRITERION_SPECIAL,
136cdc920a0Smrg   ATTRIB_CRITERION_IGNORE
1374a49301eSmrg};
1384a49301eSmrg
1394a49301eSmrg
1404a49301eSmrg/* EGL spec Table 3.1 and 3.4 */
1414a49301eSmrgstatic const struct {
1424a49301eSmrg   EGLint attr;
14301e04c3fSmrg   enum type type;
14401e04c3fSmrg   enum criterion criterion;
1454a49301eSmrg   EGLint default_value;
1464a49301eSmrg} _eglValidationTable[] =
1474a49301eSmrg{
1483464ebd5Sriastradh   /* core */
1494a49301eSmrg   { EGL_BUFFER_SIZE,               ATTRIB_TYPE_INTEGER,
1504a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1514a49301eSmrg                                    0 },
1524a49301eSmrg   { EGL_RED_SIZE,                  ATTRIB_TYPE_INTEGER,
1534a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1544a49301eSmrg                                    0 },
1554a49301eSmrg   { EGL_GREEN_SIZE,                ATTRIB_TYPE_INTEGER,
1564a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1574a49301eSmrg                                    0 },
1584a49301eSmrg   { EGL_BLUE_SIZE,                 ATTRIB_TYPE_INTEGER,
1594a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1604a49301eSmrg                                    0 },
1614a49301eSmrg   { EGL_LUMINANCE_SIZE,            ATTRIB_TYPE_INTEGER,
1624a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1634a49301eSmrg                                    0 },
1644a49301eSmrg   { EGL_ALPHA_SIZE,                ATTRIB_TYPE_INTEGER,
1654a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1664a49301eSmrg                                    0 },
1674a49301eSmrg   { EGL_ALPHA_MASK_SIZE,           ATTRIB_TYPE_INTEGER,
1684a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1694a49301eSmrg                                    0 },
1704a49301eSmrg   { EGL_BIND_TO_TEXTURE_RGB,       ATTRIB_TYPE_BOOLEAN,
1714a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1724a49301eSmrg                                    EGL_DONT_CARE },
1734a49301eSmrg   { EGL_BIND_TO_TEXTURE_RGBA,      ATTRIB_TYPE_BOOLEAN,
1744a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1754a49301eSmrg                                    EGL_DONT_CARE },
1764a49301eSmrg   { EGL_COLOR_BUFFER_TYPE,         ATTRIB_TYPE_ENUM,
1774a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1784a49301eSmrg                                    EGL_RGB_BUFFER },
1794a49301eSmrg   { EGL_CONFIG_CAVEAT,             ATTRIB_TYPE_ENUM,
1804a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1814a49301eSmrg                                    EGL_DONT_CARE },
1824a49301eSmrg   { EGL_CONFIG_ID,                 ATTRIB_TYPE_INTEGER,
1834a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1844a49301eSmrg                                    EGL_DONT_CARE },
1854a49301eSmrg   { EGL_CONFORMANT,                ATTRIB_TYPE_BITMASK,
1864a49301eSmrg                                    ATTRIB_CRITERION_MASK,
1874a49301eSmrg                                    0 },
1884a49301eSmrg   { EGL_DEPTH_SIZE,                ATTRIB_TYPE_INTEGER,
1894a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1904a49301eSmrg                                    0 },
1914a49301eSmrg   { EGL_LEVEL,                     ATTRIB_TYPE_PLATFORM,
1924a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1934a49301eSmrg                                    0 },
1944a49301eSmrg   { EGL_MAX_PBUFFER_WIDTH,         ATTRIB_TYPE_INTEGER,
1954a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1964a49301eSmrg                                    0 },
1974a49301eSmrg   { EGL_MAX_PBUFFER_HEIGHT,        ATTRIB_TYPE_INTEGER,
1984a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1994a49301eSmrg                                    0 },
2004a49301eSmrg   { EGL_MAX_PBUFFER_PIXELS,        ATTRIB_TYPE_INTEGER,
2014a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
2024a49301eSmrg                                    0 },
2034a49301eSmrg   { EGL_MAX_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
2044a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2054a49301eSmrg                                    EGL_DONT_CARE },
2064a49301eSmrg   { EGL_MIN_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
2074a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2084a49301eSmrg                                    EGL_DONT_CARE },
2094a49301eSmrg   { EGL_NATIVE_RENDERABLE,         ATTRIB_TYPE_BOOLEAN,
2104a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2114a49301eSmrg                                    EGL_DONT_CARE },
2124a49301eSmrg   { EGL_NATIVE_VISUAL_ID,          ATTRIB_TYPE_PLATFORM,
2134a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
2144a49301eSmrg                                    0 },
2154a49301eSmrg   { EGL_NATIVE_VISUAL_TYPE,        ATTRIB_TYPE_PLATFORM,
2164a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2174a49301eSmrg                                    EGL_DONT_CARE },
2184a49301eSmrg   { EGL_RENDERABLE_TYPE,           ATTRIB_TYPE_BITMASK,
2194a49301eSmrg                                    ATTRIB_CRITERION_MASK,
2204a49301eSmrg                                    EGL_OPENGL_ES_BIT },
2214a49301eSmrg   { EGL_SAMPLE_BUFFERS,            ATTRIB_TYPE_INTEGER,
2224a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2234a49301eSmrg                                    0 },
2244a49301eSmrg   { EGL_SAMPLES,                   ATTRIB_TYPE_INTEGER,
2254a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2264a49301eSmrg                                    0 },
2274a49301eSmrg   { EGL_STENCIL_SIZE,              ATTRIB_TYPE_INTEGER,
2284a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2294a49301eSmrg                                    0 },
2304a49301eSmrg   { EGL_SURFACE_TYPE,              ATTRIB_TYPE_BITMASK,
2314a49301eSmrg                                    ATTRIB_CRITERION_MASK,
2324a49301eSmrg                                    EGL_WINDOW_BIT },
2334a49301eSmrg   { EGL_TRANSPARENT_TYPE,          ATTRIB_TYPE_ENUM,
2344a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2354a49301eSmrg                                    EGL_NONE },
2364a49301eSmrg   { EGL_TRANSPARENT_RED_VALUE,     ATTRIB_TYPE_INTEGER,
2374a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2384a49301eSmrg                                    EGL_DONT_CARE },
2394a49301eSmrg   { EGL_TRANSPARENT_GREEN_VALUE,   ATTRIB_TYPE_INTEGER,
2404a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2414a49301eSmrg                                    EGL_DONT_CARE },
2424a49301eSmrg   { EGL_TRANSPARENT_BLUE_VALUE,    ATTRIB_TYPE_INTEGER,
2434a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2444a49301eSmrg                                    EGL_DONT_CARE },
2454a49301eSmrg   { EGL_MATCH_NATIVE_PIXMAP,       ATTRIB_TYPE_PSEUDO,
2464a49301eSmrg                                    ATTRIB_CRITERION_SPECIAL,
2474a49301eSmrg                                    EGL_NONE },
2483464ebd5Sriastradh   /* extensions */
2493464ebd5Sriastradh   { EGL_Y_INVERTED_NOK,            ATTRIB_TYPE_BOOLEAN,
2503464ebd5Sriastradh                                    ATTRIB_CRITERION_EXACT,
25101e04c3fSmrg                                    EGL_DONT_CARE },
25201e04c3fSmrg   { EGL_FRAMEBUFFER_TARGET_ANDROID, ATTRIB_TYPE_BOOLEAN,
25301e04c3fSmrg                                    ATTRIB_CRITERION_EXACT,
25401e04c3fSmrg                                    EGL_DONT_CARE },
25501e04c3fSmrg   { EGL_RECORDABLE_ANDROID,        ATTRIB_TYPE_BOOLEAN,
25601e04c3fSmrg                                    ATTRIB_CRITERION_EXACT,
25701e04c3fSmrg                                    EGL_DONT_CARE },
25801e04c3fSmrg   { EGL_COLOR_COMPONENT_TYPE_EXT,  ATTRIB_TYPE_ENUM,
25901e04c3fSmrg                                    ATTRIB_CRITERION_EXACT,
26001e04c3fSmrg                                    EGL_COLOR_COMPONENT_TYPE_FIXED_EXT },
2614a49301eSmrg};
2624a49301eSmrg
2634a49301eSmrg
2644a49301eSmrg/**
2654a49301eSmrg * Return true if a config is valid.  When for_matching is true,
2664a49301eSmrg * EGL_DONT_CARE is accepted as a valid attribute value, and checks
2674a49301eSmrg * for conflicting attribute values are skipped.
2684a49301eSmrg *
2694a49301eSmrg * Note that some attributes are platform-dependent and are not
2704a49301eSmrg * checked.
2714a49301eSmrg */
2724a49301eSmrgEGLBoolean
2734a49301eSmrg_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
2744a49301eSmrg{
27501e04c3fSmrg   _EGLDisplay *disp = conf->Display;
2764a49301eSmrg   EGLint i, attr, val;
2774a49301eSmrg   EGLBoolean valid = EGL_TRUE;
2784a49301eSmrg
2794a49301eSmrg   /* check attributes by their types */
2804a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
2814a49301eSmrg      EGLint mask;
2824a49301eSmrg
2834a49301eSmrg      attr = _eglValidationTable[i].attr;
2843464ebd5Sriastradh      val = _eglGetConfigKey(conf, attr);
2854a49301eSmrg
2864a49301eSmrg      switch (_eglValidationTable[i].type) {
2874a49301eSmrg      case ATTRIB_TYPE_INTEGER:
2884a49301eSmrg         switch (attr) {
2894a49301eSmrg         case EGL_CONFIG_ID:
2904a49301eSmrg            /* config id must be positive */
2914a49301eSmrg            if (val <= 0)
2924a49301eSmrg               valid = EGL_FALSE;
2934a49301eSmrg            break;
2944a49301eSmrg         case EGL_SAMPLE_BUFFERS:
2954a49301eSmrg            /* there can be at most 1 sample buffer */
2963464ebd5Sriastradh            if (val > 1 || val < 0)
2974a49301eSmrg               valid = EGL_FALSE;
2984a49301eSmrg            break;
2993464ebd5Sriastradh         default:
3003464ebd5Sriastradh            if (val < 0)
3013464ebd5Sriastradh               valid = EGL_FALSE;
3024a49301eSmrg            break;
3034a49301eSmrg         }
3044a49301eSmrg         break;
3054a49301eSmrg      case ATTRIB_TYPE_BOOLEAN:
3064a49301eSmrg         if (val != EGL_TRUE && val != EGL_FALSE)
3074a49301eSmrg            valid = EGL_FALSE;
3084a49301eSmrg         break;
3094a49301eSmrg      case ATTRIB_TYPE_ENUM:
3104a49301eSmrg         switch (attr) {
3114a49301eSmrg         case EGL_CONFIG_CAVEAT:
3124a49301eSmrg            if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
3134a49301eSmrg                val != EGL_NON_CONFORMANT_CONFIG)
3144a49301eSmrg               valid = EGL_FALSE;
3154a49301eSmrg            break;
3164a49301eSmrg         case EGL_TRANSPARENT_TYPE:
3174a49301eSmrg            if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
3184a49301eSmrg               valid = EGL_FALSE;
3194a49301eSmrg            break;
3204a49301eSmrg         case EGL_COLOR_BUFFER_TYPE:
3214a49301eSmrg            if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
3224a49301eSmrg               valid = EGL_FALSE;
3234a49301eSmrg            break;
32401e04c3fSmrg         case EGL_COLOR_COMPONENT_TYPE_EXT:
32501e04c3fSmrg            if (val != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT &&
32601e04c3fSmrg                val != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT)
32701e04c3fSmrg               valid = EGL_FALSE;
32801e04c3fSmrg            break;
3294a49301eSmrg         default:
33001e04c3fSmrg            unreachable("check _eglValidationTable[]");
3314a49301eSmrg            break;
3324a49301eSmrg         }
3334a49301eSmrg         break;
3344a49301eSmrg      case ATTRIB_TYPE_BITMASK:
3354a49301eSmrg         switch (attr) {
3364a49301eSmrg         case EGL_SURFACE_TYPE:
3374a49301eSmrg            mask = EGL_PBUFFER_BIT |
3384a49301eSmrg                   EGL_PIXMAP_BIT |
3394a49301eSmrg                   EGL_WINDOW_BIT |
3404a49301eSmrg                   EGL_VG_COLORSPACE_LINEAR_BIT |
3414a49301eSmrg                   EGL_VG_ALPHA_FORMAT_PRE_BIT |
3424a49301eSmrg                   EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
3434a49301eSmrg                   EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
34401e04c3fSmrg            if (disp->Extensions.KHR_mutable_render_buffer)
34501e04c3fSmrg               mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR;
3464a49301eSmrg            break;
3474a49301eSmrg         case EGL_RENDERABLE_TYPE:
3484a49301eSmrg         case EGL_CONFORMANT:
3494a49301eSmrg            mask = EGL_OPENGL_ES_BIT |
3504a49301eSmrg                   EGL_OPENVG_BIT |
3514a49301eSmrg                   EGL_OPENGL_ES2_BIT |
352af69d88dSmrg                   EGL_OPENGL_ES3_BIT_KHR |
3534a49301eSmrg                   EGL_OPENGL_BIT;
3544a49301eSmrg            break;
3554a49301eSmrg         default:
35601e04c3fSmrg            unreachable("check _eglValidationTable[]");
357af69d88dSmrg            mask = 0;
3584a49301eSmrg            break;
3594a49301eSmrg         }
3604a49301eSmrg         if (val & ~mask)
3614a49301eSmrg            valid = EGL_FALSE;
3624a49301eSmrg         break;
3634a49301eSmrg      case ATTRIB_TYPE_PLATFORM:
3644a49301eSmrg         /* unable to check platform-dependent attributes here */
3654a49301eSmrg         break;
3664a49301eSmrg      case ATTRIB_TYPE_PSEUDO:
3674a49301eSmrg         /* pseudo attributes should not be set */
3684a49301eSmrg         if (val != 0)
3694a49301eSmrg            valid = EGL_FALSE;
3704a49301eSmrg         break;
3714a49301eSmrg      }
3724a49301eSmrg
3734a49301eSmrg      if (!valid && for_matching) {
3744a49301eSmrg         /* accept EGL_DONT_CARE as a valid value */
3754a49301eSmrg         if (val == EGL_DONT_CARE)
3764a49301eSmrg            valid = EGL_TRUE;
3774a49301eSmrg         if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
3784a49301eSmrg            valid = EGL_TRUE;
3794a49301eSmrg      }
380cdc920a0Smrg      if (!valid) {
381cdc920a0Smrg         _eglLog(_EGL_DEBUG,
382cdc920a0Smrg               "attribute 0x%04x has an invalid value 0x%x", attr, val);
3834a49301eSmrg         break;
384cdc920a0Smrg      }
3854a49301eSmrg   }
3864a49301eSmrg
3874a49301eSmrg   /* any invalid attribute value should have been catched */
3884a49301eSmrg   if (!valid || for_matching)
3894a49301eSmrg      return valid;
3904a49301eSmrg
3914a49301eSmrg   /* now check for conflicting attribute values */
3924a49301eSmrg
3933464ebd5Sriastradh   switch (conf->ColorBufferType) {
3944a49301eSmrg   case EGL_RGB_BUFFER:
3953464ebd5Sriastradh      if (conf->LuminanceSize)
3964a49301eSmrg         valid = EGL_FALSE;
3973464ebd5Sriastradh      if (conf->RedSize + conf->GreenSize +
3983464ebd5Sriastradh            conf->BlueSize + conf->AlphaSize != conf->BufferSize)
3994a49301eSmrg         valid = EGL_FALSE;
4004a49301eSmrg      break;
4014a49301eSmrg   case EGL_LUMINANCE_BUFFER:
4023464ebd5Sriastradh      if (conf->RedSize || conf->GreenSize || conf->BlueSize)
4034a49301eSmrg         valid = EGL_FALSE;
4043464ebd5Sriastradh      if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
4054a49301eSmrg         valid = EGL_FALSE;
4064a49301eSmrg      break;
4074a49301eSmrg   }
408cdc920a0Smrg   if (!valid) {
409cdc920a0Smrg      _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
410cdc920a0Smrg      return EGL_FALSE;
411cdc920a0Smrg   }
4124a49301eSmrg
4133464ebd5Sriastradh   if (!conf->SampleBuffers && conf->Samples)
4144a49301eSmrg      valid = EGL_FALSE;
415cdc920a0Smrg   if (!valid) {
416cdc920a0Smrg      _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
417cdc920a0Smrg      return EGL_FALSE;
418cdc920a0Smrg   }
4194a49301eSmrg
4203464ebd5Sriastradh   if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
4213464ebd5Sriastradh      if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE)
4224a49301eSmrg         valid = EGL_FALSE;
4234a49301eSmrg   }
4243464ebd5Sriastradh   if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) {
4253464ebd5Sriastradh      if (conf->BindToTextureRGB || conf->BindToTextureRGBA)
4264a49301eSmrg         valid = EGL_FALSE;
4274a49301eSmrg   }
428cdc920a0Smrg   if (!valid) {
429cdc920a0Smrg      _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
430cdc920a0Smrg      return EGL_FALSE;
431cdc920a0Smrg   }
4324a49301eSmrg
4334a49301eSmrg   return valid;
4344a49301eSmrg}
4354a49301eSmrg
4364a49301eSmrg
4374a49301eSmrg/**
4384a49301eSmrg * Return true if a config matches the criteria.  This and
4394a49301eSmrg * _eglParseConfigAttribList together implement the algorithm
4404a49301eSmrg * described in "Selection of EGLConfigs".
4414a49301eSmrg *
4424a49301eSmrg * Note that attributes that are special (currently, only
4434a49301eSmrg * EGL_MATCH_NATIVE_PIXMAP) are ignored.
4444a49301eSmrg */
4454a49301eSmrgEGLBoolean
4464a49301eSmrg_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
4474a49301eSmrg{
4484a49301eSmrg   EGLint attr, val, i;
4494a49301eSmrg   EGLBoolean matched = EGL_TRUE;
4504a49301eSmrg
4514a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
4524a49301eSmrg      EGLint cmp;
4534a49301eSmrg      if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
4544a49301eSmrg         continue;
4554a49301eSmrg
4564a49301eSmrg      attr = _eglValidationTable[i].attr;
4573464ebd5Sriastradh      cmp = _eglGetConfigKey(criteria, attr);
4584a49301eSmrg      if (cmp == EGL_DONT_CARE)
4594a49301eSmrg         continue;
4604a49301eSmrg
4613464ebd5Sriastradh      val = _eglGetConfigKey(conf, attr);
4624a49301eSmrg      switch (_eglValidationTable[i].criterion) {
4634a49301eSmrg      case ATTRIB_CRITERION_EXACT:
4644a49301eSmrg         if (val != cmp)
4654a49301eSmrg            matched = EGL_FALSE;
4664a49301eSmrg         break;
4674a49301eSmrg      case ATTRIB_CRITERION_ATLEAST:
4684a49301eSmrg         if (val < cmp)
4694a49301eSmrg            matched = EGL_FALSE;
4704a49301eSmrg         break;
4714a49301eSmrg      case ATTRIB_CRITERION_MASK:
4724a49301eSmrg         if ((val & cmp) != cmp)
4734a49301eSmrg            matched = EGL_FALSE;
4744a49301eSmrg         break;
4754a49301eSmrg      case ATTRIB_CRITERION_SPECIAL:
4764a49301eSmrg         /* ignored here */
4774a49301eSmrg         break;
47801e04c3fSmrg      case ATTRIB_CRITERION_IGNORE:
47901e04c3fSmrg         unreachable("already handled above");
4804a49301eSmrg         break;
4814a49301eSmrg      }
4824a49301eSmrg
483cdc920a0Smrg      if (!matched) {
4843464ebd5Sriastradh#ifndef DEBUG
4853464ebd5Sriastradh         /* only print the common errors when DEBUG is not defined */
4863464ebd5Sriastradh         if (attr != EGL_RENDERABLE_TYPE)
4873464ebd5Sriastradh            break;
4883464ebd5Sriastradh#endif
489cdc920a0Smrg         _eglLog(_EGL_DEBUG,
490cdc920a0Smrg               "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
491cdc920a0Smrg               val, attr, cmp);
4924a49301eSmrg         break;
493cdc920a0Smrg      }
4944a49301eSmrg   }
4954a49301eSmrg
4964a49301eSmrg   return matched;
4974a49301eSmrg}
4984a49301eSmrg
49901e04c3fSmrgstatic inline EGLBoolean
5003464ebd5Sriastradh_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
5013464ebd5Sriastradh{
5023464ebd5Sriastradh   if (_eglOffsetOfConfig(attr) < 0)
5033464ebd5Sriastradh      return EGL_FALSE;
5043464ebd5Sriastradh
5053464ebd5Sriastradh   switch (attr) {
5063464ebd5Sriastradh   case EGL_Y_INVERTED_NOK:
5073464ebd5Sriastradh      return conf->Display->Extensions.NOK_texture_from_pixmap;
50801e04c3fSmrg   case EGL_FRAMEBUFFER_TARGET_ANDROID:
50901e04c3fSmrg      return conf->Display->Extensions.ANDROID_framebuffer_target;
51001e04c3fSmrg   case EGL_RECORDABLE_ANDROID:
51101e04c3fSmrg      return conf->Display->Extensions.ANDROID_recordable;
5123464ebd5Sriastradh   default:
5133464ebd5Sriastradh      break;
5143464ebd5Sriastradh   }
5153464ebd5Sriastradh
5163464ebd5Sriastradh   return EGL_TRUE;
5173464ebd5Sriastradh}
5184a49301eSmrg
5194a49301eSmrg/**
5204a49301eSmrg * Initialize a criteria config from the given attribute list.
5214a49301eSmrg * Return EGL_FALSE if any of the attribute is invalid.
5224a49301eSmrg */
5234a49301eSmrgEGLBoolean
5243464ebd5Sriastradh_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *dpy,
5253464ebd5Sriastradh                          const EGLint *attrib_list)
5264a49301eSmrg{
5274a49301eSmrg   EGLint attr, val, i;
5283464ebd5Sriastradh
5293464ebd5Sriastradh   _eglInitConfig(conf, dpy, EGL_DONT_CARE);
5304a49301eSmrg
5314a49301eSmrg   /* reset to default values */
5324a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
5334a49301eSmrg      attr = _eglValidationTable[i].attr;
5344a49301eSmrg      val = _eglValidationTable[i].default_value;
5353464ebd5Sriastradh      _eglSetConfigKey(conf, attr, val);
5364a49301eSmrg   }
5374a49301eSmrg
5384a49301eSmrg   /* parse the list */
5394a49301eSmrg   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
5404a49301eSmrg      attr = attrib_list[i];
5414a49301eSmrg      val = attrib_list[i + 1];
5424a49301eSmrg
5433464ebd5Sriastradh      if (!_eglIsConfigAttribValid(conf, attr))
54401e04c3fSmrg         return EGL_FALSE;
5454a49301eSmrg
5463464ebd5Sriastradh      _eglSetConfigKey(conf, attr, val);
5474a49301eSmrg   }
5484a49301eSmrg
5494a49301eSmrg   if (!_eglValidateConfig(conf, EGL_TRUE))
5504a49301eSmrg      return EGL_FALSE;
5514a49301eSmrg
552af69d88dSmrg   /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */
553af69d88dSmrg   if (conf->Level == EGL_DONT_CARE ||
554af69d88dSmrg       conf->MatchNativePixmap == EGL_DONT_CARE)
5554a49301eSmrg      return EGL_FALSE;
5564a49301eSmrg
5574a49301eSmrg   /* ignore other attributes when EGL_CONFIG_ID is given */
5583464ebd5Sriastradh   if (conf->ConfigID != EGL_DONT_CARE) {
5593464ebd5Sriastradh      for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
5603464ebd5Sriastradh         attr = _eglValidationTable[i].attr;
5613464ebd5Sriastradh         if (attr != EGL_CONFIG_ID)
5623464ebd5Sriastradh            _eglSetConfigKey(conf, attr, EGL_DONT_CARE);
5633464ebd5Sriastradh      }
5644a49301eSmrg   }
5654a49301eSmrg   else {
5663464ebd5Sriastradh      if (!(conf->SurfaceType & EGL_WINDOW_BIT))
5673464ebd5Sriastradh         conf->NativeVisualType = EGL_DONT_CARE;
5684a49301eSmrg
5693464ebd5Sriastradh      if (conf->TransparentType == EGL_NONE) {
5703464ebd5Sriastradh         conf->TransparentRedValue = EGL_DONT_CARE;
5713464ebd5Sriastradh         conf->TransparentGreenValue = EGL_DONT_CARE;
5723464ebd5Sriastradh         conf->TransparentBlueValue = EGL_DONT_CARE;
5734a49301eSmrg      }
5744a49301eSmrg   }
5754a49301eSmrg
5764a49301eSmrg   return EGL_TRUE;
5774a49301eSmrg}
5784a49301eSmrg
5794a49301eSmrg
5804a49301eSmrg/**
5814a49301eSmrg * Decide the ordering of conf1 and conf2, under the given criteria.
5824a49301eSmrg * When compare_id is true, this implements the algorithm described
5834a49301eSmrg * in "Sorting of EGLConfigs".  When compare_id is false,
5844a49301eSmrg * EGL_CONFIG_ID is not compared.
5854a49301eSmrg *
5864a49301eSmrg * It returns a negative integer if conf1 is considered to come
5874a49301eSmrg * before conf2;  a positive integer if conf2 is considered to come
5884a49301eSmrg * before conf1;  zero if the ordering cannot be decided.
5894a49301eSmrg *
5904a49301eSmrg * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
5914a49301eSmrg * ignored here.
5924a49301eSmrg */
5934a49301eSmrgEGLint
5944a49301eSmrg_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
5954a49301eSmrg                   const _EGLConfig *criteria, EGLBoolean compare_id)
5964a49301eSmrg{
5974a49301eSmrg   const EGLint compare_attribs[] = {
5984a49301eSmrg      EGL_BUFFER_SIZE,
5994a49301eSmrg      EGL_SAMPLE_BUFFERS,
6004a49301eSmrg      EGL_SAMPLES,
6014a49301eSmrg      EGL_DEPTH_SIZE,
6024a49301eSmrg      EGL_STENCIL_SIZE,
6034a49301eSmrg      EGL_ALPHA_MASK_SIZE,
6044a49301eSmrg   };
6054a49301eSmrg   EGLint val1, val2;
6064a49301eSmrg   EGLint i;
6074a49301eSmrg
6084a49301eSmrg   if (conf1 == conf2)
6094a49301eSmrg      return 0;
6104a49301eSmrg
6114a49301eSmrg   /* the enum values have the desired ordering */
61201e04c3fSmrg   STATIC_ASSERT(EGL_NONE < EGL_SLOW_CONFIG);
61301e04c3fSmrg   STATIC_ASSERT(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
6143464ebd5Sriastradh   val1 = conf1->ConfigCaveat - conf2->ConfigCaveat;
6153464ebd5Sriastradh   if (val1)
6163464ebd5Sriastradh      return val1;
6174a49301eSmrg
6184a49301eSmrg   /* the enum values have the desired ordering */
61901e04c3fSmrg   STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
6203464ebd5Sriastradh   val1 = conf1->ColorBufferType - conf2->ColorBufferType;
6213464ebd5Sriastradh   if (val1)
6223464ebd5Sriastradh      return val1;
6234a49301eSmrg
6244a49301eSmrg   if (criteria) {
6254a49301eSmrg      val1 = val2 = 0;
6263464ebd5Sriastradh      if (conf1->ColorBufferType == EGL_RGB_BUFFER) {
6273464ebd5Sriastradh         if (criteria->RedSize > 0) {
6283464ebd5Sriastradh            val1 += conf1->RedSize;
6293464ebd5Sriastradh            val2 += conf2->RedSize;
6304a49301eSmrg         }
6313464ebd5Sriastradh         if (criteria->GreenSize > 0) {
6323464ebd5Sriastradh            val1 += conf1->GreenSize;
6333464ebd5Sriastradh            val2 += conf2->GreenSize;
6344a49301eSmrg         }
6353464ebd5Sriastradh         if (criteria->BlueSize > 0) {
6363464ebd5Sriastradh            val1 += conf1->BlueSize;
6373464ebd5Sriastradh            val2 += conf2->BlueSize;
6384a49301eSmrg         }
6394a49301eSmrg      }
6404a49301eSmrg      else {
6413464ebd5Sriastradh         if (criteria->LuminanceSize > 0) {
6423464ebd5Sriastradh            val1 += conf1->LuminanceSize;
6433464ebd5Sriastradh            val2 += conf2->LuminanceSize;
6444a49301eSmrg         }
6454a49301eSmrg      }
6463464ebd5Sriastradh      if (criteria->AlphaSize > 0) {
6473464ebd5Sriastradh         val1 += conf1->AlphaSize;
6483464ebd5Sriastradh         val2 += conf2->AlphaSize;
6494a49301eSmrg      }
6504a49301eSmrg   }
6514a49301eSmrg   else {
6524a49301eSmrg      /* assume the default criteria, which gives no specific ordering */
6534a49301eSmrg      val1 = val2 = 0;
6544a49301eSmrg   }
6554a49301eSmrg
6564a49301eSmrg   /* for color bits, larger one is preferred */
6574a49301eSmrg   if (val1 != val2)
6584a49301eSmrg      return (val2 - val1);
6594a49301eSmrg
6604a49301eSmrg   for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
6613464ebd5Sriastradh      val1 = _eglGetConfigKey(conf1, compare_attribs[i]);
6623464ebd5Sriastradh      val2 = _eglGetConfigKey(conf2, compare_attribs[i]);
6634a49301eSmrg      if (val1 != val2)
6644a49301eSmrg         return (val1 - val2);
6654a49301eSmrg   }
6664a49301eSmrg
6674a49301eSmrg   /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
6684a49301eSmrg
6693464ebd5Sriastradh   return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
6704a49301eSmrg}
6714a49301eSmrg
6724a49301eSmrg
67301e04c3fSmrgstatic inline
6744a49301eSmrgvoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
6754a49301eSmrg{
6764a49301eSmrg   const _EGLConfig *tmp = *conf1;
6774a49301eSmrg   *conf1 = *conf2;
6784a49301eSmrg   *conf2 = tmp;
6794a49301eSmrg}
6804a49301eSmrg
6814a49301eSmrg
6824a49301eSmrg/**
6834a49301eSmrg * Quick sort an array of configs.  This differs from the standard
6844a49301eSmrg * qsort() in that the compare function accepts an additional
6854a49301eSmrg * argument.
6864a49301eSmrg */
687af69d88dSmrgstatic void
6884a49301eSmrg_eglSortConfigs(const _EGLConfig **configs, EGLint count,
6894a49301eSmrg                EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
6904a49301eSmrg                                  void *),
6914a49301eSmrg                void *priv_data)
6924a49301eSmrg{
6934a49301eSmrg   const EGLint pivot = 0;
6944a49301eSmrg   EGLint i, j;
6954a49301eSmrg
6964a49301eSmrg   if (count <= 1)
6974a49301eSmrg      return;
6984a49301eSmrg
6994a49301eSmrg   _eglSwapConfigs(&configs[pivot], &configs[count / 2]);
7004a49301eSmrg   i = 1;
7014a49301eSmrg   j = count - 1;
7024a49301eSmrg   do {
7034a49301eSmrg      while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
7044a49301eSmrg         i++;
7054a49301eSmrg      while (compare(configs[j], configs[pivot], priv_data) > 0)
7064a49301eSmrg         j--;
7074a49301eSmrg      if (i < j) {
7084a49301eSmrg         _eglSwapConfigs(&configs[i], &configs[j]);
7094a49301eSmrg         i++;
7104a49301eSmrg         j--;
7114a49301eSmrg      }
7124a49301eSmrg      else if (i == j) {
7134a49301eSmrg         i++;
7144a49301eSmrg         j--;
7154a49301eSmrg         break;
7164a49301eSmrg      }
7174a49301eSmrg   } while (i <= j);
7184a49301eSmrg   _eglSwapConfigs(&configs[pivot], &configs[j]);
7194a49301eSmrg
7204a49301eSmrg   _eglSortConfigs(configs, j, compare, priv_data);
7214a49301eSmrg   _eglSortConfigs(configs + i, count - i, compare, priv_data);
7224a49301eSmrg}
7234a49301eSmrg
7244a49301eSmrg
7254a49301eSmrg/**
726af69d88dSmrg * A helper function for implementing eglChooseConfig.  See _eglFilterArray and
727af69d88dSmrg * _eglSortConfigs for the meanings of match and compare.
7284a49301eSmrg */
7294a49301eSmrgEGLBoolean
730af69d88dSmrg_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs,
731af69d88dSmrg                      EGLint config_size, EGLint *num_configs,
732af69d88dSmrg                      EGLBoolean (*match)(const _EGLConfig *, void *),
733af69d88dSmrg                      EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
734af69d88dSmrg                                        void *),
735af69d88dSmrg                      void *priv_data)
7364a49301eSmrg{
737af69d88dSmrg   _EGLConfig **configList;
7384a49301eSmrg   EGLint i, count;
7394a49301eSmrg
7404a49301eSmrg   if (!num_configs)
74101e04c3fSmrg      return _eglError(EGL_BAD_PARAMETER, "eglChooseConfig");
7424a49301eSmrg
7433464ebd5Sriastradh   /* get the number of matched configs */
744af69d88dSmrg   count = _eglFilterArray(array, NULL, 0,
745af69d88dSmrg         (_EGLArrayForEach) match, priv_data);
7463464ebd5Sriastradh   if (!count) {
7473464ebd5Sriastradh      *num_configs = count;
7483464ebd5Sriastradh      return EGL_TRUE;
7493464ebd5Sriastradh   }
7503464ebd5Sriastradh
7513464ebd5Sriastradh   configList = malloc(sizeof(*configList) * count);
7524a49301eSmrg   if (!configList)
7534a49301eSmrg      return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
7544a49301eSmrg
7553464ebd5Sriastradh   /* get the matched configs */
756af69d88dSmrg   _eglFilterArray(array, (void **) configList, count,
757af69d88dSmrg         (_EGLArrayForEach) match, priv_data);
7584a49301eSmrg
7594a49301eSmrg   /* perform sorting of configs */
7604a49301eSmrg   if (configs && count) {
7614a49301eSmrg      _eglSortConfigs((const _EGLConfig **) configList, count,
762af69d88dSmrg                      compare, priv_data);
7634a49301eSmrg      count = MIN2(count, config_size);
7644a49301eSmrg      for (i = 0; i < count; i++)
7654a49301eSmrg         configs[i] = _eglGetConfigHandle(configList[i]);
7664a49301eSmrg   }
7674a49301eSmrg
7684a49301eSmrg   free(configList);
7694a49301eSmrg
7704a49301eSmrg   *num_configs = count;
7714a49301eSmrg
7724a49301eSmrg   return EGL_TRUE;
7734a49301eSmrg}
7744a49301eSmrg
7754a49301eSmrg
776af69d88dSmrgstatic EGLBoolean
777af69d88dSmrg_eglFallbackMatch(const _EGLConfig *conf, void *priv_data)
778af69d88dSmrg{
779af69d88dSmrg   return _eglMatchConfig(conf, (const _EGLConfig *) priv_data);
780af69d88dSmrg}
781af69d88dSmrg
782af69d88dSmrg
783af69d88dSmrgstatic EGLint
784af69d88dSmrg_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
785af69d88dSmrg                    void *priv_data)
786af69d88dSmrg{
787af69d88dSmrg   return _eglCompareConfigs(conf1, conf2,
788af69d88dSmrg         (const _EGLConfig *) priv_data, EGL_TRUE);
789af69d88dSmrg}
790af69d88dSmrg
791af69d88dSmrg
792af69d88dSmrg/**
793af69d88dSmrg * Typical fallback routine for eglChooseConfig
794af69d88dSmrg */
795af69d88dSmrgEGLBoolean
796af69d88dSmrg_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
797af69d88dSmrg                 EGLConfig *configs, EGLint config_size, EGLint *num_configs)
798af69d88dSmrg{
799af69d88dSmrg   _EGLConfig criteria;
800af69d88dSmrg
801af69d88dSmrg   if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
802af69d88dSmrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
803af69d88dSmrg
804af69d88dSmrg   return _eglFilterConfigArray(disp->Configs,
805af69d88dSmrg         configs, config_size, num_configs,
806af69d88dSmrg         _eglFallbackMatch, _eglFallbackCompare,
807af69d88dSmrg         (void *) &criteria);
808af69d88dSmrg}
809af69d88dSmrg
810af69d88dSmrg
8114a49301eSmrg/**
8124a49301eSmrg * Fallback for eglGetConfigAttrib.
8134a49301eSmrg */
8144a49301eSmrgEGLBoolean
8154a49301eSmrg_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
8164a49301eSmrg                    EGLint attribute, EGLint *value)
8174a49301eSmrg{
8184a49301eSmrg   if (!_eglIsConfigAttribValid(conf, attribute))
8194a49301eSmrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
8203464ebd5Sriastradh
8213464ebd5Sriastradh   /* nonqueryable attributes */
8223464ebd5Sriastradh   switch (attribute) {
8233464ebd5Sriastradh   case EGL_MATCH_NATIVE_PIXMAP:
8243464ebd5Sriastradh      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
8253464ebd5Sriastradh      break;
8263464ebd5Sriastradh   default:
8273464ebd5Sriastradh      break;
8283464ebd5Sriastradh   }
8293464ebd5Sriastradh
8304a49301eSmrg   if (!value)
8314a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
8324a49301eSmrg
8333464ebd5Sriastradh   *value = _eglGetConfigKey(conf, attribute);
8344a49301eSmrg   return EGL_TRUE;
8354a49301eSmrg}
8364a49301eSmrg
8374a49301eSmrg
8383464ebd5Sriastradhstatic EGLBoolean
8393464ebd5Sriastradh_eglFlattenConfig(void *elem, void *buffer)
8403464ebd5Sriastradh{
8413464ebd5Sriastradh   _EGLConfig *conf = (_EGLConfig *) elem;
8423464ebd5Sriastradh   EGLConfig *handle = (EGLConfig *) buffer;
8433464ebd5Sriastradh   *handle = _eglGetConfigHandle(conf);
8443464ebd5Sriastradh   return EGL_TRUE;
8453464ebd5Sriastradh}
8463464ebd5Sriastradh
8474a49301eSmrg/**
8484a49301eSmrg * Fallback for eglGetConfigs.
8494a49301eSmrg */
8504a49301eSmrgEGLBoolean
8514a49301eSmrg_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
8524a49301eSmrg               EGLint config_size, EGLint *num_config)
8534a49301eSmrg{
8544a49301eSmrg   if (!num_config)
8554a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
8564a49301eSmrg
8573464ebd5Sriastradh   *num_config = _eglFlattenArray(disp->Configs, (void *) configs,
8583464ebd5Sriastradh         sizeof(configs[0]), config_size, _eglFlattenConfig);
8594a49301eSmrg
8604a49301eSmrg   return EGL_TRUE;
8614a49301eSmrg}
862