static GLboolean AllocDispatchIndex(__GLXvendorInfo *vendor, const GLubyte *procName) { __GLXdispatchIndexHash *pEntry = malloc(sizeof(*pEntry)); if (!pEntry) { return GL_FALSE; } pEntry->procName = (GLubyte *)strdup((const char *)procName); if (!pEntry->procName) { free(pEntry); return GL_FALSE; } LKDHASH_WRLOCK(__glXPthreadFuncs, __glXDispatchIndexHash); pEntry->index = __glXNextUnusedHashIndex++; // Notify the vendor this is the index which should be used vendor->staticDispatch-> glxvc.setDispatchIndex(procName, pEntry->index); HASH_ADD_INT(_LH(__glXDispatchIndexHash), index, pEntry); LKDHASH_UNLOCK(__glXPthreadFuncs, __glXDispatchIndexHash); return GL_TRUE; }
/*! * This function queries each loaded vendor to determine if there is * a vendor-implemented dispatch function. The dispatch function * uses the vendor <-> API library ABI to determine the screen given * the parameters of the function and dispatch to the correct vendor's * implementation. */ __GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName) { __GLXextFuncPtr addr = NULL; __GLXvendorNameHash *pEntry, *tmp; /* * Note that if a GLX extension function doesn't depend on calling any * other GLX functions first, then the app could call it before loading any * vendor libraries. If that happens, then the entrypoint would go to a * no-op stub instead of the correct dispatch stub. * * Running into that case would be an application bug, since it means that * the application is calling an extension function without checking the * extension string -- calling glXGetClientString would have loaded the * vendor libraries for every screen. * * In order to work with a buggy app like that, we might have to find and * load all available vendor libraries until we find one that supports the * function. Lacking that, a user could work around the issue by setting * __GLX_VENDOR_LIBRARY_NAME. */ // Look through the vendors that we've already loaded, and see if any of // them support the function. LKDHASH_RDLOCK(__glXPthreadFuncs, __glXVendorNameHash); HASH_ITER(hh, _LH(__glXVendorNameHash), pEntry, tmp) { addr = __glXFindVendorDispatchAddress((const char *)procName, pEntry->vendor); if (addr) { break; } }
/* * This function queries each loaded vendor to determine if there is * a vendor-implemented dispatch function. The dispatch function * uses the vendor <-> API library ABI to determine the screen given * the parameters of the function and dispatch to the correct vendor's * implementation. */ __GLXextFuncPtr __glXGetGLXDispatchAddress(const GLubyte *procName) { __GLXextFuncPtr addr = NULL; __GLXvendorNameHash *pEntry, *tmp; /* * XXX for full correctness, we should probably load vendors * on all screens up-front before doing this. However, that * might be bad for performance? */ LKDHASH_RDLOCK(__glXPthreadFuncs, __glXVendorNameHash); HASH_ITER(hh, _LH(__glXVendorNameHash), pEntry, tmp) { // See if the current vendor supports this GLX entry point addr = pEntry->vendor->staticDispatch-> glxvc.getDispatchAddress(procName); if (addr) { // Allocate the new dispatch index. if (!AllocDispatchIndex(pEntry->vendor, procName)) { addr = NULL; } break; } }