Esempio n. 1
0
/**
 * Convert an _EGLConfig to a __GLcontextModes object.
 * NOTE: This routine may be incomplete - we're only making sure that
 * the fields needed by Mesa (for _mesa_create_context/framebuffer) are
 * set correctly.
 */
void
_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
{
   memset(mode, 0, sizeof(*mode));

   mode->rgbMode = GL_TRUE; /* no color index */
   mode->colorIndexMode = GL_FALSE;
   mode->doubleBufferMode = GL_TRUE;  /* always DB for now */
   mode->stereoMode = GL_FALSE;

   mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
   mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
   mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
   mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
   mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);

   /* no rgba masks - fix? */

   mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
   mode->haveDepthBuffer = mode->depthBits > 0;

   mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
   mode->haveStencilBuffer = mode->stencilBits > 0;

   /* no accum */

   mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
   mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
   mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);

   /* surface type - not really needed */
   mode->visualType = GLX_TRUE_COLOR;
   mode->renderType = GLX_RGBA_BIT;
}
Esempio n. 2
0
/**
 * Return true if a config matches the criteria.  This and
 * _eglParseConfigAttribList together implement the algorithm
 * described in "Selection of EGLConfigs".
 *
 * Note that attributes that are special (currently, only
 * EGL_MATCH_NATIVE_PIXMAP) are ignored.
 */
EGLBoolean
_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
{
   EGLint attr, val, i;
   EGLBoolean matched = EGL_TRUE;

   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
      EGLint cmp;
      if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
         continue;

      attr = _eglValidationTable[i].attr;
      cmp = GET_CONFIG_ATTRIB(criteria, attr);
      if (cmp == EGL_DONT_CARE)
         continue;

      val = GET_CONFIG_ATTRIB(conf, attr);
      switch (_eglValidationTable[i].criterion) {
      case ATTRIB_CRITERION_EXACT:
         if (val != cmp)
            matched = EGL_FALSE;
         break;
      case ATTRIB_CRITERION_ATLEAST:
         if (val < cmp)
            matched = EGL_FALSE;
         break;
      case ATTRIB_CRITERION_MASK:
         if ((val & cmp) != cmp)
            matched = EGL_FALSE;
         break;
      case ATTRIB_CRITERION_SPECIAL:
         /* ignored here */
         break;
      default:
         assert(0);
         break;
      }

      if (!matched) {
#ifdef DEBUG
         _eglLog(_EGL_DEBUG,
               "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
               val, attr, cmp);
#endif
         break;
      }
   }

   return matched;
}
EGLBoolean
_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
                 EGLint attribute, EGLint *value)
{
   _EGLContext *c = _eglLookupContext(ctx);

   (void) drv;
   (void) dpy;

   if (!c) {
      _eglError(EGL_BAD_CONTEXT, "eglQueryContext");
      return EGL_FALSE;
   }

   switch (attribute) {
   case EGL_CONFIG_ID:
      *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
      return EGL_TRUE;
#ifdef EGL_VERSION_1_2
   case EGL_CONTEXT_CLIENT_TYPE:
      *value = c->ClientAPI;
      return EGL_FALSE;
#endif /* EGL_VERSION_1_2 */
   default:
      _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
      return EGL_FALSE;
   }
}
Esempio n. 4
0
/**
 * Link a config to a display and return the handle of the link.
 * The handle can be passed to client directly.
 *
 * Note that we just save the ptr to the config (we don't copy the config).
 */
EGLConfig
_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
{
   _EGLConfig **configs;

   /* sanity check */
   assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0);

   configs = dpy->Configs;
   if (dpy->NumConfigs >= dpy->MaxConfigs) {
      EGLint new_size = dpy->MaxConfigs + 16;
      assert(dpy->NumConfigs < new_size);

      configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0]));
      if (!configs)
         return (EGLConfig) NULL;

      dpy->Configs = configs;
      dpy->MaxConfigs = new_size;
   }

   conf->Display = dpy;
   dpy->Configs[dpy->NumConfigs++] = conf;

   return (EGLConfig) conf;
}
Esempio n. 5
0
EGLBoolean
_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
                 EGLint attribute, EGLint *value)
{
   (void) drv;
   (void) dpy;

   if (!value)
      return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");

   switch (attribute) {
   case EGL_CONFIG_ID:
      *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
      break;
   case EGL_CONTEXT_CLIENT_VERSION:
      *value = c->ClientVersion;
      break;
#ifdef EGL_VERSION_1_2
   case EGL_CONTEXT_CLIENT_TYPE:
      *value = c->ClientAPI;
      break;
   case EGL_RENDER_BUFFER:
      *value = _eglQueryContextRenderBuffer(c);
      break;
#endif /* EGL_VERSION_1_2 */
   default:
      return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
   }

   return EGL_TRUE;
}
Esempio n. 6
0
static EGLBoolean
convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m)
{
   static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
                                   EGL_OPENGL_ES2_BIT |
                                   EGL_OPENVG_BIT |
                                   EGL_OPENGL_BIT);
   EGLint val;

   _eglInitConfig(conf, id);
   if (!_eglConfigFromContextModesRec(conf, m, all_apis, all_apis))
      return EGL_FALSE;

   if (m->doubleBufferMode) {
      /* pixmap and pbuffer surfaces are always single-buffered */
      val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
      val &= ~(EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
      SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, val);
   }
   else {
      /* EGL requires OpenGL ES context to be double-buffered */
      val = GET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE);
      val &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
      SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, val);
   }
   /* skip "empty" config */
   if (!val)
      return EGL_FALSE;

   val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
   if (!(val & EGL_PBUFFER_BIT)) {
      /* bind-to-texture cannot be EGL_TRUE without pbuffer bit */
      SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE);
      SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE);
   }

   /* EGL_NATIVE_RENDERABLE is a boolean */
   val = GET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE);
   if (val != EGL_TRUE)
      SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_FALSE);

   return _eglValidateConfig(conf, EGL_FALSE);
}
Esempio n. 7
0
/**
 * Fallback for eglGetConfigAttrib.
 */
EGLBoolean
_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
                    EGLint attribute, EGLint *value)
{
   if (!_eglIsConfigAttribValid(conf, attribute))
      return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
   if (!value)
      return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");

   *value = GET_CONFIG_ATTRIB(conf, attribute);
   return EGL_TRUE;
}
Esempio n. 8
0
/**
 * Parse the list of context attributes and return the proper error code.
 */
static EGLint
_eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list)
{
   EGLenum api = ctx->ClientAPI;
   EGLint i, err = EGL_SUCCESS;

   if (!attrib_list)
      return EGL_SUCCESS;

   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
      EGLint attr = attrib_list[i++];
      EGLint val = attrib_list[i];

      switch (attr) {
      case EGL_CONTEXT_CLIENT_VERSION:
         if (api != EGL_OPENGL_ES_API) {
            err = EGL_BAD_ATTRIBUTE;
            break;
         }
         if (val != 1 && val != 2) {
            err = EGL_BAD_ATTRIBUTE;
            break;
         }
         ctx->ClientVersion = val;
         break;
      default:
         err = EGL_BAD_ATTRIBUTE;
         break;
      }

      if (err != EGL_SUCCESS) {
         _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
         break;
      }
   }

   if (err == EGL_SUCCESS) {
      EGLint renderable_type, api_bit;

      renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
      api_bit = _eglGetContextAPIBit(ctx);
      if (!(renderable_type & api_bit))
         err = EGL_BAD_CONFIG;
   }

   return err;
}
static EGLBoolean
fbFillInConfigs(_EGLDisplay *disp, unsigned pixel_bits, unsigned depth_bits,
               unsigned stencil_bits, GLboolean have_back_buffer) {
   _EGLConfig *configs;
   _EGLConfig *c;
   unsigned int i, num_configs;
   unsigned int depth_buffer_factor;
   unsigned int back_buffer_factor;
   GLenum fb_format;
   GLenum fb_type;

   /* Right now GLX_SWAP_COPY_OML isn't supported, but it would be easy
   * enough to add support.  Basically, if a context is created with an
   * fbconfig where the swap method is GLX_SWAP_COPY_OML, pageflipping
   * will never be used.
   */
   static const GLenum back_buffer_modes[] = {
            GLX_NONE, GLX_SWAP_UNDEFINED_OML /*, GLX_SWAP_COPY_OML */
         };

   u_int8_t depth_bits_array[2];
   u_int8_t stencil_bits_array[2];

   depth_bits_array[0] = 0;
   depth_bits_array[1] = depth_bits;

   /* Just like with the accumulation buffer, always provide some modes
   * with a stencil buffer.  It will be a sw fallback, but some apps won't
   * care about that.
   */
   stencil_bits_array[0] = 0;
   stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;

   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 2 : 1;
   back_buffer_factor = (have_back_buffer) ? 2 : 1;

   num_configs = depth_buffer_factor * back_buffer_factor * 2;

   if (pixel_bits == 16) {
      fb_format = GL_RGB;
      fb_type = GL_UNSIGNED_SHORT_5_6_5;
   } else {
      fb_format = GL_RGBA;
      fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
   }

   configs = calloc(sizeof(*configs), num_configs);
   c = configs;
   if (!_eglFillInConfigs(c, fb_format, fb_type,
                          depth_bits_array, stencil_bits_array, depth_buffer_factor,
                          back_buffer_modes, back_buffer_factor,
                          GLX_TRUE_COLOR)) {
      fprintf(stderr, "[%s:%u] Error creating FBConfig!\n",
               __func__, __LINE__);
      return EGL_FALSE;
   }

   /* Mark the visual as slow if there are "fake" stencil bits.
   */
   for (i = 0, c = configs; i < num_configs; i++, c++) {
      int stencil = GET_CONFIG_ATTRIB(c, EGL_STENCIL_SIZE);
      if ((stencil != 0)  && (stencil != stencil_bits)) {
         SET_CONFIG_ATTRIB(c, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG);
      }
   }

   for (i = 0, c = configs; i < num_configs; i++, c++)
      _eglAddConfig(disp, c);
      
   free(configs);
   
   return EGL_TRUE;
}
Esempio n. 10
0
/**
 * Show the given surface on the named screen.
 * If surface is EGL_NO_SURFACE, disable the screen's output.
 */
static EGLBoolean
fbShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
                    EGLSurface surface, EGLModeMESA m)
{
   fbDisplay *display = Lookup_fbDisplay(dpy);
   fbScreen *scrn = Lookup_fbScreen(dpy, screen);
   fbSurface *surf = Lookup_fbSurface(surface);
   FILE *file;
   char buffer[NAME_MAX];
   _EGLMode *mode = _eglLookupMode(dpy, m);
   int bits;
   
   if (!_eglShowSurfaceMESA(drv, dpy, screen, surface, m))
      return EGL_FALSE;
      
   snprintf(buffer, sizeof(buffer), "%s/%s/blank", sysfs, scrn->fb);
   
   file = fopen(buffer, "r+");
   if (!file) {
err:
      printf("chown all fb sysfs attrib to allow write - %s\n", buffer);
      return EGL_FALSE;
   }
   snprintf(buffer, sizeof(buffer), "%d", (m == EGL_NO_MODE_MESA ? VESA_POWERDOWN : VESA_VSYNC_SUSPEND));
   fputs(buffer, file);
   fclose(file);
   
   if (m == EGL_NO_MODE_MESA)
      return EGL_TRUE;
   
   snprintf(buffer, sizeof(buffer), "%s/%s/mode", sysfs, scrn->fb);
   
   file = fopen(buffer, "r+");
   if (!file)
      goto err;
   fputs(mode->Name, file);
   fclose(file);
   
   snprintf(buffer, sizeof(buffer), "%s/%s/bits_per_pixel", sysfs, scrn->fb);
   
   file = fopen(buffer, "r+");
   if (!file)
      goto err;
   bits = GET_CONFIG_ATTRIB(surf->Base.Config, EGL_BUFFER_SIZE);
   snprintf(buffer, sizeof(buffer), "%d", bits);
   fputs(buffer, file);
   fclose(file);

   fbSetupFramebuffer(display, scrn->fb);
   
   snprintf(buffer, sizeof(buffer), "%s/%s/blank", sysfs, scrn->fb);
   
   file = fopen(buffer, "r+");
   if (!file)
      goto err;
      
   snprintf(buffer, sizeof(buffer), "%d", VESA_NO_BLANKING);
   fputs(buffer, file);
   fclose(file);
   
   return EGL_TRUE;
}
Esempio n. 11
0
/**
 * Decide the ordering of conf1 and conf2, under the given criteria.
 * When compare_id is true, this implements the algorithm described
 * in "Sorting of EGLConfigs".  When compare_id is false,
 * EGL_CONFIG_ID is not compared.
 *
 * It returns a negative integer if conf1 is considered to come
 * before conf2;  a positive integer if conf2 is considered to come
 * before conf1;  zero if the ordering cannot be decided.
 *
 * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
 * ignored here.
 */
EGLint
_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
                   const _EGLConfig *criteria, EGLBoolean compare_id)
{
   const EGLint compare_attribs[] = {
      EGL_BUFFER_SIZE,
      EGL_SAMPLE_BUFFERS,
      EGL_SAMPLES,
      EGL_DEPTH_SIZE,
      EGL_STENCIL_SIZE,
      EGL_ALPHA_MASK_SIZE,
   };
   EGLint val1, val2;
   EGLBoolean rgb_buffer;
   EGLint i;

   if (conf1 == conf2)
      return 0;

   /* the enum values have the desired ordering */
   assert(EGL_NONE < EGL_SLOW_CONFIG);
   assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
   val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_CAVEAT);
   val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_CAVEAT);
   if (val1 != val2)
      return (val1 - val2);

   /* the enum values have the desired ordering */
   assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
   val1 = GET_CONFIG_ATTRIB(conf1, EGL_COLOR_BUFFER_TYPE);
   val2 = GET_CONFIG_ATTRIB(conf2, EGL_COLOR_BUFFER_TYPE);
   if (val1 != val2)
      return (val1 - val2);
   rgb_buffer = (val1 == EGL_RGB_BUFFER);

   if (criteria) {
      val1 = val2 = 0;
      if (rgb_buffer) {
         if (GET_CONFIG_ATTRIB(criteria, EGL_RED_SIZE) > 0) {
            val1 += GET_CONFIG_ATTRIB(conf1, EGL_RED_SIZE);
            val2 += GET_CONFIG_ATTRIB(conf2, EGL_RED_SIZE);
         }
         if (GET_CONFIG_ATTRIB(criteria, EGL_GREEN_SIZE) > 0) {
            val1 += GET_CONFIG_ATTRIB(conf1, EGL_GREEN_SIZE);
            val2 += GET_CONFIG_ATTRIB(conf2, EGL_GREEN_SIZE);
         }
         if (GET_CONFIG_ATTRIB(criteria, EGL_BLUE_SIZE) > 0) {
            val1 += GET_CONFIG_ATTRIB(conf1, EGL_BLUE_SIZE);
            val2 += GET_CONFIG_ATTRIB(conf2, EGL_BLUE_SIZE);
         }
      }
      else {
         if (GET_CONFIG_ATTRIB(criteria, EGL_LUMINANCE_SIZE) > 0) {
            val1 += GET_CONFIG_ATTRIB(conf1, EGL_LUMINANCE_SIZE);
            val2 += GET_CONFIG_ATTRIB(conf2, EGL_LUMINANCE_SIZE);
         }
      }
      if (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) {
         val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE);
         val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE);
      }
   }
   else {
      /* assume the default criteria, which gives no specific ordering */
      val1 = val2 = 0;
   }

   /* for color bits, larger one is preferred */
   if (val1 != val2)
      return (val2 - val1);

   for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) {
      val1 = GET_CONFIG_ATTRIB(conf1, compare_attribs[i]);
      val2 = GET_CONFIG_ATTRIB(conf2, compare_attribs[i]);
      if (val1 != val2)
         return (val1 - val2);
   }

   /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */

   if (compare_id) {
      val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_ID);
      val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_ID);
      assert(val1 != val2);
   }
   else {
      val1 = val2 = 0;
   }

   return (val1 - val2);
}
Esempio n. 12
0
/**
 * Initialize a criteria config from the given attribute list.
 * Return EGL_FALSE if any of the attribute is invalid.
 */
EGLBoolean
_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list)
{
   EGLint attr, val, i;
   EGLint config_id = 0, level = 0;
   EGLBoolean has_native_visual_type = EGL_FALSE;
   EGLBoolean has_transparent_color = EGL_FALSE;

   /* reset to default values */
   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
      attr = _eglValidationTable[i].attr;
      val = _eglValidationTable[i].default_value;
      SET_CONFIG_ATTRIB(conf, attr, val);
   }

   /* parse the list */
   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) {
      EGLint idx;

      attr = attrib_list[i];
      val = attrib_list[i + 1];

      idx = _eglIndexConfig(conf, attr);
      if (idx < 0)
         return EGL_FALSE;
      conf->Storage[idx] = val;

      /* rememeber some attributes for post-processing */
      switch (attr) {
      case EGL_CONFIG_ID:
         config_id = val;
         break;
      case EGL_LEVEL:
         level = val;
         break;
      case EGL_NATIVE_VISUAL_TYPE:
         has_native_visual_type = EGL_TRUE;
         break;
      case EGL_TRANSPARENT_RED_VALUE:
      case EGL_TRANSPARENT_GREEN_VALUE:
      case EGL_TRANSPARENT_BLUE_VALUE:
         has_transparent_color = EGL_TRUE;
         break;
      default:
         break;
      }
   }

   if (!_eglValidateConfig(conf, EGL_TRUE))
      return EGL_FALSE;

   /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */
   if (level == EGL_DONT_CARE)
      return EGL_FALSE;

   /* ignore other attributes when EGL_CONFIG_ID is given */
   if (config_id > 0) {
      _eglResetConfigKeys(conf, EGL_DONT_CARE);
      SET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID, config_id);
   }
   else {
      if (has_native_visual_type) {
         val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
         if (!(val & EGL_WINDOW_BIT))
            SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
      }

      if (has_transparent_color) {
         val = GET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE);
         if (val == EGL_NONE) {
            SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE,
                              EGL_DONT_CARE);
            SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE,
                              EGL_DONT_CARE);
            SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE,
                              EGL_DONT_CARE);
         }
      }
   }

   return EGL_TRUE;
}
Esempio n. 13
0
/**
 * Return true if a config is valid.  When for_matching is true,
 * EGL_DONT_CARE is accepted as a valid attribute value, and checks
 * for conflicting attribute values are skipped.
 *
 * Note that some attributes are platform-dependent and are not
 * checked.
 */
EGLBoolean
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
{
   EGLint i, attr, val;
   EGLBoolean valid = EGL_TRUE;
   EGLint red_size = 0, green_size = 0, blue_size = 0, luminance_size = 0;
   EGLint alpha_size = 0, buffer_size = 0;

   /* all attributes should have been listed */
   assert(ARRAY_SIZE(_eglValidationTable) == _EGL_CONFIG_NUM_ATTRIBS);

   /* check attributes by their types */
   for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
      EGLint mask;

      attr = _eglValidationTable[i].attr;
      val = GET_CONFIG_ATTRIB(conf, attr);

      switch (_eglValidationTable[i].type) {
      case ATTRIB_TYPE_INTEGER:
         switch (attr) {
         case EGL_CONFIG_ID:
            /* config id must be positive */
            if (val <= 0)
               valid = EGL_FALSE;
            break;
         case EGL_SAMPLE_BUFFERS:
            /* there can be at most 1 sample buffer */
            if (val > 1)
               valid = EGL_FALSE;
            break;
         case EGL_RED_SIZE:
            red_size = val;
            break;
         case EGL_GREEN_SIZE:
            green_size = val;
            break;
         case EGL_BLUE_SIZE:
            blue_size = val;
            break;
         case EGL_LUMINANCE_SIZE:
            luminance_size = val;
            break;
         case EGL_ALPHA_SIZE:
            alpha_size = val;
            break;
         case EGL_BUFFER_SIZE:
            buffer_size = val;
            break;
         }
         if (val < 0)
            valid = EGL_FALSE;
         break;
      case ATTRIB_TYPE_BOOLEAN:
         if (val != EGL_TRUE && val != EGL_FALSE)
            valid = EGL_FALSE;
         break;
      case ATTRIB_TYPE_ENUM:
         switch (attr) {
         case EGL_CONFIG_CAVEAT:
            if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
                val != EGL_NON_CONFORMANT_CONFIG)
               valid = EGL_FALSE;
            break;
         case EGL_TRANSPARENT_TYPE:
            if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
               valid = EGL_FALSE;
            break;
         case EGL_COLOR_BUFFER_TYPE:
            if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
               valid = EGL_FALSE;
            break;
         default:
            assert(0);
            break;
         }
         break;
      case ATTRIB_TYPE_BITMASK:
         switch (attr) {
         case EGL_SURFACE_TYPE:
            mask = EGL_PBUFFER_BIT |
                   EGL_PIXMAP_BIT |
                   EGL_WINDOW_BIT |
                   EGL_VG_COLORSPACE_LINEAR_BIT |
                   EGL_VG_ALPHA_FORMAT_PRE_BIT |
                   EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
                   EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
            if (conf->Display->Extensions.MESA_screen_surface)
               mask |= EGL_SCREEN_BIT_MESA;
            break;
         case EGL_RENDERABLE_TYPE:
         case EGL_CONFORMANT:
            mask = EGL_OPENGL_ES_BIT |
                   EGL_OPENVG_BIT |
                   EGL_OPENGL_ES2_BIT |
                   EGL_OPENGL_BIT;
            break;
         default:
            assert(0);
            break;
         }
         if (val & ~mask)
            valid = EGL_FALSE;
         break;
      case ATTRIB_TYPE_PLATFORM:
         /* unable to check platform-dependent attributes here */
         break;
      case ATTRIB_TYPE_PSEUDO:
         /* pseudo attributes should not be set */
         if (val != 0)
            valid = EGL_FALSE;
         break;
      default:
         assert(0);
         break;
      }

      if (!valid && for_matching) {
         /* accept EGL_DONT_CARE as a valid value */
         if (val == EGL_DONT_CARE)
            valid = EGL_TRUE;
         if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
            valid = EGL_TRUE;
      }
      if (!valid) {
         _eglLog(_EGL_DEBUG,
               "attribute 0x%04x has an invalid value 0x%x", attr, val);
         break;
      }
   }

   /* any invalid attribute value should have been catched */
   if (!valid || for_matching)
      return valid;

   /* now check for conflicting attribute values */

   switch (GET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE)) {
   case EGL_RGB_BUFFER:
      if (luminance_size)
         valid = EGL_FALSE;
      if (red_size + green_size + blue_size + alpha_size != buffer_size)
         valid = EGL_FALSE;
      break;
   case EGL_LUMINANCE_BUFFER:
      if (red_size || green_size || blue_size)
         valid = EGL_FALSE;
      if (luminance_size + alpha_size != buffer_size)
         valid = EGL_FALSE;
      break;
   }
   if (!valid) {
      _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes");
      return EGL_FALSE;
   }

   val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS);
   if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES))
      valid = EGL_FALSE;
   if (!valid) {
      _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers");
      return EGL_FALSE;
   }

   val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
   if (!(val & EGL_WINDOW_BIT)) {
      if (GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID) != 0 ||
          GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE) != EGL_NONE)
         valid = EGL_FALSE;
   }
   if (!(val & EGL_PBUFFER_BIT)) {
      if (GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB) ||
          GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA))
         valid = EGL_FALSE;
   }
   if (!valid) {
      _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding");
      return EGL_FALSE;
   }

   return valid;
}