diff --git a/src/EGL/libegl.c b/src/EGL/libegl.c index 4e9f615..30468b1 100644 --- a/src/EGL/libegl.c +++ b/src/EGL/libegl.c @@ -955,9 +955,73 @@ PUBLIC const char *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) } } +static EGLBoolean QueryVendorDevices(__EGLvendorInfo *vendor, EGLint max_devices, + EGLDeviceEXT *devices, EGLint *num_devices) +{ + EGLDeviceEXT *vendorDevices = NULL; + EGLint vendorCount = 0; + EGLint i; + + if (!vendor->supportsDevice) { + return EGL_TRUE; + } + + if (!vendor->staticDispatch.queryDevicesEXT(0, NULL, &vendorCount)) { + // Even if this vendor fails, we can still return the devices from any + // other vendors + return EGL_TRUE; + } + if (vendorCount <= 0) { + return EGL_TRUE; + } + + if (devices == NULL) { + // We're only getting the number of devices. + *num_devices += vendorCount; + return EGL_TRUE; + } + + vendorDevices = malloc(sizeof(EGLDeviceEXT) * vendorCount); + if (vendorDevices == NULL) + { + __eglReportCritical(EGL_BAD_ALLOC, "eglQueryDevicesEXT", + __eglGetThreadLabel(), "Out of memory allocating device list"); + return EGL_FALSE; + } + + if (!vendor->staticDispatch.queryDevicesEXT(vendorCount, vendorDevices, &vendorCount)) { + free(vendorDevices); + return EGL_TRUE; + } + + // Add or update our mapping for all of the devices, and fill in the + // caller's array. + for (i=0; isupportsDevice) { + if (dev == EGL_NO_DEVICE_EXT) { + // If the handle is NULL, then just silently ignore it. return EGL_TRUE; } - if (!vendor->staticDispatch.queryDevicesEXT(0, NULL, &count)) { - // Even if this vendor fails, we can still return the devices from any - // other vendors - return EGL_TRUE; - } - if (count <= 0) { - return EGL_TRUE; - } - - devices = (EGLDeviceEXT *) malloc(count * sizeof(EGLDeviceEXT)); - if (devices == NULL) { - return EGL_FALSE; - } - - if (!vendor->staticDispatch.queryDevicesEXT(count, devices, &count)) { - free(devices); - return EGL_FALSE; - } - - newDevList = (__EGLdeviceInfo *) realloc(__eglDeviceList, - (__eglDeviceCount + count) * sizeof(__EGLdeviceInfo)); - if (newDevList == NULL) { - free(devices); - return EGL_FALSE; - } - __eglDeviceList = newDevList; - - for (i=0; ihandle = dev; + HASH_ADD_PTR(_LH(__eglDeviceHash), handle, devInfo); } - free(devices); - + devInfo->vendor = vendor; + LKDHASH_UNLOCK(__eglDeviceHash); return EGL_TRUE; } -void InitDeviceListInternal(void) -{ - struct glvnd_list *vendorList = __eglLoadVendors(); - __EGLvendorInfo *vendor; - EGLint i; - - __eglDeviceList = NULL; - __eglDeviceHash = NULL; - __eglDeviceCount = 0; - - glvnd_list_for_each_entry(vendor, vendorList, entry) { - if (!AddVendorDevices(vendor)) { - free(__eglDeviceList); - __eglDeviceList = NULL; - __eglDeviceCount = 0; - return; - } - } - - // Build a hashtable for the devices. - for (i=0; i<__eglDeviceCount; i++) { - __EGLdeviceInfo *dev = &__eglDeviceList[i]; - HASH_ADD_PTR(__eglDeviceHash, handle, dev); - } -} - -void __eglInitDeviceList(void) -{ - __glvndPthreadFuncs.once(&deviceListInitOnce, InitDeviceListInternal); -} - __EGLvendorInfo *__eglGetVendorFromDevice(EGLDeviceEXT dev) { __EGLdeviceInfo *devInfo; + __EGLvendorInfo *vendor = NULL; - __eglInitDeviceList(); - - HASH_FIND_PTR(__eglDeviceHash, &dev, devInfo); + LKDHASH_RDLOCK(__eglDeviceHash); + HASH_FIND_PTR(_LH(__eglDeviceHash), &dev, devInfo); if (devInfo != NULL) { - return devInfo->vendor; + vendor = devInfo->vendor; } else { - return NULL; + vendor = NULL; } + LKDHASH_UNLOCK(__eglDeviceHash); + + return vendor; } diff --git a/src/EGL/libeglmapping.h b/src/EGL/libeglmapping.h index 26747e4..d1018d9 100644 --- a/src/EGL/libeglmapping.h +++ b/src/EGL/libeglmapping.h @@ -44,16 +44,6 @@ typedef struct __EGLdisplayInfoRec { __EGLvendorInfo *vendor; } __EGLdisplayInfo; -typedef struct __EGLdeviceInfoRec { - EGLDeviceEXT handle; - __EGLvendorInfo *vendor; - UT_hash_handle hh; -} __EGLdeviceInfo; - -extern __EGLdeviceInfo *__eglDeviceList; -extern __EGLdeviceInfo *__eglDeviceHash; -extern int __eglDeviceCount; - void __eglThreadInitialize(void); /*! @@ -61,22 +51,12 @@ void __eglThreadInitialize(void); */ void __eglMappingInit(void); -/*! - * Initializes the EGLDeviceEXT list and hashtable. - * - * This function must be called before trying to access the \c __eglDeviceList - * array. - */ -void __eglInitDeviceList(void); - /*! * This handles freeing all mapping state during library teardown * or resetting locks on fork recovery. */ void __eglMappingTeardown(EGLBoolean doReset); -const __EGLdeviceInfo *__eglGetDeviceList(EGLint *deviceCount); - /*! * Looks up the __EGLdisplayInfo structure for a display. If the display does * not exist, then this returns NULL. @@ -110,6 +90,11 @@ __eglMustCastToProperFunctionPointerType __eglGetEGLDispatchAddress(const char * __eglMustCastToProperFunctionPointerType __eglFetchDispatchEntry(__EGLvendorInfo *vendor, int index); +/** + * Adds an EGLDeviceEXT handle to libglvnd's mapping. + */ +EGLBoolean __eglAddDevice(EGLDeviceEXT dev, __EGLvendorInfo *vendor); + __EGLvendorInfo *__eglGetVendorFromDevice(EGLDeviceEXT dev); void __eglSetError(EGLint errorCode);