*/
-#include <assert.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "dlfcn.h"
+#include <stdlib.h>
+#include <string.h>
#include <X11/Xlib.h>
-#include <GL/gl.h>
+#include <dlfcn.h>
+
#include "glxclient.h"
+#include "eglconfigutil.h"
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldisplay.h"
#include "egllog.h"
#include "eglsurface.h"
-#include <GL/gl.h>
-
#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
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;
+
};
struct GLX_egl_config
{
_EGLConfig Base; /**< base class */
+ EGLBoolean double_buffered;
int index;
};
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().
*/
}
}
- 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;
}