diff options
Diffstat (limited to 'src/GLX/libglxmapping.c')
-rw-r--r-- | src/GLX/libglxmapping.c | 132 |
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; } /*! |