summaryrefslogtreecommitdiff
path: root/src/GLX/libglxmapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/GLX/libglxmapping.c')
-rw-r--r--src/GLX/libglxmapping.c132
1 files changed, 77 insertions, 55 deletions
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;
}
/*!