egl: Add new EGL driver that wraps GLX.
authorAlan Hourihane <alanh@tungstengraphics.com>
Fri, 26 Sep 2008 10:18:58 +0000 (11:18 +0100)
committerAlan Hourihane <alanh@tungstengraphics.com>
Fri, 26 Sep 2008 10:20:21 +0000 (11:20 +0100)
src/egl/drivers/glx/Makefile [new file with mode: 0644]
src/egl/drivers/glx/egl_glx.c [new file with mode: 0644]

diff --git a/src/egl/drivers/glx/Makefile b/src/egl/drivers/glx/Makefile
new file mode 100644 (file)
index 0000000..3cd5276
--- /dev/null
@@ -0,0 +1,74 @@
+# src/egl/drivers/glx/Makefile
+
+# Build XEGL DRI driver loader library:  egl_glx.so
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+EXTRA_DEFINES = -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
+
+DRIVER_NAME = egl_glx.so
+
+
+INCLUDE_DIRS = \
+       -I. \
+       -I/usr/include \
+       $(shell pkg-config --cflags-only-I libdrm) \
+       -I$(TOP)/include \
+       -I$(TOP)/include/GL/internal \
+       -I$(TOP)/src/mesa/glapi \
+       -I$(TOP)/src/mesa/drivers/dri/common \
+       -I$(TOP)/src/mesa/main \
+       -I$(TOP)/src/mesa \
+       -I$(TOP)/src/egl/main \
+       -I$(TOP)/src/glx/x11
+
+SOURCES = egl_glx.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+DRM_LIB = `pkg-config --libs libdrm`
+
+MISC_LIBS = -ldl -lXext -lGL
+
+
+.c.o:
+       $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
+
+
+.PHONY: library
+
+
+default: depend library Makefile
+
+
+library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
+
+
+# Make the egl_glx.so library
+$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS)
+       $(TOP)/bin/mklib -o $(DRIVER_NAME) \
+               -noprefix \
+               -major 1 -minor 0 \
+               -L$(TOP)/$(LIB_DIR) \
+               -install $(TOP)/$(LIB_DIR) \
+               $(OBJECTS) $(DRM_LIB) $(MISC_LIBS)
+
+
+clean:
+       rm -f *.o
+       rm -f *.so
+       rm -f depend depend.bak
+
+
+depend: $(SOURCES) $(HEADERS)
+       @ echo "running $(MKDEP)"
+       @ rm -f depend
+       @ touch depend
+       $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
+               $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null
+
+include depend
+# DO NOT DELETE
diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
new file mode 100644 (file)
index 0000000..4274493
--- /dev/null
@@ -0,0 +1,574 @@
+/**************************************************************************
+ * 
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ **************************************************************************/
+
+
+/**
+ * This is an EGL driver that wraps GLX. This gives the benefit of being
+ * completely agnostic of the direct rendering implementation.
+ *
+ * Authors: Alan Hourihane <alanh@tungstengraphics.com>
+ */
+
+/*
+ * TODO: 
+ *
+ * Add GLXFBConfig support
+ * Pbuffer & Pixmap support
+ * test eglBind/ReleaseTexImage
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "dlfcn.h"
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include "glxclient.h"
+
+#define _EGL_PLATFORM_X
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglhash.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);
+
+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
+{
+   _EGLDriver Base;   /**< base class */
+
+   XVisualInfo *visuals;
+
+   /* GLXFBConfig *fbconfigs - todo */
+};
+
+
+/** subclass of _EGLContext */
+struct GLX_egl_context
+{
+   _EGLContext Base;   /**< base class */
+
+   GLXContext context;
+};
+
+
+/** subclass of _EGLSurface */
+struct GLX_egl_surface
+{
+   _EGLSurface Base;   /**< base class */
+
+   GLXDrawable drawable;
+};
+
+
+/** subclass of _EGLConfig */
+struct GLX_egl_config
+{
+   _EGLConfig Base;   /**< base class */
+};
+
+/** cast wrapper */
+static struct GLX_egl_driver *
+GLX_egl_driver(_EGLDriver *drv)
+{
+   return (struct GLX_egl_driver *) drv;
+}
+
+static struct GLX_egl_context *
+GLX_egl_context(_EGLContext *ctx)
+{
+   return (struct GLX_egl_context *) ctx;
+}
+
+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)
+{
+   const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
+   int rgba;
+
+   memset(attribs, 0, sizeof(struct visual_attribs));
+
+   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);
+   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;
+   }
+
+#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
+
+   return GL_TRUE;
+}
+
+static EGLBoolean
+create_configs(_EGLDisplay *disp, struct GLX_egl_driver *GLX_drv)
+{
+   XVisualInfo theTemplate;
+   int numVisuals;
+   long mask;
+   int i;
+   struct visual_attribs attribs;
+
+   /* 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;
+
+      if (!get_visual_attribs(disp->Xdpy, &GLX_drv->visuals[i], &attribs))
+        continue;
+
+      if (attribs.doubleBuffer) {
+      config = CALLOC_STRUCT(GLX_egl_config);
+
+      _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);
+      }
+   }
+
+   return EGL_TRUE;
+}
+
+/**
+ * Called via eglInitialize(), GLX_drv->API.Initialize().
+ */
+static EGLBoolean
+GLX_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
+                   EGLint *minor, EGLint *major)
+{
+   struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+   _eglLog(_EGL_DEBUG, "XDRI: eglInitialize");
+
+   if (!disp->Xdpy) {
+      disp->Xdpy = XOpenDisplay(NULL);
+      if (!disp->Xdpy) {
+         _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed");
+         return EGL_FALSE;
+      }
+   }
+
+   GLX_drv->Base.Initialized = EGL_TRUE;
+
+   GLX_drv->Base.Name = "GLX";
+
+   /* we're supporting EGL 1.4 */
+   *minor = 1;
+   *major = 4;
+
+   create_configs(disp, GLX_drv);
+
+   return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+GLX_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+   _eglLog(_EGL_DEBUG, "XDRI: eglTerminate");
+
+//   XCloseDisplay(disp->Xdpy);
+
+   return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static EGLContext
+GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+                      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;
+
+   if (!GLX_ctx)
+      return EGL_NO_CONTEXT;
+
+   if (!_eglInitContext(drv, dpy, &GLX_ctx->Base, config, attrib_list)) {
+      free(GLX_ctx);
+      return EGL_NO_CONTEXT;
+   }
+
+   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);
+   }
+
+   conf = _eglLookupConfig(drv, dpy, config);
+   assert(conf);
+
+   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;
+
+   /* need to have a direct rendering context */
+   if (!glXIsDirect(disp->Xdpy, GLX_ctx->context))
+      return EGL_FALSE;
+
+   return _eglGetContextHandle(&GLX_ctx->Base);
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+GLX_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
+                    EGLSurface r, EGLContext context)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLContext *ctx = _eglLookupContext(context);
+   _EGLSurface *dsurf = _eglLookupSurface(d);
+   _EGLSurface *rsurf = _eglLookupSurface(r);
+   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))
+      return EGL_FALSE;
+
+//   if (!glXMakeContextCurrent(disp->Xdpy, GLX_dsurf->drawable, GLX_rsurf->drawable, GLX_ctx->context))
+   if (!glXMakeCurrent(disp->Xdpy, GLX_dsurf ? GLX_dsurf->drawable : 0, GLX_ctx ? GLX_ctx->context : NULL))
+      return EGL_FALSE;
+
+   return EGL_TRUE;
+}
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+   Window root;
+   Status stat;
+   int xpos, ypos;
+   unsigned int w, h, bw, depth;
+   stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+   *width = w;
+   *height = h;
+   return stat;
+}
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static EGLSurface
+GLX_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+                            NativeWindowType window, const EGLint *attrib_list)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   struct GLX_egl_surface *GLX_surf;
+   uint width, height;
+
+   GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
+   if (!GLX_surf)
+      return EGL_NO_SURFACE;
+
+   if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_WINDOW_BIT,
+                        config, attrib_list)) {
+      free(GLX_surf);
+      return EGL_FALSE;
+   }
+
+   _eglSaveSurface(&GLX_surf->Base);
+
+   GLX_surf->drawable = window;
+   get_drawable_size(disp->Xdpy, window, &width, &height);
+   GLX_surf->Base.Width = width;
+   GLX_surf->Base.Height = height;
+
+   return _eglGetSurfaceHandle(&GLX_surf->Base);
+}
+
+static EGLBoolean
+GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+{
+   _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);
+      }
+
+      return EGL_TRUE;
+   }
+   else {
+      _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
+      return EGL_FALSE;
+   }
+}
+
+
+static EGLBoolean
+GLX_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+                     EGLint buffer)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface);
+   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+   /* buffer ?? */
+   glXBindTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT, NULL);
+
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+                        EGLint buffer)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface);
+   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+   /* buffer ?? */
+   glXReleaseTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT);
+
+   return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+{
+   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(draw);
+   struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+   _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers 0x%x",draw);
+
+   /* error checking step: */
+   if (!_eglSwapBuffers(drv, dpy, draw))
+      return EGL_FALSE;
+
+   glXSwapBuffers(disp->Xdpy, GLX_surf->drawable);
+
+   return EGL_TRUE;
+}
+
+/*
+ * Called from eglGetProcAddress() via drv->API.GetProcAddress().
+ */
+static _EGLProc
+GLX_eglGetProcAddress(const char *procname)
+{
+   return (_EGLProc)glXGetProcAddress((const GLubyte *)procname);   
+}
+
+
+/**
+ * This is the main entrypoint into the driver, called by libEGL.
+ * Create a new _EGLDriver object and init its dispatch table.
+ */
+_EGLDriver *
+_eglMain(_EGLDisplay *disp, const char *args)
+{
+   struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
+   if (!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;
+   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.ClientAPIsMask = all_apis;
+   GLX_drv->Base.Name = "GLX";
+
+   _eglLog(_EGL_DEBUG, "GLX: main(%s)", args);
+
+   /* set new DRI path to pick up EGL version (no mesa code), but don't
+    * override if one is already set.
+    */
+   setenv("LIBGL_DRIVERS_PATH", DEFAULT_DRIVER_DIR"/egl", 0);
+
+   return &GLX_drv->Base;
+}