eglconfig.c revision af69d88d
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>
394a49301eSmrg#include "eglconfig.h"
404a49301eSmrg#include "egldisplay.h"
41cdc920a0Smrg#include "eglcurrent.h"
424a49301eSmrg#include "egllog.h"
434a49301eSmrg
444a49301eSmrg
454a49301eSmrg#define MIN2(A, B)  (((A) < (B)) ? (A) : (B))
464a49301eSmrg
474a49301eSmrg
484a49301eSmrg/**
494a49301eSmrg * Init the given _EGLconfig to default values.
504a49301eSmrg * \param id  the configuration's ID.
514a49301eSmrg *
524a49301eSmrg * Note that id must be positive for the config to be valid.
534a49301eSmrg * It is also recommended that when there are N configs, their
544a49301eSmrg * IDs are from 1 to N respectively.
554a49301eSmrg */
564a49301eSmrgvoid
573464ebd5Sriastradh_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id)
584a49301eSmrg{
593464ebd5Sriastradh   memset(conf, 0, sizeof(*conf));
604a49301eSmrg
613464ebd5Sriastradh   conf->Display = dpy;
62cdc920a0Smrg
634a49301eSmrg   /* some attributes take non-zero default values */
643464ebd5Sriastradh   conf->ConfigID = id;
653464ebd5Sriastradh   conf->ConfigCaveat = EGL_NONE;
663464ebd5Sriastradh   conf->TransparentType = EGL_NONE;
673464ebd5Sriastradh   conf->NativeVisualType = EGL_NONE;
683464ebd5Sriastradh   conf->ColorBufferType = EGL_RGB_BUFFER;
694a49301eSmrg}
704a49301eSmrg
714a49301eSmrg
724a49301eSmrg/**
733464ebd5Sriastradh * Link a config to its display and return the handle of the link.
744a49301eSmrg * The handle can be passed to client directly.
754a49301eSmrg *
764a49301eSmrg * Note that we just save the ptr to the config (we don't copy the config).
774a49301eSmrg */
783464ebd5SriastradhPUBLIC EGLConfig
793464ebd5Sriastradh_eglLinkConfig(_EGLConfig *conf)
804a49301eSmrg{
813464ebd5Sriastradh   _EGLDisplay *dpy = conf->Display;
824a49301eSmrg
834a49301eSmrg   /* sanity check */
843464ebd5Sriastradh   assert(dpy && conf->ConfigID > 0);
854a49301eSmrg
863464ebd5Sriastradh   if (!dpy->Configs) {
873464ebd5Sriastradh      dpy->Configs = _eglCreateArray("Config", 16);
883464ebd5Sriastradh      if (!dpy->Configs)
894a49301eSmrg         return (EGLConfig) NULL;
904a49301eSmrg   }
914a49301eSmrg
923464ebd5Sriastradh   _eglAppendArray(dpy->Configs, (void *) conf);
934a49301eSmrg
944a49301eSmrg   return (EGLConfig) conf;
954a49301eSmrg}
964a49301eSmrg
974a49301eSmrg
983464ebd5Sriastradh/**
993464ebd5Sriastradh * Lookup a handle to find the linked config.
1003464ebd5Sriastradh * Return NULL if the handle has no corresponding linked config.
1013464ebd5Sriastradh */
1023464ebd5Sriastradh_EGLConfig *
1033464ebd5Sriastradh_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy)
1044a49301eSmrg{
1053464ebd5Sriastradh   _EGLConfig *conf;
1064a49301eSmrg
1073464ebd5Sriastradh   if (!dpy)
1083464ebd5Sriastradh      return NULL;
1093464ebd5Sriastradh
1103464ebd5Sriastradh   conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
1113464ebd5Sriastradh   if (conf)
1123464ebd5Sriastradh      assert(conf->Display == dpy);
1133464ebd5Sriastradh
1143464ebd5Sriastradh   return conf;
1154a49301eSmrg}
1164a49301eSmrg
1174a49301eSmrg
1184a49301eSmrgenum {
1194a49301eSmrg   /* types */
1204a49301eSmrg   ATTRIB_TYPE_INTEGER,
1214a49301eSmrg   ATTRIB_TYPE_BOOLEAN,
1224a49301eSmrg   ATTRIB_TYPE_BITMASK,
1234a49301eSmrg   ATTRIB_TYPE_ENUM,
1244a49301eSmrg   ATTRIB_TYPE_PSEUDO, /* non-queryable */
1254a49301eSmrg   ATTRIB_TYPE_PLATFORM, /* platform-dependent */
1264a49301eSmrg   /* criteria */
1274a49301eSmrg   ATTRIB_CRITERION_EXACT,
1284a49301eSmrg   ATTRIB_CRITERION_ATLEAST,
1294a49301eSmrg   ATTRIB_CRITERION_MASK,
1304a49301eSmrg   ATTRIB_CRITERION_SPECIAL,
131cdc920a0Smrg   ATTRIB_CRITERION_IGNORE
1324a49301eSmrg};
1334a49301eSmrg
1344a49301eSmrg
1354a49301eSmrg/* EGL spec Table 3.1 and 3.4 */
1364a49301eSmrgstatic const struct {
1374a49301eSmrg   EGLint attr;
1384a49301eSmrg   EGLint type;
1394a49301eSmrg   EGLint criterion;
1404a49301eSmrg   EGLint default_value;
1414a49301eSmrg} _eglValidationTable[] =
1424a49301eSmrg{
1433464ebd5Sriastradh   /* core */
1444a49301eSmrg   { EGL_BUFFER_SIZE,               ATTRIB_TYPE_INTEGER,
1454a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1464a49301eSmrg                                    0 },
1474a49301eSmrg   { EGL_RED_SIZE,                  ATTRIB_TYPE_INTEGER,
1484a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1494a49301eSmrg                                    0 },
1504a49301eSmrg   { EGL_GREEN_SIZE,                ATTRIB_TYPE_INTEGER,
1514a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1524a49301eSmrg                                    0 },
1534a49301eSmrg   { EGL_BLUE_SIZE,                 ATTRIB_TYPE_INTEGER,
1544a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1554a49301eSmrg                                    0 },
1564a49301eSmrg   { EGL_LUMINANCE_SIZE,            ATTRIB_TYPE_INTEGER,
1574a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1584a49301eSmrg                                    0 },
1594a49301eSmrg   { EGL_ALPHA_SIZE,                ATTRIB_TYPE_INTEGER,
1604a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1614a49301eSmrg                                    0 },
1624a49301eSmrg   { EGL_ALPHA_MASK_SIZE,           ATTRIB_TYPE_INTEGER,
1634a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1644a49301eSmrg                                    0 },
1654a49301eSmrg   { EGL_BIND_TO_TEXTURE_RGB,       ATTRIB_TYPE_BOOLEAN,
1664a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1674a49301eSmrg                                    EGL_DONT_CARE },
1684a49301eSmrg   { EGL_BIND_TO_TEXTURE_RGBA,      ATTRIB_TYPE_BOOLEAN,
1694a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1704a49301eSmrg                                    EGL_DONT_CARE },
1714a49301eSmrg   { EGL_COLOR_BUFFER_TYPE,         ATTRIB_TYPE_ENUM,
1724a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1734a49301eSmrg                                    EGL_RGB_BUFFER },
1744a49301eSmrg   { EGL_CONFIG_CAVEAT,             ATTRIB_TYPE_ENUM,
1754a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1764a49301eSmrg                                    EGL_DONT_CARE },
1774a49301eSmrg   { EGL_CONFIG_ID,                 ATTRIB_TYPE_INTEGER,
1784a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1794a49301eSmrg                                    EGL_DONT_CARE },
1804a49301eSmrg   { EGL_CONFORMANT,                ATTRIB_TYPE_BITMASK,
1814a49301eSmrg                                    ATTRIB_CRITERION_MASK,
1824a49301eSmrg                                    0 },
1834a49301eSmrg   { EGL_DEPTH_SIZE,                ATTRIB_TYPE_INTEGER,
1844a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1854a49301eSmrg                                    0 },
1864a49301eSmrg   { EGL_LEVEL,                     ATTRIB_TYPE_PLATFORM,
1874a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1884a49301eSmrg                                    0 },
1894a49301eSmrg   { EGL_MAX_PBUFFER_WIDTH,         ATTRIB_TYPE_INTEGER,
1904a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1914a49301eSmrg                                    0 },
1924a49301eSmrg   { EGL_MAX_PBUFFER_HEIGHT,        ATTRIB_TYPE_INTEGER,
1934a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1944a49301eSmrg                                    0 },
1954a49301eSmrg   { EGL_MAX_PBUFFER_PIXELS,        ATTRIB_TYPE_INTEGER,
1964a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1974a49301eSmrg                                    0 },
1984a49301eSmrg   { EGL_MAX_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
1994a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2004a49301eSmrg                                    EGL_DONT_CARE },
2014a49301eSmrg   { EGL_MIN_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
2024a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2034a49301eSmrg                                    EGL_DONT_CARE },
2044a49301eSmrg   { EGL_NATIVE_RENDERABLE,         ATTRIB_TYPE_BOOLEAN,
2054a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2064a49301eSmrg                                    EGL_DONT_CARE },
2074a49301eSmrg   { EGL_NATIVE_VISUAL_ID,          ATTRIB_TYPE_PLATFORM,
2084a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
2094a49301eSmrg                                    0 },
2104a49301eSmrg   { EGL_NATIVE_VISUAL_TYPE,        ATTRIB_TYPE_PLATFORM,
2114a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2124a49301eSmrg                                    EGL_DONT_CARE },
2134a49301eSmrg   { EGL_RENDERABLE_TYPE,           ATTRIB_TYPE_BITMASK,
2144a49301eSmrg                                    ATTRIB_CRITERION_MASK,
2154a49301eSmrg                                    EGL_OPENGL_ES_BIT },
2164a49301eSmrg   { EGL_SAMPLE_BUFFERS,            ATTRIB_TYPE_INTEGER,
2174a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2184a49301eSmrg                                    0 },
2194a49301eSmrg   { EGL_SAMPLES,                   ATTRIB_TYPE_INTEGER,
2204a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2214a49301eSmrg                                    0 },
2224a49301eSmrg   { EGL_STENCIL_SIZE,              ATTRIB_TYPE_INTEGER,
2234a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2244a49301eSmrg                                    0 },
2254a49301eSmrg   { EGL_SURFACE_TYPE,              ATTRIB_TYPE_BITMASK,
2264a49301eSmrg                                    ATTRIB_CRITERION_MASK,
2274a49301eSmrg                                    EGL_WINDOW_BIT },
2284a49301eSmrg   { EGL_TRANSPARENT_TYPE,          ATTRIB_TYPE_ENUM,
2294a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2304a49301eSmrg                                    EGL_NONE },
2314a49301eSmrg   { EGL_TRANSPARENT_RED_VALUE,     ATTRIB_TYPE_INTEGER,
2324a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2334a49301eSmrg                                    EGL_DONT_CARE },
2344a49301eSmrg   { EGL_TRANSPARENT_GREEN_VALUE,   ATTRIB_TYPE_INTEGER,
2354a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2364a49301eSmrg                                    EGL_DONT_CARE },
2374a49301eSmrg   { EGL_TRANSPARENT_BLUE_VALUE,    ATTRIB_TYPE_INTEGER,
2384a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2394a49301eSmrg                                    EGL_DONT_CARE },
2404a49301eSmrg   { EGL_MATCH_NATIVE_PIXMAP,       ATTRIB_TYPE_PSEUDO,
2414a49301eSmrg                                    ATTRIB_CRITERION_SPECIAL,
2424a49301eSmrg                                    EGL_NONE },
2433464ebd5Sriastradh   /* extensions */
2443464ebd5Sriastradh   { EGL_Y_INVERTED_NOK,            ATTRIB_TYPE_BOOLEAN,
2453464ebd5Sriastradh                                    ATTRIB_CRITERION_EXACT,
2463464ebd5Sriastradh                                    EGL_DONT_CARE }
2474a49301eSmrg};
2484a49301eSmrg
2494a49301eSmrg
2504a49301eSmrg/**
2514a49301eSmrg * Return true if a config is valid.  When for_matching is true,
2524a49301eSmrg * EGL_DONT_CARE is accepted as a valid attribute value, and checks
2534a49301eSmrg * for conflicting attribute values are skipped.
2544a49301eSmrg *
2554a49301eSmrg * Note that some attributes are platform-dependent and are not
2564a49301eSmrg * checked.
2574a49301eSmrg */
2584a49301eSmrgEGLBoolean
2594a49301eSmrg_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
2604a49301eSmrg{
2614a49301eSmrg   EGLint i, attr, val;
2624a49301eSmrg   EGLBoolean valid = EGL_TRUE;
2634a49301eSmrg
2644a49301eSmrg   /* check attributes by their types */
2654a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
2664a49301eSmrg      EGLint mask;
2674a49301eSmrg
2684a49301eSmrg      attr = _eglValidationTable[i].attr;
2693464ebd5Sriastradh      val = _eglGetConfigKey(conf, attr);
2704a49301eSmrg
2714a49301eSmrg      switch (_eglValidationTable[i].type) {
2724a49301eSmrg      case ATTRIB_TYPE_INTEGER:
2734a49301eSmrg         switch (attr) {
2744a49301eSmrg         case EGL_CONFIG_ID:
2754a49301eSmrg            /* config id must be positive */
2764a49301eSmrg            if (val <= 0)
2774a49301eSmrg               valid = EGL_FALSE;
2784a49301eSmrg            break;
2794a49301eSmrg         case EGL_SAMPLE_BUFFERS:
2804a49301eSmrg            /* there can be at most 1 sample buffer */
2813464ebd5Sriastradh            if (val > 1 || val < 0)
2824a49301eSmrg               valid = EGL_FALSE;
2834a49301eSmrg            break;
2843464ebd5Sriastradh         default:
2853464ebd5Sriastradh            if (val < 0)
2863464ebd5Sriastradh               valid = EGL_FALSE;
2874a49301eSmrg            break;
2884a49301eSmrg         }
2894a49301eSmrg         break;
2904a49301eSmrg      case ATTRIB_TYPE_BOOLEAN:
2914a49301eSmrg         if (val != EGL_TRUE && val != EGL_FALSE)
2924a49301eSmrg            valid = EGL_FALSE;
2934a49301eSmrg         break;
2944a49301eSmrg      case ATTRIB_TYPE_ENUM:
2954a49301eSmrg         switch (attr) {
2964a49301eSmrg         case EGL_CONFIG_CAVEAT:
2974a49301eSmrg            if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
2984a49301eSmrg                val != EGL_NON_CONFORMANT_CONFIG)
2994a49301eSmrg               valid = EGL_FALSE;
3004a49301eSmrg            break;
3014a49301eSmrg         case EGL_TRANSPARENT_TYPE:
3024a49301eSmrg            if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
3034a49301eSmrg               valid = EGL_FALSE;
3044a49301eSmrg            break;
3054a49301eSmrg         case EGL_COLOR_BUFFER_TYPE:
3064a49301eSmrg            if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
3074a49301eSmrg               valid = EGL_FALSE;
3084a49301eSmrg            break;
3094a49301eSmrg         default:
3104a49301eSmrg            assert(0);
3114a49301eSmrg            break;
3124a49301eSmrg         }
3134a49301eSmrg         break;
3144a49301eSmrg      case ATTRIB_TYPE_BITMASK:
3154a49301eSmrg         switch (attr) {
3164a49301eSmrg         case EGL_SURFACE_TYPE:
3174a49301eSmrg            mask = EGL_PBUFFER_BIT |
3184a49301eSmrg                   EGL_PIXMAP_BIT |
3194a49301eSmrg                   EGL_WINDOW_BIT |
3204a49301eSmrg                   EGL_VG_COLORSPACE_LINEAR_BIT |
3214a49301eSmrg                   EGL_VG_ALPHA_FORMAT_PRE_BIT |
3224a49301eSmrg                   EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
3234a49301eSmrg                   EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
3243464ebd5Sriastradh#ifdef EGL_MESA_screen_surface
325cdc920a0Smrg            if (conf->Display->Extensions.MESA_screen_surface)
326cdc920a0Smrg               mask |= EGL_SCREEN_BIT_MESA;
3273464ebd5Sriastradh#endif
3284a49301eSmrg            break;
3294a49301eSmrg         case EGL_RENDERABLE_TYPE:
3304a49301eSmrg         case EGL_CONFORMANT:
3314a49301eSmrg            mask = EGL_OPENGL_ES_BIT |
3324a49301eSmrg                   EGL_OPENVG_BIT |
3334a49301eSmrg                   EGL_OPENGL_ES2_BIT |
334af69d88dSmrg                   EGL_OPENGL_ES3_BIT_KHR |
3354a49301eSmrg                   EGL_OPENGL_BIT;
3364a49301eSmrg            break;
3374a49301eSmrg         default:
3384a49301eSmrg            assert(0);
339af69d88dSmrg            mask = 0;
3404a49301eSmrg            break;
3414a49301eSmrg         }
3424a49301eSmrg         if (val & ~mask)
3434a49301eSmrg            valid = EGL_FALSE;
3444a49301eSmrg         break;
3454a49301eSmrg      case ATTRIB_TYPE_PLATFORM:
3464a49301eSmrg         /* unable to check platform-dependent attributes here */
3474a49301eSmrg         break;
3484a49301eSmrg      case ATTRIB_TYPE_PSEUDO:
3494a49301eSmrg         /* pseudo attributes should not be set */
3504a49301eSmrg         if (val != 0)
3514a49301eSmrg            valid = EGL_FALSE;
3524a49301eSmrg         break;
3534a49301eSmrg      default:
3544a49301eSmrg         assert(0);
3554a49301eSmrg         break;
3564a49301eSmrg      }
3574a49301eSmrg
3584a49301eSmrg      if (!valid && for_matching) {
3594a49301eSmrg         /* accept EGL_DONT_CARE as a valid value */
3604a49301eSmrg         if (val == EGL_DONT_CARE)
3614a49301eSmrg            valid = EGL_TRUE;
3624a49301eSmrg         if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
3634a49301eSmrg            valid = EGL_TRUE;
3644a49301eSmrg      }
365cdc920a0Smrg      if (!valid) {
366cdc920a0Smrg         _eglLog(_EGL_DEBUG,
367cdc920a0Smrg               "attribute 0x%04x has an invalid value 0x%x", attr, val);
3684a49301eSmrg         break;
369cdc920a0Smrg      }
3704a49301eSmrg   }
3714a49301eSmrg
3724a49301eSmrg   /* any invalid attribute value should have been catched */
3734a49301eSmrg   if (!valid || for_matching)
3744a49301eSmrg      return valid;
3754a49301eSmrg
3764a49301eSmrg   /* now check for conflicting attribute values */
3774a49301eSmrg
3783464ebd5Sriastradh   switch (conf->ColorBufferType) {
3794a49301eSmrg   case EGL_RGB_BUFFER:
3803464ebd5Sriastradh      if (conf->LuminanceSize)
3814a49301eSmrg         valid = EGL_FALSE;
3823464ebd5Sriastradh      if (conf->RedSize + conf->GreenSize +
3833464ebd5Sriastradh            conf->BlueSize + conf->AlphaSize != conf->BufferSize)
3844a49301eSmrg         valid = EGL_FALSE;
3854a49301eSmrg      break;
3864a49301eSmrg   case EGL_LUMINANCE_BUFFER:
3873464ebd5Sriastradh      if (conf->RedSize || conf->GreenSize || conf->BlueSize)
3884a49301eSmrg         valid = EGL_FALSE;
3893464ebd5Sriastradh      if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize)
3904a49301eSmrg         valid = EGL_FALSE;
3914a49301eSmrg      break;
3924a49301eSmrg   }
393cdc920a0Smrg   if (!valid) {
394cdc920a0Smrg      _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
395cdc920a0Smrg      return EGL_FALSE;
396cdc920a0Smrg   }
3974a49301eSmrg
3983464ebd5Sriastradh   if (!conf->SampleBuffers && conf->Samples)
3994a49301eSmrg      valid = EGL_FALSE;
400cdc920a0Smrg   if (!valid) {
401cdc920a0Smrg      _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
402cdc920a0Smrg      return EGL_FALSE;
403cdc920a0Smrg   }
4044a49301eSmrg
4053464ebd5Sriastradh   if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
4063464ebd5Sriastradh      if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE)
4074a49301eSmrg         valid = EGL_FALSE;
4084a49301eSmrg   }
4093464ebd5Sriastradh   if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) {
4103464ebd5Sriastradh      if (conf->BindToTextureRGB || conf->BindToTextureRGBA)
4114a49301eSmrg         valid = EGL_FALSE;
4124a49301eSmrg   }
413cdc920a0Smrg   if (!valid) {
414cdc920a0Smrg      _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
415cdc920a0Smrg      return EGL_FALSE;
416cdc920a0Smrg   }
4174a49301eSmrg
4184a49301eSmrg   return valid;
4194a49301eSmrg}
4204a49301eSmrg
4214a49301eSmrg
4224a49301eSmrg/**
4234a49301eSmrg * Return true if a config matches the criteria.  This and
4244a49301eSmrg * _eglParseConfigAttribList together implement the algorithm
4254a49301eSmrg * described in "Selection of EGLConfigs".
4264a49301eSmrg *
4274a49301eSmrg * Note that attributes that are special (currently, only
4284a49301eSmrg * EGL_MATCH_NATIVE_PIXMAP) are ignored.
4294a49301eSmrg */
4304a49301eSmrgEGLBoolean
4314a49301eSmrg_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
4324a49301eSmrg{
4334a49301eSmrg   EGLint attr, val, i;
4344a49301eSmrg   EGLBoolean matched = EGL_TRUE;
4354a49301eSmrg
4364a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
4374a49301eSmrg      EGLint cmp;
4384a49301eSmrg      if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
4394a49301eSmrg         continue;
4404a49301eSmrg
4414a49301eSmrg      attr = _eglValidationTable[i].attr;
4423464ebd5Sriastradh      cmp = _eglGetConfigKey(criteria, attr);
4434a49301eSmrg      if (cmp == EGL_DONT_CARE)
4444a49301eSmrg         continue;
4454a49301eSmrg
4463464ebd5Sriastradh      val = _eglGetConfigKey(conf, attr);
4474a49301eSmrg      switch (_eglValidationTable[i].criterion) {
4484a49301eSmrg      case ATTRIB_CRITERION_EXACT:
4494a49301eSmrg         if (val != cmp)
4504a49301eSmrg            matched = EGL_FALSE;
4514a49301eSmrg         break;
4524a49301eSmrg      case ATTRIB_CRITERION_ATLEAST:
4534a49301eSmrg         if (val < cmp)
4544a49301eSmrg            matched = EGL_FALSE;
4554a49301eSmrg         break;
4564a49301eSmrg      case ATTRIB_CRITERION_MASK:
4574a49301eSmrg         if ((val & cmp) != cmp)
4584a49301eSmrg            matched = EGL_FALSE;
4594a49301eSmrg         break;
4604a49301eSmrg      case ATTRIB_CRITERION_SPECIAL:
4614a49301eSmrg         /* ignored here */
4624a49301eSmrg         break;
4634a49301eSmrg      default:
4644a49301eSmrg         assert(0);
4654a49301eSmrg         break;
4664a49301eSmrg      }
4674a49301eSmrg
468cdc920a0Smrg      if (!matched) {
4693464ebd5Sriastradh#ifndef DEBUG
4703464ebd5Sriastradh         /* only print the common errors when DEBUG is not defined */
4713464ebd5Sriastradh         if (attr != EGL_RENDERABLE_TYPE)
4723464ebd5Sriastradh            break;
4733464ebd5Sriastradh#endif
474cdc920a0Smrg         _eglLog(_EGL_DEBUG,
475cdc920a0Smrg               "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
476cdc920a0Smrg               val, attr, cmp);
4774a49301eSmrg         break;
478cdc920a0Smrg      }
4794a49301eSmrg   }
4804a49301eSmrg
4814a49301eSmrg   return matched;
4824a49301eSmrg}
4834a49301eSmrg
4843464ebd5Sriastradhstatic INLINE EGLBoolean
4853464ebd5Sriastradh_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
4863464ebd5Sriastradh{
4873464ebd5Sriastradh   if (_eglOffsetOfConfig(attr) < 0)
4883464ebd5Sriastradh      return EGL_FALSE;
4893464ebd5Sriastradh
4903464ebd5Sriastradh   switch (attr) {
4913464ebd5Sriastradh   case EGL_Y_INVERTED_NOK:
4923464ebd5Sriastradh      return conf->Display->Extensions.NOK_texture_from_pixmap;
4933464ebd5Sriastradh   default:
4943464ebd5Sriastradh      break;
4953464ebd5Sriastradh   }
4963464ebd5Sriastradh
4973464ebd5Sriastradh   return EGL_TRUE;
4983464ebd5Sriastradh}
4994a49301eSmrg
5004a49301eSmrg/**
5014a49301eSmrg * Initialize a criteria config from the given attribute list.
5024a49301eSmrg * Return EGL_FALSE if any of the attribute is invalid.
5034a49301eSmrg */
5044a49301eSmrgEGLBoolean
5053464ebd5Sriastradh_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *dpy,
5063464ebd5Sriastradh                          const EGLint *attrib_list)
5074a49301eSmrg{
5084a49301eSmrg   EGLint attr, val, i;
5093464ebd5Sriastradh
5103464ebd5Sriastradh   _eglInitConfig(conf, dpy, EGL_DONT_CARE);
5114a49301eSmrg
5124a49301eSmrg   /* reset to default values */
5134a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
5144a49301eSmrg      attr = _eglValidationTable[i].attr;
5154a49301eSmrg      val = _eglValidationTable[i].default_value;
5163464ebd5Sriastradh      _eglSetConfigKey(conf, attr, val);
5174a49301eSmrg   }
5184a49301eSmrg
5194a49301eSmrg   /* parse the list */
5204a49301eSmrg   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
5214a49301eSmrg      attr = attrib_list[i];
5224a49301eSmrg      val = attrib_list[i + 1];
5234a49301eSmrg
5243464ebd5Sriastradh      if (!_eglIsConfigAttribValid(conf, attr))
5253464ebd5Sriastradh	 return EGL_FALSE;
5264a49301eSmrg
5273464ebd5Sriastradh      _eglSetConfigKey(conf, attr, val);
5284a49301eSmrg   }
5294a49301eSmrg
5304a49301eSmrg   if (!_eglValidateConfig(conf, EGL_TRUE))
5314a49301eSmrg      return EGL_FALSE;
5324a49301eSmrg
533af69d88dSmrg   /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */
534af69d88dSmrg   if (conf->Level == EGL_DONT_CARE ||
535af69d88dSmrg       conf->MatchNativePixmap == EGL_DONT_CARE)
5364a49301eSmrg      return EGL_FALSE;
5374a49301eSmrg
5384a49301eSmrg   /* ignore other attributes when EGL_CONFIG_ID is given */
5393464ebd5Sriastradh   if (conf->ConfigID != EGL_DONT_CARE) {
5403464ebd5Sriastradh      for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
5413464ebd5Sriastradh         attr = _eglValidationTable[i].attr;
5423464ebd5Sriastradh         if (attr != EGL_CONFIG_ID)
5433464ebd5Sriastradh            _eglSetConfigKey(conf, attr, EGL_DONT_CARE);
5443464ebd5Sriastradh      }
5454a49301eSmrg   }
5464a49301eSmrg   else {
5473464ebd5Sriastradh      if (!(conf->SurfaceType & EGL_WINDOW_BIT))
5483464ebd5Sriastradh         conf->NativeVisualType = EGL_DONT_CARE;
5494a49301eSmrg
5503464ebd5Sriastradh      if (conf->TransparentType == EGL_NONE) {
5513464ebd5Sriastradh         conf->TransparentRedValue = EGL_DONT_CARE;
5523464ebd5Sriastradh         conf->TransparentGreenValue = EGL_DONT_CARE;
5533464ebd5Sriastradh         conf->TransparentBlueValue = EGL_DONT_CARE;
5544a49301eSmrg      }
5554a49301eSmrg   }
5564a49301eSmrg
5574a49301eSmrg   return EGL_TRUE;
5584a49301eSmrg}
5594a49301eSmrg
5604a49301eSmrg
5614a49301eSmrg/**
5624a49301eSmrg * Decide the ordering of conf1 and conf2, under the given criteria.
5634a49301eSmrg * When compare_id is true, this implements the algorithm described
5644a49301eSmrg * in "Sorting of EGLConfigs".  When compare_id is false,
5654a49301eSmrg * EGL_CONFIG_ID is not compared.
5664a49301eSmrg *
5674a49301eSmrg * It returns a negative integer if conf1 is considered to come
5684a49301eSmrg * before conf2;  a positive integer if conf2 is considered to come
5694a49301eSmrg * before conf1;  zero if the ordering cannot be decided.
5704a49301eSmrg *
5714a49301eSmrg * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
5724a49301eSmrg * ignored here.
5734a49301eSmrg */
5744a49301eSmrgEGLint
5754a49301eSmrg_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
5764a49301eSmrg                   const _EGLConfig *criteria, EGLBoolean compare_id)
5774a49301eSmrg{
5784a49301eSmrg   const EGLint compare_attribs[] = {
5794a49301eSmrg      EGL_BUFFER_SIZE,
5804a49301eSmrg      EGL_SAMPLE_BUFFERS,
5814a49301eSmrg      EGL_SAMPLES,
5824a49301eSmrg      EGL_DEPTH_SIZE,
5834a49301eSmrg      EGL_STENCIL_SIZE,
5844a49301eSmrg      EGL_ALPHA_MASK_SIZE,
5854a49301eSmrg   };
5864a49301eSmrg   EGLint val1, val2;
5874a49301eSmrg   EGLint i;
5884a49301eSmrg
5894a49301eSmrg   if (conf1 == conf2)
5904a49301eSmrg      return 0;
5914a49301eSmrg
5924a49301eSmrg   /* the enum values have the desired ordering */
5934a49301eSmrg   assert(EGL_NONE < EGL_SLOW_CONFIG);
5944a49301eSmrg   assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
5953464ebd5Sriastradh   val1 = conf1->ConfigCaveat - conf2->ConfigCaveat;
5963464ebd5Sriastradh   if (val1)
5973464ebd5Sriastradh      return val1;
5984a49301eSmrg
5994a49301eSmrg   /* the enum values have the desired ordering */
6004a49301eSmrg   assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
6013464ebd5Sriastradh   val1 = conf1->ColorBufferType - conf2->ColorBufferType;
6023464ebd5Sriastradh   if (val1)
6033464ebd5Sriastradh      return val1;
6044a49301eSmrg
6054a49301eSmrg   if (criteria) {
6064a49301eSmrg      val1 = val2 = 0;
6073464ebd5Sriastradh      if (conf1->ColorBufferType == EGL_RGB_BUFFER) {
6083464ebd5Sriastradh         if (criteria->RedSize > 0) {
6093464ebd5Sriastradh            val1 += conf1->RedSize;
6103464ebd5Sriastradh            val2 += conf2->RedSize;
6114a49301eSmrg         }
6123464ebd5Sriastradh         if (criteria->GreenSize > 0) {
6133464ebd5Sriastradh            val1 += conf1->GreenSize;
6143464ebd5Sriastradh            val2 += conf2->GreenSize;
6154a49301eSmrg         }
6163464ebd5Sriastradh         if (criteria->BlueSize > 0) {
6173464ebd5Sriastradh            val1 += conf1->BlueSize;
6183464ebd5Sriastradh            val2 += conf2->BlueSize;
6194a49301eSmrg         }
6204a49301eSmrg      }
6214a49301eSmrg      else {
6223464ebd5Sriastradh         if (criteria->LuminanceSize > 0) {
6233464ebd5Sriastradh            val1 += conf1->LuminanceSize;
6243464ebd5Sriastradh            val2 += conf2->LuminanceSize;
6254a49301eSmrg         }
6264a49301eSmrg      }
6273464ebd5Sriastradh      if (criteria->AlphaSize > 0) {
6283464ebd5Sriastradh         val1 += conf1->AlphaSize;
6293464ebd5Sriastradh         val2 += conf2->AlphaSize;
6304a49301eSmrg      }
6314a49301eSmrg   }
6324a49301eSmrg   else {
6334a49301eSmrg      /* assume the default criteria, which gives no specific ordering */
6344a49301eSmrg      val1 = val2 = 0;
6354a49301eSmrg   }
6364a49301eSmrg
6374a49301eSmrg   /* for color bits, larger one is preferred */
6384a49301eSmrg   if (val1 != val2)
6394a49301eSmrg      return (val2 - val1);
6404a49301eSmrg
6414a49301eSmrg   for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
6423464ebd5Sriastradh      val1 = _eglGetConfigKey(conf1, compare_attribs[i]);
6433464ebd5Sriastradh      val2 = _eglGetConfigKey(conf2, compare_attribs[i]);
6444a49301eSmrg      if (val1 != val2)
6454a49301eSmrg         return (val1 - val2);
6464a49301eSmrg   }
6474a49301eSmrg
6484a49301eSmrg   /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
6494a49301eSmrg
6503464ebd5Sriastradh   return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0;
6514a49301eSmrg}
6524a49301eSmrg
6534a49301eSmrg
6544a49301eSmrgstatic INLINE
6554a49301eSmrgvoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
6564a49301eSmrg{
6574a49301eSmrg   const _EGLConfig *tmp = *conf1;
6584a49301eSmrg   *conf1 = *conf2;
6594a49301eSmrg   *conf2 = tmp;
6604a49301eSmrg}
6614a49301eSmrg
6624a49301eSmrg
6634a49301eSmrg/**
6644a49301eSmrg * Quick sort an array of configs.  This differs from the standard
6654a49301eSmrg * qsort() in that the compare function accepts an additional
6664a49301eSmrg * argument.
6674a49301eSmrg */
668af69d88dSmrgstatic void
6694a49301eSmrg_eglSortConfigs(const _EGLConfig **configs, EGLint count,
6704a49301eSmrg                EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
6714a49301eSmrg                                  void *),
6724a49301eSmrg                void *priv_data)
6734a49301eSmrg{
6744a49301eSmrg   const EGLint pivot = 0;
6754a49301eSmrg   EGLint i, j;
6764a49301eSmrg
6774a49301eSmrg   if (count <= 1)
6784a49301eSmrg      return;
6794a49301eSmrg
6804a49301eSmrg   _eglSwapConfigs(&configs[pivot], &configs[count / 2]);
6814a49301eSmrg   i = 1;
6824a49301eSmrg   j = count - 1;
6834a49301eSmrg   do {
6844a49301eSmrg      while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
6854a49301eSmrg         i++;
6864a49301eSmrg      while (compare(configs[j], configs[pivot], priv_data) > 0)
6874a49301eSmrg         j--;
6884a49301eSmrg      if (i < j) {
6894a49301eSmrg         _eglSwapConfigs(&configs[i], &configs[j]);
6904a49301eSmrg         i++;
6914a49301eSmrg         j--;
6924a49301eSmrg      }
6934a49301eSmrg      else if (i == j) {
6944a49301eSmrg         i++;
6954a49301eSmrg         j--;
6964a49301eSmrg         break;
6974a49301eSmrg      }
6984a49301eSmrg   } while (i <= j);
6994a49301eSmrg   _eglSwapConfigs(&configs[pivot], &configs[j]);
7004a49301eSmrg
7014a49301eSmrg   _eglSortConfigs(configs, j, compare, priv_data);
7024a49301eSmrg   _eglSortConfigs(configs + i, count - i, compare, priv_data);
7034a49301eSmrg}
7044a49301eSmrg
7054a49301eSmrg
7064a49301eSmrg/**
707af69d88dSmrg * A helper function for implementing eglChooseConfig.  See _eglFilterArray and
708af69d88dSmrg * _eglSortConfigs for the meanings of match and compare.
7094a49301eSmrg */
7104a49301eSmrgEGLBoolean
711af69d88dSmrg_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs,
712af69d88dSmrg                      EGLint config_size, EGLint *num_configs,
713af69d88dSmrg                      EGLBoolean (*match)(const _EGLConfig *, void *),
714af69d88dSmrg                      EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
715af69d88dSmrg                                        void *),
716af69d88dSmrg                      void *priv_data)
7174a49301eSmrg{
718af69d88dSmrg   _EGLConfig **configList;
7194a49301eSmrg   EGLint i, count;
7204a49301eSmrg
7214a49301eSmrg   if (!num_configs)
7224a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
7234a49301eSmrg
7243464ebd5Sriastradh   /* get the number of matched configs */
725af69d88dSmrg   count = _eglFilterArray(array, NULL, 0,
726af69d88dSmrg         (_EGLArrayForEach) match, priv_data);
7273464ebd5Sriastradh   if (!count) {
7283464ebd5Sriastradh      *num_configs = count;
7293464ebd5Sriastradh      return EGL_TRUE;
7303464ebd5Sriastradh   }
7313464ebd5Sriastradh
7323464ebd5Sriastradh   configList = malloc(sizeof(*configList) * count);
7334a49301eSmrg   if (!configList)
7344a49301eSmrg      return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
7354a49301eSmrg
7363464ebd5Sriastradh   /* get the matched configs */
737af69d88dSmrg   _eglFilterArray(array, (void **) configList, count,
738af69d88dSmrg         (_EGLArrayForEach) match, priv_data);
7394a49301eSmrg
7404a49301eSmrg   /* perform sorting of configs */
7414a49301eSmrg   if (configs && count) {
7424a49301eSmrg      _eglSortConfigs((const _EGLConfig **) configList, count,
743af69d88dSmrg                      compare, priv_data);
7444a49301eSmrg      count = MIN2(count, config_size);
7454a49301eSmrg      for (i = 0; i < count; i++)
7464a49301eSmrg         configs[i] = _eglGetConfigHandle(configList[i]);
7474a49301eSmrg   }
7484a49301eSmrg
7494a49301eSmrg   free(configList);
7504a49301eSmrg
7514a49301eSmrg   *num_configs = count;
7524a49301eSmrg
7534a49301eSmrg   return EGL_TRUE;
7544a49301eSmrg}
7554a49301eSmrg
7564a49301eSmrg
757af69d88dSmrgstatic EGLBoolean
758af69d88dSmrg_eglFallbackMatch(const _EGLConfig *conf, void *priv_data)
759af69d88dSmrg{
760af69d88dSmrg   return _eglMatchConfig(conf, (const _EGLConfig *) priv_data);
761af69d88dSmrg}
762af69d88dSmrg
763af69d88dSmrg
764af69d88dSmrgstatic EGLint
765af69d88dSmrg_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
766af69d88dSmrg                    void *priv_data)
767af69d88dSmrg{
768af69d88dSmrg   return _eglCompareConfigs(conf1, conf2,
769af69d88dSmrg         (const _EGLConfig *) priv_data, EGL_TRUE);
770af69d88dSmrg}
771af69d88dSmrg
772af69d88dSmrg
773af69d88dSmrg/**
774af69d88dSmrg * Typical fallback routine for eglChooseConfig
775af69d88dSmrg */
776af69d88dSmrgEGLBoolean
777af69d88dSmrg_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
778af69d88dSmrg                 EGLConfig *configs, EGLint config_size, EGLint *num_configs)
779af69d88dSmrg{
780af69d88dSmrg   _EGLConfig criteria;
781af69d88dSmrg
782af69d88dSmrg   if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
783af69d88dSmrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
784af69d88dSmrg
785af69d88dSmrg   return _eglFilterConfigArray(disp->Configs,
786af69d88dSmrg         configs, config_size, num_configs,
787af69d88dSmrg         _eglFallbackMatch, _eglFallbackCompare,
788af69d88dSmrg         (void *) &criteria);
789af69d88dSmrg}
790af69d88dSmrg
791af69d88dSmrg
7924a49301eSmrg/**
7934a49301eSmrg * Fallback for eglGetConfigAttrib.
7944a49301eSmrg */
7954a49301eSmrgEGLBoolean
7964a49301eSmrg_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
7974a49301eSmrg                    EGLint attribute, EGLint *value)
7984a49301eSmrg{
7994a49301eSmrg   if (!_eglIsConfigAttribValid(conf, attribute))
8004a49301eSmrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
8013464ebd5Sriastradh
8023464ebd5Sriastradh   /* nonqueryable attributes */
8033464ebd5Sriastradh   switch (attribute) {
8043464ebd5Sriastradh   case EGL_MATCH_NATIVE_PIXMAP:
8053464ebd5Sriastradh      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
8063464ebd5Sriastradh      break;
8073464ebd5Sriastradh   default:
8083464ebd5Sriastradh      break;
8093464ebd5Sriastradh   }
8103464ebd5Sriastradh
8114a49301eSmrg   if (!value)
8124a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
8134a49301eSmrg
8143464ebd5Sriastradh   *value = _eglGetConfigKey(conf, attribute);
8154a49301eSmrg   return EGL_TRUE;
8164a49301eSmrg}
8174a49301eSmrg
8184a49301eSmrg
8193464ebd5Sriastradhstatic EGLBoolean
8203464ebd5Sriastradh_eglFlattenConfig(void *elem, void *buffer)
8213464ebd5Sriastradh{
8223464ebd5Sriastradh   _EGLConfig *conf = (_EGLConfig *) elem;
8233464ebd5Sriastradh   EGLConfig *handle = (EGLConfig *) buffer;
8243464ebd5Sriastradh   *handle = _eglGetConfigHandle(conf);
8253464ebd5Sriastradh   return EGL_TRUE;
8263464ebd5Sriastradh}
8273464ebd5Sriastradh
8284a49301eSmrg/**
8294a49301eSmrg * Fallback for eglGetConfigs.
8304a49301eSmrg */
8314a49301eSmrgEGLBoolean
8324a49301eSmrg_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
8334a49301eSmrg               EGLint config_size, EGLint *num_config)
8344a49301eSmrg{
8354a49301eSmrg   if (!num_config)
8364a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
8374a49301eSmrg
8383464ebd5Sriastradh   *num_config = _eglFlattenArray(disp->Configs, (void *) configs,
8393464ebd5Sriastradh         sizeof(configs[0]), config_size, _eglFlattenConfig);
8404a49301eSmrg
8414a49301eSmrg   return EGL_TRUE;
8424a49301eSmrg}
843