/** * Init the given _EGLconfig to default values. * \param id the configuration's ID. * * Note that id must be positive for the config to be valid. * It is also recommended that when there are N configs, their * IDs are from 1 to N respectively. */ void _eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id) { memset(config, 0, sizeof(*config)); config->Display = dpy; /* some attributes take non-zero default values */ SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_NONE); SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE); SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); #ifdef EGL_VERSION_1_2 SET_CONFIG_ATTRIB(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); #endif /* EGL_VERSION_1_2 */ }
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); }
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; }
/** * Convert a __GLcontextModes object to an _EGLConfig. */ EGLBoolean _eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m, EGLint conformant, EGLint renderable_type) { EGLint config_caveat, surface_type; /* must be RGBA */ if (!m->rgbMode || !(m->renderType & GLX_RGBA_BIT)) return EGL_FALSE; config_caveat = EGL_NONE; if (m->visualRating == GLX_SLOW_CONFIG) config_caveat = EGL_SLOW_CONFIG; if (m->visualRating == GLX_NON_CONFORMANT_CONFIG) conformant &= ~EGL_OPENGL_BIT; if (!(conformant & EGL_OPENGL_ES_BIT)) config_caveat = EGL_NON_CONFORMANT_CONFIG; surface_type = 0; if (m->drawableType & GLX_WINDOW_BIT) surface_type |= EGL_WINDOW_BIT; if (m->drawableType & GLX_PIXMAP_BIT) surface_type |= EGL_PIXMAP_BIT; if (m->drawableType & GLX_PBUFFER_BIT) surface_type |= EGL_PBUFFER_BIT; SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, m->rgbBits); SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, m->redBits); SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, m->greenBits); SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, m->blueBits); SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, m->alphaBits); SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, m->bindToTextureRgb); SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, m->bindToTextureRgba); SET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, config_caveat); SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, conformant); SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, m->depthBits); SET_CONFIG_ATTRIB(conf, EGL_LEVEL, m->level); SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, m->maxPbufferWidth); SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, m->maxPbufferHeight); SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, m->maxPbufferPixels); SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, m->xRenderable); SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, m->visualID); if (m->visualType != GLX_NONE) SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, m->visualType); else SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, renderable_type); SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, m->sampleBuffers); SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, m->samples); SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, m->stencilBits); SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type); /* what to do with GLX_TRANSPARENT_INDEX? */ if (m->transparentPixel == GLX_TRANSPARENT_RGB) { SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB); SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, m->transparentRed); SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, m->transparentGreen); SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, m->transparentBlue); } else { SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_NONE); } return EGL_TRUE; }
/** * Create the EGLConfigs. (one per X visual) */ static void create_configs(_EGLDriver *drv, EGLDisplay dpy) { static const EGLint all_apis = (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT | EGL_OPENGL_BIT); _EGLDisplay *disp = _eglLookupDisplay(dpy); XVisualInfo *visInfo, visTemplate; int num_visuals, i; /* get list of all X visuals, create an EGL config for each */ visTemplate.screen = DefaultScreen(disp->Xdpy); visInfo = XGetVisualInfo(disp->Xdpy, VisualScreenMask, &visTemplate, &num_visuals); if (!visInfo) { printf("egl_xlib.c: couldn't get any X visuals\n"); abort(); } for (i = 0; i < num_visuals; i++) { _EGLConfig *config = calloc(1, sizeof(_EGLConfig)); int id = i + 1; int rbits = bitcount(visInfo[i].red_mask); int gbits = bitcount(visInfo[i].green_mask); int bbits = bitcount(visInfo[i].blue_mask); int abits = bbits == 8 ? 8 : 0; int zbits = 24; int sbits = 8; int visid = visInfo[i].visualid; #if defined(__cplusplus) || defined(c_plusplus) int vistype = visInfo[i].c_class; #else int vistype = visInfo[i].class; #endif _eglInitConfig(config, id); SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits); SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits); SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits); SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits); SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits); SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits); SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits); SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid); SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype); SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE); SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis); SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis); SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); _eglAddConfig(disp, config); } }
/** * 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; }