From 78c3a351bc91eed49a07108682013a323d87540e Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 1 Oct 2009 18:16:10 +0800 Subject: [PATCH] egl_glx: Clean up the initialization code. Proper detection of GLX extensions. Convert fbconfigs or visuals in a more unified way and validate the resulting configs. Signed-off-by: Chia-I Wu --- src/egl/drivers/glx/egl_glx.c | 658 +++++++++++++++++++--------------- 1 file changed, 371 insertions(+), 287 deletions(-) diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c index 4685f600e29..404c998dcbc 100644 --- a/src/egl/drivers/glx/egl_glx.c +++ b/src/egl/drivers/glx/egl_glx.c @@ -40,16 +40,14 @@ */ -#include -#include -#include -#include -#include -#include "dlfcn.h" +#include +#include #include -#include +#include + #include "glxclient.h" +#include "eglconfigutil.h" #include "eglconfig.h" #include "eglcontext.h" #include "egldisplay.h" @@ -58,46 +56,19 @@ #include "egllog.h" #include "eglsurface.h" -#include - #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) -static const EGLint all_apis = (EGL_OPENGL_ES_BIT - | EGL_OPENGL_ES2_BIT - | EGL_OPENVG_BIT - /* | EGL_OPENGL_BIT */); /* can't do */ +#ifndef GLX_VERSION_1_4 +#error "GL/glx.h must be equal to or greater than GLX 1.4" +#endif + +/* + * report OpenGL ES bits because apps usually forget to specify + * EGL_RENDERABLE_TYPE when choosing configs + */ +#define GLX_EGL_APIS (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT) -struct visual_attribs -{ - /* X visual attribs */ - int id; - int klass; - int depth; - int redMask, greenMask, blueMask; - int colormapSize; - int bitsPerRGB; - - /* GL visual attribs */ - int supportsGL; - int transparentType; - int transparentRedValue; - int transparentGreenValue; - int transparentBlueValue; - int transparentAlphaValue; - int transparentIndexValue; - int bufferSize; - int level; - int render_type; - int doubleBuffer; - int stereo; - int auxBuffers; - int redSize, greenSize, blueSize, alphaSize; - int depthSize; - int stencilSize; - int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize; - int numSamples, numMultisample; - int visualCaveat; -}; /** subclass of _EGLDriver */ struct GLX_egl_driver @@ -114,6 +85,21 @@ struct GLX_egl_display GLXFBConfig *fbconfigs; int glx_maj, glx_min; + + const char *extensions; + EGLBoolean have_1_3; + EGLBoolean have_make_current_read; + EGLBoolean have_fbconfig; + EGLBoolean have_pbuffer; + + /* GLX_SGIX_pbuffer */ + PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX; + PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX; + + /* workaround quirks of different GLX implementations */ + EGLBoolean single_buffered_quirk; + EGLBoolean glx_window_quirk; + }; @@ -139,6 +125,7 @@ struct GLX_egl_surface struct GLX_egl_config { _EGLConfig Base; /**< base class */ + EGLBoolean double_buffered; int index; }; @@ -173,288 +160,369 @@ GLX_egl_config_index(_EGLConfig *conf) return ((struct GLX_egl_config *) conf)->index; } -static GLboolean -get_visual_attribs(Display *dpy, XVisualInfo *vInfo, - struct visual_attribs *attribs) -{ - const char *ext = glXQueryExtensionsString(dpy, vInfo->screen); - int rgba; - memset(attribs, 0, sizeof(struct visual_attribs)); +#define MAP_ATTRIB(attr, memb) \ + { attr, offsetof(__GLcontextModes, memb) } + + +static const struct { + int attr; + int offset; +} fbconfig_attributes[] = { + /* table 3.1 of GLX 1.4 */ + MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID), + MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits), + MAP_ATTRIB(GLX_LEVEL, level), + MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode), + MAP_ATTRIB(GLX_STEREO, stereoMode), + MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers), + MAP_ATTRIB(GLX_RED_SIZE, redBits), + MAP_ATTRIB(GLX_GREEN_SIZE, greenBits), + MAP_ATTRIB(GLX_BLUE_SIZE, blueBits), + MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits), + MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits), + MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits), + MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits), + MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits), + MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits), + MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits), + MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers), + MAP_ATTRIB(GLX_SAMPLES, samples), + MAP_ATTRIB(GLX_RENDER_TYPE, renderType), + MAP_ATTRIB(GLX_DRAWABLE_TYPE, drawableType), + MAP_ATTRIB(GLX_X_RENDERABLE, xRenderable), + MAP_ATTRIB(GLX_X_VISUAL_TYPE, visualType), + MAP_ATTRIB(GLX_CONFIG_CAVEAT, visualRating), + MAP_ATTRIB(GLX_TRANSPARENT_TYPE, transparentPixel), + MAP_ATTRIB(GLX_TRANSPARENT_INDEX_VALUE, transparentIndex), + MAP_ATTRIB(GLX_TRANSPARENT_RED_VALUE, transparentRed), + MAP_ATTRIB(GLX_TRANSPARENT_GREEN_VALUE, transparentGreen), + MAP_ATTRIB(GLX_TRANSPARENT_BLUE_VALUE, transparentBlue), + MAP_ATTRIB(GLX_TRANSPARENT_ALPHA_VALUE, transparentAlpha), + MAP_ATTRIB(GLX_MAX_PBUFFER_WIDTH, maxPbufferWidth), + MAP_ATTRIB(GLX_MAX_PBUFFER_HEIGHT, maxPbufferHeight), + MAP_ATTRIB(GLX_MAX_PBUFFER_PIXELS, maxPbufferPixels), + MAP_ATTRIB(GLX_VISUAL_ID, visualID), +}; - attribs->id = vInfo->visualid; -#if defined(__cplusplus) || defined(c_plusplus) - attribs->klass = vInfo->c_class; -#else - attribs->klass = vInfo->class; -#endif - attribs->depth = vInfo->depth; - attribs->redMask = vInfo->red_mask; - attribs->greenMask = vInfo->green_mask; - attribs->blueMask = vInfo->blue_mask; - attribs->colormapSize = vInfo->colormap_size; - attribs->bitsPerRGB = vInfo->bits_per_rgb; - - if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 || - !attribs->supportsGL) - return GL_FALSE; - glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize); - glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level); - glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba); - if (!rgba) - return GL_FALSE; - attribs->render_type = GLX_RGBA_BIT; - - glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); - if (!attribs->doubleBuffer) - return GL_FALSE; - - glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo); - glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers); - glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize); - glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize); - glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize); - glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize); - glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize); - glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize); - glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); - glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); - glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); - glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); - - /* get transparent pixel stuff */ - glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType); - if (attribs->transparentType == GLX_TRANSPARENT_RGB) { - glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); - glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); - glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); - glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); - } - else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { - glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); - } - /* multisample attribs */ -#ifdef GLX_ARB_multisample - if (ext && strstr(ext, "GLX_ARB_multisample")) { - glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample); - glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples); - } -#endif - else { - attribs->numSamples = 0; - attribs->numMultisample = 0; +static EGLBoolean +convert_fbconfig(Display *dpy, GLXFBConfig fbconfig, + struct GLX_egl_config *GLX_conf) +{ + __GLcontextModes mode; + int err = 0, attr, val, i; + + memset(&mode, 0, sizeof(mode)); + + for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) { + int offset = fbconfig_attributes[i].offset; + attr = fbconfig_attributes[i].attr; + err = glXGetFBConfigAttrib(dpy, fbconfig, attr, &val); + if (err) { + if (err == GLX_BAD_ATTRIBUTE) { + err = 0; + continue; + } + break; + } + *((int *) ((char *) &mode + offset)) = val; } + if (err) + return EGL_FALSE; -#if defined(GLX_EXT_visual_rating) - if (ext && strstr(ext, "GLX_EXT_visual_rating")) { - glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat); - } - else { - attribs->visualCaveat = GLX_NONE_EXT; + /* must have rgba bit */ + if (!(mode.renderType & GLX_RGBA_BIT)) + return EGL_FALSE; + + /* pixmap and pbuffer surfaces must be single-buffered in EGL */ + if (mode.doubleBufferMode) { + mode.drawableType &= ~(GLX_PIXMAP_BIT | GLX_PBUFFER_BIT); + if (!mode.drawableType) + return EGL_FALSE; } -#else - attribs->visualCaveat = 0; -#endif - return GL_TRUE; + mode.rgbMode = GL_TRUE; + mode.haveAccumBuffer = (mode.accumRedBits + + mode.accumGreenBits + + mode.accumBlueBits + + mode.accumAlphaBits > 0); + mode.haveDepthBuffer = (mode.depthBits > 0); + mode.haveStencilBuffer = (mode.stencilBits > 0); + + GLX_conf->double_buffered = (mode.doubleBufferMode != 0); + return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode, + GLX_EGL_APIS, GLX_EGL_APIS); } -#ifdef GLX_VERSION_1_3 + +static const struct { + int attr; + int offset; +} visual_attributes[] = { + /* table 3.7 of GLX 1.4 */ + /* no GLX_USE_GL */ + MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits), + MAP_ATTRIB(GLX_LEVEL, level), + MAP_ATTRIB(GLX_RGBA, rgbMode), + MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode), + MAP_ATTRIB(GLX_STEREO, stereoMode), + MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers), + MAP_ATTRIB(GLX_RED_SIZE, redBits), + MAP_ATTRIB(GLX_GREEN_SIZE, greenBits), + MAP_ATTRIB(GLX_BLUE_SIZE, blueBits), + MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits), + MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits), + MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits), + MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits), + MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits), + MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits), + MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits), + MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers), + MAP_ATTRIB(GLX_SAMPLES, samples), + MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID), + /* GLX_EXT_visual_rating */ + MAP_ATTRIB(GLX_VISUAL_CAVEAT_EXT, visualRating), +}; + static int -glx_token_to_visual_class(int visual_type) -{ - switch (visual_type) { - case GLX_TRUE_COLOR: - return TrueColor; - case GLX_DIRECT_COLOR: - return DirectColor; - case GLX_PSEUDO_COLOR: - return PseudoColor; - case GLX_STATIC_COLOR: - return StaticColor; - case GLX_GRAY_SCALE: - return GrayScale; - case GLX_STATIC_GRAY: - return StaticGray; - case GLX_NONE: +get_visual_type(const XVisualInfo *vis) +{ + int klass; + +#if defined(__cplusplus) || defined(c_plusplus) + klass = vis->c_class; +#else + klass = vis->class; +#endif + + switch (klass) { + case TrueColor: + return GLX_TRUE_COLOR; + case DirectColor: + return GLX_DIRECT_COLOR; + case PseudoColor: + return GLX_PSEUDO_COLOR; + case StaticColor: + return GLX_STATIC_COLOR; + case GrayScale: + return GLX_GRAY_SCALE; + case StaticGray: + return GLX_STATIC_GRAY; default: - return None; + return GLX_NONE; } } -static int -get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig, - struct visual_attribs *attribs) -{ - int visual_type; - int fbconfig_id; - memset(attribs, 0, sizeof(struct visual_attribs)); +static EGLBoolean +convert_visual(Display *dpy, XVisualInfo *vinfo, + struct GLX_egl_config *GLX_conf) +{ + __GLcontextModes mode; + int err, attr, val, i; - glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id); + /* the visual must support OpenGL */ + err = glXGetConfig(dpy, vinfo, GLX_USE_GL, &val); + if (err || !val) + return EGL_FALSE; - glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id); + memset(&mode, 0, sizeof(mode)); + + for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) { + int offset = visual_attributes[i].offset; + attr = visual_attributes[i].attr; + err = glXGetConfig(dpy, vinfo, attr, &val); + if (err) { + if (err == GLX_BAD_ATTRIBUTE) { + err = 0; + continue; + } + break; + } + *((int *) ((char *) &mode + offset)) = val; + } + if (err) + return EGL_FALSE; -#if 0 - attribs->depth = vInfo->depth; - attribs->redMask = vInfo->red_mask; - attribs->greenMask = vInfo->green_mask; - attribs->blueMask = vInfo->blue_mask; - attribs->colormapSize = vInfo->colormap_size; - attribs->bitsPerRGB = vInfo->bits_per_rgb; -#endif + /* must be RGB mode */ + if (!mode.rgbMode) + return EGL_FALSE; - glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type); - attribs->klass = glx_token_to_visual_class(visual_type); - - glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type); - if (!(attribs->render_type & GLX_RGBA_BIT)) - return 0; - - glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); - if (!attribs->doubleBuffer) - return 0; - - glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers); - - glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize); - - glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); - - /* get transparent pixel stuff */ - glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType); - if (attribs->transparentType == GLX_TRANSPARENT_RGB) { - glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); - } - else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { - glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); - } + mode.visualID = vinfo->visualid; + mode.visualType = get_visual_type(vinfo); + mode.redMask = vinfo->red_mask; + mode.greenMask = vinfo->green_mask; + mode.blueMask = vinfo->blue_mask; + + mode.drawableType = GLX_WINDOW_BIT; + /* pixmap surfaces must be single-buffered in EGL */ + if (!mode.doubleBufferMode) + mode.drawableType |= GLX_PIXMAP_BIT; + + mode.renderType = GLX_RGBA_BIT; + mode.xRenderable = GL_TRUE; + mode.haveAccumBuffer = (mode.accumRedBits + + mode.accumGreenBits + + mode.accumBlueBits + + mode.accumAlphaBits > 0); + mode.haveDepthBuffer = (mode.depthBits > 0); + mode.haveStencilBuffer = (mode.stencilBits > 0); + + GLX_conf->double_buffered = (mode.doubleBufferMode != 0); + return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode, + GLX_EGL_APIS, GLX_EGL_APIS); +} - glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples); - glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat); +static void +fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf) +{ + _EGLConfig *conf = &GLX_conf->Base; + EGLint surface_type, r, g, b, a; + + surface_type = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); + if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) { + /* some GLX impls do not like single-buffered window surface */ + surface_type &= ~EGL_WINDOW_BIT; + /* pbuffer bit is usually not set */ + if (GLX_dpy->have_pbuffer) + surface_type |= EGL_PBUFFER_BIT; + SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type); + } - if (attribs->id == 0) { - attribs->id = fbconfig_id; - return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT; + /* no visual attribs unless window bit is set */ + if (!(surface_type & EGL_WINDOW_BIT)) { + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, 0); + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); } - return EGL_WINDOW_BIT; + /* make sure buffer size is set correctly */ + r = GET_CONFIG_ATTRIB(conf, EGL_RED_SIZE); + g = GET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE); + b = GET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE); + a = GET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE); + SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, r + g + b + a); } -#endif static EGLBoolean -create_configs(_EGLDisplay *disp, struct GLX_egl_display *GLX_dpy) +create_configs(_EGLDisplay *dpy, struct GLX_egl_display *GLX_dpy, + EGLint screen) { - XVisualInfo theTemplate; - int numVisuals; - long mask; - int i; - struct visual_attribs attribs; + EGLint num_configs = 0, i; + EGLint id = 1; - GLX_dpy->fbconfigs = NULL; - -#ifdef GLX_VERSION_1_3 - /* get list of all fbconfigs on this screen */ - GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, DefaultScreen(GLX_dpy->dpy), &numVisuals); + if (GLX_dpy->have_fbconfig) { + GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs); + } + else { + XVisualInfo vinfo_template; + long mask; - if (numVisuals == 0) { - GLX_dpy->fbconfigs = NULL; - goto xvisual; + vinfo_template.screen = screen; + mask = VisualScreenMask; + GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template, + &num_configs); } - for (i = 0; i < numVisuals; i++) { - struct GLX_egl_config *config; - int bit; + if (!num_configs) + return EGL_FALSE; - bit = get_fbconfig_attribs(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &attribs); - if (!bit) + for (i = 0; i < num_configs; i++) { + struct GLX_egl_config *GLX_conf, template; + EGLBoolean ok; + + memset(&template, 0, sizeof(template)); + _eglInitConfig(&template.Base, id); + if (GLX_dpy->have_fbconfig) + ok = convert_fbconfig(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &template); + else + ok = convert_visual(GLX_dpy->dpy, &GLX_dpy->visuals[i], &template); + if (!ok) + continue; + + fix_config(GLX_dpy, &template); + if (!_eglValidateConfig(&template.Base, EGL_FALSE)) { + _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i); continue; + } + + GLX_conf = CALLOC_STRUCT(GLX_egl_config); + if (GLX_conf) { + memcpy(GLX_conf, &template, sizeof(template)); + GLX_conf->index = i; - config = CALLOC_STRUCT(GLX_egl_config); - - config->index = i; - _eglInitConfig(&config->Base, (i+1)); - SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id); - SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples); - SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample); - SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); - SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); - SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, bit); - - /* XXX possibly other things to init... */ - - _eglAddConfig(disp, &config->Base); + _eglAddConfig(dpy, &GLX_conf->Base); + id++; + } } - goto end; -#endif + return EGL_TRUE; +} + + +static void +check_extensions(struct GLX_egl_display *GLX_dpy, EGLint screen) +{ + GLX_dpy->extensions = + glXQueryExtensionsString(GLX_dpy->dpy, screen); + if (GLX_dpy->extensions) { + /* glXGetProcAddress is assumed */ + + if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) { + /* GLX 1.3 entry points are used */ + GLX_dpy->have_make_current_read = EGL_TRUE; + } -xvisual: - /* get list of all visuals on this screen */ - theTemplate.screen = DefaultScreen(GLX_dpy->dpy); - mask = VisualScreenMask; - GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &theTemplate, &numVisuals); - - for (i = 0; i < numVisuals; i++) { - struct GLX_egl_config *config; - - if (!get_visual_attribs(GLX_dpy->dpy, &GLX_dpy->visuals[i], &attribs)) - continue; - - config = CALLOC_STRUCT(GLX_egl_config); - - config->index = i; - _eglInitConfig(&config->Base, (i+1)); - SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id); - SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize); - SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples); - SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample); - SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); - SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); - SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, - (EGL_WINDOW_BIT /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/)); - - /* XXX possibly other things to init... */ - - _eglAddConfig(disp, &config->Base); + if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) { + /* GLX 1.3 entry points are used */ + GLX_dpy->have_fbconfig = EGL_TRUE; + } + + if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) { + GLX_dpy->glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC) + glXGetProcAddress((const GLubyte *) "glXCreateGLXPbufferSGIX"); + GLX_dpy->glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC) + glXGetProcAddress((const GLubyte *) "glXDestroyGLXPbufferSGIX"); + + if (GLX_dpy->glXCreateGLXPbufferSGIX && + GLX_dpy->glXDestroyGLXPbufferSGIX && + GLX_dpy->have_fbconfig) + GLX_dpy->have_pbuffer = EGL_TRUE; + } } -end: - return EGL_TRUE; + if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) { + GLX_dpy->have_1_3 = EGL_TRUE; + GLX_dpy->have_make_current_read = EGL_TRUE; + GLX_dpy->have_fbconfig = EGL_TRUE; + GLX_dpy->have_pbuffer = EGL_TRUE; + } +} + + +static void +check_quirks(struct GLX_egl_display *GLX_dpy, EGLint screen) +{ + const char *vendor; + + GLX_dpy->single_buffered_quirk = EGL_TRUE; + GLX_dpy->glx_window_quirk = EGL_TRUE; + + vendor = glXGetClientString(GLX_dpy->dpy, GLX_VENDOR); + if (vendor && strstr(vendor, "NVIDIA")) { + vendor = glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR); + if (vendor && strstr(vendor, "NVIDIA")) { + _eglLog(_EGL_DEBUG, "disable quirks"); + GLX_dpy->single_buffered_quirk = EGL_FALSE; + GLX_dpy->glx_window_quirk = EGL_FALSE; + } + } } + /** * Called via eglInitialize(), GLX_drv->API.Initialize(). */ @@ -478,17 +546,33 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp, } } - disp->DriverData = (void *) GLX_dpy; - disp->ClientAPIsMask = all_apis; + if (!glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) { + _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed"); + if (!disp->NativeDisplay) + XCloseDisplay(GLX_dpy->dpy); + free(GLX_dpy); + return EGL_FALSE; + } - glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min); + check_extensions(GLX_dpy, DefaultScreen(GLX_dpy->dpy)); + check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy)); + + create_configs(disp, GLX_dpy, DefaultScreen(GLX_dpy->dpy)); + if (!disp->NumConfigs) { + _eglLog(_EGL_WARNING, "GLX: failed to create any config"); + if (!disp->NativeDisplay) + XCloseDisplay(GLX_dpy->dpy); + free(GLX_dpy); + return EGL_FALSE; + } + + disp->DriverData = (void *) GLX_dpy; + disp->ClientAPIsMask = GLX_EGL_APIS; /* we're supporting EGL 1.4 */ *major = 1; *minor = 4; - create_configs(disp, GLX_dpy); - return EGL_TRUE; } -- 2.30.2