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.
This commit is contained in:
parent
da7ae346e3
commit
3a84276f63
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
__GLdispatchPatchCallbacks *patchCallbacks;
|
||||
|
||||
/*!
|
||||
* (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.
|
||||
*/
|
||||
void (*patchThreadAttach)(void);
|
||||
|
||||
} __GLXapiImports;
|
||||
|
||||
|
|
|
@ -866,7 +866,7 @@ static Bool InternalMakeCurrentDispatch(
|
|||
&apiState->glas,
|
||||
vendor->glDispatch,
|
||||
vendor->vendorID,
|
||||
vendor->glxvc->patchCallbacks
|
||||
vendor->patchCallbacks
|
||||
);
|
||||
|
||||
if (ret) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -50,6 +50,7 @@ struct __GLXvendorInfoRec {
|
|||
__GLdispatchTable *glDispatch; //< GL dispatch table
|
||||
|
||||
const __GLXapiImports *glxvc;
|
||||
const __GLdispatchPatchCallbacks *patchCallbacks;
|
||||
__GLXdispatchTableStatic staticDispatch; //< static GLX dispatch table
|
||||
};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue