summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Brenneman <kbrenneman@nvidia.com>2016-03-28 17:40:51 -0600
committerKyle Brenneman <kbrenneman@nvidia.com>2016-03-28 17:40:51 -0600
commit95a5bfcdfbc3c38e201e81d6497efe6c7b97f72b (patch)
tree84d622feb712ea43d432a2c8b0ca9cd65e8ae20d
parent5c8e63290620d78763503f9ba4de28530ae1961e (diff)
parent86585e3bb0781ad1ef925e6fd81888190c12b1a5 (diff)
Merge pull request #74 from kbrenneman/libglx-abi-version-1.
Updates to libGLX vendor library interface.
-rw-r--r--configure.ac2
-rw-r--r--include/glvnd/GLdispatchABI.h101
-rw-r--r--include/glvnd/libglxabi.h195
-rw-r--r--src/GLX/libglx.c90
-rw-r--r--src/GLX/libglxmapping.c132
-rw-r--r--src/GLX/libglxmapping.h17
-rw-r--r--src/GLdispatch/GLdispatch.c10
-rw-r--r--src/GLdispatch/GLdispatch.h75
-rw-r--r--src/GLdispatch/GLdispatchPrivate.h19
-rw-r--r--src/GLdispatch/vnd-glapi/mapi/entry.h10
-rw-r--r--src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.c3
-rw-r--r--src/GLdispatch/vnd-glapi/mapi/entry_pure_c.c3
-rw-r--r--src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tls.c3
-rw-r--r--src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tsd.c3
-rw-r--r--src/GLdispatch/vnd-glapi/mapi/entry_x86_tsd.c3
-rw-r--r--tests/GLX_dummy/GLX_dummy.c97
16 files changed, 475 insertions, 288 deletions
diff --git a/configure.ac b/configure.ac
index b2ba9f8..8d00683 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl configure.ac
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.63])
-AC_INIT([libglvnd], [0.0.0], [kbrenneman@nvidia.com])
+AC_INIT([libglvnd], [0.1.0], [kbrenneman@nvidia.com])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])
diff --git a/include/glvnd/GLdispatchABI.h b/include/glvnd/GLdispatchABI.h
index d16de2d..25d593a 100644
--- a/include/glvnd/GLdispatchABI.h
+++ b/include/glvnd/GLdispatchABI.h
@@ -44,18 +44,45 @@ extern "C" {
* these client ABIs.
*/
-/*
- * Thread-local implementation used by libglvnd. This is passed into
- * the patch function callback via the type parameter.
+/*!
+ * Thread-local implementation used by libglvnd. This is passed into the patch
+ * function callback via the type parameter.
+ *
+ * For most architectures, the vendor library can ignore this parameter, since
+ * it will always be the same value. It's used for systems like ARM, where the
+ * stubs might be use the ARM or Thumb instruction sets.
+ *
+ * The stub type does not make any distinction between TLS and TSD stubs. The
+ * entire purpose of entrypoint rewriting is to skip the dispatch table in
+ * libGLdispatch.so, so it doesn't matter how that dispatch table is stored.
*/
enum {
- __GLDISPATCH_STUB_X86_TLS,
- __GLDISPATCH_STUB_X86_64_TLS,
- __GLDISPATCH_STUB_X86_TSD,
- __GLDISPATCH_STUB_PURE_C,
- __GLDISPATCH_STUB_X86_64_TSD,
- __GLDISPATCH_STUB_ARMV7_THUMB_TSD,
- __GLDISPATCH_STUB_NUM_TYPES
+ /*!
+ * Indicates that the stubs aren't defined in assembly. For example, if the
+ * dispatch stubs are written in C. Vendor libraries generally won't see
+ * this value.
+ */
+ __GLDISPATCH_STUB_UNKNOWN,
+
+ /*!
+ * Used for stubs on x86 systems.
+ */
+ __GLDISPATCH_STUB_X86,
+
+ /*!
+ * Used for stubs on x86-64 systems.
+ */
+ __GLDISPATCH_STUB_X86_64,
+
+ /*!
+ * Used for stubs on ARMv7, using the Thumb instruction set.
+ */
+ __GLDISPATCH_STUB_ARMV7_THUMB,
+
+ /*!
+ * Used for stubs on ARMv7, using the normal ARM instruction set.
+ */
+ __GLDISPATCH_STUB_ARMV7_ARM
};
/*!
@@ -86,60 +113,6 @@ enum {
typedef GLboolean (*DispatchPatchLookupStubOffset)(const char *funcName,
void **writePtr, const void **execPtr);
-typedef struct __GLdispatchPatchCallbacksRec {
- /*!
- * Checks to see if the vendor library supports patching the given stub
- * type and size.
- *
- * \param type The type of entrypoints. This will be a one of the
- * __GLDISPATCH_STUB_* values.
- * \param stubSize The maximum size of the stub that the vendor library can
- * write, in bytes.
- * \param lookupStubOffset A callback into libglvnd to look up the address
- * of each entrypoint.
- */
- GLboolean (* checkPatchSupported)(int type, int stubSize);
-
- /*!
- * Called by libglvnd to request that a vendor library patch its top-level
- * entrypoints.
- *
- * The vendor library should use the \p lookupStubOffset callback to find
- * the addresses of each entrypoint.
- *
- * This function may be called more than once to patch multiple sets of
- * entrypoints. For example, depending on how they're built, libOpenGL.so
- * or libGL.so may have their own entrypoints that are separate functions
- * from the ones in libGLdispatch.
- *
- * Note that during this call is the only time that the entrypoints can be
- * modified. After the call to \c initiatePatch returns, the vendor library
- * should treat the entrypoints as read-only.
- *
- * \param type The type of entrypoints. This will be a one of the
- * __GLDISPATCH_STUB_* values.
- * \param stubSize The maximum size of the stub that the vendor library can
- * write, in bytes.
- * \param lookupStubOffset A callback into libglvnd to look up the address
- * of each entrypoint.
- *
- * \return GL_TRUE if the vendor library supports patching with this type
- * and size.
- */
- GLboolean (*initiatePatch)(int type,
- int stubSize,
- DispatchPatchLookupStubOffset lookupStubOffset);
-
- /*!
- * Called by libglvnd to notify the current vendor that it no longer owns
- * the top-level entrypoints.
- *
- * Libglvnd will take care of the restoring the entrypoints back to their
- * original state. The vendor library must not try to modify them.
- */
- void (*releasePatch)(void);
-} __GLdispatchPatchCallbacks;
-
#if defined(__cplusplus)
}
#endif
diff --git a/include/glvnd/libglxabi.h b/include/glvnd/libglxabi.h
index 3a59691..b664e76 100644
--- a/include/glvnd/libglxabi.h
+++ b/include/glvnd/libglxabi.h
@@ -90,8 +90,18 @@ extern "C" {
/*!
* Current version of the ABI.
+ *
+ * This version number contains a major number in the high-order 16 bits, and
+ * a minor version number in the low-order 16 bits.
+ *
+ * The major version number is incremented when an interface change will break
+ * backwards compatibility with existing vendor libraries. The minor version
+ * number is incremented when there's a change but existing vendor libraries
+ * will still work.
*/
-#define GLX_VENDOR_ABI_VERSION 0
+#define GLX_VENDOR_ABI_VERSION ((1 << 16) | 0)
+#define GLX_VENDOR_ABI_GET_MAJOR_VERSION(version) ((version) & 0xFFFF)
+#define GLX_VENDOR_ABI_GET_MINOR_VERSION(version) ((version) >> 16)
/*!
@@ -151,15 +161,19 @@ typedef struct __GLXapiExportsRec {
/************************************************************************
* These routines are used by vendor dispatch functions to look up
- * and add mappings between various objects and screens.
+ * and add mappings between various objects and vendors.
************************************************************************/
/*!
- * Records the screen number and vendor for a context. The screen and
- * vendor must be the ones returned for the XVisualInfo or GLXFBConfig that
- * the context is created from.
+ * Records the vendor for a context. The vendor must be the one returned
+ * for the XVisualInfo or GLXFBConfig that the context is created from.
+ *
+ * \param dpy The display pointer.
+ * \param context The context handle.
+ * \param vendor The vendor that created the context.
+ * \return Zero on success, non-zero on error.
*/
- void (*addVendorContextMapping)(Display *dpy, GLXContext context, __GLXvendorInfo *vendor);
+ int (*addVendorContextMapping)(Display *dpy, GLXContext context, __GLXvendorInfo *vendor);
/*!
* Removes a mapping from context to vendor. The context must have been
@@ -168,33 +182,27 @@ typedef struct __GLXapiExportsRec {
void (*removeVendorContextMapping)(Display *dpy, GLXContext context);
/*!
- * Looks up the screen and vendor for a context.
+ * Looks up the vendor for a context.
*
- * If no mapping is found, then \p retScreen will be set to -1, and
- * \p retVendor and \p retDisplay will be set to NULL.
- *
- * \p retScreen, \p retVendor, and \p retDisplay may be NULL if the screen,
- * vendor, or display are not required.
+ * If no mapping is found, then this function will return \c NULL. No
+ * errors are raised, so the dispatch function must raise any appropriate X
+ * errors.
*
* Note that this function does not take a display connection, since
* there are cases (e.g., glXGetContextIDEXT) that take a GLXContext but
* not a display.
*
* \param context The context to look up.
- * \param[out] retVendor Returns the vendor.
- * \return Zero if a match was found, or non-zero if it was not.
+ * \return The vendor for the context, or NULL if no matching context was
+ * found.
*/
- int (*vendorFromContext)(GLXContext context, __GLXvendorInfo **retVendor);
+ __GLXvendorInfo * (*vendorFromContext)(GLXContext context);
- void (*addVendorFBConfigMapping)(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor);
+ int (*addVendorFBConfigMapping)(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor);
void (*removeVendorFBConfigMapping)(Display *dpy, GLXFBConfig config);
- int (*vendorFromFBConfig)(Display *dpy, GLXFBConfig config, __GLXvendorInfo **retVendor);
-
- void (*addScreenVisualMapping)(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo *vendor);
- void (*removeScreenVisualMapping)(Display *dpy, const XVisualInfo *visual);
- int (*vendorFromVisual)(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo **retVendor);
+ __GLXvendorInfo * (*vendorFromFBConfig)(Display *dpy, GLXFBConfig config);
- void (*addVendorDrawableMapping)(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor);
+ int (*addVendorDrawableMapping)(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor);
void (*removeVendorDrawableMapping)(Display *dpy, GLXDrawable drawable);
/*!
@@ -210,7 +218,7 @@ typedef struct __GLXapiExportsRec {
* All of this should be opaque to a dispatch function, since the only
* thing that matters is finding out which vendor to dispatch to.
*/
- int (*vendorFromDrawable)(Display *dpy, GLXDrawable drawable, __GLXvendorInfo **retVendor);
+ __GLXvendorInfo * (*vendorFromDrawable)(Display *dpy, GLXDrawable drawable);
} __GLXapiExports;
@@ -231,7 +239,7 @@ typedef struct __GLXapiImportsRec {
* \param screen The screen number.
* \return True if the vendor library can support this screen.
*/
- Bool (* checkSupportsScreen) (Display *dpy, int screen);
+ Bool (* isScreenSupported) (Display *dpy, int screen);
/*!
* This retrieves the pointer to the real GLX or core GL function.
@@ -289,39 +297,134 @@ typedef struct __GLXapiImportsRec {
XID resid, unsigned char opcode,
Bool coreX11error);
- /*!
- * (OPTIONAL) Callbacks by which the vendor library may re-write libglvnd's
+ /*
+ * The vendor library may use the isPatchSupported, initiatePatch,
+ * releasePatch, and patchThreadAttach callbacks to re-write libglvnd's
* entrypoints at make current time, provided no other contexts are current
- * and the TLS model supports this functionality. This is a performance
+ * and the TLS model supports this functionality. This is a performance
* optimization that may not be available at runtime; the vendor library
- * must not depend on this functionality for correctness. This should
- * point to a statically-allocated structure, or NULL if unimplemented.
+ * must not depend on this functionality for correctness.
+ *
+ * To use this optimization, the vendor library must provide at least the
+ * isPatchSupported and initiatePatch entrypoints.
+ */
+
+ /*!
+ * (OPTIONAL) Checks to see if the vendor library supports patching the
+ * given stub type and size.
+ *
+ * \param type The type of entrypoints. This will be a one of the
+ * __GLDISPATCH_STUB_* values.
+ * \param stubSize The maximum size of the stub that the vendor library can
+ * write, in bytes.
+ * \param lookupStubOffset A callback into libglvnd to look up the address
+ * of each entrypoint.
+ */
+ GLboolean (* isPatchSupported)(int type, int stubSize);
+
+ /*!
+ * (OPTIONAL) Called by libglvnd to request that a vendor library patch its
+ * top-level entrypoints.
+ *
+ * The vendor library should use the \p lookupStubOffset callback to find
+ * the addresses of each entrypoint.
+ *
+ * This function may be called more than once to patch multiple sets of
+ * entrypoints. For example, depending on how they're built, libOpenGL.so
+ * or libGL.so may have their own entrypoints that are separate functions
+ * from the ones in libGLdispatch.
+ *
+ * Note that during this call is the only time that the entrypoints can be
+ * modified. After the call to \c initiatePatch returns, the vendor library
+ * should treat the entrypoints as read-only.
+ *
+ * \param type The type of entrypoints. This will be a one of the
+ * __GLDISPATCH_STUB_* values.
+ * \param stubSize The maximum size of the stub that the vendor library can
+ * write, in bytes.
+ * \param lookupStubOffset A callback into libglvnd to look up the address
+ * of each entrypoint.
+ *
+ * \return GL_TRUE if the vendor library supports patching with this type
+ * and size.
+ */
+ GLboolean (*initiatePatch)(int type,
+ int stubSize,
+ DispatchPatchLookupStubOffset lookupStubOffset);
+
+ /*!
+ * (OPTIONAL) Called by libglvnd to notify the current vendor that it no
+ * longer owns the top-level entrypoints.
+ *
+ * Libglvnd will take care of the restoring the entrypoints back to their
+ * original state. The vendor library must not try to modify them.
+ */
+ void (*releasePatch)(void);
+
+ /*!
+ * (OPTIONAL) Called at the start of window-system functions (GLX and EGL).
+ * This callback allows vendor libraries to perform any per-thread
+ * initialization.
+ *
+ * This is basically a workaround for broken applications. A lot of apps
+ * will make one or more invalid GLX/EGL calls on a thread (often including
+ * a MakeCurrent with invalid parameters), and then will try to call an
+ * OpenGL function.
+ *
+ * A non-libglvnd-based driver would be able to initialize any thread state
+ * even on a bogus GLX call, but with libglvnd, those calls wouldn't get
+ * past libGLX.
+ *
+ * This function is optional. If it's \c NULL, then libGLdispatch will
+ * simply ignore it.
+ *
+ * \note This function may be called concurrently from multiple threads.
*/
- const __GLdispatchPatchCallbacks *patchCallbacks;
+ void (*patchThreadAttach)(void);
} __GLXapiImports;
/*****************************************************************************/
+#define __GLX_MAIN_PROTO_NAME "__glx_Main"
+#define __GLX_MAIN_PROTO(version, exports, vendor, imports) \
+ Bool __glx_Main(uint32_t version, \
+ const __GLXapiExports *exports, \
+ __GLXvendorInfo *vendor, \
+ __GLXapiImports *imports)
+
+typedef Bool (*__PFNGLXMAINPROC)
+ (uint32_t version, const __GLXapiExports *exports, __GLXvendorInfo *vendor, __GLXapiImports *imports);
+
/*!
* Vendor libraries must export a function called __glx_Main() with the
- * following prototype. This function also performs a handshake based on the ABI
- * version number. This function receives a pointer to an exports table whose
- * lifetime is only guaranteed to be at a minimum that of the call to
- * __glx_Main(), in addition to the version number and a string identifying the
- * vendor. If there is an ABI version mismatch or some other error occurs, this
- * function returns NULL; otherwise this returns a pointer to a filled-in
- * dispatch table.
+ * following prototype.
+ *
+ * This function also performs a handshake based on the ABI version number.
+ * Vendor libraries can optionally use the version number to support older
+ * versions of the ABI.
+ *
+ * \param[in] version The ABI version. The upper 16 bits contains the major version
+ * number, and the lower 16 bits contains the minor version number.
+ *
+ * \param[in] exports The table of functions provided by libGLX. This pointer will
+ * remain valid for as long as the vendor is loaded.
+ *
+ * \param[in] vendor The opaque pointer used to identify this vendor library. This
+ * may be used in future versions to provide additional per-vendor information.
+ *
+ * \param[out] imports The function table that the vendor library should fill
+ * in. The vendor library must assign every non-optional function in the
+ * struct.
+ *
+ * \return True on success. If the vendor library does not support the
+ * requested ABI version or if some other error occurs, then it should return
+ * False.
*/
-#define __GLX_MAIN_PROTO_NAME "__glx_Main"
-#define __GLX_MAIN_PROTO(version, exports, vendorName) \
- const __GLXapiImports *__glx_Main(uint32_t version, \
- const __GLXapiExports *exports, \
- const char *vendorName, \
- int vendorID)
-
-typedef const __GLXapiImports *(*__PFNGLXMAINPROC)
- (uint32_t, const __GLXapiExports *, const char *, int);
+Bool __glx_Main(uint32_t version,
+ const __GLXapiExports *exports,
+ __GLXvendorInfo *vendor,
+ __GLXapiImports *imports);
/*!
* @}
diff --git a/src/GLX/libglx.c b/src/GLX/libglx.c
index df3f4d2..f3a408a 100644
--- a/src/GLX/libglx.c
+++ b/src/GLX/libglx.c
@@ -163,7 +163,7 @@ static __GLXvendorInfo *CommonDispatchDrawable(Display *dpy, GLXDrawable draw,
if (draw != None) {
__glXThreadInitialize();
- __glXVendorFromDrawable(dpy, draw, &vendor);
+ vendor = __glXVendorFromDrawable(dpy, draw);
}
if (vendor == NULL) {
__glXSendError(dpy, errorCode, draw, minorCode, coreX11error);
@@ -178,7 +178,7 @@ static __GLXvendorInfo *CommonDispatchContext(Display *dpy, GLXContext context,
if (context != NULL) {
__glXThreadInitialize();
- __glXVendorFromContext(context, &vendor);
+ vendor = __glXVendorFromContext(context);
}
if (vendor == NULL) {
__glXSendError(dpy, GLXBadContext, 0, minorCode, False);
@@ -193,7 +193,7 @@ static __GLXvendorInfo *CommonDispatchFBConfig(Display *dpy, GLXFBConfig config,
if (config != NULL) {
__glXThreadInitialize();
- __glXVendorFromFBConfig(dpy, config, &vendor);
+ vendor = __glXVendorFromFBConfig(dpy, config);
}
if (vendor == NULL) {
__glXSendError(dpy, GLXBadFBConfig, 0, minorCode, False);
@@ -238,7 +238,10 @@ PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis,
vendor = __glXLookupVendorByScreen(dpy, vis->screen);
if (vendor != NULL) {
GLXContext context = vendor->staticDispatch.createContext(dpy, vis, share_list, direct);
- __glXAddVendorContextMapping(dpy, context, vendor);
+ if (__glXAddVendorContextMapping(dpy, context, vendor) != 0) {
+ vendor->staticDispatch.destroyContext(dpy, context);
+ context = NULL;
+ }
return context;
} else {
return NULL;
@@ -255,7 +258,10 @@ PUBLIC GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config,
if (vendor != NULL) {
context = vendor->staticDispatch.createNewContext(dpy, config, render_type,
share_list, direct);
- __glXAddVendorContextMapping(dpy, context, vendor);
+ if (__glXAddVendorContextMapping(dpy, context, vendor) != 0) {
+ vendor->staticDispatch.destroyContext(dpy, context);
+ context = NULL;
+ }
}
return context;
}
@@ -407,9 +413,13 @@ static GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID)
}
vendor = __glXLookupVendorByScreen(dpy, screen);
- if (vendor != NULL && vendor->staticDispatch.importContextEXT != NULL) {
+ if (vendor != NULL && vendor->staticDispatch.importContextEXT != NULL
+ && vendor->staticDispatch.freeContextEXT) {
GLXContext context = vendor->staticDispatch.importContextEXT(dpy, contextID);
- __glXAddVendorContextMapping(dpy, context, vendor);
+ if (__glXAddVendorContextMapping(dpy, context, vendor) != 0) {
+ vendor->staticDispatch.freeContextEXT(dpy, context);
+ context = NULL;
+ }
return context;
} else {
return NULL;
@@ -422,7 +432,7 @@ static void glXFreeContextEXT(Display *dpy, GLXContext context)
__glXThreadInitialize();
- __glXVendorFromContext(context, &vendor);
+ vendor = __glXVendorFromContext(context);
if (vendor != NULL && vendor->staticDispatch.freeContextEXT != NULL) {
__glXRemoveVendorContextMapping(dpy, context);
vendor->staticDispatch.freeContextEXT(dpy, context);
@@ -439,7 +449,10 @@ PUBLIC GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *vis, Pixmap pixma
vendor = __glXLookupVendorByScreen(dpy, vis->screen);
if (vendor != NULL) {
GLXPixmap pmap = vendor->staticDispatch.createGLXPixmap(dpy, vis, pixmap);
- __glXAddVendorDrawableMapping(dpy, pmap, vendor);
+ if (__glXAddVendorDrawableMapping(dpy, pmap, vendor) != 0) {
+ vendor->staticDispatch.destroyGLXPixmap(dpy, pmap);
+ pmap = None;
+ }
return pmap;
} else {
return None;
@@ -635,7 +648,7 @@ void __glXRemoveVendorContextMapping(Display *dpy, GLXContext context)
__glvndPthreadFuncs.mutex_unlock(&glxContextHashLock);
}
-void __glXAddVendorContextMapping(Display *dpy, GLXContext context, __GLXvendorInfo *vendor)
+int __glXAddVendorContextMapping(Display *dpy, GLXContext context, __GLXvendorInfo *vendor)
{
__GLXcontextInfo *ctxInfo;
@@ -644,19 +657,27 @@ void __glXAddVendorContextMapping(Display *dpy, GLXContext context, __GLXvendorI
HASH_FIND_PTR(glxContextHash, &context, ctxInfo);
if (ctxInfo == NULL) {
ctxInfo = (__GLXcontextInfo *) malloc(sizeof(__GLXcontextInfo));
+ if (ctxInfo == NULL) {
+ __glvndPthreadFuncs.mutex_unlock(&glxContextHashLock);
+ return -1;
+ }
ctxInfo->context = context;
ctxInfo->vendor = vendor;
ctxInfo->currentCount = 0;
ctxInfo->deleted = False;
HASH_ADD_PTR(glxContextHash, context, ctxInfo);
} else {
- assert(ctxInfo->vendor == vendor);
+ if (ctxInfo->vendor != vendor) {
+ __glvndPthreadFuncs.mutex_unlock(&glxContextHashLock);
+ return -1;
+ }
}
__glvndPthreadFuncs.mutex_unlock(&glxContextHashLock);
+ return 0;
}
-int __glXVendorFromContext(GLXContext context, __GLXvendorInfo **retVendor)
+__GLXvendorInfo *__glXVendorFromContext(GLXContext context)
{
__GLXcontextInfo *ctxInfo;
__GLXvendorInfo *vendor = NULL;
@@ -668,10 +689,7 @@ int __glXVendorFromContext(GLXContext context, __GLXvendorInfo **retVendor)
}
__glvndPthreadFuncs.mutex_unlock(&glxContextHashLock);
- if (retVendor != NULL) {
- *retVendor = vendor;
- }
- return (vendor != NULL ? 0 : -1);
+ return vendor;
}
static void FreeContextInfo(__GLXcontextInfo *ctx)
@@ -848,7 +866,7 @@ static Bool InternalMakeCurrentDispatch(
&threadState->glas,
vendor->glDispatch,
vendor->vendorID,
- vendor->glxvc->patchCallbacks
+ vendor->patchCallbacks
);
if (ret) {
@@ -1425,7 +1443,6 @@ PUBLIC const char *glXQueryExtensionsString(Display *dpy, int screen)
return pDispatch->queryExtensionsString(dpy, screen);
}
-
PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen,
const int *attrib_list, int *nelements)
{
@@ -1440,8 +1457,17 @@ PUBLIC GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen,
if (fbconfigs != NULL) {
int i;
+ Bool success = True;
for (i = 0; i < *nelements; i++) {
- __glXAddVendorFBConfigMapping(dpy, fbconfigs[i], vendor);
+ if (__glXAddVendorFBConfigMapping(dpy, fbconfigs[i], vendor) != 0) {
+ success = False;
+ break;
+ }
+ }
+ if (!success) {
+ XFree(fbconfigs);
+ fbconfigs = NULL;
+ *nelements = 0;
}
}
return fbconfigs;
@@ -1458,7 +1484,10 @@ PUBLIC GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config,
__GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreatePbuffer);
if (vendor != NULL) {
pbuffer = vendor->staticDispatch.createPbuffer(dpy, config, attrib_list);
- __glXAddVendorDrawableMapping(dpy, pbuffer, vendor);
+ if (__glXAddVendorDrawableMapping(dpy, pbuffer, vendor) != 0) {
+ vendor->staticDispatch.destroyPbuffer(dpy, pbuffer);
+ pbuffer = None;
+ }
}
return pbuffer;
}
@@ -1471,7 +1500,10 @@ PUBLIC GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config,
__GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreatePixmap);
if (vendor != NULL) {
glxPixmap = vendor->staticDispatch.createPixmap(dpy, config, pixmap, attrib_list);
- __glXAddVendorDrawableMapping(dpy, glxPixmap, vendor);
+ if (__glXAddVendorDrawableMapping(dpy, glxPixmap, vendor) != 0) {
+ vendor->staticDispatch.destroyGLXPixmap(dpy, glxPixmap);
+ glxPixmap = None;
+ }
}
return glxPixmap;
}
@@ -1484,7 +1516,10 @@ PUBLIC GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config,
__GLXvendorInfo *vendor = CommonDispatchFBConfig(dpy, config, X_GLXCreateWindow);
if (vendor != NULL) {
glxWindow = vendor->staticDispatch.createWindow(dpy, config, win, attrib_list);
- __glXAddVendorDrawableMapping(dpy, glxWindow, vendor);
+ if (__glXAddVendorDrawableMapping(dpy, glxWindow, vendor) != 0) {
+ vendor->staticDispatch.destroyWindow(dpy, glxWindow);
+ glxWindow = None;
+ }
}
return glxWindow;
}
@@ -1545,8 +1580,17 @@ PUBLIC GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
GLXFBConfig *fbconfigs = vendor->staticDispatch.getFBConfigs(dpy, screen, nelements);
if (fbconfigs != NULL) {
int i;
+ Bool success = True;
for (i = 0; i < *nelements; i++) {
- __glXAddVendorFBConfigMapping(dpy, fbconfigs[i], vendor);
+ if (__glXAddVendorFBConfigMapping(dpy, fbconfigs[i], vendor) != 0) {
+ success = False;
+ break;
+ }
+ }
+ if (!success) {
+ XFree(fbconfigs);
+ fbconfigs = NULL;
+ *nelements = 0;
}
}
return fbconfigs;
diff --git a/src/GLX/libglxmapping.c b/src/GLX/libglxmapping.c
index 67d5d7d..506cb06 100644
--- a/src/GLX/libglxmapping.c
+++ b/src/GLX/libglxmapping.c
@@ -104,6 +104,15 @@ typedef struct __GLXdispatchFuncHashRec {
*/
typedef struct __GLXvendorNameHashRec {
__GLXvendorInfo vendor;
+
+ /**
+ * The imports table for this vendor. This is allocated and zeroed by
+ * libGLX.so, so that we can add functions to the end without breaking
+ * backward compatibility.
+ */
+ __GLXapiImports imports;
+ __GLdispatchPatchCallbacks patchCallbacks;
+
UT_hash_handle hh;
} __GLXvendorNameHash;
@@ -143,10 +152,6 @@ static const __GLXapiExports glxExportsTable = {
.removeVendorFBConfigMapping = __glXRemoveVendorFBConfigMapping,
.vendorFromFBConfig = __glXVendorFromFBConfig,
- .addScreenVisualMapping = __glXAddScreenVisualMapping,
- .removeScreenVisualMapping = __glXRemoveScreenVisualMapping,
- .vendorFromVisual = __glXVendorFromVisual,
-
.addVendorDrawableMapping = __glXAddVendorDrawableMapping,
.removeVendorDrawableMapping = __glXRemoveVendorDrawableMapping,
.vendorFromDrawable = __glXVendorFromDrawable,
@@ -476,6 +481,7 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
__GLXvendorInfo *vendor;
__PFNGLXMAINPROC glxMainProc;
char *filename;
+ Bool success;
// Previously unseen vendor. dlopen() the new vendor and add it to the
// hash table.
@@ -485,6 +491,7 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
}
vendor = &pEntry->vendor;
+ vendor->glxvc = &pEntry->imports;
vendor->name = (char *) (pEntry + 1);
memcpy(vendor->name, vendorName, vendorNameLen + 1);
@@ -505,18 +512,6 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
vendor->vendorID = __glDispatchNewVendorID();
assert(vendor->vendorID >= 0);
- vendor->glxvc = (*glxMainProc)(GLX_VENDOR_ABI_VERSION,
- &glxExportsTable,
- vendor->name,
- vendor->vendorID);
- if (!vendor->glxvc) {
- goto fail;
- }
-
- if (!LookupVendorEntrypoints(vendor)) {
- goto fail;
- }
-
vendor->glDispatch = (__GLdispatchTable *)
__glDispatchCreateTable(
VendorGetProcAddressCallback,
@@ -529,6 +524,37 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
/* Initialize the dynamic dispatch table */
LKDHASH_INIT(vendor->dynDispatchHash);
+ success = (*glxMainProc)(GLX_VENDOR_ABI_VERSION,
+ &glxExportsTable,
+ vendor, &pEntry->imports);
+ if (!success) {
+ goto fail;
+ }
+
+ // Make sure all the required functions are there.
+ if (pEntry->imports.isScreenSupported == NULL
+ || pEntry->imports.getProcAddress == NULL
+ || pEntry->imports.getDispatchAddress == NULL
+ || pEntry->imports.setDispatchIndex == NULL)
+ {
+ goto fail;
+ }
+
+ if (!LookupVendorEntrypoints(vendor)) {
+ goto fail;
+ }
+
+ // Check to see whether this vendor library can support entrypoint
+ // patching.
+ if (pEntry->imports.isPatchSupported != NULL
+ && pEntry->imports.initiatePatch != NULL) {
+ pEntry->patchCallbacks.isPatchSupported = pEntry->imports.isPatchSupported;
+ pEntry->patchCallbacks.initiatePatch = pEntry->imports.initiatePatch;
+ pEntry->patchCallbacks.releasePatch = pEntry->imports.releasePatch;
+ pEntry->patchCallbacks.threadAttach = pEntry->imports.patchThreadAttach;
+ pEntry->vendor.patchCallbacks = &pEntry->patchCallbacks;
+ }
+
HASH_ADD_KEYPTR(hh, _LH(__glXVendorNameHash), vendor->name,
strlen(vendor->name), pEntry);
LKDHASH_UNLOCK(__glXVendorNameHash);
@@ -604,7 +630,7 @@ __GLXvendorInfo *__glXLookupVendorByScreen(Display *dpy, const int screen)
// Make sure that the vendor library can support this screen.
// If it can't, then we'll fall back to the indirect rendering
// library.
- if (vendor != NULL && !vendor->glxvc->checkSupportsScreen(dpy, screen)) {
+ if (vendor != NULL && !vendor->glxvc->isScreenSupported(dpy, screen)) {
vendor = NULL;
}
}
@@ -794,16 +820,16 @@ typedef struct {
static DEFINE_LKDHASH(__GLXvendorConfigMappingHash, fbconfigHashtable);
-void __glXAddVendorFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor)
+int __glXAddVendorFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor)
{
__GLXvendorConfigMappingHash *pEntry;
if (config == NULL) {
- return;
+ return 0;
}
if (vendor == NULL) {
- return;
+ return -1;
}
LKDHASH_WRLOCK(fbconfigHashtable);
@@ -812,6 +838,10 @@ void __glXAddVendorFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendor
if (pEntry == NULL) {
pEntry = malloc(sizeof(*pEntry));
+ if (pEntry == NULL) {
+ LKDHASH_UNLOCK(fbconfigHashtable);
+ return -1;
+ }
pEntry->config = config;
pEntry->vendor = vendor;
HASH_ADD_PTR(_LH(fbconfigHashtable), config, pEntry);
@@ -819,10 +849,14 @@ void __glXAddVendorFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendor
// Any GLXContext or GLXFBConfig handles must be unique to a single
// vendor at a time. If we get two different vendors, then there's
// either a bug in libGLX or in at least one of the vendor libraries.
- assert(pEntry->vendor == vendor);
+ if (pEntry->vendor != vendor) {
+ LKDHASH_UNLOCK(fbconfigHashtable);
+ return -1;
+ }
}
LKDHASH_UNLOCK(fbconfigHashtable);
+ return 0;
}
void __glXRemoveVendorFBConfigMapping(Display *dpy, GLXFBConfig config)
@@ -845,7 +879,7 @@ void __glXRemoveVendorFBConfigMapping(Display *dpy, GLXFBConfig config)
LKDHASH_UNLOCK(fbconfigHashtable);
}
-int __glXVendorFromFBConfig(Display *dpy, GLXFBConfig config, __GLXvendorInfo **retVendor)
+__GLXvendorInfo *__glXVendorFromFBConfig(Display *dpy, GLXFBConfig config)
{
__GLXvendorConfigMappingHash *pEntry;
__GLXvendorInfo *vendor = NULL;
@@ -862,28 +896,7 @@ int __glXVendorFromFBConfig(Display *dpy, GLXFBConfig config, __GLXvendorInfo **
LKDHASH_UNLOCK(fbconfigHashtable);
- if (retVendor != NULL) {
- *retVendor = vendor;
- }
- return (vendor != NULL ? 0 : -1);
-}
-
-// Internally, we use the screen number to look up a vendor, so we don't need
-// to record anything else for an XVisualInfo.
-void __glXAddScreenVisualMapping(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo *vendor)
-{
-}
-void __glXRemoveScreenVisualMapping(Display *dpy, const XVisualInfo *visual)
-{
-}
-int __glXVendorFromVisual(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo **retVendor)
-{
- __glXThreadInitialize();
-
- if (retVendor != NULL) {
- *retVendor = __glXLookupVendorByScreen(dpy, visual->screen);
- }
- return 0;
+ return vendor;
}
@@ -894,16 +907,16 @@ int __glXVendorFromVisual(Display *dpy, const XVisualInfo *visual, __GLXvendorIn
*/
-static void AddVendorXIDMapping(Display *dpy, __GLXdisplayInfo *dpyInfo, XID xid, __GLXvendorInfo *vendor)
+static int AddVendorXIDMapping(Display *dpy, __GLXdisplayInfo *dpyInfo, XID xid, __GLXvendorInfo *vendor)
{
__GLXvendorXIDMappingHash *pEntry = NULL;
if (xid == None) {
- return;
+ return 0;
}
if (vendor == NULL) {
- return;
+ return -1;
}
LKDHASH_WRLOCK(dpyInfo->xidVendorHash);
@@ -912,16 +925,24 @@ static void AddVendorXIDMapping(Display *dpy, __GLXdisplayInfo *dpyInfo, XID xid
if (pEntry == NULL) {
pEntry = malloc(sizeof(*pEntry));
+ if (pEntry == NULL) {
+ LKDHASH_UNLOCK(dpyInfo->xidVendorHash);
+ return -1;
+ }
pEntry->xid = xid;
pEntry->vendor = vendor;
HASH_ADD(hh, _LH(dpyInfo->xidVendorHash), xid, sizeof(xid), pEntry);
} else {
// Like GLXContext and GLXFBConfig handles, any GLXDrawables must map
// to a single vendor library.
- assert(pEntry->vendor == vendor);
+ if (pEntry->vendor != vendor) {
+ LKDHASH_UNLOCK(dpyInfo->xidVendorHash);
+ return -1;
+ }
}
LKDHASH_UNLOCK(dpyInfo->xidVendorHash);
+ return 0;
}
@@ -967,6 +988,8 @@ static void VendorFromXID(Display *dpy, __GLXdisplayInfo *dpyInfo, XID xid,
if (screen >= 0 && screen < ScreenCount(dpy)) {
vendor = __glXLookupVendorByScreen(dpy, screen);
if (vendor != NULL) {
+ // Note that if this fails, it's not necessarily a problem.
+ // We can just query it again next time.
AddVendorXIDMapping(dpy, dpyInfo, xid, vendor);
}
}
@@ -979,11 +1002,13 @@ static void VendorFromXID(Display *dpy, __GLXdisplayInfo *dpyInfo, XID xid,
}
-void __glXAddVendorDrawableMapping(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor)
+int __glXAddVendorDrawableMapping(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor)
{
__GLXdisplayInfo *dpyInfo = __glXLookupDisplay(dpy);
if (dpyInfo != NULL) {
- AddVendorXIDMapping(dpy, dpyInfo, drawable, vendor);
+ return AddVendorXIDMapping(dpy, dpyInfo, drawable, vendor);
+ } else {
+ return -1;
}
}
@@ -997,7 +1022,7 @@ void __glXRemoveVendorDrawableMapping(Display *dpy, GLXDrawable drawable)
}
-int __glXVendorFromDrawable(Display *dpy, GLXDrawable drawable, __GLXvendorInfo **retVendor)
+__GLXvendorInfo *__glXVendorFromDrawable(Display *dpy, GLXDrawable drawable)
{
__glXThreadInitialize();
@@ -1012,10 +1037,7 @@ int __glXVendorFromDrawable(Display *dpy, GLXDrawable drawable, __GLXvendorInfo
}
}
- if (retVendor != NULL) {
- *retVendor = vendor;
- }
- return (vendor != NULL ? 0 : -1);
+ return vendor;
}
/*!
diff --git a/src/GLX/libglxmapping.h b/src/GLX/libglxmapping.h
index 984b374..2c377e7 100644
--- a/src/GLX/libglxmapping.h
+++ b/src/GLX/libglxmapping.h
@@ -50,6 +50,7 @@ struct __GLXvendorInfoRec {
__GLdispatchTable *glDispatch; //< GL dispatch table
const __GLXapiImports *glxvc;
+ const __GLdispatchPatchCallbacks *patchCallbacks;
__GLXdispatchTableStatic staticDispatch; //< static GLX dispatch table
};
@@ -98,21 +99,17 @@ __GLdispatchTable *__glXGetGLDispatch(Display *dpy, const int screen);
* Various functions to manage mappings used to determine the screen
* of a particular GLX call.
*/
-void __glXAddVendorContextMapping(Display *dpy, GLXContext context, __GLXvendorInfo *vendor);
+int __glXAddVendorContextMapping(Display *dpy, GLXContext context, __GLXvendorInfo *vendor);
void __glXRemoveVendorContextMapping(Display *dpy, GLXContext context);
-int __glXVendorFromContext(GLXContext context, __GLXvendorInfo **retVendor);
+__GLXvendorInfo *__glXVendorFromContext(GLXContext context);
-void __glXAddVendorFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor);
+int __glXAddVendorFBConfigMapping(Display *dpy, GLXFBConfig config, __GLXvendorInfo *vendor);
void __glXRemoveVendorFBConfigMapping(Display *dpy, GLXFBConfig config);
-int __glXVendorFromFBConfig(Display *dpy, GLXFBConfig config, __GLXvendorInfo **retVendor);
+__GLXvendorInfo *__glXVendorFromFBConfig(Display *dpy, GLXFBConfig config);
-void __glXAddScreenVisualMapping(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo *vendor);
-void __glXRemoveScreenVisualMapping(Display *dpy, const XVisualInfo *visual);
-int __glXVendorFromVisual(Display *dpy, const XVisualInfo *visual, __GLXvendorInfo **retVendor);
-
-void __glXAddVendorDrawableMapping(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor);
+int __glXAddVendorDrawableMapping(Display *dpy, GLXDrawable drawable, __GLXvendorInfo *vendor);
void __glXRemoveVendorDrawableMapping(Display *dpy, GLXDrawable drawable);
-int __glXVendorFromDrawable(Display *dpy, GLXDrawable drawable, __GLXvendorInfo **retVendor);
+__GLXvendorInfo *__glXVendorFromDrawable(Display *dpy, GLXDrawable drawable);
__GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName);
__GLXextFuncPtr __glXGenerateGLXEntrypoint(const GLubyte *procName);
diff --git a/src/GLdispatch/GLdispatch.c b/src/GLdispatch/GLdispatch.c
index 9c22498..aa0b64d 100644
--- a/src/GLdispatch/GLdispatch.c
+++ b/src/GLdispatch/GLdispatch.c
@@ -563,14 +563,16 @@ static int PatchEntrypoints(
if (stubCurrentPatchCb) {
// Notify the previous vendor that it no longer owns these
// entrypoints.
- stubCurrentPatchCb->releasePatch();
+ if (stubCurrentPatchCb->releasePatch != NULL) {
+ stubCurrentPatchCb->releasePatch();
+ }
}
if (patchCb) {
GLboolean anySuccess = GL_FALSE;
glvnd_list_for_each_entry(stub, &dispatchStubList, entry) {
- if (patchCb->checkPatchSupported(stub->callbacks.getStubType(),
+ if (patchCb->isPatchSupported(stub->callbacks.getStubType(),
stub->callbacks.getStubSize()))
{
if (stub->callbacks.startPatch()) {
@@ -826,6 +828,10 @@ void __glDispatchCheckMultithreaded(void)
}
}
UnlockDispatch();
+
+ if (stubCurrentPatchCb != NULL && stubCurrentPatchCb->threadAttach != NULL) {
+ stubCurrentPatchCb->threadAttach();
+ }
}
}
diff --git a/src/GLdispatch/GLdispatch.h b/src/GLdispatch/GLdispatch.h
index 5dd700a..3d83215 100644
--- a/src/GLdispatch/GLdispatch.h
+++ b/src/GLdispatch/GLdispatch.h
@@ -137,6 +137,81 @@ typedef struct __GLdispatchThreadStateRec {
struct __GLdispatchThreadStatePrivateRec *priv;
} __GLdispatchThreadState;
+typedef struct __GLdispatchPatchCallbacksRec {
+ /*!
+ * Checks to see if the vendor library supports patching the given stub
+ * type and size.
+ *
+ * \param type The type of entrypoints. This will be a one of the
+ * __GLDISPATCH_STUB_* values.
+ * \param stubSize The maximum size of the stub that the vendor library can
+ * write, in bytes.
+ * \param lookupStubOffset A callback into libglvnd to look up the address
+ * of each entrypoint.
+ */
+ GLboolean (* isPatchSupported)(int type, int stubSize);
+
+ /*!
+ * Called by libglvnd to request that a vendor library patch its top-level
+ * entrypoints.
+ *
+ * The vendor library should use the \p lookupStubOffset callback to find
+ * the addresses of each entrypoint.
+ *
+ * This function may be called more than once to patch multiple sets of
+ * entrypoints. For example, depending on how they're built, libOpenGL.so
+ * or libGL.so may have their own entrypoints that are separate functions
+ * from the ones in libGLdispatch.
+ *
+ * Note that during this call is the only time that the entrypoints can be
+ * modified. After the call to \c initiatePatch returns, the vendor library
+ * should treat the entrypoints as read-only.
+ *
+ * \param type The type of entrypoints. This will be a one of the
+ * __GLDISPATCH_STUB_* values.
+ * \param stubSize The maximum size of the stub that the vendor library can
+ * write, in bytes.
+ * \param lookupStubOffset A callback into libglvnd to look up the address
+ * of each entrypoint.
+ *
+ * \return GL_TRUE if the vendor library supports patching with this type
+ * and size.
+ */
+ GLboolean (*initiatePatch)(int type,
+ int stubSize,
+ DispatchPatchLookupStubOffset lookupStubOffset);
+
+ /*!
+ * (OPTIONAL) Called by libglvnd to notify the current vendor that it no
+ * longer owns the top-level entrypoints.
+ *
+ * Libglvnd will take care of the restoring the entrypoints back to their
+ * original state. The vendor library must not try to modify them.
+ */
+ void (*releasePatch)(void);
+
+ /*!
+ * (OPTIONAL) Called at the start of window-system functions (GLX and EGL).
+ * This callback allows vendor libraries to perform any per-thread
+ * initialization.
+ *
+ * This is basically a workaround for broken applications. A lot of apps
+ * will make one or more invalid GLX/EGL calls on a thread (often including
+ * a MakeCurrent with invalid parameters), and then will try to call an
+ * OpenGL function.
+ *
+ * A non-libglvnd-based driver would be able to initialize any thread state
+ * even on a bogus GLX call, but with libglvnd, those calls wouldn't get
+ * past libGLX.
+ *
+ * This function is optional. If it's \c NULL, then libGLdispatch will
+ * simply ignore it.
+ *
+ * \note This function may be called concurrently from multiple threads.
+ */
+ void (*threadAttach)(void);
+} __GLdispatchPatchCallbacks;
+
/*!
* Gets the version number for the ABI between libGLdispatch and the
* window-system libraries.
diff --git a/src/GLdispatch/GLdispatchPrivate.h b/src/GLdispatch/GLdispatchPrivate.h
index b025483..aca8de7 100644
--- a/src/GLdispatch/GLdispatchPrivate.h
+++ b/src/GLdispatch/GLdispatchPrivate.h
@@ -37,25 +37,6 @@
#include "utils_misc.h"
/*!
- * XXX: Any changes to the internal mapi enum should be accompanied by an ABI
- * update, and vice versa.
- */
-#define TLS_TYPE_CHECK(x) STATIC_ASSERT((int)__GLDISPATCH_STUB_ ## x == (int)ENTRY_ ## x)
-
-static inline void UNUSED __unused_tls_type_check(void)
-{
- TLS_TYPE_CHECK(X86_TLS);
- TLS_TYPE_CHECK(X86_64_TLS);
- TLS_TYPE_CHECK(X86_TSD);
- TLS_TYPE_CHECK(PURE_C);
- TLS_TYPE_CHECK(X86_64_TSD);
- TLS_TYPE_CHECK(ARMV7_THUMB_TSD);
- TLS_TYPE_CHECK(NUM_TYPES);
-}
-
-#undef TLS_TYPE_CHECK
-
-/*!
* Private dispatch table structure. This is used by GLdispatch for tracking
* and updating dispatch tables.
*/
diff --git a/src/GLdispatch/vnd-glapi/mapi/entry.h b/src/GLdispatch/vnd-glapi/mapi/entry.h
index 35758a2..bea812d 100644
--- a/src/GLdispatch/vnd-glapi/mapi/entry.h
+++ b/src/GLdispatch/vnd-glapi/mapi/entry.h
@@ -32,16 +32,6 @@
typedef void (*mapi_func)(void);
-enum {
- ENTRY_X86_TLS,
- ENTRY_X86_64_TLS,
- ENTRY_X86_TSD,
- ENTRY_PURE_C,
- ENTRY_X86_64_TSD,
- ENTRY_ARMV7_THUMB_TSD,
- ENTRY_NUM_TYPES
-};
-
extern const int entry_type;
extern const int entry_stub_size;
diff --git a/src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.c b/src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.c
index be394c9..7bd9da0 100644
--- a/src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.c
+++ b/src/GLdispatch/vnd-glapi/mapi/entry_armv7_tsd.c
@@ -39,6 +39,7 @@
#include "u_macros.h"
#include "u_current.h"
#include "utils_misc.h"
+#include "glvnd/GLdispatchABI.h"
/*
* See: https://sourceware.org/binutils/docs/as/ARM-Directives.html
@@ -157,7 +158,7 @@ __asm__(".balign 4096\n"
__asm__(".arm\n\t");
#endif
-const int entry_type = ENTRY_ARMV7_THUMB_TSD;
+const int entry_type = __GLDISPATCH_STUB_ARMV7_THUMB;
const int entry_stub_size = ARMV7_ENTRY_SIZE;
static const int TEMPLATE_OFFSET_CURRENT_TABLE = ARMV7_BYTECODE_SIZE - 3*4;
diff --git a/src/GLdispatch/vnd-glapi/mapi/entry_pure_c.c b/src/GLdispatch/vnd-glapi/mapi/entry_pure_c.c
index 7b9ea82..134143e 100644
--- a/src/GLdispatch/vnd-glapi/mapi/entry_pure_c.c
+++ b/src/GLdispatch/vnd-glapi/mapi/entry_pure_c.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include "glapi/glapi.h"
+#include "glvnd/GLdispatchABI.h"
static INLINE const struct _glapi_table *
entry_current_get(void)
@@ -48,7 +49,7 @@ entry_current_get(void)
#define MAPI_TMP_PUBLIC_ENTRIES
#include "mapi_tmp.h"
-const int entry_type = ENTRY_PURE_C;
+const int entry_type = __GLDISPATCH_STUB_UNKNOWN;
const int entry_stub_size = 0;
void
diff --git a/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tls.c b/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tls.c
index 7ac068c..d99c8a4 100644
--- a/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tls.c
+++ b/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tls.c
@@ -36,6 +36,7 @@
#include "utils_misc.h"
#include "u_macros.h"
#include "glapi/glapi.h"
+#include "glvnd/GLdispatchABI.h"
#define ENTRY_STUB_ALIGN 32
#define ENTRY_STUB_SIZE ENTRY_STUB_ALIGN
@@ -74,7 +75,7 @@ __asm__("x86_64_current_tls:\n\t"
extern unsigned long
x86_64_current_tls();
-const int entry_type = ENTRY_X86_64_TLS;
+const int entry_type = __GLDISPATCH_STUB_X86_64;
const int entry_stub_size = ENTRY_STUB_SIZE;
void entry_generate_default_code(char *entry, int slot)
diff --git a/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tsd.c b/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tsd.c
index e2199a0..008d5ea 100644
--- a/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tsd.c
+++ b/src/GLdispatch/vnd-glapi/mapi/entry_x86_64_tsd.c
@@ -38,6 +38,7 @@
#include "u_macros.h"
#include "glapi/glapi.h"
+#include "glvnd/GLdispatchABI.h"
#define X86_64_ENTRY_SIZE 64
@@ -90,7 +91,7 @@ __asm__(".balign 4096\n"
"public_entry_end:");
__asm__(".text\n");
-const int entry_type = ENTRY_X86_64_TSD;
+const int entry_type = __GLDISPATCH_STUB_X86_64;
const int entry_stub_size = X86_64_ENTRY_SIZE;
static const unsigned char ENTRY_TEMPLATE[] =
diff --git a/src/GLdispatch/vnd-glapi/mapi/entry_x86_tsd.c b/src/GLdispatch/vnd-glapi/mapi/entry_x86_tsd.c
index 1f58642..4c23239 100644
--- a/src/GLdispatch/vnd-glapi/mapi/entry_x86_tsd.c
+++ b/src/GLdispatch/vnd-glapi/mapi/entry_x86_tsd.c
@@ -36,6 +36,7 @@
#include "u_macros.h"
#include "glapi/glapi.h"
+#include "glvnd/GLdispatchABI.h"
#define X86_ENTRY_SIZE 32
@@ -68,7 +69,7 @@ __asm__(".balign 4096\n"
"public_entry_end:");
__asm__(".text\n");
-const int entry_type = ENTRY_X86_TSD;
+const int entry_type = __GLDISPATCH_STUB_X86;
const int entry_stub_size = X86_ENTRY_SIZE;
static const unsigned char ENTRY_TEMPLATE[] =
diff --git a/tests/GLX_dummy/GLX_dummy.c b/tests/GLX_dummy/GLX_dummy.c
index 2e15db8..29465c9 100644
--- a/tests/GLX_dummy/GLX_dummy.c
+++ b/tests/GLX_dummy/GLX_dummy.c
@@ -42,8 +42,7 @@
#include "compiler.h"
-static char *thisVendorName;
-static __GLXapiExports apiExports;
+static const __GLXapiExports *apiExports = NULL;
/*
* Dummy context structure.
@@ -330,7 +329,7 @@ static void dummySelectEvent (Display *dpy,
*/
static void dummy_glBegin (void)
{
- GLXContext ctx = apiExports.getCurrentContext();
+ GLXContext ctx = apiExports->getCurrentContext();
assert(ctx);
ctx->beginHit++;
@@ -338,7 +337,7 @@ static void dummy_glBegin (void)
static void dummy_glVertex3fv(GLfloat *v)
{
- GLXContext ctx = apiExports.getCurrentContext();
+ GLXContext ctx = apiExports->getCurrentContext();
assert(ctx);
ctx->vertex3fvHit++;
@@ -346,7 +345,7 @@ static void dummy_glVertex3fv(GLfloat *v)
static void dummy_glEnd (void)
{
- GLXContext ctx = apiExports.getCurrentContext();
+ GLXContext ctx = apiExports->getCurrentContext();
assert(ctx);
ctx->endHit++;
@@ -356,7 +355,7 @@ static void dummy_glMakeCurrentTestResults(GLint req,
GLboolean *saw,
void **ret)
{
- GLXContext ctx = apiExports.getCurrentContext();
+ GLXContext ctx = apiExports->getCurrentContext();
assert(ctx);
*saw = GL_TRUE;
@@ -372,7 +371,11 @@ static void dummy_glMakeCurrentTestResults(GLint req,
break;
case GL_MC_VENDOR_STRING:
{
- *ret = thisVendorName ? strdup(thisVendorName) : NULL;
+ // FIXME: This is used from testglxnscreens to check that the
+ // correct vendor library is loaded from each display. Originally,
+ // it used the vendor name passed to __glx_Main, but libGLX doesn't
+ // provide the vendor name anymore.
+ *ret = NULL;
}
break;
case GL_MC_LAST_REQ:
@@ -402,13 +405,13 @@ static void dispatch_glXExampleExtensionFunction(Display *dpy,
ExampleExtensionFunctionPtr func;
const int index = dummyExampleExtensionFunctionIndex;
- dynDispatch = apiExports.getDynDispatch(dpy, screen);
+ dynDispatch = apiExports->getDynDispatch(dpy, screen);
if (!dynDispatch) {
return;
}
func = (ExampleExtensionFunctionPtr)
- apiExports.fetchDispatchEntry(dynDispatch, index);
+ apiExports->fetchDispatchEntry(dynDispatch, index);
if (func) {
func(dpy, screen, retval);
}
@@ -503,7 +506,7 @@ static void dummySetDispatchIndex (const GLubyte *procName, int ind
#if defined(PATCH_ENTRYPOINTS)
PUBLIC int __glXSawVertex3fv;
-static void patch_x86_64_tls(char *writeEntry,
+static void patch_x86_64(char *writeEntry,
const char *execEntry,
int stubSize)
{
@@ -535,7 +538,7 @@ static void patch_x86_64_tls(char *writeEntry,
#endif
}
-static void patch_x86_tls(char *writeEntry,
+static void patch_x86(char *writeEntry,
const char *execEntry,
int stubSize)
{
@@ -575,7 +578,7 @@ static void patch_x86_tls(char *writeEntry,
#endif
}
-static void patch_armv7_thumb_tsd(char *writeEntry,
+static void patch_armv7_thumb(char *writeEntry,
const char *execEntry,
int stubSize)
{
@@ -621,11 +624,9 @@ static void patch_armv7_thumb_tsd(char *writeEntry,
static GLboolean dummyCheckPatchSupported(int type, int stubSize)
{
switch (type) {
- case __GLDISPATCH_STUB_X86_64_TLS:
- case __GLDISPATCH_STUB_X86_TLS:
- case __GLDISPATCH_STUB_X86_TSD:
- case __GLDISPATCH_STUB_X86_64_TSD:
- case __GLDISPATCH_STUB_ARMV7_THUMB_TSD:
+ case __GLDISPATCH_STUB_X86_64:
+ case __GLDISPATCH_STUB_X86:
+ case __GLDISPATCH_STUB_ARMV7_THUMB:
return GL_TRUE;
default:
return GL_FALSE;
@@ -646,16 +647,14 @@ static GLboolean dummyInitiatePatch(int type,
if (lookupStubOffset("Vertex3fv", &writeAddr, &execAddr)) {
switch (type) {
- case __GLDISPATCH_STUB_X86_64_TLS:
- case __GLDISPATCH_STUB_X86_64_TSD:
- patch_x86_64_tls(writeAddr, execAddr, stubSize);
+ case __GLDISPATCH_STUB_X86_64:
+ patch_x86_64(writeAddr, execAddr, stubSize);
break;
- case __GLDISPATCH_STUB_X86_TLS:
- case __GLDISPATCH_STUB_X86_TSD:
- patch_x86_tls(writeAddr, execAddr, stubSize);
+ case __GLDISPATCH_STUB_X86:
+ patch_x86(writeAddr, execAddr, stubSize);
break;
- case __GLDISPATCH_STUB_ARMV7_THUMB_TSD:
- patch_armv7_thumb_tsd(writeAddr, execAddr, stubSize);
+ case __GLDISPATCH_STUB_ARMV7_THUMB:
+ patch_armv7_thumb(writeAddr, execAddr, stubSize);
break;
default:
assert(0);
@@ -665,38 +664,30 @@ static GLboolean dummyInitiatePatch(int type,
return GL_TRUE;
}
-static void dummyReleasePatch(void)
-{
-}
-
-static const __GLdispatchPatchCallbacks dummyPatchCallbacks =
-{
- .checkPatchSupported = dummyCheckPatchSupported,
- .initiatePatch = dummyInitiatePatch,
- .releasePatch = dummyReleasePatch,
-};
#endif // defined(PATCH_ENTRYPOINTS)
-static const __GLXapiImports dummyImports =
-{
- .checkSupportsScreen = dummyCheckSupportsScreen,
- .getProcAddress = dummyGetProcAddress,
- .getDispatchAddress = dummyGetDispatchAddress,
- .setDispatchIndex = dummySetDispatchIndex,
+PUBLIC Bool __glx_Main(uint32_t version,
+ const __GLXapiExports *exports,
+ __GLXvendorInfo *vendor,
+ __GLXapiImports *imports)
+{
+ if (GLX_VENDOR_ABI_GET_MAJOR_VERSION(version)
+ == GLX_VENDOR_ABI_GET_MAJOR_VERSION(GLX_VENDOR_ABI_VERSION)) {
+ if (GLX_VENDOR_ABI_GET_MINOR_VERSION(version)
+ >= GLX_VENDOR_ABI_GET_MINOR_VERSION(GLX_VENDOR_ABI_VERSION)) {
+ apiExports = exports;
+
+ imports->isScreenSupported = dummyCheckSupportsScreen;
+ imports->getProcAddress = dummyGetProcAddress;
+ imports->getDispatchAddress = dummyGetDispatchAddress;
+ imports->setDispatchIndex = dummySetDispatchIndex;
#if defined(PATCH_ENTRYPOINTS)
- .patchCallbacks = &dummyPatchCallbacks,
-#else
- .patchCallbacks = NULL,
+ imports->isPatchSupported = dummyCheckPatchSupported;
+ imports->initiatePatch = dummyInitiatePatch;
#endif
-};
-PUBLIC __GLX_MAIN_PROTO(version, exports, vendorName)
-{
- thisVendorName = strdup(vendorName);
- if (version <= GLX_VENDOR_ABI_VERSION) {
- memcpy(&apiExports, exports, sizeof(*exports));
- return &dummyImports;
- } else {
- return NULL;
+ return True;
+ }
}
+ return False;
}