eglconfig.c revision 4a49301e
14a49301eSmrg/**
24a49301eSmrg * EGL Configuration (pixel format) functions.
34a49301eSmrg */
44a49301eSmrg
54a49301eSmrg
64a49301eSmrg#include <stdlib.h>
74a49301eSmrg#include <stdio.h>
84a49301eSmrg#include <string.h>
94a49301eSmrg#include <assert.h>
104a49301eSmrg#include "eglconfig.h"
114a49301eSmrg#include "egldisplay.h"
124a49301eSmrg#include "egldriver.h"
134a49301eSmrg#include "eglglobals.h"
144a49301eSmrg#include "egllog.h"
154a49301eSmrg
164a49301eSmrg
174a49301eSmrg#define MIN2(A, B)  (((A) < (B)) ? (A) : (B))
184a49301eSmrg#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
194a49301eSmrg
204a49301eSmrg
214a49301eSmrg/**
224a49301eSmrg * Init the given _EGLconfig to default values.
234a49301eSmrg * \param id  the configuration's ID.
244a49301eSmrg *
254a49301eSmrg * Note that id must be positive for the config to be valid.
264a49301eSmrg * It is also recommended that when there are N configs, their
274a49301eSmrg * IDs are from 1 to N respectively.
284a49301eSmrg */
294a49301eSmrgvoid
304a49301eSmrg_eglInitConfig(_EGLConfig *config, EGLint id)
314a49301eSmrg{
324a49301eSmrg   memset(config, 0, sizeof(*config));
334a49301eSmrg
344a49301eSmrg   /* some attributes take non-zero default values */
354a49301eSmrg   SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID,               id);
364a49301eSmrg   SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT,           EGL_NONE);
374a49301eSmrg   SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE,        EGL_NONE);
384a49301eSmrg   SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE,      EGL_NONE);
394a49301eSmrg#ifdef EGL_VERSION_1_2
404a49301eSmrg   SET_CONFIG_ATTRIB(config, EGL_COLOR_BUFFER_TYPE,       EGL_RGB_BUFFER);
414a49301eSmrg#endif /* EGL_VERSION_1_2 */
424a49301eSmrg}
434a49301eSmrg
444a49301eSmrg
454a49301eSmrg/**
464a49301eSmrg * Link a config to a display and return the handle of the link.
474a49301eSmrg * The handle can be passed to client directly.
484a49301eSmrg *
494a49301eSmrg * Note that we just save the ptr to the config (we don't copy the config).
504a49301eSmrg */
514a49301eSmrgEGLConfig
524a49301eSmrg_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
534a49301eSmrg{
544a49301eSmrg   _EGLConfig **configs;
554a49301eSmrg
564a49301eSmrg   /* sanity check */
574a49301eSmrg   assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0);
584a49301eSmrg
594a49301eSmrg   configs = dpy->Configs;
604a49301eSmrg   if (dpy->NumConfigs >= dpy->MaxConfigs) {
614a49301eSmrg      EGLint new_size = dpy->MaxConfigs + 16;
624a49301eSmrg      assert(dpy->NumConfigs < new_size);
634a49301eSmrg
644a49301eSmrg      configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0]));
654a49301eSmrg      if (!configs)
664a49301eSmrg         return (EGLConfig) NULL;
674a49301eSmrg
684a49301eSmrg      dpy->Configs = configs;
694a49301eSmrg      dpy->MaxConfigs = new_size;
704a49301eSmrg   }
714a49301eSmrg
724a49301eSmrg   conf->Display = dpy;
734a49301eSmrg   dpy->Configs[dpy->NumConfigs++] = conf;
744a49301eSmrg
754a49301eSmrg   return (EGLConfig) conf;
764a49301eSmrg}
774a49301eSmrg
784a49301eSmrg
794a49301eSmrg#ifndef _EGL_SKIP_HANDLE_CHECK
804a49301eSmrg
814a49301eSmrg
824a49301eSmrgEGLBoolean
834a49301eSmrg_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
844a49301eSmrg{
854a49301eSmrg   EGLint num_configs = (dpy) ? dpy->NumConfigs : 0;
864a49301eSmrg   EGLint i;
874a49301eSmrg
884a49301eSmrg   for (i = 0; i < num_configs; i++) {
894a49301eSmrg      _EGLConfig *conf = dpy->Configs[i];
904a49301eSmrg      if (conf == (_EGLConfig *) config) {
914a49301eSmrg         assert(conf->Display == dpy);
924a49301eSmrg         break;
934a49301eSmrg      }
944a49301eSmrg   }
954a49301eSmrg   return (i < num_configs);
964a49301eSmrg}
974a49301eSmrg
984a49301eSmrg
994a49301eSmrg#endif /* _EGL_SKIP_HANDLE_CHECK */
1004a49301eSmrg
1014a49301eSmrg
1024a49301eSmrgenum {
1034a49301eSmrg   /* types */
1044a49301eSmrg   ATTRIB_TYPE_INTEGER,
1054a49301eSmrg   ATTRIB_TYPE_BOOLEAN,
1064a49301eSmrg   ATTRIB_TYPE_BITMASK,
1074a49301eSmrg   ATTRIB_TYPE_ENUM,
1084a49301eSmrg   ATTRIB_TYPE_PSEUDO, /* non-queryable */
1094a49301eSmrg   ATTRIB_TYPE_PLATFORM, /* platform-dependent */
1104a49301eSmrg   /* criteria */
1114a49301eSmrg   ATTRIB_CRITERION_EXACT,
1124a49301eSmrg   ATTRIB_CRITERION_ATLEAST,
1134a49301eSmrg   ATTRIB_CRITERION_MASK,
1144a49301eSmrg   ATTRIB_CRITERION_SPECIAL,
1154a49301eSmrg   ATTRIB_CRITERION_IGNORE,
1164a49301eSmrg};
1174a49301eSmrg
1184a49301eSmrg
1194a49301eSmrg/* EGL spec Table 3.1 and 3.4 */
1204a49301eSmrgstatic const struct {
1214a49301eSmrg   EGLint attr;
1224a49301eSmrg   EGLint type;
1234a49301eSmrg   EGLint criterion;
1244a49301eSmrg   EGLint default_value;
1254a49301eSmrg} _eglValidationTable[] =
1264a49301eSmrg{
1274a49301eSmrg   { EGL_BUFFER_SIZE,               ATTRIB_TYPE_INTEGER,
1284a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1294a49301eSmrg                                    0 },
1304a49301eSmrg   { EGL_RED_SIZE,                  ATTRIB_TYPE_INTEGER,
1314a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1324a49301eSmrg                                    0 },
1334a49301eSmrg   { EGL_GREEN_SIZE,                ATTRIB_TYPE_INTEGER,
1344a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1354a49301eSmrg                                    0 },
1364a49301eSmrg   { EGL_BLUE_SIZE,                 ATTRIB_TYPE_INTEGER,
1374a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1384a49301eSmrg                                    0 },
1394a49301eSmrg   { EGL_LUMINANCE_SIZE,            ATTRIB_TYPE_INTEGER,
1404a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1414a49301eSmrg                                    0 },
1424a49301eSmrg   { EGL_ALPHA_SIZE,                ATTRIB_TYPE_INTEGER,
1434a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1444a49301eSmrg                                    0 },
1454a49301eSmrg   { EGL_ALPHA_MASK_SIZE,           ATTRIB_TYPE_INTEGER,
1464a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1474a49301eSmrg                                    0 },
1484a49301eSmrg   { EGL_BIND_TO_TEXTURE_RGB,       ATTRIB_TYPE_BOOLEAN,
1494a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1504a49301eSmrg                                    EGL_DONT_CARE },
1514a49301eSmrg   { EGL_BIND_TO_TEXTURE_RGBA,      ATTRIB_TYPE_BOOLEAN,
1524a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1534a49301eSmrg                                    EGL_DONT_CARE },
1544a49301eSmrg   { EGL_COLOR_BUFFER_TYPE,         ATTRIB_TYPE_ENUM,
1554a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1564a49301eSmrg                                    EGL_RGB_BUFFER },
1574a49301eSmrg   { EGL_CONFIG_CAVEAT,             ATTRIB_TYPE_ENUM,
1584a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1594a49301eSmrg                                    EGL_DONT_CARE },
1604a49301eSmrg   { EGL_CONFIG_ID,                 ATTRIB_TYPE_INTEGER,
1614a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1624a49301eSmrg                                    EGL_DONT_CARE },
1634a49301eSmrg   { EGL_CONFORMANT,                ATTRIB_TYPE_BITMASK,
1644a49301eSmrg                                    ATTRIB_CRITERION_MASK,
1654a49301eSmrg                                    0 },
1664a49301eSmrg   { EGL_DEPTH_SIZE,                ATTRIB_TYPE_INTEGER,
1674a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
1684a49301eSmrg                                    0 },
1694a49301eSmrg   { EGL_LEVEL,                     ATTRIB_TYPE_PLATFORM,
1704a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1714a49301eSmrg                                    0 },
1724a49301eSmrg   { EGL_MAX_PBUFFER_WIDTH,         ATTRIB_TYPE_INTEGER,
1734a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1744a49301eSmrg                                    0 },
1754a49301eSmrg   { EGL_MAX_PBUFFER_HEIGHT,        ATTRIB_TYPE_INTEGER,
1764a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1774a49301eSmrg                                    0 },
1784a49301eSmrg   { EGL_MAX_PBUFFER_PIXELS,        ATTRIB_TYPE_INTEGER,
1794a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1804a49301eSmrg                                    0 },
1814a49301eSmrg   { EGL_MAX_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
1824a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1834a49301eSmrg                                    EGL_DONT_CARE },
1844a49301eSmrg   { EGL_MIN_SWAP_INTERVAL,         ATTRIB_TYPE_INTEGER,
1854a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1864a49301eSmrg                                    EGL_DONT_CARE },
1874a49301eSmrg   { EGL_NATIVE_RENDERABLE,         ATTRIB_TYPE_BOOLEAN,
1884a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1894a49301eSmrg                                    EGL_DONT_CARE },
1904a49301eSmrg   { EGL_NATIVE_VISUAL_ID,          ATTRIB_TYPE_PLATFORM,
1914a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
1924a49301eSmrg                                    0 },
1934a49301eSmrg   { EGL_NATIVE_VISUAL_TYPE,        ATTRIB_TYPE_PLATFORM,
1944a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
1954a49301eSmrg                                    EGL_DONT_CARE },
1964a49301eSmrg   { EGL_RENDERABLE_TYPE,           ATTRIB_TYPE_BITMASK,
1974a49301eSmrg                                    ATTRIB_CRITERION_MASK,
1984a49301eSmrg                                    EGL_OPENGL_ES_BIT },
1994a49301eSmrg   { EGL_SAMPLE_BUFFERS,            ATTRIB_TYPE_INTEGER,
2004a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2014a49301eSmrg                                    0 },
2024a49301eSmrg   { EGL_SAMPLES,                   ATTRIB_TYPE_INTEGER,
2034a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2044a49301eSmrg                                    0 },
2054a49301eSmrg   { EGL_STENCIL_SIZE,              ATTRIB_TYPE_INTEGER,
2064a49301eSmrg                                    ATTRIB_CRITERION_ATLEAST,
2074a49301eSmrg                                    0 },
2084a49301eSmrg   { EGL_SURFACE_TYPE,              ATTRIB_TYPE_BITMASK,
2094a49301eSmrg                                    ATTRIB_CRITERION_MASK,
2104a49301eSmrg                                    EGL_WINDOW_BIT },
2114a49301eSmrg   { EGL_TRANSPARENT_TYPE,          ATTRIB_TYPE_ENUM,
2124a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2134a49301eSmrg                                    EGL_NONE },
2144a49301eSmrg   { EGL_TRANSPARENT_RED_VALUE,     ATTRIB_TYPE_INTEGER,
2154a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2164a49301eSmrg                                    EGL_DONT_CARE },
2174a49301eSmrg   { EGL_TRANSPARENT_GREEN_VALUE,   ATTRIB_TYPE_INTEGER,
2184a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2194a49301eSmrg                                    EGL_DONT_CARE },
2204a49301eSmrg   { EGL_TRANSPARENT_BLUE_VALUE,    ATTRIB_TYPE_INTEGER,
2214a49301eSmrg                                    ATTRIB_CRITERION_EXACT,
2224a49301eSmrg                                    EGL_DONT_CARE },
2234a49301eSmrg   /* these are not real attributes */
2244a49301eSmrg   { EGL_MATCH_NATIVE_PIXMAP,       ATTRIB_TYPE_PSEUDO,
2254a49301eSmrg                                    ATTRIB_CRITERION_SPECIAL,
2264a49301eSmrg                                    EGL_NONE },
2274a49301eSmrg   { EGL_PRESERVED_RESOURCES,       ATTRIB_TYPE_PSEUDO,
2284a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
2294a49301eSmrg                                    0 },
2304a49301eSmrg   { EGL_NONE,                      ATTRIB_TYPE_PSEUDO,
2314a49301eSmrg                                    ATTRIB_CRITERION_IGNORE,
2324a49301eSmrg                                    0 }
2334a49301eSmrg};
2344a49301eSmrg
2354a49301eSmrg
2364a49301eSmrg/**
2374a49301eSmrg * Return true if a config is valid.  When for_matching is true,
2384a49301eSmrg * EGL_DONT_CARE is accepted as a valid attribute value, and checks
2394a49301eSmrg * for conflicting attribute values are skipped.
2404a49301eSmrg *
2414a49301eSmrg * Note that some attributes are platform-dependent and are not
2424a49301eSmrg * checked.
2434a49301eSmrg */
2444a49301eSmrgEGLBoolean
2454a49301eSmrg_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
2464a49301eSmrg{
2474a49301eSmrg   EGLint i, attr, val;
2484a49301eSmrg   EGLBoolean valid = EGL_TRUE;
2494a49301eSmrg   EGLint red_size = 0, green_size = 0, blue_size = 0, luminance_size = 0;
2504a49301eSmrg   EGLint alpha_size = 0, buffer_size = 0;
2514a49301eSmrg
2524a49301eSmrg   /* all attributes should have been listed */
2534a49301eSmrg   assert(ARRAY_SIZE(_eglValidationTable) == _EGL_CONFIG_NUM_ATTRIBS);
2544a49301eSmrg
2554a49301eSmrg   /* check attributes by their types */
2564a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
2574a49301eSmrg      EGLint mask;
2584a49301eSmrg
2594a49301eSmrg      attr = _eglValidationTable[i].attr;
2604a49301eSmrg      val = GET_CONFIG_ATTRIB(conf, attr);
2614a49301eSmrg
2624a49301eSmrg      switch (_eglValidationTable[i].type) {
2634a49301eSmrg      case ATTRIB_TYPE_INTEGER:
2644a49301eSmrg         switch (attr) {
2654a49301eSmrg         case EGL_CONFIG_ID:
2664a49301eSmrg            /* config id must be positive */
2674a49301eSmrg            if (val <= 0)
2684a49301eSmrg               valid = EGL_FALSE;
2694a49301eSmrg            break;
2704a49301eSmrg         case EGL_SAMPLE_BUFFERS:
2714a49301eSmrg            /* there can be at most 1 sample buffer */
2724a49301eSmrg            if (val > 1)
2734a49301eSmrg               valid = EGL_FALSE;
2744a49301eSmrg            break;
2754a49301eSmrg         case EGL_RED_SIZE:
2764a49301eSmrg            red_size = val;
2774a49301eSmrg            break;
2784a49301eSmrg         case EGL_GREEN_SIZE:
2794a49301eSmrg            green_size = val;
2804a49301eSmrg            break;
2814a49301eSmrg         case EGL_BLUE_SIZE:
2824a49301eSmrg            blue_size = val;
2834a49301eSmrg            break;
2844a49301eSmrg         case EGL_LUMINANCE_SIZE:
2854a49301eSmrg            luminance_size = val;
2864a49301eSmrg            break;
2874a49301eSmrg         case EGL_ALPHA_SIZE:
2884a49301eSmrg            alpha_size = val;
2894a49301eSmrg            break;
2904a49301eSmrg         case EGL_BUFFER_SIZE:
2914a49301eSmrg            buffer_size = val;
2924a49301eSmrg            break;
2934a49301eSmrg         }
2944a49301eSmrg         if (val < 0)
2954a49301eSmrg            valid = EGL_FALSE;
2964a49301eSmrg         break;
2974a49301eSmrg      case ATTRIB_TYPE_BOOLEAN:
2984a49301eSmrg         if (val != EGL_TRUE && val != EGL_FALSE)
2994a49301eSmrg            valid = EGL_FALSE;
3004a49301eSmrg         break;
3014a49301eSmrg      case ATTRIB_TYPE_ENUM:
3024a49301eSmrg         switch (attr) {
3034a49301eSmrg         case EGL_CONFIG_CAVEAT:
3044a49301eSmrg            if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
3054a49301eSmrg                val != EGL_NON_CONFORMANT_CONFIG)
3064a49301eSmrg               valid = EGL_FALSE;
3074a49301eSmrg            break;
3084a49301eSmrg         case EGL_TRANSPARENT_TYPE:
3094a49301eSmrg            if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
3104a49301eSmrg               valid = EGL_FALSE;
3114a49301eSmrg            break;
3124a49301eSmrg         case EGL_COLOR_BUFFER_TYPE:
3134a49301eSmrg            if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
3144a49301eSmrg               valid = EGL_FALSE;
3154a49301eSmrg            break;
3164a49301eSmrg         default:
3174a49301eSmrg            assert(0);
3184a49301eSmrg            break;
3194a49301eSmrg         }
3204a49301eSmrg         break;
3214a49301eSmrg      case ATTRIB_TYPE_BITMASK:
3224a49301eSmrg         switch (attr) {
3234a49301eSmrg         case EGL_SURFACE_TYPE:
3244a49301eSmrg            mask = EGL_PBUFFER_BIT |
3254a49301eSmrg                   EGL_PIXMAP_BIT |
3264a49301eSmrg                   EGL_WINDOW_BIT |
3274a49301eSmrg                   EGL_VG_COLORSPACE_LINEAR_BIT |
3284a49301eSmrg                   EGL_VG_ALPHA_FORMAT_PRE_BIT |
3294a49301eSmrg                   EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
3304a49301eSmrg                   EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
3314a49301eSmrg            break;
3324a49301eSmrg         case EGL_RENDERABLE_TYPE:
3334a49301eSmrg         case EGL_CONFORMANT:
3344a49301eSmrg            mask = EGL_OPENGL_ES_BIT |
3354a49301eSmrg                   EGL_OPENVG_BIT |
3364a49301eSmrg                   EGL_OPENGL_ES2_BIT |
3374a49301eSmrg                   EGL_OPENGL_BIT;
3384a49301eSmrg            break;
3394a49301eSmrg         default:
3404a49301eSmrg            assert(0);
3414a49301eSmrg            break;
3424a49301eSmrg         }
3434a49301eSmrg         if (val & ~mask)
3444a49301eSmrg            valid = EGL_FALSE;
3454a49301eSmrg         break;
3464a49301eSmrg      case ATTRIB_TYPE_PLATFORM:
3474a49301eSmrg         /* unable to check platform-dependent attributes here */
3484a49301eSmrg         break;
3494a49301eSmrg      case ATTRIB_TYPE_PSEUDO:
3504a49301eSmrg         /* pseudo attributes should not be set */
3514a49301eSmrg         if (val != 0)
3524a49301eSmrg            valid = EGL_FALSE;
3534a49301eSmrg         break;
3544a49301eSmrg      default:
3554a49301eSmrg         assert(0);
3564a49301eSmrg         break;
3574a49301eSmrg      }
3584a49301eSmrg
3594a49301eSmrg      if (!valid && for_matching) {
3604a49301eSmrg         /* accept EGL_DONT_CARE as a valid value */
3614a49301eSmrg         if (val == EGL_DONT_CARE)
3624a49301eSmrg            valid = EGL_TRUE;
3634a49301eSmrg         if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
3644a49301eSmrg            valid = EGL_TRUE;
3654a49301eSmrg      }
3664a49301eSmrg      if (!valid)
3674a49301eSmrg         break;
3684a49301eSmrg   }
3694a49301eSmrg
3704a49301eSmrg   /* any invalid attribute value should have been catched */
3714a49301eSmrg   if (!valid || for_matching)
3724a49301eSmrg      return valid;
3734a49301eSmrg
3744a49301eSmrg   /* now check for conflicting attribute values */
3754a49301eSmrg
3764a49301eSmrg   switch (GET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE)) {
3774a49301eSmrg   case EGL_RGB_BUFFER:
3784a49301eSmrg      if (luminance_size)
3794a49301eSmrg         valid = EGL_FALSE;
3804a49301eSmrg      if (red_size + green_size + blue_size + alpha_size != buffer_size)
3814a49301eSmrg         valid = EGL_FALSE;
3824a49301eSmrg      break;
3834a49301eSmrg   case EGL_LUMINANCE_BUFFER:
3844a49301eSmrg      if (red_size || green_size || blue_size)
3854a49301eSmrg         valid = EGL_FALSE;
3864a49301eSmrg      if (luminance_size + alpha_size != buffer_size)
3874a49301eSmrg         valid = EGL_FALSE;
3884a49301eSmrg      break;
3894a49301eSmrg   }
3904a49301eSmrg
3914a49301eSmrg   val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS);
3924a49301eSmrg   if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES))
3934a49301eSmrg      valid = EGL_FALSE;
3944a49301eSmrg
3954a49301eSmrg   val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
3964a49301eSmrg   if (!(val & EGL_WINDOW_BIT)) {
3974a49301eSmrg      if (GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID) != 0 ||
3984a49301eSmrg          GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE) != EGL_NONE)
3994a49301eSmrg         valid = EGL_FALSE;
4004a49301eSmrg   }
4014a49301eSmrg   if (!(val & EGL_PBUFFER_BIT)) {
4024a49301eSmrg      if (GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB) ||
4034a49301eSmrg          GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA))
4044a49301eSmrg         valid = EGL_FALSE;
4054a49301eSmrg   }
4064a49301eSmrg
4074a49301eSmrg   return valid;
4084a49301eSmrg}
4094a49301eSmrg
4104a49301eSmrg
4114a49301eSmrg/**
4124a49301eSmrg * Return true if a config matches the criteria.  This and
4134a49301eSmrg * _eglParseConfigAttribList together implement the algorithm
4144a49301eSmrg * described in "Selection of EGLConfigs".
4154a49301eSmrg *
4164a49301eSmrg * Note that attributes that are special (currently, only
4174a49301eSmrg * EGL_MATCH_NATIVE_PIXMAP) are ignored.
4184a49301eSmrg */
4194a49301eSmrgEGLBoolean
4204a49301eSmrg_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
4214a49301eSmrg{
4224a49301eSmrg   EGLint attr, val, i;
4234a49301eSmrg   EGLBoolean matched = EGL_TRUE;
4244a49301eSmrg
4254a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
4264a49301eSmrg      EGLint cmp;
4274a49301eSmrg      if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
4284a49301eSmrg         continue;
4294a49301eSmrg
4304a49301eSmrg      attr = _eglValidationTable[i].attr;
4314a49301eSmrg      cmp = GET_CONFIG_ATTRIB(criteria, attr);
4324a49301eSmrg      if (cmp == EGL_DONT_CARE)
4334a49301eSmrg         continue;
4344a49301eSmrg
4354a49301eSmrg      val = GET_CONFIG_ATTRIB(conf, attr);
4364a49301eSmrg      switch (_eglValidationTable[i].criterion) {
4374a49301eSmrg      case ATTRIB_CRITERION_EXACT:
4384a49301eSmrg         if (val != cmp)
4394a49301eSmrg            matched = EGL_FALSE;
4404a49301eSmrg         break;
4414a49301eSmrg      case ATTRIB_CRITERION_ATLEAST:
4424a49301eSmrg         if (val < cmp)
4434a49301eSmrg            matched = EGL_FALSE;
4444a49301eSmrg         break;
4454a49301eSmrg      case ATTRIB_CRITERION_MASK:
4464a49301eSmrg         if ((val & cmp) != cmp)
4474a49301eSmrg            matched = EGL_FALSE;
4484a49301eSmrg         break;
4494a49301eSmrg      case ATTRIB_CRITERION_SPECIAL:
4504a49301eSmrg         /* ignored here */
4514a49301eSmrg         break;
4524a49301eSmrg      default:
4534a49301eSmrg         assert(0);
4544a49301eSmrg         break;
4554a49301eSmrg      }
4564a49301eSmrg
4574a49301eSmrg      if (!matched)
4584a49301eSmrg         break;
4594a49301eSmrg   }
4604a49301eSmrg
4614a49301eSmrg   return matched;
4624a49301eSmrg}
4634a49301eSmrg
4644a49301eSmrg
4654a49301eSmrg/**
4664a49301eSmrg * Initialize a criteria config from the given attribute list.
4674a49301eSmrg * Return EGL_FALSE if any of the attribute is invalid.
4684a49301eSmrg */
4694a49301eSmrgEGLBoolean
4704a49301eSmrg_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list)
4714a49301eSmrg{
4724a49301eSmrg   EGLint attr, val, i;
4734a49301eSmrg   EGLint config_id = 0, level = 0;
4744a49301eSmrg   EGLBoolean has_native_visual_type = EGL_FALSE;
4754a49301eSmrg   EGLBoolean has_transparent_color = EGL_FALSE;
4764a49301eSmrg
4774a49301eSmrg   /* reset to default values */
4784a49301eSmrg   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
4794a49301eSmrg      attr = _eglValidationTable[i].attr;
4804a49301eSmrg      val = _eglValidationTable[i].default_value;
4814a49301eSmrg      SET_CONFIG_ATTRIB(conf, attr, val);
4824a49301eSmrg   }
4834a49301eSmrg
4844a49301eSmrg   /* parse the list */
4854a49301eSmrg   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
4864a49301eSmrg      EGLint idx;
4874a49301eSmrg
4884a49301eSmrg      attr = attrib_list[i];
4894a49301eSmrg      val = attrib_list[i + 1];
4904a49301eSmrg
4914a49301eSmrg      idx = _eglIndexConfig(conf, attr);
4924a49301eSmrg      if (idx < 0)
4934a49301eSmrg         return EGL_FALSE;
4944a49301eSmrg      conf->Storage[idx] = val;
4954a49301eSmrg
4964a49301eSmrg      /* rememeber some attributes for post-processing */
4974a49301eSmrg      switch (attr) {
4984a49301eSmrg      case EGL_CONFIG_ID:
4994a49301eSmrg         config_id = val;
5004a49301eSmrg         break;
5014a49301eSmrg      case EGL_LEVEL:
5024a49301eSmrg         level = val;
5034a49301eSmrg         break;
5044a49301eSmrg      case EGL_NATIVE_VISUAL_TYPE:
5054a49301eSmrg         has_native_visual_type = EGL_TRUE;
5064a49301eSmrg         break;
5074a49301eSmrg      case EGL_TRANSPARENT_RED_VALUE:
5084a49301eSmrg      case EGL_TRANSPARENT_GREEN_VALUE:
5094a49301eSmrg      case EGL_TRANSPARENT_BLUE_VALUE:
5104a49301eSmrg         has_transparent_color = EGL_TRUE;
5114a49301eSmrg         break;
5124a49301eSmrg      default:
5134a49301eSmrg         break;
5144a49301eSmrg      }
5154a49301eSmrg   }
5164a49301eSmrg
5174a49301eSmrg   if (!_eglValidateConfig(conf, EGL_TRUE))
5184a49301eSmrg      return EGL_FALSE;
5194a49301eSmrg
5204a49301eSmrg   /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */
5214a49301eSmrg   if (level == EGL_DONT_CARE)
5224a49301eSmrg      return EGL_FALSE;
5234a49301eSmrg
5244a49301eSmrg   /* ignore other attributes when EGL_CONFIG_ID is given */
5254a49301eSmrg   if (config_id > 0) {
5264a49301eSmrg      _eglResetConfigKeys(conf, EGL_DONT_CARE);
5274a49301eSmrg      SET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID, config_id);
5284a49301eSmrg   }
5294a49301eSmrg   else {
5304a49301eSmrg      if (has_native_visual_type) {
5314a49301eSmrg         val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
5324a49301eSmrg         if (!(val & EGL_WINDOW_BIT))
5334a49301eSmrg            SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
5344a49301eSmrg      }
5354a49301eSmrg
5364a49301eSmrg      if (has_transparent_color) {
5374a49301eSmrg         val = GET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE);
5384a49301eSmrg         if (val == EGL_NONE) {
5394a49301eSmrg            SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE,
5404a49301eSmrg                              EGL_DONT_CARE);
5414a49301eSmrg            SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE,
5424a49301eSmrg                              EGL_DONT_CARE);
5434a49301eSmrg            SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE,
5444a49301eSmrg                              EGL_DONT_CARE);
5454a49301eSmrg         }
5464a49301eSmrg      }
5474a49301eSmrg   }
5484a49301eSmrg
5494a49301eSmrg   return EGL_TRUE;
5504a49301eSmrg}
5514a49301eSmrg
5524a49301eSmrg
5534a49301eSmrg/**
5544a49301eSmrg * Decide the ordering of conf1 and conf2, under the given criteria.
5554a49301eSmrg * When compare_id is true, this implements the algorithm described
5564a49301eSmrg * in "Sorting of EGLConfigs".  When compare_id is false,
5574a49301eSmrg * EGL_CONFIG_ID is not compared.
5584a49301eSmrg *
5594a49301eSmrg * It returns a negative integer if conf1 is considered to come
5604a49301eSmrg * before conf2;  a positive integer if conf2 is considered to come
5614a49301eSmrg * before conf1;  zero if the ordering cannot be decided.
5624a49301eSmrg *
5634a49301eSmrg * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
5644a49301eSmrg * ignored here.
5654a49301eSmrg */
5664a49301eSmrgEGLint
5674a49301eSmrg_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
5684a49301eSmrg                   const _EGLConfig *criteria, EGLBoolean compare_id)
5694a49301eSmrg{
5704a49301eSmrg   const EGLint compare_attribs[] = {
5714a49301eSmrg      EGL_BUFFER_SIZE,
5724a49301eSmrg      EGL_SAMPLE_BUFFERS,
5734a49301eSmrg      EGL_SAMPLES,
5744a49301eSmrg      EGL_DEPTH_SIZE,
5754a49301eSmrg      EGL_STENCIL_SIZE,
5764a49301eSmrg      EGL_ALPHA_MASK_SIZE,
5774a49301eSmrg   };
5784a49301eSmrg   EGLint val1, val2;
5794a49301eSmrg   EGLBoolean rgb_buffer;
5804a49301eSmrg   EGLint i;
5814a49301eSmrg
5824a49301eSmrg   if (conf1 == conf2)
5834a49301eSmrg      return 0;
5844a49301eSmrg
5854a49301eSmrg   /* the enum values have the desired ordering */
5864a49301eSmrg   assert(EGL_NONE < EGL_SLOW_CONFIG);
5874a49301eSmrg   assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
5884a49301eSmrg   val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_CAVEAT);
5894a49301eSmrg   val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_CAVEAT);
5904a49301eSmrg   if (val1 != val2)
5914a49301eSmrg      return (val1 - val2);
5924a49301eSmrg
5934a49301eSmrg   /* the enum values have the desired ordering */
5944a49301eSmrg   assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
5954a49301eSmrg   val1 = GET_CONFIG_ATTRIB(conf1, EGL_COLOR_BUFFER_TYPE);
5964a49301eSmrg   val2 = GET_CONFIG_ATTRIB(conf2, EGL_COLOR_BUFFER_TYPE);
5974a49301eSmrg   if (val1 != val2)
5984a49301eSmrg      return (val1 - val2);
5994a49301eSmrg   rgb_buffer = (val1 == EGL_RGB_BUFFER);
6004a49301eSmrg
6014a49301eSmrg   if (criteria) {
6024a49301eSmrg      val1 = val2 = 0;
6034a49301eSmrg      if (rgb_buffer) {
6044a49301eSmrg         if (GET_CONFIG_ATTRIB(criteria, EGL_RED_SIZE) > 0) {
6054a49301eSmrg            val1 += GET_CONFIG_ATTRIB(conf1, EGL_RED_SIZE);
6064a49301eSmrg            val2 += GET_CONFIG_ATTRIB(conf2, EGL_RED_SIZE);
6074a49301eSmrg         }
6084a49301eSmrg         if (GET_CONFIG_ATTRIB(criteria, EGL_GREEN_SIZE) > 0) {
6094a49301eSmrg            val1 += GET_CONFIG_ATTRIB(conf1, EGL_GREEN_SIZE);
6104a49301eSmrg            val2 += GET_CONFIG_ATTRIB(conf2, EGL_GREEN_SIZE);
6114a49301eSmrg         }
6124a49301eSmrg         if (GET_CONFIG_ATTRIB(criteria, EGL_BLUE_SIZE) > 0) {
6134a49301eSmrg            val1 += GET_CONFIG_ATTRIB(conf1, EGL_BLUE_SIZE);
6144a49301eSmrg            val2 += GET_CONFIG_ATTRIB(conf2, EGL_BLUE_SIZE);
6154a49301eSmrg         }
6164a49301eSmrg      }
6174a49301eSmrg      else {
6184a49301eSmrg         if (GET_CONFIG_ATTRIB(criteria, EGL_LUMINANCE_SIZE) > 0) {
6194a49301eSmrg            val1 += GET_CONFIG_ATTRIB(conf1, EGL_LUMINANCE_SIZE);
6204a49301eSmrg            val2 += GET_CONFIG_ATTRIB(conf2, EGL_LUMINANCE_SIZE);
6214a49301eSmrg         }
6224a49301eSmrg      }
6234a49301eSmrg      if (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) {
6244a49301eSmrg         val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE);
6254a49301eSmrg         val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE);
6264a49301eSmrg      }
6274a49301eSmrg   }
6284a49301eSmrg   else {
6294a49301eSmrg      /* assume the default criteria, which gives no specific ordering */
6304a49301eSmrg      val1 = val2 = 0;
6314a49301eSmrg   }
6324a49301eSmrg
6334a49301eSmrg   /* for color bits, larger one is preferred */
6344a49301eSmrg   if (val1 != val2)
6354a49301eSmrg      return (val2 - val1);
6364a49301eSmrg
6374a49301eSmrg   for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
6384a49301eSmrg      val1 = GET_CONFIG_ATTRIB(conf1, compare_attribs[i]);
6394a49301eSmrg      val2 = GET_CONFIG_ATTRIB(conf2, compare_attribs[i]);
6404a49301eSmrg      if (val1 != val2)
6414a49301eSmrg         return (val1 - val2);
6424a49301eSmrg   }
6434a49301eSmrg
6444a49301eSmrg   /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */
6454a49301eSmrg
6464a49301eSmrg   if (compare_id) {
6474a49301eSmrg      val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_ID);
6484a49301eSmrg      val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_ID);
6494a49301eSmrg      assert(val1 != val2);
6504a49301eSmrg   }
6514a49301eSmrg   else {
6524a49301eSmrg      val1 = val2 = 0;
6534a49301eSmrg   }
6544a49301eSmrg
6554a49301eSmrg   return (val1 - val2);
6564a49301eSmrg}
6574a49301eSmrg
6584a49301eSmrg
6594a49301eSmrgstatic INLINE
6604a49301eSmrgvoid _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
6614a49301eSmrg{
6624a49301eSmrg   const _EGLConfig *tmp = *conf1;
6634a49301eSmrg   *conf1 = *conf2;
6644a49301eSmrg   *conf2 = tmp;
6654a49301eSmrg}
6664a49301eSmrg
6674a49301eSmrg
6684a49301eSmrg/**
6694a49301eSmrg * Quick sort an array of configs.  This differs from the standard
6704a49301eSmrg * qsort() in that the compare function accepts an additional
6714a49301eSmrg * argument.
6724a49301eSmrg */
6734a49301eSmrgvoid
6744a49301eSmrg_eglSortConfigs(const _EGLConfig **configs, EGLint count,
6754a49301eSmrg                EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
6764a49301eSmrg                                  void *),
6774a49301eSmrg                void *priv_data)
6784a49301eSmrg{
6794a49301eSmrg   const EGLint pivot = 0;
6804a49301eSmrg   EGLint i, j;
6814a49301eSmrg
6824a49301eSmrg   if (count <= 1)
6834a49301eSmrg      return;
6844a49301eSmrg
6854a49301eSmrg   _eglSwapConfigs(&configs[pivot], &configs[count / 2]);
6864a49301eSmrg   i = 1;
6874a49301eSmrg   j = count - 1;
6884a49301eSmrg   do {
6894a49301eSmrg      while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
6904a49301eSmrg         i++;
6914a49301eSmrg      while (compare(configs[j], configs[pivot], priv_data) > 0)
6924a49301eSmrg         j--;
6934a49301eSmrg      if (i < j) {
6944a49301eSmrg         _eglSwapConfigs(&configs[i], &configs[j]);
6954a49301eSmrg         i++;
6964a49301eSmrg         j--;
6974a49301eSmrg      }
6984a49301eSmrg      else if (i == j) {
6994a49301eSmrg         i++;
7004a49301eSmrg         j--;
7014a49301eSmrg         break;
7024a49301eSmrg      }
7034a49301eSmrg   } while (i <= j);
7044a49301eSmrg   _eglSwapConfigs(&configs[pivot], &configs[j]);
7054a49301eSmrg
7064a49301eSmrg   _eglSortConfigs(configs, j, compare, priv_data);
7074a49301eSmrg   _eglSortConfigs(configs + i, count - i, compare, priv_data);
7084a49301eSmrg}
7094a49301eSmrg
7104a49301eSmrg
7114a49301eSmrgstatic int
7124a49301eSmrg_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2,
7134a49301eSmrg                   void *priv_data)
7144a49301eSmrg{
7154a49301eSmrg   const _EGLConfig *criteria = (const _EGLConfig *) priv_data;
7164a49301eSmrg   return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE);
7174a49301eSmrg}
7184a49301eSmrg
7194a49301eSmrg
7204a49301eSmrg/**
7214a49301eSmrg * Typical fallback routine for eglChooseConfig
7224a49301eSmrg */
7234a49301eSmrgEGLBoolean
7244a49301eSmrg_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
7254a49301eSmrg                 EGLConfig *configs, EGLint config_size, EGLint *num_configs)
7264a49301eSmrg{
7274a49301eSmrg   _EGLConfig **configList, criteria;
7284a49301eSmrg   EGLint i, count;
7294a49301eSmrg
7304a49301eSmrg   if (!num_configs)
7314a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
7324a49301eSmrg
7334a49301eSmrg   _eglInitConfig(&criteria, 0);
7344a49301eSmrg   if (!_eglParseConfigAttribList(&criteria, attrib_list))
7354a49301eSmrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
7364a49301eSmrg
7374a49301eSmrg   /* allocate array of config pointers */
7384a49301eSmrg   configList = (_EGLConfig **)
7394a49301eSmrg      malloc(disp->NumConfigs * sizeof(_EGLConfig *));
7404a49301eSmrg   if (!configList)
7414a49301eSmrg      return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
7424a49301eSmrg
7434a49301eSmrg   /* perform selection of configs */
7444a49301eSmrg   count = 0;
7454a49301eSmrg   for (i = 0; i < disp->NumConfigs; i++) {
7464a49301eSmrg      if (_eglMatchConfig(disp->Configs[i], &criteria))
7474a49301eSmrg         configList[count++] = disp->Configs[i];
7484a49301eSmrg   }
7494a49301eSmrg
7504a49301eSmrg   /* perform sorting of configs */
7514a49301eSmrg   if (configs && count) {
7524a49301eSmrg      _eglSortConfigs((const _EGLConfig **) configList, count,
7534a49301eSmrg                      _eglFallbackCompare, (void *) &criteria);
7544a49301eSmrg      count = MIN2(count, config_size);
7554a49301eSmrg      for (i = 0; i < count; i++)
7564a49301eSmrg         configs[i] = _eglGetConfigHandle(configList[i]);
7574a49301eSmrg   }
7584a49301eSmrg
7594a49301eSmrg   free(configList);
7604a49301eSmrg
7614a49301eSmrg   *num_configs = count;
7624a49301eSmrg
7634a49301eSmrg   return EGL_TRUE;
7644a49301eSmrg}
7654a49301eSmrg
7664a49301eSmrg
7674a49301eSmrgstatic INLINE EGLBoolean
7684a49301eSmrg_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
7694a49301eSmrg{
7704a49301eSmrg   if (_eglIndexConfig(conf, attr) < 0)
7714a49301eSmrg      return EGL_FALSE;
7724a49301eSmrg
7734a49301eSmrg   /* there are some holes in the range */
7744a49301eSmrg   switch (attr) {
7754a49301eSmrg   case EGL_PRESERVED_RESOURCES:
7764a49301eSmrg   case EGL_NONE:
7774a49301eSmrg#ifdef EGL_VERSION_1_4
7784a49301eSmrg   case EGL_MATCH_NATIVE_PIXMAP:
7794a49301eSmrg#endif
7804a49301eSmrg      return EGL_FALSE;
7814a49301eSmrg   default:
7824a49301eSmrg      break;
7834a49301eSmrg   }
7844a49301eSmrg
7854a49301eSmrg   return EGL_TRUE;
7864a49301eSmrg}
7874a49301eSmrg
7884a49301eSmrg
7894a49301eSmrg/**
7904a49301eSmrg * Fallback for eglGetConfigAttrib.
7914a49301eSmrg */
7924a49301eSmrgEGLBoolean
7934a49301eSmrg_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
7944a49301eSmrg                    EGLint attribute, EGLint *value)
7954a49301eSmrg{
7964a49301eSmrg   if (!_eglIsConfigAttribValid(conf, attribute))
7974a49301eSmrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
7984a49301eSmrg   if (!value)
7994a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
8004a49301eSmrg
8014a49301eSmrg   *value = GET_CONFIG_ATTRIB(conf, attribute);
8024a49301eSmrg   return EGL_TRUE;
8034a49301eSmrg}
8044a49301eSmrg
8054a49301eSmrg
8064a49301eSmrg/**
8074a49301eSmrg * Fallback for eglGetConfigs.
8084a49301eSmrg */
8094a49301eSmrgEGLBoolean
8104a49301eSmrg_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
8114a49301eSmrg               EGLint config_size, EGLint *num_config)
8124a49301eSmrg{
8134a49301eSmrg   if (!num_config)
8144a49301eSmrg      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
8154a49301eSmrg
8164a49301eSmrg   if (configs) {
8174a49301eSmrg      EGLint i;
8184a49301eSmrg      *num_config = MIN2(disp->NumConfigs, config_size);
8194a49301eSmrg      for (i = 0; i < *num_config; i++)
8204a49301eSmrg         configs[i] = _eglGetConfigHandle(disp->Configs[i]);
8214a49301eSmrg   }
8224a49301eSmrg   else {
8234a49301eSmrg      /* just return total number of supported configs */
8244a49301eSmrg      *num_config = disp->NumConfigs;
8254a49301eSmrg   }
8264a49301eSmrg
8274a49301eSmrg   return EGL_TRUE;
8284a49301eSmrg}
829