summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Brenneman <kbrenneman@nvidia.com>2016-03-10 16:36:45 -0700
committerKyle Brenneman <kbrenneman@nvidia.com>2016-03-10 16:57:34 -0700
commit3a84276f63242f8f231b4772448d025c1ae41cc1 (patch)
treedf28f21debcea8625f6ff77b43d9b0f1e6fb28e7
parentda7ae346e36e2b9c3e0e49ac3ad58227b3163454 (diff)
GLX: Add the patch callbacks directly to __GLXapiImports.
Added the function pointers for entrypoint rewriting as members of __GLXapiImports, instead of using a separate __GLdispatchPatchCallbacks pointer. Moved the __GLdispatchPatchCallbacks struct to GLdispatch.h.
-rw-r--r--include/glvnd/GLdispatchABI.h75
-rw-r--r--include/glvnd/libglxabi.h85
-rw-r--r--src/GLX/libglx.c2
-rw-r--r--src/GLX/libglxmapping.c56
-rw-r--r--src/GLX/libglxmapping.h1
-rw-r--r--src/GLdispatch/GLdispatch.h75
-rw-r--r--tests/GLX_dummy/GLX_dummy.c4
7 files changed, 175 insertions, 123 deletions
diff --git a/include/glvnd/GLdispatchABI.h b/include/glvnd/GLdispatchABI.h
index 16afb3d..25d593a 100644
--- a/include/glvnd/GLdispatchABI.h
+++ b/include/glvnd/GLdispatchABI.h
@@ -113,81 +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 (* 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;
-
#if defined(__cplusplus)
}
#endif
diff --git a/include/glvnd/libglxabi.h b/include/glvnd/libglxabi.h
index 52ff3b9..13189b9 100644
--- a/include/glvnd/libglxabi.h
+++ b/include/glvnd/libglxabi.h
@@ -297,19 +297,90 @@ 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
* optimization that may not be available at runtime; the vendor library
* must not depend on this functionality for correctness.
*
- * Like the __GLXapiImports struct itself, this struct is allocated and
- * zeroed by libGLX. The vendor library should assign function pointers
- * to the members of this struct, but should not change the
- * \c patchCallbacks pointer itself.
+ * 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.
*/
- __GLdispatchPatchCallbacks *patchCallbacks;
+ void (*patchThreadAttach)(void);
} __GLXapiImports;
diff --git a/src/GLX/libglx.c b/src/GLX/libglx.c
index 01ea9a7..c61c17a 100644
--- a/src/GLX/libglx.c
+++ b/src/GLX/libglx.c
@@ -866,7 +866,7 @@ static Bool InternalMakeCurrentDispatch(
&apiState->glas,
vendor->glDispatch,
vendor->vendorID,
- vendor->glxvc->patchCallbacks
+ vendor->patchCallbacks
);
if (ret) {
diff --git a/src/GLX/libglxmapping.c b/src/GLX/libglxmapping.c
index 40f36bc..506cb06 100644
--- a/src/GLX/libglxmapping.c
+++ b/src/GLX/libglxmapping.c
@@ -447,37 +447,6 @@ static GLboolean LookupVendorEntrypoints(__GLXvendorInfo *vendor)
return GL_TRUE;
}
-static Bool CheckVendorImportsTable(__GLXvendorNameHash *pEntry)
-{
- // 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)
- {
- return False;
- }
-
- // Check to see whether this vendor library can support entrypoint
- // patching.
- if (pEntry->imports.patchCallbacks != NULL) {
- if (pEntry->imports.patchCallbacks != &pEntry->patchCallbacks) {
- // The vendor library shouldn't replace the patchCallbacks
- // pointer. If it does, then just ignore it.
- pEntry->imports.patchCallbacks = NULL;
- } else {
- if (pEntry->patchCallbacks.isPatchSupported == NULL
- || pEntry->patchCallbacks.initiatePatch == NULL) {
- // If we don't have at least the isPatchSupported and
- // initiatePatch callbacks, then patching isn't
- // supported.
- pEntry->imports.patchCallbacks = NULL;
- }
- }
- }
- return True;
-}
-
static void *VendorGetProcAddressCallback(const char *procName, void *param)
{
__GLXvendorInfo *vendor = (__GLXvendorInfo *) param;
@@ -522,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);
@@ -551,9 +521,6 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
goto fail;
}
- // Plug in the vendor imports table.
- pEntry->imports.patchCallbacks = &pEntry->patchCallbacks;
-
/* Initialize the dynamic dispatch table */
LKDHASH_INIT(vendor->dynDispatchHash);
@@ -564,17 +531,30 @@ __GLXvendorInfo *__glXLookupVendorByName(const char *vendorName)
goto fail;
}
- // Check to see whether this vendor library can support entrypoint
- // patching.
- if (!CheckVendorImportsTable(pEntry)) {
+ // 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;
}
- vendor->glxvc = &pEntry->imports;
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);
diff --git a/src/GLX/libglxmapping.h b/src/GLX/libglxmapping.h
index 525ea27..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
};
diff --git a/src/GLdispatch/GLdispatch.h b/src/GLdispatch/GLdispatch.h
index 5532403..0573bba 100644
--- a/src/GLdispatch/GLdispatch.h
+++ b/src/GLdispatch/GLdispatch.h
@@ -123,6 +123,81 @@ typedef struct __GLdispatchAPIStateRec {
struct __GLdispatchAPIStatePrivateRec *priv;
} __GLdispatchAPIState;
+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/tests/GLX_dummy/GLX_dummy.c b/tests/GLX_dummy/GLX_dummy.c
index f8b6347..cb493eb 100644
--- a/tests/GLX_dummy/GLX_dummy.c
+++ b/tests/GLX_dummy/GLX_dummy.c
@@ -679,8 +679,8 @@ PUBLIC Bool __glx_Main(uint32_t version,
imports->getDispatchAddress = dummyGetDispatchAddress;
imports->setDispatchIndex = dummySetDispatchIndex;
#if defined(PATCH_ENTRYPOINTS)
- imports->patchCallbacks->isPatchSupported = dummyCheckPatchSupported;
- imports->patchCallbacks->initiatePatch = dummyInitiatePatch;
+ imports->isPatchSupported = dummyCheckPatchSupported;
+ imports->initiatePatch = dummyInitiatePatch;
#endif
return True;