/** * 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; }
/** * 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; } }
/** * 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; }
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; }
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); }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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); }
/** * 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; }
/** * 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; }