egl: Make egl_dri2 and egl_glx built-in drivers.
[mesa.git] / src / egl / drivers / glx / egl_glx.c
index c93e568cffd5450d4e1077291b21a09499b1f371..5fce06d66df4a6798c98bd29d28c3a2fc48e0c69 100644 (file)
  * Authors: Alan Hourihane <alanh@tungstengraphics.com>
  */
 
-/*
- * TODO: 
- *
- * test eglBind/ReleaseTexImage
- */
-
-
-#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 "glxclient.h"
-
-#define _EGL_PLATFORM_X
+#include <dlfcn.h>
+#include "GL/glx.h"
 
 #include "eglconfig.h"
 #include "eglcontext.h"
+#include "egldefines.h"
 #include "egldisplay.h"
 #include "egldriver.h"
-#include "eglglobals.h"
-#include "eglhash.h"
+#include "eglcurrent.h"
 #include "egllog.h"
 #include "eglsurface.h"
 
-#include <GL/gl.h>
-
 #define CALLOC_STRUCT(T)   (struct T *) calloc(1, sizeof(struct T))
 
-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
 
-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;
-};
+/* GLX 1.0 */
+typedef GLXContext (*GLXCREATECONTEXTPROC)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct );
+typedef void (*GLXDESTROYCONTEXTPROC)( Display *dpy, GLXContext ctx );
+typedef Bool (*GLXMAKECURRENTPROC)( Display *dpy, GLXDrawable drawable, GLXContext ctx);
+typedef void (*GLXSWAPBUFFERSPROC)( Display *dpy, GLXDrawable drawable );
+typedef GLXPixmap (*GLXCREATEGLXPIXMAPPROC)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
+typedef void (*GLXDESTROYGLXPIXMAPPROC)( Display *dpy, GLXPixmap pixmap );
+typedef Bool (*GLXQUERYVERSIONPROC)( Display *dpy, int *maj, int *min );
+typedef int (*GLXGETCONFIGPROC)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
+typedef void (*GLXWAITGLPROC)( void );
+typedef void (*GLXWAITXPROC)( void );
+
+/* GLX 1.1 */
+typedef const char *(*GLXQUERYEXTENSIONSSTRINGPROC)( Display *dpy, int screen );
+typedef const char *(*GLXQUERYSERVERSTRINGPROC)( Display *dpy, int screen, int name );
+typedef const char *(*GLXGETCLIENTSTRINGPROC)( Display *dpy, int name );
 
 /** subclass of _EGLDriver */
 struct GLX_egl_driver
 {
    _EGLDriver Base;   /**< base class */
 
+   void *handle;
+
+   /* GLX 1.0 */
+   GLXCREATECONTEXTPROC glXCreateContext;
+   GLXDESTROYCONTEXTPROC glXDestroyContext;
+   GLXMAKECURRENTPROC glXMakeCurrent;
+   GLXSWAPBUFFERSPROC glXSwapBuffers;
+   GLXCREATEGLXPIXMAPPROC glXCreateGLXPixmap;
+   GLXDESTROYGLXPIXMAPPROC glXDestroyGLXPixmap;
+   GLXQUERYVERSIONPROC glXQueryVersion;
+   GLXGETCONFIGPROC glXGetConfig;
+   GLXWAITGLPROC glXWaitGL;
+   GLXWAITXPROC glXWaitX;
+
+   /* GLX 1.1 */
+   GLXQUERYEXTENSIONSSTRINGPROC glXQueryExtensionsString;
+   GLXQUERYSERVERSTRINGPROC glXQueryServerString;
+   GLXGETCLIENTSTRINGPROC glXGetClientString;
+
+   /* GLX 1.3 or (GLX_SGI_make_current_read and GLX_SGIX_fbconfig) */
+   PFNGLXGETFBCONFIGSPROC glXGetFBConfigs;
+   PFNGLXGETFBCONFIGATTRIBPROC glXGetFBConfigAttrib;
+   PFNGLXGETVISUALFROMFBCONFIGPROC glXGetVisualFromFBConfig;
+   PFNGLXCREATEWINDOWPROC glXCreateWindow;
+   PFNGLXDESTROYWINDOWPROC glXDestroyWindow;
+   PFNGLXCREATEPIXMAPPROC glXCreatePixmap;
+   PFNGLXDESTROYPIXMAPPROC glXDestroyPixmap;
+   PFNGLXCREATEPBUFFERPROC glXCreatePbuffer;
+   PFNGLXDESTROYPBUFFERPROC glXDestroyPbuffer;
+   PFNGLXCREATENEWCONTEXTPROC glXCreateNewContext;
+   PFNGLXMAKECONTEXTCURRENTPROC glXMakeContextCurrent;
+
+   /* GLX 1.4 or GLX_ARB_get_proc_address */
+   PFNGLXGETPROCADDRESSPROC glXGetProcAddress;
+
+   /* GLX_SGIX_pbuffer */
+   PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
+   PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
+};
+
+
+/** driver data of _EGLDisplay */
+struct GLX_egl_display
+{
+   Display *dpy;
    XVisualInfo *visuals;
    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;
+
+   /* workaround quirks of different GLX implementations */
+   EGLBoolean single_buffered_quirk;
+   EGLBoolean glx_window_quirk;
 };
 
 
@@ -128,7 +152,10 @@ struct GLX_egl_surface
 {
    _EGLSurface Base;   /**< base class */
 
-   GLXDrawable drawable;
+   Drawable drawable;
+   GLXDrawable glx_drawable;
+
+   void (*destroy)(Display *, GLXDrawable);
 };
 
 
@@ -136,372 +163,500 @@ struct GLX_egl_surface
 struct GLX_egl_config
 {
    _EGLConfig Base;   /**< base class */
+   EGLBoolean double_buffered;
+   int index;
 };
 
-/** cast wrapper */
-static struct GLX_egl_driver *
-GLX_egl_driver(_EGLDriver *drv)
-{
-   return (struct GLX_egl_driver *) drv;
-}
+/* standard typecasts */
+_EGL_DRIVER_STANDARD_TYPECASTS(GLX_egl)
 
-static struct GLX_egl_context *
-GLX_egl_context(_EGLContext *ctx)
+static int
+GLX_egl_config_index(_EGLConfig *conf)
 {
-   return (struct GLX_egl_context *) ctx;
+   struct GLX_egl_config *GLX_conf = GLX_egl_config(conf);
+   return GLX_conf->index;
 }
 
-static struct GLX_egl_surface *
-GLX_egl_surface(_EGLSurface *surf)
-{
-   return (struct GLX_egl_surface *) surf;
-}
 
-static GLboolean
-get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
-                   struct visual_attribs *attribs)
+static const struct {
+   int attr;
+   int egl_attr;
+} fbconfig_attributes[] = {
+   /* table 3.1 of GLX 1.4 */
+   { GLX_FBCONFIG_ID,                  0 },
+   { GLX_BUFFER_SIZE,                  EGL_BUFFER_SIZE },
+   { GLX_LEVEL,                        EGL_LEVEL },
+   { GLX_DOUBLEBUFFER,                 0 },
+   { GLX_STEREO,                       0 },
+   { GLX_AUX_BUFFERS,                  0 },
+   { GLX_RED_SIZE,                     EGL_RED_SIZE },
+   { GLX_GREEN_SIZE,                   EGL_GREEN_SIZE },
+   { GLX_BLUE_SIZE,                    EGL_BLUE_SIZE },
+   { GLX_ALPHA_SIZE,                   EGL_ALPHA_SIZE },
+   { GLX_DEPTH_SIZE,                   EGL_DEPTH_SIZE },
+   { GLX_STENCIL_SIZE,                 EGL_STENCIL_SIZE },
+   { GLX_ACCUM_RED_SIZE,               0 },
+   { GLX_ACCUM_GREEN_SIZE,             0 },
+   { GLX_ACCUM_BLUE_SIZE,              0 },
+   { GLX_ACCUM_ALPHA_SIZE,             0 },
+   { GLX_SAMPLE_BUFFERS,               EGL_SAMPLE_BUFFERS },
+   { GLX_SAMPLES,                      EGL_SAMPLES },
+   { GLX_RENDER_TYPE,                  0 },
+   { GLX_DRAWABLE_TYPE,                EGL_SURFACE_TYPE },
+   { GLX_X_RENDERABLE,                 EGL_NATIVE_RENDERABLE },
+   { GLX_X_VISUAL_TYPE,                EGL_NATIVE_VISUAL_TYPE },
+   { GLX_CONFIG_CAVEAT,                EGL_CONFIG_CAVEAT },
+   { GLX_TRANSPARENT_TYPE,             EGL_TRANSPARENT_TYPE },
+   { GLX_TRANSPARENT_INDEX_VALUE,      0 },
+   { GLX_TRANSPARENT_RED_VALUE,        EGL_TRANSPARENT_RED_VALUE },
+   { GLX_TRANSPARENT_GREEN_VALUE,      EGL_TRANSPARENT_GREEN_VALUE },
+   { GLX_TRANSPARENT_BLUE_VALUE,       EGL_TRANSPARENT_BLUE_VALUE },
+   { GLX_MAX_PBUFFER_WIDTH,            EGL_MAX_PBUFFER_WIDTH },
+   { GLX_MAX_PBUFFER_HEIGHT,           EGL_MAX_PBUFFER_HEIGHT },
+   { GLX_MAX_PBUFFER_PIXELS,           EGL_MAX_PBUFFER_PIXELS },
+   { GLX_VISUAL_ID,                    EGL_NATIVE_VISUAL_ID }
+};
+
+
+static EGLBoolean
+convert_fbconfig(struct GLX_egl_driver *GLX_drv,
+                 struct GLX_egl_display *GLX_dpy, GLXFBConfig fbconfig,
+                 struct GLX_egl_config *GLX_conf)
 {
-   const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
-   int rgba;
+   Display *dpy = GLX_dpy->dpy;
+   int err, attr, val;
+   unsigned i;
 
-   memset(attribs, 0, sizeof(struct visual_attribs));
+   /* must have rgba bit */
+   err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &val);
+   if (err || !(val & GLX_RGBA_BIT))
+      return EGL_FALSE;
 
-   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;
-   }
+   /* must know whether it is double-buffered */
+   err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &val);
+   if (err)
+      return EGL_FALSE;
+   GLX_conf->double_buffered = val;
 
-#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;
-   }
-#else
-   attribs->visualCaveat = 0;
-#endif
+   GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
+   GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
 
-   return GL_TRUE;
-}
+   for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
+      EGLint egl_attr, egl_val;
 
-#ifdef GLX_VERSION_1_3
+      attr = fbconfig_attributes[i].attr;
+      egl_attr = fbconfig_attributes[i].egl_attr;
+      if (!egl_attr)
+         continue;
 
-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:
-   default:
-      return None;
+      err = GLX_drv->glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
+      if (err) {
+         if (err == GLX_BAD_ATTRIBUTE) {
+            err = 0;
+            continue;
+         }
+         break;
+      }
+
+      switch (egl_attr) {
+      case EGL_SURFACE_TYPE:
+         egl_val = 0;
+         if (val & GLX_WINDOW_BIT)
+            egl_val |= EGL_WINDOW_BIT;
+         /* pixmap and pbuffer surfaces must be single-buffered in EGL */
+         if (!GLX_conf->double_buffered) {
+            if (val & GLX_PIXMAP_BIT)
+               egl_val |= EGL_PIXMAP_BIT;
+            if (val & GLX_PBUFFER_BIT)
+               egl_val |= EGL_PBUFFER_BIT;
+         }
+         break;
+      case EGL_NATIVE_VISUAL_TYPE:
+         switch (val) {
+         case GLX_TRUE_COLOR:
+            egl_val = TrueColor;
+            break;
+         case GLX_DIRECT_COLOR:
+            egl_val = DirectColor;
+            break;
+         case GLX_PSEUDO_COLOR:
+            egl_val = PseudoColor;
+            break;
+         case GLX_STATIC_COLOR:
+            egl_val = StaticColor;
+            break;
+         case GLX_GRAY_SCALE:
+            egl_val = GrayScale;
+            break;
+         case GLX_STATIC_GRAY:
+            egl_val = StaticGray;
+            break;
+         default:
+            egl_val = EGL_NONE;
+            break;
+         }
+         break;
+      case EGL_CONFIG_CAVEAT:
+         egl_val = EGL_NONE;
+         if (val == GLX_SLOW_CONFIG) {
+            egl_val = EGL_SLOW_CONFIG;
+         }
+         else if (val == GLX_NON_CONFORMANT_CONFIG) {
+            GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
+            egl_val = EGL_NONE;
+         }
+         break;
+      case EGL_TRANSPARENT_TYPE:
+         egl_val = (val == GLX_TRANSPARENT_RGB) ?
+            EGL_TRANSPARENT_RGB : EGL_NONE;
+         break;
+      default:
+         egl_val = val;
+         break;
+      }
+
+      _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
    }
+   if (err)
+      return EGL_FALSE;
+
+   if (!GLX_conf->Base.SurfaceType)
+      return EGL_FALSE;
+
+   return EGL_TRUE;
 }
-static GLboolean
-get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
-                    struct visual_attribs *attribs)
+
+static const struct {
+   int attr;
+   int egl_attr;
+} visual_attributes[] = {
+   /* table 3.7 of GLX 1.4 */
+   { GLX_USE_GL,              0 },
+   { GLX_BUFFER_SIZE,         EGL_BUFFER_SIZE },
+   { GLX_LEVEL,               EGL_LEVEL },
+   { GLX_RGBA,                0 },
+   { GLX_DOUBLEBUFFER,        0 },
+   { GLX_STEREO,              0 },
+   { GLX_AUX_BUFFERS,         0 },
+   { GLX_RED_SIZE,            EGL_RED_SIZE },
+   { GLX_GREEN_SIZE,          EGL_GREEN_SIZE },
+   { GLX_BLUE_SIZE,           EGL_BLUE_SIZE },
+   { GLX_ALPHA_SIZE,          EGL_ALPHA_SIZE },
+   { GLX_DEPTH_SIZE,          EGL_DEPTH_SIZE },
+   { GLX_STENCIL_SIZE,        EGL_STENCIL_SIZE },
+   { GLX_ACCUM_RED_SIZE,      0 },
+   { GLX_ACCUM_GREEN_SIZE,    0 },
+   { GLX_ACCUM_BLUE_SIZE,     0 },
+   { GLX_ACCUM_ALPHA_SIZE,    0 },
+   { GLX_SAMPLE_BUFFERS,      EGL_SAMPLE_BUFFERS },
+   { GLX_SAMPLES,             EGL_SAMPLES },
+   { GLX_FBCONFIG_ID,         0 },
+   /* GLX_EXT_visual_rating */
+   { GLX_VISUAL_CAVEAT_EXT,   EGL_CONFIG_CAVEAT }
+};
+
+static EGLBoolean
+convert_visual(struct GLX_egl_driver *GLX_drv,
+               struct GLX_egl_display *GLX_dpy, XVisualInfo *vinfo,
+               struct GLX_egl_config *GLX_conf)
 {
-   int visual_type;
+   Display *dpy = GLX_dpy->dpy;
+   int err, attr, val;
+   unsigned i;
+
+   /* the visual must support OpenGL and RGBA buffer */
+   err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
+   if (!err && val)
+      err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_RGBA, &val);
+   if (err || !val)
+      return EGL_FALSE;
 
-   memset(attribs, 0, sizeof(struct visual_attribs));
+   /* must know whether it is double-buffered */
+   err = GLX_drv->glXGetConfig(dpy, vinfo, GLX_DOUBLEBUFFER, &val);
+   if (err)
+      return EGL_FALSE;
+   GLX_conf->double_buffered = val;
 
-   /* We don't use the GLX_FBCONFIG_ID here */
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id);
+   GLX_conf->Base.RenderableType = EGL_OPENGL_BIT;
+   GLX_conf->Base.Conformant = EGL_OPENGL_BIT;
+   GLX_conf->Base.SurfaceType = EGL_WINDOW_BIT;
+   /* pixmap surfaces must be single-buffered in EGL */
+   if (!GLX_conf->double_buffered)
+      GLX_conf->Base.SurfaceType |= EGL_PIXMAP_BIT;
 
-#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
+   GLX_conf->Base.NativeVisualID = vinfo->visualid;
+   GLX_conf->Base.NativeVisualType = vinfo->class;
+   GLX_conf->Base.NativeRenderable = EGL_TRUE;
 
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
-   attribs->klass = glx_token_to_visual_class(visual_type);
+   for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
+      EGLint egl_attr, egl_val;
 
-   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 GL_FALSE;
+      attr = visual_attributes[i].attr;
+      egl_attr = visual_attributes[i].egl_attr;
+      if (!egl_attr)
+         continue;
 
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
-   if (!attribs->doubleBuffer)
-      return GL_FALSE;
+      err = GLX_drv->glXGetConfig(dpy, vinfo, attr, &val);
+      if (err) {
+         if (err == GLX_BAD_ATTRIBUTE) {
+            err = 0;
+            continue;
+         }
+         break;
+      }
 
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+      switch (egl_attr) {
+      case EGL_CONFIG_CAVEAT:
+         egl_val = EGL_NONE;
+         if (val == GLX_SLOW_VISUAL_EXT) {
+            egl_val = EGL_SLOW_CONFIG;
+         }
+         else if (val == GLX_NON_CONFORMANT_VISUAL_EXT) {
+            GLX_conf->Base.Conformant &= ~EGL_OPENGL_BIT;
+            egl_val = EGL_NONE;
+         }
+         break;
+         break;
+      default:
+         egl_val = val;
+         break;
+      }
+      _eglSetConfigKey(&GLX_conf->Base, egl_attr, egl_val);
+   }
 
-   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);
+   return (err) ? EGL_FALSE : EGL_TRUE;
+}
 
-   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);
+static void
+fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
+{
+   _EGLConfig *conf = &GLX_conf->Base;
+
+   if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
+      /* some GLX impls do not like single-buffered window surface */
+      conf->SurfaceType &= ~EGL_WINDOW_BIT;
+      /* pbuffer bit is usually not set */
+      if (GLX_dpy->have_pbuffer)
+         conf->SurfaceType |= EGL_PBUFFER_BIT;
    }
 
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
+   /* no visual attribs unless window bit is set */
+   if (!(conf->SurfaceType & EGL_WINDOW_BIT)) {
+      conf->NativeVisualID = 0;
+      conf->NativeVisualType = EGL_NONE;
+   }
 
-   glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
+   if (conf->TransparentType != EGL_TRANSPARENT_RGB) {
+      /* some impls set them to -1 (GLX_DONT_CARE) */
+      conf->TransparentRedValue = 0;
+      conf->TransparentGreenValue = 0;
+      conf->TransparentBlueValue = 0;
+   }
 
-   return GL_TRUE;
+   /* make sure buffer size is set correctly */
+   conf->BufferSize =
+      conf->RedSize + conf->GreenSize + conf->BlueSize + conf->AlphaSize;
 }
 
-#endif
 
 static EGLBoolean
-create_configs(_EGLDisplay *disp, struct GLX_egl_driver *GLX_drv)
+create_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint screen)
 {
-   XVisualInfo theTemplate;
-   int numVisuals;
-   long mask;
-   int i;
-   struct visual_attribs attribs;
-
-   GLX_drv->fbconfigs = NULL;
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(dpy);
+   EGLint num_configs = 0, i;
+   EGLint id = 1;
 
-#ifdef GLX_VERSION_1_3
-   /* get list of all fbconfigs on this screen */
-   GLX_drv->fbconfigs = glXGetFBConfigs(disp->Xdpy, DefaultScreen(disp->Xdpy), &numVisuals);
+   if (GLX_dpy->have_fbconfig) {
+      GLX_dpy->fbconfigs =
+         GLX_drv->glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
+   }
+   else {
+      XVisualInfo vinfo_template;
+      long mask;
 
-   if (numVisuals == 0) {
-      GLX_drv->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;
+   if (!num_configs)
+      return EGL_FALSE;
 
-      if (!get_fbconfig_attribs(disp->Xdpy, GLX_drv->fbconfigs[i], &attribs))
-         continue;
+   for (i = 0; i < num_configs; i++) {
+      struct GLX_egl_config *GLX_conf, template;
+      EGLBoolean ok;
 
-      config = CALLOC_STRUCT(GLX_egl_config);
+      memset(&template, 0, sizeof(template));
+      _eglInitConfig(&template.Base, dpy, id);
+      if (GLX_dpy->have_fbconfig) {
+         ok = convert_fbconfig(GLX_drv, GLX_dpy,
+               GLX_dpy->fbconfigs[i], &template);
+      }
+      else {
+         ok = convert_visual(GLX_drv, GLX_dpy,
+               &GLX_dpy->visuals[i], &template);
+      }
+      if (!ok)
+        continue;
 
-      _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));
+      fix_config(GLX_dpy, &template);
+      if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
+         _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
+         continue;
+      }
 
-      /* XXX possibly other things to init... */
+      GLX_conf = CALLOC_STRUCT(GLX_egl_config);
+      if (GLX_conf) {
+         memcpy(GLX_conf, &template, sizeof(template));
+         GLX_conf->index = i;
 
-      _eglAddConfig(disp, &config->Base);
+         _eglLinkConfig(&GLX_conf->Base);
+         id++;
+      }
    }
 
-   goto end;
-#endif
+   return EGL_TRUE;
+}
 
-xvisual:
-   /* get list of all visuals on this screen */
-   theTemplate.screen = DefaultScreen(disp->Xdpy);
-   mask = VisualScreenMask;
-   GLX_drv->visuals = XGetVisualInfo(disp->Xdpy, mask, &theTemplate, &numVisuals);
 
-   for (i = 0; i < numVisuals; i++) {
-      struct GLX_egl_config *config;
+static void
+check_extensions(struct GLX_egl_driver *GLX_drv,
+                 struct GLX_egl_display *GLX_dpy, EGLint screen)
+{
+   GLX_dpy->extensions =
+      GLX_drv->glXQueryExtensionsString(GLX_dpy->dpy, screen);
+   if (GLX_dpy->extensions) {
+      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;
+      }
 
-      if (!get_visual_attribs(disp->Xdpy, &GLX_drv->visuals[i], &attribs))
-        continue;
+      if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
+         /* GLX 1.3 entry points are used */
+         GLX_dpy->have_fbconfig = EGL_TRUE;
+      }
 
-      config = CALLOC_STRUCT(GLX_egl_config);
+      if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
+         if (GLX_drv->glXCreateGLXPbufferSGIX &&
+             GLX_drv->glXDestroyGLXPbufferSGIX &&
+             GLX_dpy->have_fbconfig)
+            GLX_dpy->have_pbuffer = EGL_TRUE;
+      }
+   }
 
-      _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*/));
+   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;
+   }
+}
 
-      /* XXX possibly other things to init... */
 
-      _eglAddConfig(disp, &config->Base);
+static void
+check_quirks(struct GLX_egl_driver *GLX_drv,
+             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 = GLX_drv->glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
+   if (vendor && strstr(vendor, "NVIDIA")) {
+      vendor = GLX_drv->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;
+      }
    }
-
-end:
-   return EGL_TRUE;
 }
 
+
 /**
  * Called via eglInitialize(), GLX_drv->API.Initialize().
  */
 static EGLBoolean
-GLX_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
-                   EGLint *minor, EGLint *major)
+GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
+                   EGLint *major, EGLint *minor)
 {
    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   struct GLX_egl_display *GLX_dpy;
+
+   if (disp->Platform != _EGL_PLATFORM_X11)
+      return EGL_FALSE;
 
-   _eglLog(_EGL_DEBUG, "GLX: eglInitialize");
+   GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
+   if (!GLX_dpy)
+      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
 
-   if (!disp->Xdpy) {
-      disp->Xdpy = XOpenDisplay(NULL);
-      if (!disp->Xdpy) {
+   GLX_dpy->dpy = (Display *) disp->PlatformDisplay;
+   if (!GLX_dpy->dpy) {
+      GLX_dpy->dpy = XOpenDisplay(NULL);
+      if (!GLX_dpy->dpy) {
          _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed");
+         free(GLX_dpy);
          return EGL_FALSE;
       }
-   } 
+   }
 
-   glXQueryVersion(disp->Xdpy, &GLX_drv->glx_maj, &GLX_drv->glx_min);
-   
-   GLX_drv->Base.Initialized = EGL_TRUE;
+   if (!GLX_drv->glXQueryVersion(GLX_dpy->dpy,
+            &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
+      _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
+      if (!disp->PlatformDisplay)
+         XCloseDisplay(GLX_dpy->dpy);
+      free(GLX_dpy);
+      return EGL_FALSE;
+   }
 
-   GLX_drv->Base.Name = "GLX";
+   disp->DriverData = (void *) GLX_dpy;
+   disp->ClientAPIsMask = EGL_OPENGL_BIT;
 
-   /* we're supporting EGL 1.4 */
-   *minor = 1;
-   *major = 4;
+   check_extensions(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
+   check_quirks(GLX_drv, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
 
-   create_configs(disp, GLX_drv);
+   create_configs(drv, disp, DefaultScreen(GLX_dpy->dpy));
+   if (!_eglGetArraySize(disp->Configs)) {
+      _eglLog(_EGL_WARNING, "GLX: failed to create any config");
+      if (!disp->PlatformDisplay)
+         XCloseDisplay(GLX_dpy->dpy);
+      free(GLX_dpy);
+      return EGL_FALSE;
+   }
+
+   /* we're supporting EGL 1.4 */
+   *major = 1;
+   *minor = 4;
 
    return EGL_TRUE;
 }
 
-/*
- * Do some clean-up that normally occurs in XCloseDisplay().
- * We do this here because we're about to unload a dynamic library
- * that has added some per-display extension data and callbacks.
- * If we don't do this here we'll crash in XCloseDisplay() because it'll
- * try to call functions that went away when the driver library was unloaded.
- */
-static void
-FreeDisplayExt(Display *dpy)
-{
-   _XExtension *ext, *next;
-
-   for (ext = dpy->ext_procs; ext; ext = next) {
-      next = ext->next;
-      if (ext->close_display) {
-         ext->close_display(dpy, &ext->codes);
-         ext->close_display = NULL;
-      }
-      if (ext->name)
-         Xfree(ext->name);
-      Xfree(ext);
-   }
-   dpy->ext_procs = NULL;
-
-   _XFreeExtData (dpy->ext_data);
-   dpy->ext_data = NULL;
-}
 
 /**
  * Called via eglTerminate(), drv->API.Terminate().
  */
 static EGLBoolean
-GLX_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
+GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+
+   _eglReleaseDisplayResources(drv, disp);
+   _eglCleanupDisplay(disp);
 
-   _eglLog(_EGL_DEBUG, "GLX: eglTerminate");
+   if (GLX_dpy->visuals)
+      XFree(GLX_dpy->visuals);
+   if (GLX_dpy->fbconfigs)
+      XFree(GLX_dpy->fbconfigs);
 
-   FreeDisplayExt(disp->Xdpy);
+   if (!disp->PlatformDisplay)
+      XCloseDisplay(GLX_dpy->dpy);
+   free(GLX_dpy);
+
+   disp->DriverData = NULL;
 
    return EGL_TRUE;
 }
@@ -510,52 +665,60 @@ GLX_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
 /**
  * Called via eglCreateContext(), drv->API.CreateContext().
  */
-static EGLContext
-GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
-                      EGLContext share_list, const EGLint *attrib_list)
+static _EGLContext *
+GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
+                      _EGLContext *share_list, const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-   struct GLX_egl_context *GLX_ctx_shared = NULL;
-   _EGLConfig *conf;
+   struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+   struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list);
 
-   if (!GLX_ctx)
-      return EGL_NO_CONTEXT;
+   if (!GLX_ctx) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
+      return NULL;
+   }
 
-   if (!_eglInitContext(drv, dpy, &GLX_ctx->Base, config, attrib_list)) {
+   if (!_eglInitContext(&GLX_ctx->Base, disp, conf, attrib_list)) {
       free(GLX_ctx);
-      return EGL_NO_CONTEXT;
+      return NULL;
    }
 
-   if (share_list != EGL_NO_CONTEXT) {
-      _EGLContext *shareCtx = _eglLookupContext(share_list);
-      if (!shareCtx) {
-         _eglError(EGL_BAD_CONTEXT, "eglCreateContext(share_list)");
-         return EGL_FALSE;
-      }
-      GLX_ctx_shared = GLX_egl_context(shareCtx);
+   if (GLX_dpy->have_fbconfig) {
+      GLX_ctx->context = GLX_drv->glXCreateNewContext(GLX_dpy->dpy,
+            GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+            GLX_RGBA_TYPE,
+            GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
+            GL_TRUE);
+   }
+   else {
+      GLX_ctx->context = GLX_drv->glXCreateContext(GLX_dpy->dpy,
+            &GLX_dpy->visuals[GLX_egl_config_index(conf)],
+            GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
+            GL_TRUE);
+   }
+   if (!GLX_ctx->context) {
+      free(GLX_ctx);
+      return NULL;
    }
 
-   conf = _eglLookupConfig(drv, dpy, config);
-   assert(conf);
+   return &GLX_ctx->Base;
+}
 
-#ifdef GLX_VERSION_1_3
-   if (GLX_drv->fbconfigs)
-      GLX_ctx->context = glXCreateNewContext(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], GLX_RGBA_TYPE, GLX_ctx_shared ? GLX_ctx_shared->context : NULL, GL_TRUE);
-   else
-#endif
-      GLX_ctx->context = glXCreateContext(disp->Xdpy, &GLX_drv->visuals[(int)config-1], GLX_ctx_shared ? GLX_ctx_shared->context : NULL, GL_TRUE);
-   if (!GLX_ctx->context)
-      return EGL_FALSE;
 
-#if 1
-   /* (maybe?) need to have a direct rendering context */
-   if (!glXIsDirect(disp->Xdpy, GLX_ctx->context))
-      return EGL_FALSE;
-#endif
+/**
+ * Destroy a surface.  The display is allowed to be uninitialized.
+ */
+static void
+destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
+{
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
 
-   return _eglGetContextHandle(&GLX_ctx->Base);
+   if (GLX_surf->destroy)
+      GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable);
+
+   free(GLX_surf);
 }
 
 
@@ -563,27 +726,58 @@ GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
  * Called via eglMakeCurrent(), drv->API.MakeCurrent().
  */
 static EGLBoolean
-GLX_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
-                    EGLSurface r, EGLContext context)
+GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
+                   _EGLSurface *rsurf, _EGLContext *ctx)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLContext *ctx = _eglLookupContext(context);
-   _EGLSurface *dsurf = _eglLookupSurface(d);
-   _EGLSurface *rsurf = _eglLookupSurface(r);
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
    struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
    struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
-
-   if (!_eglMakeCurrent(drv, dpy, d, r, context))
+   _EGLContext *old_ctx;
+   _EGLSurface *old_dsurf, *old_rsurf;
+   GLXDrawable ddraw, rdraw;
+   GLXContext cctx;
+   EGLBoolean ret = EGL_FALSE;
+
+   /* make new bindings */
+   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
       return EGL_FALSE;
 
-#ifdef GLX_VERSION_1_3
-   if (!glXMakeContextCurrent(disp->Xdpy, GLX_dsurf->drawable, GLX_rsurf->drawable, GLX_ctx->context))
-#endif
-      if (!glXMakeCurrent(disp->Xdpy, GLX_dsurf ? GLX_dsurf->drawable : 0, GLX_ctx ? GLX_ctx->context : NULL))
-         return EGL_FALSE;
+   ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
+   rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None;
+   cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
+
+   if (GLX_dpy->have_make_current_read)
+      ret = GLX_drv->glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx);
+   else if (ddraw == rdraw)
+      ret = GLX_drv->glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
+
+   if (ret) {
+      if (_eglPutSurface(old_dsurf))
+         destroy_surface(disp, old_dsurf);
+      if (_eglPutSurface(old_rsurf))
+         destroy_surface(disp, old_rsurf);
+      /* no destroy? */
+      _eglPutContext(old_ctx);
+   }
+   else {
+      /* undo the previous _eglBindContext */
+      _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
+      assert(&GLX_ctx->Base == ctx &&
+             &GLX_dsurf->Base == dsurf &&
+             &GLX_rsurf->Base == rsurf);
+
+      _eglPutSurface(dsurf);
+      _eglPutSurface(rsurf);
+      _eglPutContext(ctx);
+
+      _eglPutSurface(old_dsurf);
+      _eglPutSurface(old_rsurf);
+      _eglPutContext(old_ctx);
+   }
 
-   return EGL_TRUE;
+   return ret;
 }
 
 /** Get size of given window */
@@ -603,192 +797,316 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
 /**
  * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
  */
-static EGLSurface
-GLX_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
-                            NativeWindowType window, const EGLint *attrib_list)
+static _EGLSurface *
+GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp,
+                           _EGLConfig *conf, EGLNativeWindowType window,
+                           const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    struct GLX_egl_surface *GLX_surf;
    uint width, height;
 
    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
-   if (!GLX_surf)
-      return EGL_NO_SURFACE;
+   if (!GLX_surf) {
+      _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface");
+      return NULL;
+   }
 
-   if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_WINDOW_BIT,
-                        config, attrib_list)) {
+   if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_WINDOW_BIT,
+                        conf, attrib_list)) {
       free(GLX_surf);
-      return EGL_FALSE;
+      return NULL;
    }
 
-   _eglSaveSurface(&GLX_surf->Base);
-
    GLX_surf->drawable = window;
-   get_drawable_size(disp->Xdpy, window, &width, &height);
+
+   if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk) {
+      GLX_surf->glx_drawable = GLX_drv->glXCreateWindow(GLX_dpy->dpy,
+            GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+            GLX_surf->drawable, NULL);
+   }
+   else {
+      GLX_surf->glx_drawable = GLX_surf->drawable;
+   }
+
+   if (!GLX_surf->glx_drawable) {
+      free(GLX_surf);
+      return NULL;
+   }
+
+   if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
+      GLX_surf->destroy = GLX_drv->glXDestroyWindow;
+
+   get_drawable_size(GLX_dpy->dpy, window, &width, &height);
    GLX_surf->Base.Width = width;
    GLX_surf->Base.Height = height;
 
-   return _eglGetSurfaceHandle(&GLX_surf->Base);
+   return &GLX_surf->Base;
 }
 
-#ifdef GLX_VERSION_1_3
-static EGLSurface
-GLX_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, 
-                          NativePixmapType pixmap, const EGLint *attrib_list)
+static _EGLSurface *
+GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp,
+                           _EGLConfig *conf, EGLNativePixmapType pixmap,
+                           const EGLint *attrib_list)
 {
    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    struct GLX_egl_surface *GLX_surf;
-   int i;
+   uint width, height;
 
    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
-   if (!GLX_surf)
-      return EGL_NO_SURFACE;
+   if (!GLX_surf) {
+      _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface");
+      return NULL;
+   }
 
-   if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_PIXMAP_BIT,
-                        config, attrib_list)) {
+   if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PIXMAP_BIT,
+                        conf, attrib_list)) {
       free(GLX_surf);
-      return EGL_FALSE;
+      return NULL;
    }
 
-   _eglSaveSurface(&GLX_surf->Base);
+   GLX_surf->drawable = pixmap;
 
-   for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
-      switch (attrib_list[i]) {
-         /* no attribs at this time */
-      default:
-         _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
-         return EGL_NO_SURFACE;
+   if (GLX_dpy->have_1_3) {
+      GLX_surf->glx_drawable = GLX_drv->glXCreatePixmap(GLX_dpy->dpy,
+            GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+            GLX_surf->drawable, NULL);
+   }
+   else if (GLX_dpy->have_fbconfig) {
+      GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)];
+      XVisualInfo *vinfo;
+
+      vinfo = GLX_drv->glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig);
+      if (vinfo) {
+         GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
+               vinfo, GLX_surf->drawable);
+         XFree(vinfo);
       }
    }
+   else {
+      GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPixmap(GLX_dpy->dpy,
+            &GLX_dpy->visuals[GLX_egl_config_index(conf)],
+            GLX_surf->drawable);
+   }
 
-   GLX_surf->drawable = glXCreatePixmap(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], pixmap, NULL);
+   if (!GLX_surf->glx_drawable) {
+      free(GLX_surf);
+      return NULL;
+   }
 
-   return _eglGetSurfaceHandle(&GLX_surf->Base);
+   GLX_surf->destroy = (GLX_dpy->have_1_3) ?
+      GLX_drv->glXDestroyPixmap : GLX_drv->glXDestroyGLXPixmap;
+
+   get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
+   GLX_surf->Base.Width = width;
+   GLX_surf->Base.Height = height;
+
+   return &GLX_surf->Base;
 }
 
-static EGLSurface
-GLX_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
-                            const EGLint *attrib_list)
+static _EGLSurface *
+GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
+                            _EGLConfig *conf, const EGLint *attrib_list)
 {
    struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
    struct GLX_egl_surface *GLX_surf;
    int attribs[5];
-   int i = 0, j = 0;
+   int i;
 
    GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
-   if (!GLX_surf)
-      return EGL_NO_SURFACE;
+   if (!GLX_surf) {
+      _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
+      return NULL;
+   }
 
-   if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_PBUFFER_BIT,
-                        config, attrib_list)) {
+   if (!_eglInitSurface(&GLX_surf->Base, disp, EGL_PBUFFER_BIT,
+                        conf, attrib_list)) {
       free(GLX_surf);
-      return EGL_NO_SURFACE;
+      return NULL;
    }
 
-   _eglSaveSurface(&GLX_surf->Base);
+   i = 0;
+   attribs[i] = None;
+
+   GLX_surf->drawable = None;
 
-   while(attrib_list[i] != EGL_NONE) {
-      switch (attrib_list[i]) {
-         case EGL_WIDTH:
-           attribs[j++] = GLX_PBUFFER_WIDTH;
-           attribs[j++] = attrib_list[i+1];
-           break;
-        case EGL_HEIGHT:
-           attribs[j++] = GLX_PBUFFER_HEIGHT;
-           attribs[j++] = attrib_list[i+1];
-           break;
+   if (GLX_dpy->have_1_3) {
+      /* put geometry in attribs */
+      if (GLX_surf->Base.Width) {
+         attribs[i++] = GLX_PBUFFER_WIDTH;
+         attribs[i++] = GLX_surf->Base.Width;
       }
-      i++;
+      if (GLX_surf->Base.Height) {
+         attribs[i++] = GLX_PBUFFER_HEIGHT;
+         attribs[i++] = GLX_surf->Base.Height;
+      }
+      attribs[i] = None;
+
+      GLX_surf->glx_drawable = GLX_drv->glXCreatePbuffer(GLX_dpy->dpy,
+            GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], attribs);
+   }
+   else if (GLX_dpy->have_pbuffer) {
+      GLX_surf->glx_drawable = GLX_drv->glXCreateGLXPbufferSGIX(GLX_dpy->dpy,
+            GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+            GLX_surf->Base.Width,
+            GLX_surf->Base.Height,
+            attribs);
+   }
+
+   if (!GLX_surf->glx_drawable) {
+      free(GLX_surf);
+      return NULL;
    }
-   attribs[j++] = 0;
 
-   GLX_surf->drawable = glXCreatePbuffer(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], attribs);
+   GLX_surf->destroy = (GLX_dpy->have_1_3) ?
+      GLX_drv->glXDestroyPbuffer : GLX_drv->glXDestroyGLXPbufferSGIX;
 
-   return _eglGetSurfaceHandle(&GLX_surf->Base);
+   return &GLX_surf->Base;
 }
-#endif
+
 
 static EGLBoolean
-GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLSurface *surf = _eglLookupSurface(surface);
-   return EGL_TRUE;
-   if (surf) {
-      _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
-      if (surf->IsBound) {
-         surf->DeletePending = EGL_TRUE;
-      }
-      else {
-         free(surf);
-      }
+   (void) drv;
 
-      return EGL_TRUE;
-   }
-   else {
-      _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
-      return EGL_FALSE;
-   }
+   if (_eglPutSurface(surf))
+      destroy_surface(disp, surf);
+
+   return EGL_TRUE;
 }
 
 
 static EGLBoolean
-GLX_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
-                     EGLint buffer)
+GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLSurface *surf = _eglLookupSurface(surface);
-   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
+   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
 
-   /* buffer ?? */
-   glXBindTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT, NULL);
+   GLX_drv->glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
 
    return EGL_TRUE;
 }
 
+/*
+ * Called from eglGetProcAddress() via drv->API.GetProcAddress().
+ */
+static _EGLProc
+GLX_eglGetProcAddress(_EGLDriver *drv, const char *procname)
+{
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+
+   return (_EGLProc) GLX_drv->glXGetProcAddress((const GLubyte *) procname);
+}
 
 static EGLBoolean
-GLX_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
-                        EGLint buffer)
+GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLSurface *surf = _eglLookupSurface(surface);
-   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
 
-   /* buffer ?? */
-   glXReleaseTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT);
+   (void) dpy;
+   (void) ctx;
 
+   GLX_drv->glXWaitGL();
    return EGL_TRUE;
 }
 
-
 static EGLBoolean
-GLX_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLSurface *surf = _eglLookupSurface(draw);
-   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
 
-   _eglLog(_EGL_DEBUG, "GLX: EGL SwapBuffers 0x%x",draw);
+   (void) dpy;
 
-   /* error checking step: */
-   if (!_eglSwapBuffers(drv, dpy, draw))
-      return EGL_FALSE;
+   if (engine != EGL_CORE_NATIVE_ENGINE)
+      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
+   GLX_drv->glXWaitX();
+   return EGL_TRUE;
+}
 
-   glXSwapBuffers(disp->Xdpy, GLX_surf->drawable);
+static void
+GLX_Unload(_EGLDriver *drv)
+{
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
 
-   return EGL_TRUE;
+   if (GLX_drv->handle)
+      dlclose(GLX_drv->handle);
+   free(GLX_drv);
 }
 
-/*
- * Called from eglGetProcAddress() via drv->API.GetProcAddress().
- */
-static _EGLProc
-GLX_eglGetProcAddress(const char *procname)
+
+static EGLBoolean
+GLX_Load(_EGLDriver *drv)
 {
-   return (_EGLProc)glXGetProcAddress((const GLubyte *)procname);   
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   void *handle;
+
+   handle = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
+   if (!handle)
+      goto fail;
+
+   GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddress");
+   if (!GLX_drv->glXGetProcAddress)
+      GLX_drv->glXGetProcAddress = dlsym(handle, "glXGetProcAddressARB");
+   if (!GLX_drv->glXGetProcAddress)
+      goto fail;
+
+#define GET_PROC(proc_type, proc_name, check)                        \
+   do {                                                              \
+      GLX_drv->proc_name = (proc_type)                               \
+         GLX_drv->glXGetProcAddress((const GLubyte *) #proc_name);   \
+      if (check && !GLX_drv->proc_name) goto fail;                   \
+   } while (0)
+
+   /* GLX 1.0 */
+   GET_PROC(GLXCREATECONTEXTPROC, glXCreateContext, EGL_TRUE);
+   GET_PROC(GLXDESTROYCONTEXTPROC, glXDestroyContext, EGL_TRUE);
+   GET_PROC(GLXMAKECURRENTPROC, glXMakeCurrent, EGL_TRUE);
+   GET_PROC(GLXSWAPBUFFERSPROC, glXSwapBuffers, EGL_TRUE);
+   GET_PROC(GLXCREATEGLXPIXMAPPROC, glXCreateGLXPixmap, EGL_TRUE);
+   GET_PROC(GLXDESTROYGLXPIXMAPPROC, glXDestroyGLXPixmap, EGL_TRUE);
+   GET_PROC(GLXQUERYVERSIONPROC, glXQueryVersion, EGL_TRUE);
+   GET_PROC(GLXGETCONFIGPROC, glXGetConfig, EGL_TRUE);
+   GET_PROC(GLXWAITGLPROC, glXWaitGL, EGL_TRUE);
+   GET_PROC(GLXWAITXPROC, glXWaitX, EGL_TRUE);
+
+   /* GLX 1.1 */
+   GET_PROC(GLXQUERYEXTENSIONSSTRINGPROC, glXQueryExtensionsString, EGL_TRUE);
+   GET_PROC(GLXQUERYSERVERSTRINGPROC, glXQueryServerString, EGL_TRUE);
+   GET_PROC(GLXGETCLIENTSTRINGPROC, glXGetClientString, EGL_TRUE);
+
+   /* GLX 1.3 */
+   GET_PROC(PFNGLXGETFBCONFIGSPROC, glXGetFBConfigs, EGL_FALSE);
+   GET_PROC(PFNGLXGETFBCONFIGATTRIBPROC, glXGetFBConfigAttrib, EGL_FALSE);
+   GET_PROC(PFNGLXGETVISUALFROMFBCONFIGPROC, glXGetVisualFromFBConfig, EGL_FALSE);
+   GET_PROC(PFNGLXCREATEWINDOWPROC, glXCreateWindow, EGL_FALSE);
+   GET_PROC(PFNGLXDESTROYWINDOWPROC, glXDestroyWindow, EGL_FALSE);
+   GET_PROC(PFNGLXCREATEPIXMAPPROC, glXCreatePixmap, EGL_FALSE);
+   GET_PROC(PFNGLXDESTROYPIXMAPPROC, glXDestroyPixmap, EGL_FALSE);
+   GET_PROC(PFNGLXCREATEPBUFFERPROC, glXCreatePbuffer, EGL_FALSE);
+   GET_PROC(PFNGLXDESTROYPBUFFERPROC, glXDestroyPbuffer, EGL_FALSE);
+   GET_PROC(PFNGLXCREATENEWCONTEXTPROC, glXCreateNewContext, EGL_FALSE);
+   GET_PROC(PFNGLXMAKECONTEXTCURRENTPROC, glXMakeContextCurrent, EGL_FALSE);
+
+   /* GLX_SGIX_pbuffer */
+   GET_PROC(PFNGLXCREATEGLXPBUFFERSGIXPROC,
+         glXCreateGLXPbufferSGIX, EGL_FALSE);
+   GET_PROC(PFNGLXDESTROYGLXPBUFFERSGIXPROC,
+         glXDestroyGLXPbufferSGIX, EGL_FALSE);
+#undef GET_PROC
+
+   GLX_drv->handle = handle;
+
+   return EGL_TRUE;
+
+fail:
+   if (handle)
+      dlclose(handle);
+   return EGL_FALSE;
 }
 
 
@@ -797,52 +1115,37 @@ GLX_eglGetProcAddress(const char *procname)
  * Create a new _EGLDriver object and init its dispatch table.
  */
 _EGLDriver *
-_eglMain(_EGLDisplay *disp, const char *args)
+_EGL_MAIN(const char *args)
 {
    struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
-   char *env;
-   int maj = 0, min = 0;
+
+   (void) args;
 
    if (!GLX_drv)
       return NULL;
 
+   if (!GLX_Load(&GLX_drv->Base)) {
+      _eglLog(_EGL_WARNING, "GLX: failed to load GLX");
+      free(GLX_drv);
+      return NULL;
+   }
+
    _eglInitDriverFallbacks(&GLX_drv->Base);
    GLX_drv->Base.API.Initialize = GLX_eglInitialize;
    GLX_drv->Base.API.Terminate = GLX_eglTerminate;
    GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
    GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
    GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
-#ifdef GLX_VERSION_1_3
-   if (GLX_drv->glx_maj == 1 && GLX_drv->glx_min >= 3) {
-      GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
-      GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
-      printf("GLX: Pbuffer and Pixmap support\n");
-   } else {
-      printf("GLX: No pbuffer or pixmap support\n");
-   }
-#endif
+   GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
+   GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
    GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
-   GLX_drv->Base.API.BindTexImage = GLX_eglBindTexImage;
-   GLX_drv->Base.API.ReleaseTexImage = GLX_eglReleaseTexImage;
    GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
    GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
+   GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
+   GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
 
-   GLX_drv->Base.ClientAPIsMask = all_apis;
    GLX_drv->Base.Name = "GLX";
-
-   _eglLog(_EGL_DEBUG, "GLX: main(%s)", args);
-
-   /* set new DRI path to pick up EGL version (which doesn't contain any mesa 
-    * code), but don't override if one is already set.
-    */
-   env = getenv("LIBGL_DRIVERS_PATH");
-   if (env) {
-      if (!strstr(env, "egl")) {
-         sprintf(env, "%s/egl", env);
-         setenv("LIBGL_DRIVERS_PATH", env, 1);
-      }
-   } else
-      setenv("LIBGL_DRIVERS_PATH", DEFAULT_DRIVER_DIR"/egl", 0);
+   GLX_drv->Base.Unload = GLX_Unload;
 
    return &GLX_drv->Base;
 }