[Mesa-dev] [PATCH 1/3] glx: Implement the libglvnd interface.

Adam Jackson ajax at redhat.com
Wed May 11 18:01:53 UTC 2016


From: Kyle Brenneman <kbrenneman at nvidia.com>

With reference to the libglvnd branch:

https://cgit.freedesktop.org/mesa/mesa/log/?h=libglvnd

This is a squashed commit containing all of Kyle's commits, all but two
of Emil's commits (to follow), and a small fixup from myself to mark the
rest of the glX* functions as _GLX_PUBLIC so they are not exported when
building for libglvnd. I (ajax) squashed them together both for ease of
review, and because most of the changes are un-useful intermediate
states representing the evolution of glvnd's internal API.

Co-author: Emil Velikov <emil.velikov at collabora.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
---
 configure.ac                        |  49 +-
 src/glx/Makefile.am                 |  19 +-
 src/glx/dri_glx.c                   |   4 +-
 src/glx/g_glxglvnddispatchfuncs.c   | 976 ++++++++++++++++++++++++++++++++++++
 src/glx/g_glxglvnddispatchindices.h |  92 ++++
 src/glx/glx_pbuffer.c               |  28 +-
 src/glx/glxclient.h                 |   5 +
 src/glx/glxcmds.c                   |  78 +--
 src/glx/glxcurrent.c                |  10 +-
 src/glx/glxglvnd.c                  |  75 +++
 src/glx/glxglvnd.h                  |  14 +
 src/glx/glxglvnddispatchfuncs.h     |  70 +++
 12 files changed, 1356 insertions(+), 64 deletions(-)
 create mode 100644 src/glx/g_glxglvnddispatchfuncs.c
 create mode 100644 src/glx/g_glxglvnddispatchindices.h
 create mode 100644 src/glx/glxglvnd.c
 create mode 100644 src/glx/glxglvnd.h
 create mode 100644 src/glx/glxglvnddispatchfuncs.h

diff --git a/configure.ac b/configure.ac
index 023110e..7bf28f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -514,6 +514,34 @@ else
    DEFINES="$DEFINES -DNDEBUG"
 fi
 
+DEFAULT_GL_LIB_NAME=GL
+
+dnl
+dnl Libglvnd configuration
+dnl
+AC_ARG_ENABLE([libglvnd],
+    [AS_HELP_STRING([--enable-libglvnd],
+        [Build for libglvnd @<:@default=disabled@:>@])],
+    [enable_libglvnd="$enableval"],
+    [enable_libglvnd=no])
+AM_CONDITIONAL(USE_LIBGLVND_GLX, test "x$enable_libglvnd" = xyes)
+if test "x$enable_libglvnd" = xyes ; then
+    dnl XXX: update once we can handle more than libGL/glx.
+    dnl Namely: we should error out if neither of the glvnd enabled libraries
+    dnl are built
+    if test "x$enable_glx" = xno; then
+        AC_MSG_ERROR([cannot build libglvnd without GLX])
+    fi
+
+    if test "x$enable_xlib_glx" = xyes; then
+        AC_MSG_ERROR([cannot build libgvnd when Xlib-GLX is enabled])
+    fi
+
+    PKG_CHECK_MODULES([GLVND], libglvnd >= 0.1.0)
+    DEFINES="${DEFINES} -DUSE_LIBGLVND_GLX=1"
+    DEFAULT_GL_LIB_NAME=GLX_mesa
+fi
+
 dnl
 dnl Check if linker supports -Bsymbolic
 dnl
@@ -611,6 +639,23 @@ esac
 
 AM_CONDITIONAL(HAVE_COMPAT_SYMLINKS, test "x$HAVE_COMPAT_SYMLINKS" = xyes)
 
+DEFAULT_GL_LIB_NAME=GL
+
+dnl
+dnl Libglvnd configuration
+dnl
+AC_ARG_ENABLE([libglvnd],
+    [AS_HELP_STRING([--enable-libglvnd],
+        [Build for libglvnd @<:@default=disabled@:>@])],
+    [enable_libglvnd="$enableval"],
+    [enable_libglvnd=no])
+AM_CONDITIONAL(USE_LIBGLVND_GLX, test "x$enable_libglvnd" = xyes)
+#AM_COND_IF([USE_LIBGLVND_GLX], [DEFINES="${DEFINES} -DUSE_LIBGLVND_GLX=1"])
+if test "x$enable_libglvnd" = xyes ; then
+    DEFINES="${DEFINES} -DUSE_LIBGLVND_GLX=1"
+    DEFAULT_GL_LIB_NAME=GLX_mesa
+fi
+
 dnl
 dnl library names
 dnl
@@ -648,13 +693,13 @@ AC_ARG_WITH([gl-lib-name],
   [AS_HELP_STRING([--with-gl-lib-name@<:@=NAME@:>@],
     [specify GL library name @<:@default=GL@:>@])],
   [GL_LIB=$withval],
-  [GL_LIB=GL])
+  [GL_LIB="$DEFAULT_GL_LIB_NAME"])
 AC_ARG_WITH([osmesa-lib-name],
   [AS_HELP_STRING([--with-osmesa-lib-name@<:@=NAME@:>@],
     [specify OSMesa library name @<:@default=OSMesa@:>@])],
   [OSMESA_LIB=$withval],
   [OSMESA_LIB=OSMesa])
-AS_IF([test "x$GL_LIB" = xyes], [GL_LIB=GL])
+AS_IF([test "x$GL_LIB" = xyes], [GL_LIB="$DEFAULT_GL_LIB_NAME"])
 AS_IF([test "x$OSMESA_LIB" = xyes], [OSMESA_LIB=OSMesa])
 
 dnl
diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am
index d65fb81..5154a23 100644
--- a/src/glx/Makefile.am
+++ b/src/glx/Makefile.am
@@ -46,7 +46,6 @@ AM_CFLAGS = \
 	$(EXTRA_DEFINES_XF86VIDMODE) \
 	-D_REENTRANT \
 	-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \
-	-DGL_LIB_NAME=\"lib at GL_LIB@.so.1\" \
 	$(DEFINES) \
 	$(LIBDRM_CFLAGS) \
 	$(DRI2PROTO_CFLAGS) \
@@ -146,6 +145,22 @@ SUBDIRS += apple
 libglx_la_LIBADD += $(builddir)/apple/libappleglx.la
 endif
 
+if USE_LIBGLVND_GLX
+AM_CFLAGS += \
+	-DGL_LIB_NAME=\"lib at GL_LIB@.so.0\" \
+	$(GLVND_CFLAGS)
+
+libglx_la_SOURCES += \
+          glxglvnd.c \
+          g_glxglvnddispatchfuncs.c
+
+GL_LIB_VERSION=0
+else
+AM_CFLAGS += \
+	-DGL_LIB_NAME=\"lib at GL_LIB@.so.1\"
+GL_LIB_VERSION=1:2
+endif
+
 GL_LIBS = \
 	libglx.la \
 	$(top_builddir)/src/mapi/glapi/libglapi.la \
@@ -154,7 +169,7 @@ GL_LIBS = \
 
 GL_LDFLAGS = \
 	-no-undefined \
-	-version-number 1:2 \
+	-version-number $(GL_LIB_VERSION) \
 	$(BSYMBOLIC) \
 	$(GC_SECTIONS) \
 	$(LD_NO_UNDEFINED)
diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c
index d087751..d61ffa3 100644
--- a/src/glx/dri_glx.c
+++ b/src/glx/dri_glx.c
@@ -148,7 +148,7 @@ driGetDriverName(Display * dpy, int scrNum, char **driverName)
  * The returned char pointer points to a static array that will be
  * overwritten by subsequent calls.
  */
-_X_EXPORT const char *
+_GLX_PUBLIC const char *
 glXGetScreenDriver(Display * dpy, int scrNum)
 {
    static char ret[32];
@@ -178,7 +178,7 @@ glXGetScreenDriver(Display * dpy, int scrNum)
  *
  * Note: The driver remains opened after this function returns.
  */
-_X_EXPORT const char *
+_GLX_PUBLIC const char *
 glXGetDriverConfig(const char *driverName)
 {
    void *handle = driOpenDriver(driverName);
diff --git a/src/glx/g_glxglvnddispatchfuncs.c b/src/glx/g_glxglvnddispatchfuncs.c
new file mode 100644
index 0000000..13fbc5e
--- /dev/null
+++ b/src/glx/g_glxglvnddispatchfuncs.c
@@ -0,0 +1,976 @@
+/*
+ * THIS FILE IS AUTOMATICALLY GENERATED BY gen_scrn_dispatch.pl
+ * DO NOT EDIT!!
+ */
+#include <stdlib.h>
+
+#include "glxglvnd.h"
+#include "glxglvnddispatchfuncs.h"
+#include "g_glxglvnddispatchindices.h"
+
+const int DI_FUNCTION_COUNT = DI_LAST_INDEX;
+int __glXDispatchTableIndices[DI_LAST_INDEX];
+const __GLXapiExports *__glXGLVNDAPIExports;
+
+const char * const __glXDispatchTableStrings[DI_LAST_INDEX] = {
+#define __ATTRIB(field) \
+    [DI_##field] = "glX"#field
+
+    __ATTRIB(BindTexImageEXT),
+    // glXChooseFBConfig implemented by libglvnd
+    __ATTRIB(ChooseFBConfigSGIX),
+    // glXChooseVisual implemented by libglvnd
+    // glXCopyContext implemented by libglvnd
+    // glXCreateContext implemented by libglvnd
+    __ATTRIB(CreateContextAttribsARB),
+    __ATTRIB(CreateContextWithConfigSGIX),
+    __ATTRIB(CreateGLXPbufferSGIX),
+    // glXCreateGLXPixmap implemented by libglvnd
+    __ATTRIB(CreateGLXPixmapWithConfigSGIX),
+    // glXCreateNewContext implemented by libglvnd
+    // glXCreatePbuffer implemented by libglvnd
+    // glXCreatePixmap implemented by libglvnd
+    // glXCreateWindow implemented by libglvnd
+    // glXDestroyContext implemented by libglvnd
+    __ATTRIB(DestroyGLXPbufferSGIX),
+    // glXDestroyGLXPixmap implemented by libglvnd
+    // glXDestroyPbuffer implemented by libglvnd
+    // glXDestroyPixmap implemented by libglvnd
+    // glXDestroyWindow implemented by libglvnd
+    // glXFreeContextEXT implemented by libglvnd
+    // glXGetClientString implemented by libglvnd
+    // glXGetConfig implemented by libglvnd
+    __ATTRIB(GetContextIDEXT),
+    // glXGetCurrentContext implemented by libglvnd
+    // glXGetCurrentDisplay implemented by libglvnd
+    __ATTRIB(GetCurrentDisplayEXT),
+    // glXGetCurrentDrawable implemented by libglvnd
+    // glXGetCurrentReadDrawable implemented by libglvnd
+    // glXGetFBConfigAttrib implemented by libglvnd
+    __ATTRIB(GetFBConfigAttribSGIX),
+    __ATTRIB(GetFBConfigFromVisualSGIX),
+    // glXGetFBConfigs implemented by libglvnd
+    // glXGetProcAddress implemented by libglvnd
+    // glXGetProcAddressARB implemented by libglvnd
+    // glXGetSelectedEvent implemented by libglvnd
+    __ATTRIB(GetSelectedEventSGIX),
+    __ATTRIB(GetVideoSyncSGI),
+    // glXGetVisualFromFBConfig implemented by libglvnd
+    __ATTRIB(GetVisualFromFBConfigSGIX),
+    // glXImportContextEXT implemented by libglvnd
+    // glXIsDirect implemented by libglvnd
+    // glXMakeContextCurrent implemented by libglvnd
+    // glXMakeCurrent implemented by libglvnd
+    // glXQueryContext implemented by libglvnd
+    __ATTRIB(QueryContextInfoEXT),
+    // glXQueryDrawable implemented by libglvnd
+    // glXQueryExtension implemented by libglvnd
+    // glXQueryExtensionsString implemented by libglvnd
+    __ATTRIB(QueryGLXPbufferSGIX),
+    // glXQueryServerString implemented by libglvnd
+    // glXQueryVersion implemented by libglvnd
+    __ATTRIB(ReleaseTexImageEXT),
+    // glXSelectEvent implemented by libglvnd
+    __ATTRIB(SelectEventSGIX),
+    // glXSwapBuffers implemented by libglvnd
+    __ATTRIB(SwapIntervalSGI),
+    // glXUseXFont implemented by libglvnd
+    // glXWaitGL implemented by libglvnd
+    __ATTRIB(WaitVideoSyncSGI),
+    // glXWaitX implemented by libglvnd
+
+    __ATTRIB(glXBindSwapBarrierSGIX),
+    __ATTRIB(glXCopySubBufferMESA),
+    __ATTRIB(glXCreateGLXPixmapMESA),
+    __ATTRIB(glXGetMscRateOML),
+    __ATTRIB(glXGetScreenDriver),
+    __ATTRIB(glXGetSwapIntervalMESA),
+    __ATTRIB(glXGetSyncValuesOML),
+    __ATTRIB(glXJoinSwapGroupSGIX),
+    __ATTRIB(glXQueryCurrentRendererIntegerMESA),
+    __ATTRIB(glXQueryCurrentRendererStringMESA),
+    __ATTRIB(glXQueryMaxSwapBarriersSGIX),
+    __ATTRIB(glXQueryRendererIntegerMESA),
+    __ATTRIB(glXQueryRendererStringMESA),
+    __ATTRIB(glXReleaseBuffersMESA),
+    __ATTRIB(glXSwapBuffersMscOML),
+    __ATTRIB(glXSwapIntervalMESA),
+    __ATTRIB(glXWaitForMscOML),
+    __ATTRIB(glXWaitForSbcOML),
+
+#undef __ATTRIB
+};
+
+#define __FETCH_FUNCTION_PTR(func_name) \
+    p##func_name = (void *) \
+        __VND->fetchDispatchEntry(dd, __glXDispatchTableIndices[DI_##func_name])
+
+
+static void dispatch_BindTexImageEXT(Display *dpy, GLXDrawable drawable,
+                                     int buffer, const int *attrib_list)
+{
+    PFNGLXBINDTEXIMAGEEXTPROC pBindTexImageEXT;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(BindTexImageEXT);
+    if (pBindTexImageEXT == NULL)
+        return;
+
+    (*pBindTexImageEXT)(dpy, drawable, buffer, attrib_list);
+}
+
+
+
+static GLXFBConfigSGIX *dispatch_ChooseFBConfigSGIX(Display *dpy, int screen,
+                                                    const int *attrib_list,
+                                                    int *nelements)
+{
+    PFNGLXCHOOSEFBCONFIGSGIXPROC pChooseFBConfigSGIX;
+    __GLXvendorInfo *dd;
+    GLXFBConfigSGIX *ret;
+
+    dd = __VND->getDynDispatch(dpy, screen);
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(ChooseFBConfigSGIX);
+    if (pChooseFBConfigSGIX == NULL)
+        return NULL;
+
+    ret = (*pChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements);
+    if (AddFBConfigsMapping(dpy, ret, nelements, dd)) {
+        free(ret);
+        return NULL;
+    }
+
+    return ret;
+}
+
+
+
+static GLXContext dispatch_CreateContextAttribsARB(Display *dpy,
+                                                   GLXFBConfig config,
+                                                   GLXContext share_list,
+                                                   Bool direct,
+                                                   const int *attrib_list)
+{
+    PFNGLXCREATECONTEXTATTRIBSARBPROC pCreateContextAttribsARB;
+    __GLXvendorInfo *dd;
+    GLXContext ret;
+
+    dd = GetDispatchFromFBConfig(dpy, config);
+    if (dd == NULL)
+        return None;
+
+    __FETCH_FUNCTION_PTR(CreateContextAttribsARB);
+    if (pCreateContextAttribsARB == NULL)
+        return None;
+
+    ret = (*pCreateContextAttribsARB)(dpy, config, share_list, direct, attrib_list);
+    if (AddContextMapping(dpy, ret, dd)) {
+        /* XXX: Call glXDestroyContext which lives in libglvnd. If we're not
+         * allowed to call it from here, should we extend __glXDispatchTableIndices ?
+         */
+        return None;
+    }
+
+    return ret;
+}
+
+
+
+static GLXContext dispatch_CreateContextWithConfigSGIX(Display *dpy,
+                                                       GLXFBConfigSGIX config,
+                                                       int render_type,
+                                                       GLXContext share_list,
+                                                       Bool direct)
+{
+    PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC pCreateContextWithConfigSGIX;
+    __GLXvendorInfo *dd;
+    GLXContext ret;
+
+    dd = GetDispatchFromFBConfig(dpy, config);
+    if (dd == NULL)
+        return None;
+
+    __FETCH_FUNCTION_PTR(CreateContextWithConfigSGIX);
+    if (pCreateContextWithConfigSGIX == NULL)
+        return None;
+
+    ret = (*pCreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct);
+    if (AddContextMapping(dpy, ret, dd)) {
+        /* XXX: Call glXDestroyContext which lives in libglvnd. If we're not
+         * allowed to call it from here, should we extend __glXDispatchTableIndices ?
+         */
+        return None;
+    }
+
+    return ret;
+}
+
+
+
+static GLXPbuffer dispatch_CreateGLXPbufferSGIX(Display *dpy,
+                                                GLXFBConfig config,
+                                                unsigned int width,
+                                                unsigned int height,
+                                                const int *attrib_list)
+{
+    PFNGLXCREATEGLXPBUFFERSGIXPROC pCreateGLXPbufferSGIX;
+    __GLXvendorInfo *dd;
+    GLXPbuffer ret;
+
+    dd = GetDispatchFromFBConfig(dpy, config);
+    if (dd == NULL)
+        return None;
+
+    __FETCH_FUNCTION_PTR(CreateGLXPbufferSGIX);
+    if (pCreateGLXPbufferSGIX == NULL)
+        return None;
+
+    ret = (*pCreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list);
+    if (AddDrawableMapping(dpy, ret, dd)) {
+        PFNGLXDESTROYGLXPBUFFERSGIXPROC pDestroyGLXPbufferSGIX;
+
+        __FETCH_FUNCTION_PTR(DestroyGLXPbufferSGIX);
+        if (pDestroyGLXPbufferSGIX)
+            (*pDestroyGLXPbufferSGIX)(dpy, ret);
+
+        return None;
+    }
+
+    return ret;
+}
+
+
+
+static GLXPixmap dispatch_CreateGLXPixmapWithConfigSGIX(Display *dpy,
+                                                        GLXFBConfigSGIX config,
+                                                        Pixmap pixmap)
+{
+    PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC pCreateGLXPixmapWithConfigSGIX;
+    __GLXvendorInfo *dd;
+    GLXPixmap ret;
+
+    dd = GetDispatchFromFBConfig(dpy, config);
+    if (dd == NULL)
+        return None;
+
+    __FETCH_FUNCTION_PTR(CreateGLXPixmapWithConfigSGIX);
+    if (pCreateGLXPixmapWithConfigSGIX == NULL)
+        return None;
+
+    ret = (*pCreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap);
+    if (AddDrawableMapping(dpy, ret, dd)) {
+        /* XXX: Call glXDestroyGLXPixmap which lives in libglvnd. If we're not
+         * allowed to call it from here, should we extend __glXDispatchTableIndices ?
+         */
+        return None;
+    }
+
+    return ret;
+}
+
+
+
+static void dispatch_DestroyGLXPbufferSGIX(Display *dpy, GLXPbuffer pbuf)
+{
+    PFNGLXDESTROYGLXPBUFFERSGIXPROC pDestroyGLXPbufferSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, pbuf);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(DestroyGLXPbufferSGIX);
+    if (pDestroyGLXPbufferSGIX == NULL)
+        return;
+
+    (*pDestroyGLXPbufferSGIX)(dpy, pbuf);
+}
+
+
+
+static GLXContextID dispatch_GetContextIDEXT(const GLXContext ctx)
+{
+    PFNGLXGETCONTEXTIDEXTPROC pGetContextIDEXT;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromContext(ctx);
+    if (dd == NULL)
+        return None;
+
+    __FETCH_FUNCTION_PTR(GetContextIDEXT);
+    if (pGetContextIDEXT == NULL)
+        return None;
+
+    return (*pGetContextIDEXT)(ctx);
+}
+
+
+
+static Display *dispatch_GetCurrentDisplayEXT(void)
+{
+    PFNGLXGETCURRENTDISPLAYEXTPROC pGetCurrentDisplayEXT;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return NULL;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(GetCurrentDisplayEXT);
+    if (pGetCurrentDisplayEXT == NULL)
+        return NULL;
+
+    return (*pGetCurrentDisplayEXT)();
+}
+
+
+
+static int dispatch_GetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,
+                                          int attribute, int *value_return)
+{
+    PFNGLXGETFBCONFIGATTRIBSGIXPROC pGetFBConfigAttribSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromFBConfig(dpy, config);
+    if (dd == NULL)
+        return GLX_NO_EXTENSION;
+
+    __FETCH_FUNCTION_PTR(GetFBConfigAttribSGIX);
+    if (pGetFBConfigAttribSGIX == NULL)
+        return GLX_NO_EXTENSION;
+
+    return (*pGetFBConfigAttribSGIX)(dpy, config, attribute, value_return);
+}
+
+
+
+static GLXFBConfigSGIX dispatch_GetFBConfigFromVisualSGIX(Display *dpy,
+                                                          XVisualInfo *vis)
+{
+    PFNGLXGETFBCONFIGFROMVISUALSGIXPROC pGetFBConfigFromVisualSGIX;
+    __GLXvendorInfo *dd;
+    GLXFBConfigSGIX ret = NULL;
+
+    dd = GetDispatchFromVisual(dpy, vis);
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(GetFBConfigFromVisualSGIX);
+    if (pGetFBConfigFromVisualSGIX == NULL)
+        return NULL;
+
+    ret = (*pGetFBConfigFromVisualSGIX)(dpy, vis);
+    if (AddFBConfigMapping(dpy, ret, dd))
+        /* XXX: dealloc ret ? */
+        return NULL;
+
+    return ret;
+}
+
+
+
+static void dispatch_GetSelectedEventSGIX(Display *dpy, GLXDrawable drawable,
+                                          unsigned long *mask)
+{
+    PFNGLXGETSELECTEDEVENTSGIXPROC pGetSelectedEventSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(GetSelectedEventSGIX);
+    if (pGetSelectedEventSGIX == NULL)
+        return;
+
+    (*pGetSelectedEventSGIX)(dpy, drawable, mask);
+}
+
+
+
+static int dispatch_GetVideoSyncSGI(unsigned int *count)
+{
+    PFNGLXGETVIDEOSYNCSGIPROC pGetVideoSyncSGI;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return GLX_BAD_CONTEXT;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return GLX_NO_EXTENSION;
+
+    __FETCH_FUNCTION_PTR(GetVideoSyncSGI);
+    if (pGetVideoSyncSGI == NULL)
+        return GLX_NO_EXTENSION;
+
+    return (*pGetVideoSyncSGI)(count);
+}
+
+
+
+static XVisualInfo *dispatch_GetVisualFromFBConfigSGIX(Display *dpy,
+                                                       GLXFBConfigSGIX config)
+{
+    PFNGLXGETVISUALFROMFBCONFIGSGIXPROC pGetVisualFromFBConfigSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromFBConfig(dpy, config);
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(GetVisualFromFBConfigSGIX);
+    if (pGetVisualFromFBConfigSGIX == NULL)
+        return NULL;
+
+    return (*pGetVisualFromFBConfigSGIX)(dpy, config);
+}
+
+
+
+static int dispatch_QueryContextInfoEXT(Display *dpy, GLXContext ctx,
+                                        int attribute, int *value)
+{
+    PFNGLXQUERYCONTEXTINFOEXTPROC pQueryContextInfoEXT;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromContext(ctx);
+    if (dd == NULL)
+        return GLX_NO_EXTENSION;
+
+    __FETCH_FUNCTION_PTR(QueryContextInfoEXT);
+    if (pQueryContextInfoEXT == NULL)
+        return GLX_NO_EXTENSION;
+
+    return (*pQueryContextInfoEXT)(dpy, ctx, attribute, value);
+}
+
+
+
+static void dispatch_QueryGLXPbufferSGIX(Display *dpy, GLXPbuffer pbuf,
+                                         int attribute, unsigned int *value)
+{
+    PFNGLXQUERYGLXPBUFFERSGIXPROC pQueryGLXPbufferSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, pbuf);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(QueryGLXPbufferSGIX);
+    if (pQueryGLXPbufferSGIX == NULL)
+        return;
+
+    (*pQueryGLXPbufferSGIX)(dpy, pbuf, attribute, value);
+}
+
+
+
+static void dispatch_ReleaseTexImageEXT(Display *dpy, GLXDrawable drawable,
+                                        int buffer)
+{
+    PFNGLXRELEASETEXIMAGEEXTPROC pReleaseTexImageEXT;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(ReleaseTexImageEXT);
+    if (pReleaseTexImageEXT == NULL)
+        return;
+
+    (*pReleaseTexImageEXT)(dpy, drawable, buffer);
+}
+
+
+
+static void dispatch_SelectEventSGIX(Display *dpy, GLXDrawable drawable,
+                                     unsigned long mask)
+{
+    PFNGLXSELECTEVENTSGIXPROC pSelectEventSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(SelectEventSGIX);
+    if (pSelectEventSGIX == NULL)
+        return;
+
+    (*pSelectEventSGIX)(dpy, drawable, mask);
+}
+
+
+
+static int dispatch_SwapIntervalSGI(int interval)
+{
+    PFNGLXSWAPINTERVALSGIPROC pSwapIntervalSGI;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return GLX_BAD_CONTEXT;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return GLX_NO_EXTENSION;
+
+    __FETCH_FUNCTION_PTR(SwapIntervalSGI);
+    if (pSwapIntervalSGI == NULL)
+        return GLX_NO_EXTENSION;
+
+    return (*pSwapIntervalSGI)(interval);
+}
+
+
+
+static int dispatch_WaitVideoSyncSGI(int divisor, int remainder,
+                                     unsigned int *count)
+{
+    PFNGLXWAITVIDEOSYNCSGIPROC pWaitVideoSyncSGI;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return GLX_BAD_CONTEXT;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return GLX_NO_EXTENSION;
+
+    __FETCH_FUNCTION_PTR(WaitVideoSyncSGI);
+    if (pWaitVideoSyncSGI == NULL)
+        return GLX_NO_EXTENSION;
+
+    return (*pWaitVideoSyncSGI)(divisor, remainder, count);
+}
+
+
+
+static void dispatch_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable,
+                                            int barrier)
+{
+    PFNGLXBINDSWAPBARRIERSGIXPROC pglXBindSwapBarrierSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(glXBindSwapBarrierSGIX);
+    if (pglXBindSwapBarrierSGIX == NULL)
+        return;
+
+    (*pglXBindSwapBarrierSGIX)(dpy, drawable, barrier);
+}
+
+
+
+static void dispatch_glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
+                                          int x, int y, int width, int height)
+{
+    PFNGLXCOPYSUBBUFFERMESAPROC pglXCopySubBufferMESA;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(glXCopySubBufferMESA);
+    if (pglXCopySubBufferMESA == NULL)
+        return;
+
+    (*pglXCopySubBufferMESA)(dpy, drawable, x, y, width, height);
+}
+
+
+
+static GLXPixmap dispatch_glXCreateGLXPixmapMESA(Display *dpy,
+                                                 XVisualInfo *visinfo,
+                                                 Pixmap pixmap, Colormap cmap)
+{
+    PFNGLXCREATEGLXPIXMAPMESAPROC pglXCreateGLXPixmapMESA;
+    __GLXvendorInfo *dd;
+    GLXPixmap ret;
+
+    dd = GetDispatchFromVisual(dpy, visinfo);
+    if (dd == NULL)
+        return None;
+
+    __FETCH_FUNCTION_PTR(glXCreateGLXPixmapMESA);
+    if (pglXCreateGLXPixmapMESA == NULL)
+        return None;
+
+    ret = (*pglXCreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap);
+    if (AddDrawableMapping(dpy, ret, dd)) {
+        /* XXX: Call glXDestroyGLXPixmap which lives in libglvnd. If we're not
+         * allowed to call it from here, should we extend __glXDispatchTableIndices ?
+         */
+        return None;
+    }
+
+    return ret;
+}
+
+
+
+static GLboolean dispatch_glXGetMscRateOML(Display *dpy, GLXDrawable drawable,
+                                           int32_t *numerator, int32_t *denominator)
+{
+    PFNGLXGETMSCRATEOMLPROC pglXGetMscRateOML;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return GL_FALSE;
+
+    __FETCH_FUNCTION_PTR(glXGetMscRateOML);
+    if (pglXGetMscRateOML == NULL)
+        return GL_FALSE;
+
+    return (*pglXGetMscRateOML)(dpy, drawable, numerator, denominator);
+}
+
+
+
+static const char *dispatch_glXGetScreenDriver(Display *dpy, int scrNum)
+{
+    typedef const char *(*fn_glXGetScreenDriver_ptr)(Display *dpy, int scrNum);
+    fn_glXGetScreenDriver_ptr pglXGetScreenDriver;
+    __GLXvendorInfo *dd;
+
+    dd = __VND->getDynDispatch(dpy, scrNum);
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(glXGetScreenDriver);
+    if (pglXGetScreenDriver == NULL)
+        return NULL;
+
+    return (*pglXGetScreenDriver)(dpy, scrNum);
+}
+
+
+
+static int dispatch_glXGetSwapIntervalMESA(void)
+{
+    PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return GLX_BAD_CONTEXT;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return 0;
+
+    __FETCH_FUNCTION_PTR(glXGetSwapIntervalMESA);
+    if (pglXGetSwapIntervalMESA == NULL)
+        return 0;
+
+    return (*pglXGetSwapIntervalMESA)();
+}
+
+
+
+static Bool dispatch_glXGetSyncValuesOML(Display *dpy, GLXDrawable drawable,
+                                         int64_t *ust, int64_t *msc, int64_t *sbc)
+{
+    PFNGLXGETSYNCVALUESOMLPROC pglXGetSyncValuesOML;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXGetSyncValuesOML);
+    if (pglXGetSyncValuesOML == NULL)
+        return False;
+
+    return (*pglXGetSyncValuesOML)(dpy, drawable, ust, msc, sbc);
+}
+
+
+
+static void dispatch_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable,
+                                          GLXDrawable member)
+{
+    PFNGLXJOINSWAPGROUPSGIXPROC pglXJoinSwapGroupSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return;
+
+    __FETCH_FUNCTION_PTR(glXJoinSwapGroupSGIX);
+    if (pglXJoinSwapGroupSGIX == NULL)
+        return;
+
+    (*pglXJoinSwapGroupSGIX)(dpy, drawable, member);
+}
+
+
+
+static Bool dispatch_glXQueryCurrentRendererIntegerMESA(int attribute,
+                                                        unsigned int *value)
+{
+    PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC pglXQueryCurrentRendererIntegerMESA;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return False;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXQueryCurrentRendererIntegerMESA);
+    if (pglXQueryCurrentRendererIntegerMESA == NULL)
+        return False;
+
+    return (*pglXQueryCurrentRendererIntegerMESA)(attribute, value);
+}
+
+
+
+static const char *dispatch_glXQueryCurrentRendererStringMESA(int attribute)
+{
+    PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC pglXQueryCurrentRendererStringMESA;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return NULL;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(glXQueryCurrentRendererStringMESA);
+    if (pglXQueryCurrentRendererStringMESA == NULL)
+        return NULL;
+
+    return (*pglXQueryCurrentRendererStringMESA)(attribute);
+}
+
+
+
+static Bool dispatch_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen,
+                                                 int *max)
+{
+    PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC pglXQueryMaxSwapBarriersSGIX;
+    __GLXvendorInfo *dd;
+
+    dd = __VND->getDynDispatch(dpy, screen);
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXQueryMaxSwapBarriersSGIX);
+    if (pglXQueryMaxSwapBarriersSGIX == NULL)
+        return False;
+
+    return (*pglXQueryMaxSwapBarriersSGIX)(dpy, screen, max);
+}
+
+
+
+static Bool dispatch_glXQueryRendererIntegerMESA(Display *dpy, int screen,
+                                                 int renderer, int attribute,
+                                                 unsigned int *value)
+{
+    PFNGLXQUERYRENDERERINTEGERMESAPROC pglXQueryRendererIntegerMESA;
+    __GLXvendorInfo *dd;
+
+    dd = __VND->getDynDispatch(dpy, screen);
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXQueryRendererIntegerMESA);
+    if (pglXQueryRendererIntegerMESA == NULL)
+        return False;
+
+    return (*pglXQueryRendererIntegerMESA)(dpy, screen, renderer, attribute, value);
+}
+
+
+
+static const char *dispatch_glXQueryRendererStringMESA(Display *dpy, int screen,
+                                                       int renderer, int attribute)
+{
+    PFNGLXQUERYRENDERERSTRINGMESAPROC pglXQueryRendererStringMESA;
+    __GLXvendorInfo *dd = NULL;
+
+    dd = __VND->getDynDispatch(dpy, screen);
+    if (dd == NULL)
+        return NULL;
+
+    __FETCH_FUNCTION_PTR(glXQueryRendererStringMESA);
+    if (pglXQueryRendererStringMESA == NULL)
+        return NULL;
+
+    return (*pglXQueryRendererStringMESA)(dpy, screen, renderer, attribute);
+}
+
+
+
+static Bool dispatch_glXReleaseBuffersMESA(Display *dpy, GLXDrawable d)
+{
+    PFNGLXRELEASEBUFFERSMESAPROC pglXReleaseBuffersMESA;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, d);
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXReleaseBuffersMESA);
+    if (pglXReleaseBuffersMESA == NULL)
+        return False;
+
+    return (*pglXReleaseBuffersMESA)(dpy, d);
+}
+
+
+
+static int64_t dispatch_glXSwapBuffersMscOML(Display *dpy, GLXDrawable drawable,
+                                             int64_t target_msc, int64_t divisor,
+                                             int64_t remainder)
+{
+    PFNGLXSWAPBUFFERSMSCOMLPROC pglXSwapBuffersMscOML;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return 0;
+
+    __FETCH_FUNCTION_PTR(glXSwapBuffersMscOML);
+    if (pglXSwapBuffersMscOML == NULL)
+        return 0;
+
+    return (*pglXSwapBuffersMscOML)(dpy, drawable, target_msc, divisor, remainder);
+}
+
+
+
+static int dispatch_glXSwapIntervalMESA(unsigned int interval)
+{
+    PFNGLXSWAPINTERVALMESAPROC pglXSwapIntervalMESA;
+    __GLXvendorInfo *dd;
+
+    if (!__VND->getCurrentContext())
+        return GLX_BAD_CONTEXT;
+
+    dd = __VND->getCurrentDynDispatch();
+    if (dd == NULL)
+        return 0;
+
+    __FETCH_FUNCTION_PTR(glXSwapIntervalMESA);
+    if (pglXSwapIntervalMESA == NULL)
+        return 0;
+
+    return (*pglXSwapIntervalMESA)(interval);
+}
+
+
+
+static Bool dispatch_glXWaitForMscOML(Display *dpy, GLXDrawable drawable,
+                                      int64_t target_msc, int64_t divisor,
+                                      int64_t remainder, int64_t *ust,
+                                      int64_t *msc, int64_t *sbc)
+{
+    PFNGLXWAITFORMSCOMLPROC pglXWaitForMscOML;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXWaitForMscOML);
+    if (pglXWaitForMscOML == NULL)
+        return False;
+
+    return (*pglXWaitForMscOML)(dpy, drawable, target_msc, divisor, remainder, ust, msc, sbc);
+}
+
+
+
+static Bool dispatch_glXWaitForSbcOML(Display *dpy, GLXDrawable drawable,
+                                      int64_t target_sbc, int64_t *ust,
+                                      int64_t *msc, int64_t *sbc)
+{
+    PFNGLXWAITFORSBCOMLPROC pglXWaitForSbcOML;
+    __GLXvendorInfo *dd;
+
+    dd = GetDispatchFromDrawable(dpy, drawable);
+    if (dd == NULL)
+        return False;
+
+    __FETCH_FUNCTION_PTR(glXWaitForSbcOML);
+    if (pglXWaitForSbcOML == NULL)
+        return False;
+
+    return (*pglXWaitForSbcOML)(dpy, drawable, target_sbc, ust, msc, sbc);
+}
+
+#undef __FETCH_FUNCTION_PTR
+
+
+const void * const __glXDispatchFunctions[DI_LAST_INDEX] = {
+#define __ATTRIB(field) \
+    [DI_##field] = (void *)dispatch_##field
+
+    __ATTRIB(BindTexImageEXT),
+    __ATTRIB(BindTexImageEXT),
+    __ATTRIB(ChooseFBConfigSGIX),
+    __ATTRIB(CreateContextAttribsARB),
+    __ATTRIB(CreateContextWithConfigSGIX),
+    __ATTRIB(CreateGLXPbufferSGIX),
+    __ATTRIB(CreateGLXPixmapWithConfigSGIX),
+    __ATTRIB(DestroyGLXPbufferSGIX),
+    __ATTRIB(GetContextIDEXT),
+    __ATTRIB(GetCurrentDisplayEXT),
+    __ATTRIB(GetFBConfigAttribSGIX),
+    __ATTRIB(GetFBConfigFromVisualSGIX),
+    __ATTRIB(GetSelectedEventSGIX),
+#if defined(GLX_SGI_video_sync)
+    __ATTRIB(GetVideoSyncSGI),
+#endif // defined(GLX_SGI_video_sync)
+    __ATTRIB(GetVisualFromFBConfigSGIX),
+    __ATTRIB(QueryContextInfoEXT),
+    __ATTRIB(QueryGLXPbufferSGIX),
+    __ATTRIB(ReleaseTexImageEXT),
+    __ATTRIB(SelectEventSGIX),
+#if defined(GLX_SGI_swap_control)
+    __ATTRIB(SwapIntervalSGI),
+#endif // defined(GLX_SGI_swap_control)
+#if defined(GLX_SGI_video_sync)
+    __ATTRIB(WaitVideoSyncSGI),
+#endif // defined(GLX_SGI_video_sync)
+    __ATTRIB(glXBindSwapBarrierSGIX),
+    __ATTRIB(glXCopySubBufferMESA),
+    __ATTRIB(glXCreateGLXPixmapMESA),
+    __ATTRIB(glXGetMscRateOML),
+    __ATTRIB(glXGetScreenDriver),
+    __ATTRIB(glXGetSwapIntervalMESA),
+    __ATTRIB(glXGetSyncValuesOML),
+    __ATTRIB(glXJoinSwapGroupSGIX),
+    __ATTRIB(glXQueryCurrentRendererIntegerMESA),
+    __ATTRIB(glXQueryCurrentRendererStringMESA),
+    __ATTRIB(glXQueryMaxSwapBarriersSGIX),
+    __ATTRIB(glXQueryRendererIntegerMESA),
+    __ATTRIB(glXQueryRendererStringMESA),
+    __ATTRIB(glXReleaseBuffersMESA),
+    __ATTRIB(glXSwapBuffersMscOML),
+    __ATTRIB(glXSwapIntervalMESA),
+    __ATTRIB(glXWaitForMscOML),
+    __ATTRIB(glXWaitForSbcOML),
+
+#undef __ATTRIB
+};
diff --git a/src/glx/g_glxglvnddispatchindices.h b/src/glx/g_glxglvnddispatchindices.h
new file mode 100644
index 0000000..fd2156e
--- /dev/null
+++ b/src/glx/g_glxglvnddispatchindices.h
@@ -0,0 +1,92 @@
+/*
+ * THIS FILE IS AUTOMATICALLY GENERATED BY gen_scrn_dispatch.pl
+ * DO NOT EDIT!!
+ */
+#ifndef __glxlibglvnd_dispatchindex_h__
+#define __glxlibglvnd_dispatchindex_h__
+
+typedef enum __GLXdispatchIndex {
+    DI_BindTexImageEXT,
+    // ChooseFBConfig implemented by libglvnd
+    DI_ChooseFBConfigSGIX,
+    // ChooseVisual implemented by libglvnd
+    // CopyContext implemented by libglvnd
+    // CreateContext implemented by libglvnd
+    DI_CreateContextAttribsARB,
+    DI_CreateContextWithConfigSGIX,
+    DI_CreateGLXPbufferSGIX,
+    // CreateGLXPixmap implemented by libglvnd
+    DI_CreateGLXPixmapWithConfigSGIX,
+    // CreateNewContext implemented by libglvnd
+    // CreatePbuffer implemented by libglvnd
+    // CreatePixmap implemented by libglvnd
+    // CreateWindow implemented by libglvnd
+    // DestroyContext implemented by libglvnd
+    DI_DestroyGLXPbufferSGIX,
+    // DestroyGLXPixmap implemented by libglvnd
+    // DestroyPbuffer implemented by libglvnd
+    // DestroyPixmap implemented by libglvnd
+    // DestroyWindow implemented by libglvnd
+    // FreeContextEXT implemented by libglvnd
+    // GetClientString implemented by libglvnd
+    // GetConfig implemented by libglvnd
+    DI_GetContextIDEXT,
+    // GetCurrentContext implemented by libglvnd
+    // GetCurrentDisplay implemented by libglvnd
+    DI_GetCurrentDisplayEXT,
+    // GetCurrentDrawable implemented by libglvnd
+    // GetCurrentReadDrawable implemented by libglvnd
+    // GetFBConfigAttrib implemented by libglvnd
+    DI_GetFBConfigAttribSGIX,
+    DI_GetFBConfigFromVisualSGIX,
+    // GetFBConfigs implemented by libglvnd
+    // GetProcAddress implemented by libglvnd
+    // GetProcAddressARB implemented by libglvnd
+    // GetSelectedEvent implemented by libglvnd
+    DI_GetSelectedEventSGIX,
+    DI_GetVideoSyncSGI,
+    // GetVisualFromFBConfig implemented by libglvnd
+    DI_GetVisualFromFBConfigSGIX,
+    // ImportContextEXT implemented by libglvnd
+    // IsDirect implemented by libglvnd
+    // MakeContextCurrent implemented by libglvnd
+    // MakeCurrent implemented by libglvnd
+    // QueryContext implemented by libglvnd
+    DI_QueryContextInfoEXT,
+    // QueryDrawable implemented by libglvnd
+    // QueryExtension implemented by libglvnd
+    // QueryExtensionsString implemented by libglvnd
+    DI_QueryGLXPbufferSGIX,
+    // QueryServerString implemented by libglvnd
+    // QueryVersion implemented by libglvnd
+    DI_ReleaseTexImageEXT,
+    // SelectEvent implemented by libglvnd
+    DI_SelectEventSGIX,
+    // SwapBuffers implemented by libglvnd
+    DI_SwapIntervalSGI,
+    // UseXFont implemented by libglvnd
+    // WaitGL implemented by libglvnd
+    DI_WaitVideoSyncSGI,
+    // WaitX implemented by libglvnd
+    DI_glXBindSwapBarrierSGIX,
+    DI_glXCopySubBufferMESA,
+    DI_glXCreateGLXPixmapMESA,
+    DI_glXGetMscRateOML,
+    DI_glXGetScreenDriver,
+    DI_glXGetSwapIntervalMESA,
+    DI_glXGetSyncValuesOML,
+    DI_glXJoinSwapGroupSGIX,
+    DI_glXQueryCurrentRendererIntegerMESA,
+    DI_glXQueryCurrentRendererStringMESA,
+    DI_glXQueryMaxSwapBarriersSGIX,
+    DI_glXQueryRendererIntegerMESA,
+    DI_glXQueryRendererStringMESA,
+    DI_glXReleaseBuffersMESA,
+    DI_glXSwapBuffersMscOML,
+    DI_glXSwapIntervalMESA,
+    DI_glXWaitForMscOML,
+    DI_glXWaitForSbcOML,
+    DI_LAST_INDEX
+} __GLXdispatchIndex;
+
+#endif // __glxlibglvnd_dispatchindex_h__
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c
index 231ab20..a0c1e3d 100644
--- a/src/glx/glx_pbuffer.c
+++ b/src/glx/glx_pbuffer.c
@@ -679,7 +679,7 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable)
 /**
  * Create a new pbuffer.
  */
-_X_EXPORT GLXPbufferSGIX
+_GLX_PUBLIC GLXPbufferSGIX
 glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
                         unsigned int width, unsigned int height,
                         int *attrib_list)
@@ -694,7 +694,7 @@ glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
 /**
  * Create a new pbuffer.
  */
-_X_EXPORT GLXPbuffer
+_GLX_PUBLIC GLXPbuffer
 glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
 {
    int i, width, height;
@@ -769,7 +769,7 @@ glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
 /**
  * Destroy an existing pbuffer.
  */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
 {
 #ifdef GLX_USE_APPLEGL
@@ -785,7 +785,7 @@ glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
 /**
  * Query an attribute of a drawable.
  */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXQueryDrawable(Display * dpy, GLXDrawable drawable,
                  int attribute, unsigned int *value)
 {
@@ -834,7 +834,7 @@ glXQueryDrawable(Display * dpy, GLXDrawable drawable,
 /**
  * Query an attribute of a pbuffer.
  */
-_X_EXPORT int
+_GLX_PUBLIC int
 glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
                        int attribute, unsigned int *value)
 {
@@ -845,7 +845,7 @@ glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
 /**
  * Select the event mask for a drawable.
  */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
 {
 #ifdef GLX_USE_APPLEGL
@@ -878,7 +878,7 @@ glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
 /**
  * Get the selected event mask for a drawable.
  */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
 {
 #ifdef GLX_USE_APPLEGL
@@ -915,7 +915,7 @@ glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
 }
 
 
-_X_EXPORT GLXPixmap
+_GLX_PUBLIC GLXPixmap
 glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
                 const int *attrib_list)
 {
@@ -935,7 +935,7 @@ glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
 }
 
 
-_X_EXPORT GLXWindow
+_GLX_PUBLIC GLXWindow
 glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
                 const int *attrib_list)
 {
@@ -970,7 +970,7 @@ glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
 }
 
 
-_X_EXPORT void
+_GLX_PUBLIC void
 glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
 {
    WARN_ONCE_GLX_1_3(dpy, __func__);
@@ -983,7 +983,7 @@ glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
 }
 
 
-_X_EXPORT void
+_GLX_PUBLIC void
 glXDestroyWindow(Display * dpy, GLXWindow win)
 {
    WARN_ONCE_GLX_1_3(dpy, __func__);
@@ -993,17 +993,17 @@ glXDestroyWindow(Display * dpy, GLXWindow win)
 }
 
 #ifndef GLX_USE_APPLEGL
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
                (Display * dpy, GLXPbufferSGIX pbuf),
                (dpy, pbuf), glXDestroyPbuffer)
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS_VOID(glXSelectEventSGIX,
                (Display * dpy, GLXDrawable drawable,
                 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
                (Display * dpy, GLXDrawable drawable,
                 unsigned long *mask), (dpy, drawable, mask),
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index 141e46a..aa795a7 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -56,6 +56,11 @@
 
 #include "glxextensions.h"
 
+#if defined(USE_LIBGLVND_GLX)
+#define _GLX_PUBLIC _X_HIDDEN
+#else
+#define _GLX_PUBLIC _X_EXPORT
+#endif
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c
index 63f4921..a67f7a8 100644
--- a/src/glx/glxcmds.c
+++ b/src/glx/glxcmds.c
@@ -374,7 +374,7 @@ CreateContext(Display *dpy, int generic_id, struct glx_config *config,
    return (GLXContext) gc;
 }
 
-_X_EXPORT GLXContext
+_GLX_PUBLIC GLXContext
 glXCreateContext(Display * dpy, XVisualInfo * vis,
                  GLXContext shareList, Bool allowDirect)
 {
@@ -451,7 +451,7 @@ glx_send_destroy_context(Display *dpy, XID xid)
 ** Destroy the named context
 */
 
-_X_EXPORT void
+_GLX_PUBLIC void
 glXDestroyContext(Display * dpy, GLXContext ctx)
 {
    struct glx_context *gc = (struct glx_context *) ctx;
@@ -479,7 +479,7 @@ glXDestroyContext(Display * dpy, GLXContext ctx)
 /*
 ** Return the major and minor version #s for the GLX extension
 */
-_X_EXPORT Bool
+_GLX_PUBLIC Bool
 glXQueryVersion(Display * dpy, int *major, int *minor)
 {
    struct glx_display *priv;
@@ -499,7 +499,7 @@ glXQueryVersion(Display * dpy, int *major, int *minor)
 /*
 ** Query the existence of the GLX extension
 */
-_X_EXPORT Bool
+_GLX_PUBLIC Bool
 glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
 {
    int major_op, erb, evb;
@@ -519,7 +519,7 @@ glXQueryExtension(Display * dpy, int *errorBase, int *eventBase)
 ** Put a barrier in the token stream that forces the GL to finish its
 ** work before X can proceed.
 */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXWaitGL(void)
 {
    struct glx_context *gc = __glXGetCurrentContext();
@@ -532,7 +532,7 @@ glXWaitGL(void)
 ** Put a barrier in the token stream that forces X to finish its
 ** work before GL can proceed.
 */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXWaitX(void)
 {
    struct glx_context *gc = __glXGetCurrentContext();
@@ -541,7 +541,7 @@ glXWaitX(void)
       gc->vtable->wait_x(gc);
 }
 
-_X_EXPORT void
+_GLX_PUBLIC void
 glXUseXFont(Font font, int first, int count, int listBase)
 {
    struct glx_context *gc = __glXGetCurrentContext();
@@ -556,7 +556,7 @@ glXUseXFont(Font font, int first, int count, int listBase)
 ** Copy the source context to the destination context using the
 ** attribute "mask".
 */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXCopyContext(Display * dpy, GLXContext source_user,
 	       GLXContext dest_user, unsigned long mask)
 {
@@ -657,7 +657,7 @@ __glXIsDirect(Display * dpy, GLXContextID contextID)
  * \c GLX_DIRECT_RENDERING is not defined?  Do we really need to bother with
  * the GLX protocol here at all?
  */
-_X_EXPORT Bool
+_GLX_PUBLIC Bool
 glXIsDirect(Display * dpy, GLXContext gc_user)
 {
    struct glx_context *gc = (struct glx_context *) gc_user;
@@ -675,7 +675,7 @@ glXIsDirect(Display * dpy, GLXContext gc_user)
 #endif
 }
 
-_X_EXPORT GLXPixmap
+_GLX_PUBLIC GLXPixmap
 glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
 {
 #ifdef GLX_USE_APPLEGL
@@ -775,7 +775,7 @@ glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap)
 /*
 ** Destroy the named pixmap
 */
-_X_EXPORT void
+_GLX_PUBLIC void
 glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
 {
 #ifdef GLX_USE_APPLEGL
@@ -815,7 +815,7 @@ glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap)
 #endif /* GLX_USE_APPLEGL */
 }
 
-_X_EXPORT void
+_GLX_PUBLIC void
 glXSwapBuffers(Display * dpy, GLXDrawable drawable)
 {
 #ifdef GLX_USE_APPLEGL
@@ -875,7 +875,7 @@ glXSwapBuffers(Display * dpy, GLXDrawable drawable)
 ** Return configuration information for the given display, screen and
 ** visual combination.
 */
-_X_EXPORT int
+_GLX_PUBLIC int
 glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute,
              int *value_return)
 {
@@ -1234,7 +1234,7 @@ choose_visual(struct glx_config ** configs, int num_configs,
 ** Return the visual that best matches the template.  Return None if no
 ** visual matches the template.
 */
-_X_EXPORT XVisualInfo *
+_GLX_PUBLIC XVisualInfo *
 glXChooseVisual(Display * dpy, int screen, int *attribList)
 {
    XVisualInfo *visualList = NULL;
@@ -1300,7 +1300,7 @@ glXChooseVisual(Display * dpy, int screen, int *attribList)
 }
 
 
-_X_EXPORT const char *
+_GLX_PUBLIC const char *
 glXQueryExtensionsString(Display * dpy, int screen)
 {
    struct glx_screen *psc;
@@ -1329,7 +1329,7 @@ glXQueryExtensionsString(Display * dpy, int screen)
    return psc->effectiveGLXexts;
 }
 
-_X_EXPORT const char *
+_GLX_PUBLIC const char *
 glXGetClientString(Display * dpy, int name)
 {
    (void) dpy;
@@ -1346,7 +1346,7 @@ glXGetClientString(Display * dpy, int name)
    }
 }
 
-_X_EXPORT const char *
+_GLX_PUBLIC const char *
 glXQueryServerString(Display * dpy, int screen, int name)
 {
    struct glx_screen *psc;
@@ -1384,7 +1384,7 @@ glXQueryServerString(Display * dpy, int screen, int name)
 ** EXT_import_context
 */
 
-_X_EXPORT Display *
+_GLX_PUBLIC Display *
 glXGetCurrentDisplay(void)
 {
    struct glx_context *gc = __glXGetCurrentContext();
@@ -1393,12 +1393,12 @@ glXGetCurrentDisplay(void)
    return gc->currentDpy;
 }
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (),
           glXGetCurrentDisplay)
 
 #ifndef GLX_USE_APPLEGL
-_X_EXPORT GLXContext
+_GLX_PUBLIC GLXContext
 glXImportContextEXT(Display *dpy, GLXContextID contextID)
 {
    struct glx_display *priv = __glXInitialize(dpy);
@@ -1537,7 +1537,7 @@ glXImportContextEXT(Display *dpy, GLXContextID contextID)
 
 #endif
 
-_X_EXPORT int
+_GLX_PUBLIC int
 glXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value)
 {
    struct glx_context *ctx = (struct glx_context *) ctx_user;
@@ -1564,19 +1564,19 @@ glXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value)
    return Success;
 }
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS(int, glXQueryContextInfoEXT,
           (Display * dpy, GLXContext ctx, int attribute, int *value),
           (dpy, ctx, attribute, value), glXQueryContext)
 
-_X_EXPORT GLXContextID glXGetContextIDEXT(const GLXContext ctx_user)
+_GLX_PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx_user)
 {
    struct glx_context *ctx = (struct glx_context *) ctx_user;
 
    return (ctx == NULL) ? None : ctx->xid;
 }
 
-_X_EXPORT void
+_GLX_PUBLIC void
 glXFreeContextEXT(Display *dpy, GLXContext ctx)
 {
    struct glx_context *gc = (struct glx_context *) ctx;
@@ -1601,7 +1601,7 @@ glXFreeContextEXT(Display *dpy, GLXContext ctx)
    __glXUnlock();
 }
 
-_X_EXPORT GLXFBConfig *
+_GLX_PUBLIC GLXFBConfig *
 glXChooseFBConfig(Display * dpy, int screen,
                   const int *attribList, int *nitems)
 {
@@ -1625,7 +1625,7 @@ glXChooseFBConfig(Display * dpy, int screen,
 }
 
 
-_X_EXPORT GLXContext
+_GLX_PUBLIC GLXContext
 glXCreateNewContext(Display * dpy, GLXFBConfig fbconfig,
                     int renderType, GLXContext shareList, Bool allowDirect)
 {
@@ -1637,7 +1637,7 @@ glXCreateNewContext(Display * dpy, GLXFBConfig fbconfig,
 }
 
 
-_X_EXPORT GLXDrawable
+_GLX_PUBLIC GLXDrawable
 glXGetCurrentReadDrawable(void)
 {
    struct glx_context *gc = __glXGetCurrentContext();
@@ -1646,7 +1646,7 @@ glXGetCurrentReadDrawable(void)
 }
 
 
-_X_EXPORT GLXFBConfig *
+_GLX_PUBLIC GLXFBConfig *
 glXGetFBConfigs(Display * dpy, int screen, int *nelements)
 {
    struct glx_display *priv = __glXInitialize(dpy);
@@ -1687,7 +1687,7 @@ glXGetFBConfigs(Display * dpy, int screen, int *nelements)
 }
 
 
-_X_EXPORT int
+_GLX_PUBLIC int
 glXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig,
                      int attribute, int *value)
 {
@@ -1700,7 +1700,7 @@ glXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig,
 }
 
 
-_X_EXPORT XVisualInfo *
+_GLX_PUBLIC XVisualInfo *
 glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig)
 {
    XVisualInfo visualTemplate;
@@ -1909,21 +1909,21 @@ __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
 ** GLX_functions table.
 */
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS(int, glXGetFBConfigAttribSGIX,
           (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value),
           (dpy, config, attribute, value), glXGetFBConfigAttrib)
 
-_X_EXPORT GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
+_GLX_PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX,
                  (Display * dpy, int screen, int *attrib_list,
                   int *nelements), (dpy, screen, attrib_list, nelements),
                  glXChooseFBConfig)
 
-_X_EXPORT GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
+_GLX_PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX,
                  (Display * dpy, GLXFBConfigSGIX config),
                  (dpy, config), glXGetVisualFromFBConfig)
 
-_X_EXPORT GLXPixmap
+_GLX_PUBLIC GLXPixmap
 glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
                                  GLXFBConfigSGIX fbconfig,
                                  Pixmap pixmap)
@@ -1976,7 +1976,7 @@ glXCreateGLXPixmapWithConfigSGIX(Display * dpy,
 #endif
 }
 
-_X_EXPORT GLXContext
+_GLX_PUBLIC GLXContext
 glXCreateContextWithConfigSGIX(Display * dpy,
                                GLXFBConfigSGIX fbconfig, int renderType,
                                GLXContext shareList, Bool allowDirect)
@@ -2003,7 +2003,7 @@ glXCreateContextWithConfigSGIX(Display * dpy,
 }
 
 
-_X_EXPORT GLXFBConfigSGIX
+_GLX_PUBLIC GLXFBConfigSGIX
 glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis)
 {
    struct glx_display *priv;
@@ -2319,7 +2319,7 @@ __glXReleaseBuffersMESA(Display * dpy, GLXDrawable d)
 }
 
 
-_X_EXPORT GLXPixmap
+_GLX_PUBLIC GLXPixmap
 glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual,
                        Pixmap pixmap, Colormap cmap)
 {
@@ -2606,7 +2606,7 @@ get_glx_proc_address(const char *funcName)
  *
  * \sa glXGetProcAddress
  */
-_X_EXPORT void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
+_GLX_PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
 {
    typedef void (*gl_function) (void);
    gl_function f;
@@ -2645,7 +2645,7 @@ _X_EXPORT void (*glXGetProcAddressARB(const GLubyte * procName)) (void)
  *
  * \sa glXGetProcAddressARB
  */
-_X_EXPORT void (*glXGetProcAddress(const GLubyte * procName)) (void)
+_GLX_PUBLIC void (*glXGetProcAddress(const GLubyte * procName)) (void)
 #if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED)
 # if defined(USE_MGL_NAMESPACE)
    __attribute__ ((alias("mglXGetProcAddressARB")));
diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c
index 7f47a42..f2e3865 100644
--- a/src/glx/glxcurrent.c
+++ b/src/glx/glxcurrent.c
@@ -145,7 +145,7 @@ __glXSetCurrentContextNull(void)
 #endif
 }
 
-_X_EXPORT GLXContext
+_GLX_PUBLIC GLXContext
 glXGetCurrentContext(void)
 {
    struct glx_context *cx = __glXGetCurrentContext();
@@ -158,7 +158,7 @@ glXGetCurrentContext(void)
    }
 }
 
-_X_EXPORT GLXDrawable
+_GLX_PUBLIC GLXDrawable
 glXGetCurrentDrawable(void)
 {
    struct glx_context *gc = __glXGetCurrentContext();
@@ -256,18 +256,18 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
 }
 
 
-_X_EXPORT Bool
+_GLX_PUBLIC Bool
 glXMakeCurrent(Display * dpy, GLXDrawable draw, GLXContext gc)
 {
    return MakeContextCurrent(dpy, draw, draw, gc);
 }
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
           (Display * dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
           (dpy, d, r, ctx), MakeContextCurrent)
 
-_X_EXPORT
+_GLX_PUBLIC
 GLX_ALIAS(Bool, glXMakeContextCurrent,
           (Display * dpy, GLXDrawable d, GLXDrawable r,
            GLXContext ctx), (dpy, d, r, ctx), MakeContextCurrent)
diff --git a/src/glx/glxglvnd.c b/src/glx/glxglvnd.c
new file mode 100644
index 0000000..c7c35ca
--- /dev/null
+++ b/src/glx/glxglvnd.c
@@ -0,0 +1,75 @@
+#include <string.h>
+#include <X11/Xlib.h>
+
+#include "glvnd/libglxabi.h"
+
+#include "glxglvnd.h"
+
+
+static Bool __glXGLVNDIsScreenSupported(Display *dpy, int screen)
+{
+    /* TODO: Think of a better heuristic... */
+    return True;
+}
+
+static void *__glXGLVNDGetProcAddress(const GLubyte *procName)
+{
+    return glXGetProcAddressARB(procName);
+}
+
+static int FindGLXFunction(const GLubyte *name)
+{
+    int i;
+
+    for (i = 0; i < DI_FUNCTION_COUNT; i++) {
+        if (strcmp((const char *) name, __glXDispatchTableStrings[i]) == 0)
+            return i;
+    }
+    return -1;
+}
+
+static void *__glXGLVNDGetDispatchAddress(const GLubyte *procName)
+{
+    int internalIndex = FindGLXFunction(procName);
+
+    if (internalIndex >= 0) {
+        return __glXDispatchFunctions[internalIndex];
+    }
+
+    return NULL;
+}
+
+static void __glXGLVNDSetDispatchIndex(const GLubyte *procName, int index)
+{
+    int internalIndex = FindGLXFunction(procName);
+
+    if (internalIndex >= 0)
+        __glXDispatchTableIndices[internalIndex] = index;
+}
+
+_X_EXPORT Bool __glx_Main(uint32_t version, const __GLXapiExports *exports,
+                          __GLXvendorInfo *vendor, __GLXapiImports *imports)
+{
+    static Bool initDone = False;
+
+    if (GLX_VENDOR_ABI_GET_MAJOR_VERSION(version) !=
+        GLX_VENDOR_ABI_MAJOR_VERSION ||
+        GLX_VENDOR_ABI_GET_MINOR_VERSION(version) <
+        GLX_VENDOR_ABI_MINOR_VERSION)
+        return False;
+
+    if (!initDone) {
+        initDone = True;
+        __glXGLVNDAPIExports = exports;
+
+        imports->isScreenSupported = __glXGLVNDIsScreenSupported;
+        imports->getProcAddress = __glXGLVNDGetProcAddress;
+        imports->getDispatchAddress = __glXGLVNDGetDispatchAddress;
+        imports->setDispatchIndex = __glXGLVNDSetDispatchIndex;
+        imports->notifyError = NULL;
+        imports->isPatchSupported = NULL;
+        imports->initiatePatch = NULL;
+    }
+
+    return True;
+}
diff --git a/src/glx/glxglvnd.h b/src/glx/glxglvnd.h
new file mode 100644
index 0000000..b1d8b62
--- /dev/null
+++ b/src/glx/glxglvnd.h
@@ -0,0 +1,14 @@
+#ifndef _glx_lib_glvnd_h_
+#define _glx_lib_glvnd_h_
+
+typedef struct __GLXapiExportsRec __GLXapiExports;
+
+extern const __GLXapiExports *__glXGLVNDAPIExports;
+
+extern const int DI_FUNCTION_COUNT;
+
+extern const void * const __glXDispatchFunctions[];
+extern int __glXDispatchTableIndices[];
+extern const char * const __glXDispatchTableStrings[];
+
+#endif
diff --git a/src/glx/glxglvnddispatchfuncs.h b/src/glx/glxglvnddispatchfuncs.h
new file mode 100644
index 0000000..d9362ff
--- /dev/null
+++ b/src/glx/glxglvnddispatchfuncs.h
@@ -0,0 +1,70 @@
+#ifndef __glx_glvnd_dispatch_funcs_h__
+#define __glx_glvnd_dispatch_funcs_h__
+/*
+ * Helper functions used by g_glxglvnddispatchfuncs.c.
+ */
+#include "glvnd/libglxabi.h"
+#include "glxglvnd.h"
+
+#define __VND __glXGLVNDAPIExports
+
+static inline int AddFBConfigMapping(Display *dpy, GLXFBConfig config,
+                                     __GLXvendorInfo *vendor)
+{
+    return __VND->addVendorFBConfigMapping(dpy, config, vendor);
+}
+
+static inline int AddFBConfigsMapping(Display *dpy, const GLXFBConfig *ret,
+                                      int *nelements, __GLXvendorInfo *vendor)
+{
+    int i, r;
+
+    if (!nelements || !ret)
+        return 0;
+
+    for (i = 0; i < *nelements; i++) {
+        r = __VND->addVendorFBConfigMapping(dpy, ret[i], vendor);
+        if (r) {
+            for (; i >= 0; i--)
+                __VND->removeVendorFBConfigMapping(dpy, ret[i]);
+            break;
+        }
+    }
+    return r;
+}
+
+static inline int AddDrawableMapping(Display *dpy, GLXDrawable drawable,
+                                     __GLXvendorInfo *vendor)
+{
+    return __VND->addVendorDrawableMapping(dpy, drawable, vendor);
+}
+
+static inline int AddContextMapping(Display *dpy, GLXContext ctx,
+                                    __GLXvendorInfo *vendor)
+{
+    return __VND->addVendorContextMapping(dpy, ctx, vendor);
+}
+
+static inline __GLXvendorInfo *GetDispatchFromDrawable(Display *dpy,
+                                                       GLXDrawable drawable)
+{
+    return __VND->vendorFromDrawable(dpy, drawable);
+}
+
+static inline __GLXvendorInfo *GetDispatchFromContext(GLXContext ctx)
+{
+    return __VND->vendorFromContext(ctx);
+}
+
+static inline __GLXvendorInfo *GetDispatchFromFBConfig(Display *dpy, GLXFBConfig config)
+{
+    return __VND->vendorFromFBConfig(dpy, config);
+}
+
+static inline __GLXvendorInfo *GetDispatchFromVisual(Display *dpy,
+                                                     const XVisualInfo *visual)
+{
+    return __VND->getDynDispatch(dpy, visual->screen);
+}
+
+#endif // __glx_glvnd_dispatch_funcs_h__
-- 
2.7.4



More information about the mesa-dev mailing list