Merge branch 'egl-allow-adding-devices' into 'master'
EGL: Allow adding EGLDeviceEXT handles See merge request glvnd/libglvnd!239
This commit is contained in:
commit
055a4bab62
|
@ -82,7 +82,7 @@ extern "C" {
|
|||
* will still work.
|
||||
*/
|
||||
#define EGL_VENDOR_ABI_MAJOR_VERSION ((uint32_t) 0)
|
||||
#define EGL_VENDOR_ABI_MINOR_VERSION ((uint32_t) 1)
|
||||
#define EGL_VENDOR_ABI_MINOR_VERSION ((uint32_t) 2)
|
||||
#define EGL_VENDOR_ABI_VERSION ((EGL_VENDOR_ABI_MAJOR_VERSION << 16) | EGL_VENDOR_ABI_MINOR_VERSION)
|
||||
static inline uint32_t EGL_VENDOR_ABI_GET_MAJOR_VERSION(uint32_t version)
|
||||
{
|
||||
|
@ -191,6 +191,14 @@ typedef struct __EGLapiExportsRec {
|
|||
* Returns the EGL vendor for an EGLDeviceEXT handle.
|
||||
*/
|
||||
__EGLvendorInfo *(*getVendorFromDevice)(EGLDeviceEXT dev);
|
||||
|
||||
/**
|
||||
* Sets the EGL vendor for an EGLDeviceEXT handle. The dispatch stub for
|
||||
* any function that returns an EGLDeviceEXT handle should call this.
|
||||
*
|
||||
* Supported since ABI version 1.2.
|
||||
*/
|
||||
EGLBoolean (* setVendorForDevice)(EGLDeviceEXT dev, __EGLvendorInfo *vendor);
|
||||
} __EGLapiExports;
|
||||
|
||||
/*****************************************************************************
|
||||
|
|
119
src/EGL/libegl.c
119
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; i<vendorCount; i++)
|
||||
{
|
||||
if (!__eglAddDevice(vendorDevices[i], vendor))
|
||||
{
|
||||
__eglReportCritical(EGL_BAD_ALLOC, "eglQueryDevicesEXT",
|
||||
__eglGetThreadLabel(), "Out of memory allocating device/vendor map");
|
||||
free(vendorDevices);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (*num_devices < max_devices)
|
||||
{
|
||||
devices[*num_devices] = vendorDevices[i];
|
||||
(*num_devices)++;
|
||||
}
|
||||
}
|
||||
free(vendorDevices);
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean EGLAPIENTRY eglQueryDevicesEXT(EGLint max_devices,
|
||||
EGLDeviceEXT *devices, EGLint *num_devices)
|
||||
{
|
||||
struct glvnd_list *vendorList;
|
||||
__EGLvendorInfo *vendor;
|
||||
|
||||
__eglEntrypointCommon();
|
||||
|
||||
if (num_devices == NULL || (max_devices <= 0 && devices != NULL)) {
|
||||
|
@ -966,21 +1030,58 @@ EGLBoolean EGLAPIENTRY eglQueryDevicesEXT(EGLint max_devices,
|
|||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
__eglInitDeviceList();
|
||||
vendorList = __eglLoadVendors();
|
||||
|
||||
if (devices != NULL) {
|
||||
EGLint i;
|
||||
|
||||
*num_devices = (max_devices < __eglDeviceCount ? max_devices : __eglDeviceCount);
|
||||
for (i = 0; i < *num_devices; i++) {
|
||||
devices[i] = __eglDeviceList[i].handle;
|
||||
// Initialize num_devices. QueryVendorDevices will update it.
|
||||
*num_devices = 0;
|
||||
glvnd_list_for_each_entry(vendor, vendorList, entry) {
|
||||
if (!QueryVendorDevices(vendor, max_devices, devices, num_devices)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
} else {
|
||||
*num_devices = __eglDeviceCount;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean eglQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
|
||||
if (value == NULL) {
|
||||
__eglReportError(EGL_BAD_PARAMETER, "eglQueryDisplayAttribEXT", NULL,
|
||||
"Missing value pointer");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
vendor = __eglGetVendorFromDisplay(dpy);
|
||||
if (vendor == NULL) {
|
||||
__eglReportError(EGL_BAD_DISPLAY, "eglQueryDisplayAttribEXT", NULL,
|
||||
"Invalid EGLDisplay handle");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (vendor->staticDispatch.queryDisplayAttribEXT == NULL) {
|
||||
__eglReportError(EGL_BAD_DISPLAY, "eglQueryDisplayAttribEXT", NULL,
|
||||
"Driver does not support eglQueryDisplayAttribEXT");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
__eglSetLastVendor(vendor);
|
||||
if (!vendor->staticDispatch.queryDisplayAttribEXT(dpy, attribute, value)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (attribute == EGL_DEVICE_EXT && (EGLDeviceEXT) *value != EGL_NO_DEVICE_EXT) {
|
||||
if (!__eglAddDevice((EGLDeviceEXT) *value, vendor)) {
|
||||
__eglReportCritical(EGL_BAD_ALLOC, "eglQueryDevicesEXT",
|
||||
__eglGetThreadLabel(), "Out of memory allocating device/vendor map");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
// TODO: The function hash is the same as in GLX. It should go into a common
|
||||
// file.
|
||||
typedef struct {
|
||||
|
|
|
@ -91,6 +91,7 @@ typedef struct __EGLdispatchTableStaticRec {
|
|||
|
||||
// Extension functions that libEGL cares about.
|
||||
EGLBoolean (* queryDevicesEXT) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
|
||||
EGLBoolean (* queryDisplayAttribEXT) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
|
||||
|
||||
|
||||
EGLint (* debugMessageControlKHR) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
|
||||
|
|
|
@ -41,10 +41,12 @@
|
|||
|
||||
static glvnd_mutex_t dispatchIndexMutex = GLVND_MUTEX_INITIALIZER;
|
||||
|
||||
__EGLdeviceInfo *__eglDeviceList = NULL;
|
||||
__EGLdeviceInfo *__eglDeviceHash = NULL;
|
||||
int __eglDeviceCount = 0;
|
||||
static glvnd_once_t deviceListInitOnce = GLVND_ONCE_INIT;
|
||||
typedef struct __EGLdeviceInfoRec {
|
||||
EGLDeviceEXT handle;
|
||||
__EGLvendorInfo *vendor;
|
||||
UT_hash_handle hh;
|
||||
} __EGLdeviceInfo;
|
||||
static DEFINE_INITIALIZED_LKDHASH(__EGLdeviceInfo, __eglDeviceHash);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
@ -256,111 +258,52 @@ void __eglMappingTeardown(EGLBoolean doReset)
|
|||
LKDHASH_TEARDOWN(__EGLdisplayInfoHash,
|
||||
__eglDisplayInfoHash, NULL, NULL, EGL_FALSE);
|
||||
|
||||
LKDHASH_TEARDOWN(__EGLdeviceInfo,
|
||||
__eglDeviceHash, NULL, NULL, EGL_FALSE);
|
||||
|
||||
__glvndWinsysDispatchCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
static EGLBoolean AddVendorDevices(__EGLvendorInfo *vendor)
|
||||
EGLBoolean __eglAddDevice(EGLDeviceEXT dev, __EGLvendorInfo *vendor)
|
||||
{
|
||||
EGLDeviceEXT *devices = NULL;
|
||||
EGLint count = 0;
|
||||
__EGLdeviceInfo *newDevList;
|
||||
EGLint i, j;
|
||||
__EGLdeviceInfo *devInfo = NULL;
|
||||
|
||||
if (!vendor->supportsDevice) {
|
||||
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; i<count; i++) {
|
||||
// Make sure we haven't already gotten a device with this handle.
|
||||
EGLBoolean found = EGL_FALSE;
|
||||
for (j=0; j<__eglDeviceCount; j++) {
|
||||
if (__eglDeviceList[j].handle == devices[i]) {
|
||||
found = EGL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
__eglDeviceList[__eglDeviceCount].handle = devices[i];
|
||||
__eglDeviceList[__eglDeviceCount].vendor = vendor;
|
||||
__eglDeviceCount++;
|
||||
LKDHASH_WRLOCK(__eglDeviceHash);
|
||||
HASH_FIND_PTR(_LH(__eglDeviceHash), &dev, devInfo);
|
||||
if (devInfo == NULL) {
|
||||
devInfo = malloc(sizeof(__EGLdeviceInfo));
|
||||
if (devInfo == NULL) {
|
||||
LKDHASH_UNLOCK(__eglDeviceHash);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
devInfo->handle = 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -164,6 +164,7 @@ const __EGLapiExports __eglExportsTable = {
|
|||
__eglSetLastVendor, // setLastVendor
|
||||
__eglGetVendorFromDisplay, // getVendorFromDisplay
|
||||
__eglGetVendorFromDevice, // getVendorFromDevice
|
||||
__eglAddDevice, // setVendorForDevice
|
||||
};
|
||||
|
||||
void TeardownVendor(__EGLvendorInfo *vendor)
|
||||
|
@ -241,6 +242,7 @@ static GLboolean LookupVendorEntrypoints(__EGLvendorInfo *vendor)
|
|||
LOADENTRYPOINT(createPlatformPixmapSurface, "eglCreatePlatformPixmapSurface" );
|
||||
LOADENTRYPOINT(waitSync, "eglWaitSync" );
|
||||
LOADENTRYPOINT(queryDevicesEXT, "eglQueryDevicesEXT" );
|
||||
LOADENTRYPOINT(queryDisplayAttribEXT, "eglQueryDisplayAttribEXT" );
|
||||
|
||||
LOADENTRYPOINT(debugMessageControlKHR, "eglDebugMessageControlKHR" );
|
||||
LOADENTRYPOINT(queryDebugKHR, "eglQueryDebugKHR" );
|
||||
|
|
|
@ -139,6 +139,9 @@ EGL_FUNCTIONS = (
|
|||
# EGL_EXT_device_enumeration
|
||||
_eglExt("eglQueryDevicesEXT", "custom"),
|
||||
|
||||
# EGL_EXT_device_query
|
||||
_eglExt("eglQueryDisplayAttribEXT", "custom"),
|
||||
|
||||
# EGL_KHR_debug
|
||||
_eglExt("eglDebugMessageControlKHR", "custom"),
|
||||
_eglExt("eglQueryDebugKHR", "custom"),
|
||||
|
|
|
@ -172,6 +172,9 @@ endif # ENABLE_GLX
|
|||
TESTS_EGL =
|
||||
TESTS_EGL += testegldisplay.sh
|
||||
TESTS_EGL += testegldevice.sh
|
||||
TESTS_EGL += testegldeviceadd_querydevices.sh
|
||||
TESTS_EGL += testegldeviceadd_returndevice.sh
|
||||
TESTS_EGL += testegldeviceadd_querydisplay.sh
|
||||
TESTS_EGL += testeglgetprocaddress.sh
|
||||
TESTS_EGL += testeglmakecurrent.sh
|
||||
TESTS_EGL += testeglerror.sh
|
||||
|
@ -185,32 +188,38 @@ check_PROGRAMS += testegldisplay
|
|||
testegldisplay_SOURCES = \
|
||||
testegldisplay.c \
|
||||
egl_test_utils.c
|
||||
testegldisplay_LDADD = $(top_builddir)/src/EGL/libEGL.la
|
||||
testegldisplay_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
|
||||
check_PROGRAMS += testegldevice
|
||||
testegldevice_SOURCES = \
|
||||
testegldevice.c \
|
||||
egl_test_utils.c
|
||||
testegldevice_LDADD = $(top_builddir)/src/EGL/libEGL.la
|
||||
testegldevice_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
|
||||
check_PROGRAMS += testegldeviceadd
|
||||
testegldeviceadd_SOURCES = \
|
||||
testegldeviceadd.c \
|
||||
egl_test_utils.c
|
||||
testegldeviceadd_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
|
||||
check_PROGRAMS += testeglgetprocaddress
|
||||
testeglgetprocaddress_SOURCES = \
|
||||
testeglgetprocaddress.c \
|
||||
egl_test_utils.c
|
||||
testeglgetprocaddress_LDADD = $(top_builddir)/src/EGL/libEGL.la
|
||||
testeglgetprocaddress_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
|
||||
check_PROGRAMS += testeglmakecurrent
|
||||
testeglmakecurrent_SOURCES = \
|
||||
testeglmakecurrent.c \
|
||||
egl_test_utils.c
|
||||
testeglmakecurrent_LDADD = $(top_builddir)/src/EGL/libEGL.la
|
||||
testeglmakecurrent_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
testeglmakecurrent_LDADD += $(top_builddir)/src/OpenGL/libOpenGL.la
|
||||
|
||||
check_PROGRAMS += testeglerror
|
||||
testeglerror_SOURCES = \
|
||||
testeglerror.c \
|
||||
egl_test_utils.c
|
||||
testeglerror_LDADD = $(top_builddir)/src/EGL/libEGL.la
|
||||
testeglerror_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
testeglerror_LDADD += $(top_builddir)/src/OpenGL/libOpenGL.la
|
||||
|
||||
|
||||
|
@ -218,7 +227,7 @@ check_PROGRAMS += testegldebug
|
|||
testegldebug_SOURCES = \
|
||||
testegldebug.c \
|
||||
egl_test_utils.c
|
||||
testegldebug_LDADD = $(top_builddir)/src/EGL/libEGL.la
|
||||
testegldebug_LDADD = $(top_builddir)/src/EGL/libEGL.la @LIB_DL@
|
||||
|
||||
endif # ENABLE_EGL
|
||||
|
||||
|
|
|
@ -38,13 +38,18 @@ enum
|
|||
DI_eglTestDispatchDisplay,
|
||||
DI_eglTestDispatchDevice,
|
||||
DI_eglTestDispatchCurrent,
|
||||
DI_eglTestReturnDevice,
|
||||
DI_eglQueryDeviceAttribEXT,
|
||||
DI_eglQueryDeviceStringEXT,
|
||||
DI_COUNT,
|
||||
};
|
||||
|
||||
static const char *CLIENT_EXTENSIONS =
|
||||
"EGL_KHR_client_get_all_proc_addresses"
|
||||
" EGL_EXT_client_extensions"
|
||||
" EGL_EXT_device_base"
|
||||
" EGL_EXT_device_enumeration"
|
||||
" EGL_EXT_device_query"
|
||||
;
|
||||
|
||||
static const char *PLATFORM_EXTENSIONS =
|
||||
|
@ -57,6 +62,7 @@ typedef struct DummyEGLDisplayRec {
|
|||
EGLenum platform;
|
||||
void *native_display;
|
||||
EGLLabelKHR label;
|
||||
EGLDeviceEXT device;
|
||||
|
||||
struct glvnd_list entry;
|
||||
} DummyEGLDisplay;
|
||||
|
@ -82,6 +88,11 @@ static EGLint failNextMakeCurrentError = EGL_NONE;
|
|||
static EGLDEBUGPROCKHR debugCallbackFunc = NULL;
|
||||
static EGLBoolean debugCallbackEnabled = EGL_TRUE;
|
||||
|
||||
// The EGLDeviceEXT handle values have to be pointers, so just use the
|
||||
// address of an array element for each EGLDeviceEXT handle.
|
||||
static const char EGL_DEVICE_HANDLES[DUMMY_EGL_MAX_DEVICE_COUNT];
|
||||
static EGLint deviceCount = DUMMY_EGL_DEVICE_COUNT;
|
||||
|
||||
static DummyThreadState *GetThreadState(void)
|
||||
{
|
||||
DummyThreadState *thr = (DummyThreadState *)
|
||||
|
@ -144,18 +155,14 @@ static DummyEGLDisplay *LookupEGLDisplay(EGLDisplay dpy)
|
|||
|
||||
static EGLDeviceEXT GetEGLDevice(EGLint index)
|
||||
{
|
||||
// The EGLDeviceEXT handle values have to be pointers, so just use the
|
||||
// address of an array element for each EGLDeviceEXT handle.
|
||||
static const char EGL_DEVICE_HANDLES[DUMMY_EGL_DEVICE_COUNT];
|
||||
|
||||
assert(index >= 0 && index < DUMMY_EGL_DEVICE_COUNT);
|
||||
assert(index >= 0 && index < DUMMY_EGL_MAX_DEVICE_COUNT);
|
||||
return (EGLDeviceEXT) (EGL_DEVICE_HANDLES + index);
|
||||
}
|
||||
|
||||
static EGLBoolean IsEGLDeviceValid(EGLDeviceEXT dev)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<DUMMY_EGL_DEVICE_COUNT; i++) {
|
||||
for (i=0; i<deviceCount; i++) {
|
||||
if (dev == GetEGLDevice(i)) {
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
@ -177,6 +184,7 @@ static EGLDisplay dummyGetPlatformDisplay(EGLenum platform, void *native_display
|
|||
{
|
||||
CommonEntrypoint();
|
||||
DummyEGLDisplay *disp = NULL;
|
||||
EGLDeviceEXT device = EGL_NO_DEVICE_EXT;
|
||||
|
||||
if (platform == EGL_NONE) {
|
||||
if (native_display != EGL_DEFAULT_DISPLAY) {
|
||||
|
@ -198,6 +206,20 @@ static EGLDisplay dummyGetPlatformDisplay(EGLenum platform, void *native_display
|
|||
// Set the native_display pointer to NULL. This makes it simpler to
|
||||
// find the same dispaly below.
|
||||
native_display = NULL;
|
||||
|
||||
if (attrib_list != NULL) {
|
||||
int i;
|
||||
for (i=0; attrib_list[i] != EGL_NONE; i += 2) {
|
||||
if (attrib_list[i] == EGL_DEVICE_INDEX) {
|
||||
EGLint index = (EGLint) attrib_list[i + 1];
|
||||
assert(index >= 0 && index < deviceCount);
|
||||
device = GetEGLDevice(index);
|
||||
} else {
|
||||
printf("Invalid attribute 0x%04llx\n", (unsigned long long) attrib_list[i]);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (platform == EGL_PLATFORM_DEVICE_EXT) {
|
||||
if (native_display == EGL_DEFAULT_DISPLAY) {
|
||||
|
@ -207,6 +229,7 @@ static EGLDisplay dummyGetPlatformDisplay(EGLenum platform, void *native_display
|
|||
return EGL_NO_DISPLAY;
|
||||
}
|
||||
}
|
||||
device = (EGLDeviceEXT) native_display;
|
||||
} else {
|
||||
// We don't support this platform.
|
||||
SetLastError("eglGetPlatformDisplay", NULL, EGL_BAD_PARAMETER);
|
||||
|
@ -215,7 +238,7 @@ static EGLDisplay dummyGetPlatformDisplay(EGLenum platform, void *native_display
|
|||
|
||||
__glvndPthreadFuncs.mutex_lock(&displayListLock);
|
||||
glvnd_list_for_each_entry(disp, &displayList, entry) {
|
||||
if (disp->platform == platform && disp->native_display == native_display) {
|
||||
if (disp->platform == platform && disp->native_display == native_display && disp->device == device) {
|
||||
__glvndPthreadFuncs.mutex_unlock(&displayListLock);
|
||||
return disp;
|
||||
}
|
||||
|
@ -225,6 +248,7 @@ static EGLDisplay dummyGetPlatformDisplay(EGLenum platform, void *native_display
|
|||
disp = (DummyEGLDisplay *) calloc(1, sizeof(DummyEGLDisplay));
|
||||
disp->platform = platform;
|
||||
disp->native_display = native_display;
|
||||
disp->device = device;
|
||||
glvnd_list_append(&disp->entry, &displayList);
|
||||
__glvndPthreadFuncs.mutex_unlock(&displayListLock);
|
||||
return disp;
|
||||
|
@ -504,21 +528,51 @@ static EGLBoolean EGLAPIENTRY dummy_eglQueryDevicesEXT(EGLint max_devices, EGLDe
|
|||
CommonEntrypoint();
|
||||
if (devices != NULL) {
|
||||
EGLint i;
|
||||
if (max_devices != DUMMY_EGL_DEVICE_COUNT) {
|
||||
if (max_devices != deviceCount) {
|
||||
// libEGL should only every query the full list of devices.
|
||||
printf("Wrong max_devices in eglQueryDevicesEXT: %d\n", max_devices);
|
||||
abort();
|
||||
}
|
||||
*num_devices = DUMMY_EGL_DEVICE_COUNT;
|
||||
*num_devices = deviceCount;
|
||||
for (i=0; i<*num_devices; i++) {
|
||||
devices[i] = GetEGLDevice(i);
|
||||
}
|
||||
} else {
|
||||
*num_devices = DUMMY_EGL_DEVICE_COUNT;
|
||||
*num_devices = deviceCount;
|
||||
}
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static EGLBoolean EGLAPIENTRY dummy_eglQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
|
||||
{
|
||||
DummyEGLDisplay *disp = LookupEGLDisplay(dpy);
|
||||
|
||||
if (attribute == EGL_DEVICE_EXT) {
|
||||
*value = (EGLAttrib) disp->device;
|
||||
return EGL_TRUE;
|
||||
} else {
|
||||
SetLastError("eglQueryDisplayAttribEXT", disp->label, EGL_BAD_ATTRIBUTE);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static EGLBoolean EGLAPIENTRY dummy_eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
|
||||
{
|
||||
// No device attributes are defined here.
|
||||
SetLastError("eglQueryDeviceAttribEXT", NULL, EGL_BAD_ATTRIBUTE);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
static const char *EGLAPIENTRY dummy_eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
|
||||
{
|
||||
if (name == EGL_EXTENSIONS) {
|
||||
return "";
|
||||
} else {
|
||||
SetLastError("eglQueryDeviceStringEXT", NULL, EGL_BAD_ATTRIBUTE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static EGLint EGLAPIENTRY dummy_eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list)
|
||||
{
|
||||
CommonEntrypoint();
|
||||
|
@ -612,9 +666,18 @@ static void *dummy_eglTestDispatchCurrent(EGLint command, EGLAttrib param)
|
|||
return CommonTestDispatch("eglTestDispatchCurrent", EGL_NO_DISPLAY, EGL_NO_DEVICE_EXT, command, param);
|
||||
}
|
||||
|
||||
static EGLDeviceEXT dummy_eglTestReturnDevice(EGLDisplay dpy, EGLint index)
|
||||
{
|
||||
assert(index >= 0 && index < deviceCount);
|
||||
return GetEGLDevice(index);
|
||||
}
|
||||
|
||||
static void *dispatch_eglTestDispatchDisplay(EGLDisplay dpy, EGLint command, EGLAttrib param);
|
||||
static void *dispatch_eglTestDispatchDevice(EGLDeviceEXT dpy, EGLint command, EGLAttrib param);
|
||||
static void *dispatch_eglTestDispatchCurrent(EGLint command, EGLAttrib param);
|
||||
static EGLDeviceEXT dispatch_eglTestReturnDevice(EGLDisplay dpy, EGLint index);
|
||||
static EGLBoolean EGLAPIENTRY dispatch_eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
|
||||
static const char *EGLAPIENTRY dispatch_eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name);
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
|
@ -626,6 +689,9 @@ static struct {
|
|||
PROC_ENTRY(eglTestDispatchDisplay),
|
||||
PROC_ENTRY(eglTestDispatchDevice),
|
||||
PROC_ENTRY(eglTestDispatchCurrent),
|
||||
PROC_ENTRY(eglTestReturnDevice),
|
||||
PROC_ENTRY(eglQueryDeviceAttribEXT),
|
||||
PROC_ENTRY(eglQueryDeviceStringEXT),
|
||||
#undef PROC_ENTRY
|
||||
};
|
||||
|
||||
|
@ -652,6 +718,17 @@ static __eglMustCastToProperFunctionPointerType FetchVendorFunc(__EGLvendorInfo
|
|||
return func;
|
||||
}
|
||||
|
||||
static __eglMustCastToProperFunctionPointerType FetchByDevice(EGLDeviceEXT dev, int index)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
__eglMustCastToProperFunctionPointerType func;
|
||||
|
||||
apiExports->threadInit();
|
||||
vendor = apiExports->getVendorFromDevice(dev);
|
||||
func = FetchVendorFunc(vendor, index, EGL_BAD_DEVICE_EXT);
|
||||
return func;
|
||||
}
|
||||
|
||||
static void *dispatch_eglTestDispatchDisplay(EGLDisplay dpy, EGLint command, EGLAttrib param)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
|
@ -697,6 +774,45 @@ static void *dispatch_eglTestDispatchCurrent(EGLint command, EGLAttrib param)
|
|||
}
|
||||
}
|
||||
|
||||
static EGLDeviceEXT dispatch_eglTestReturnDevice(EGLDisplay dpy, EGLint index)
|
||||
{
|
||||
__EGLvendorInfo *vendor;
|
||||
pfn_eglTestReturnDevice func;
|
||||
EGLDeviceEXT ret;
|
||||
|
||||
apiExports->threadInit();
|
||||
vendor = apiExports->getVendorFromDisplay(dpy);
|
||||
func = (pfn_eglTestReturnDevice) FetchVendorFunc(vendor, DI_eglTestReturnDevice, EGL_BAD_DISPLAY);
|
||||
if (func != NULL) {
|
||||
ret = func(dpy, index);
|
||||
} else {
|
||||
ret = NULL;
|
||||
}
|
||||
apiExports->setVendorForDevice(ret, vendor);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static EGLBoolean EGLAPIENTRY dispatch_eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
|
||||
{
|
||||
PFNEGLQUERYDEVICEATTRIBEXTPROC func = (PFNEGLQUERYDEVICEATTRIBEXTPROC)
|
||||
FetchByDevice(device, DI_eglQueryDeviceAttribEXT);
|
||||
if (func != NULL) {
|
||||
return func(device, attribute, value);
|
||||
} else {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *EGLAPIENTRY dispatch_eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
|
||||
{
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC func = (PFNEGLQUERYDEVICESTRINGEXTPROC)
|
||||
FetchByDevice(device, DI_eglQueryDeviceStringEXT);
|
||||
if (func != NULL) {
|
||||
return func(device, name);
|
||||
} else {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
|
@ -735,6 +851,9 @@ static const struct {
|
|||
PROC_ENTRY(eglGetError),
|
||||
|
||||
PROC_ENTRY(eglQueryDevicesEXT),
|
||||
PROC_ENTRY(eglQueryDisplayAttribEXT),
|
||||
PROC_ENTRY(eglQueryDeviceAttribEXT),
|
||||
PROC_ENTRY(eglQueryDeviceStringEXT),
|
||||
PROC_ENTRY(eglDebugMessageControlKHR),
|
||||
PROC_ENTRY(eglQueryDebugKHR),
|
||||
PROC_ENTRY(eglLabelObjectKHR),
|
||||
|
@ -791,6 +910,12 @@ static EGLBoolean dummyGetSupportsAPI(EGLenum api)
|
|||
}
|
||||
}
|
||||
|
||||
PUBLIC void DummySetDeviceCount(EGLint count)
|
||||
{
|
||||
assert(count >= 0 && count <= DUMMY_EGL_MAX_DEVICE_COUNT);
|
||||
deviceCount = count;
|
||||
}
|
||||
|
||||
PUBLIC EGLBoolean
|
||||
__egl_Main(uint32_t version, const __EGLapiExports *exports,
|
||||
__EGLvendorInfo *vendor, __EGLapiImports *imports)
|
||||
|
|
|
@ -56,11 +56,20 @@
|
|||
#define DUMMY_VENDOR_NAME_1 "dummy1"
|
||||
|
||||
/**
|
||||
* The number of devices that each dummy vendor library exposes. This is used
|
||||
* to figure out which vendor library should be behind each device.
|
||||
* The number of devices that each dummy vendor library exposes by default.
|
||||
* This is used to figure out which vendor library should be behind each
|
||||
* device.
|
||||
*/
|
||||
#define DUMMY_EGL_DEVICE_COUNT 2
|
||||
|
||||
/**
|
||||
* The maximum number of devices that each dummy vendor library can expose.
|
||||
*
|
||||
* This is used to test adding a device after the initial eglQueryDevicesEXT
|
||||
* call.
|
||||
*/
|
||||
#define DUMMY_EGL_MAX_DEVICE_COUNT 3
|
||||
|
||||
/**
|
||||
* A platform enum to select a vendor library by name.
|
||||
* The native display should be a pointer to a string with the vendor name.
|
||||
|
@ -76,6 +85,14 @@
|
|||
*/
|
||||
#define EGL_CREATE_CONTEXT_FAIL 0x010001
|
||||
|
||||
/**
|
||||
* This attribute is for eglCreatePlatformDisplay. The attribute is the index
|
||||
* of the EGLDeviceEXT handle to associate with the display.
|
||||
*
|
||||
* This is used to test eglQueryDisplayEXT.
|
||||
*/
|
||||
#define EGL_DEVICE_INDEX 0x010002
|
||||
|
||||
enum
|
||||
{
|
||||
DUMMY_COMMAND_GET_VENDOR_NAME,
|
||||
|
@ -111,4 +128,19 @@ typedef void * (* pfn_eglTestDispatchDevice) (EGLDeviceEXT dev, EGLint command,
|
|||
*/
|
||||
typedef void * (* pfn_eglTestDispatchCurrent) (EGLint command, EGLAttrib param);
|
||||
|
||||
/**
|
||||
* Returns an EGLDeviceEXT handle from the vendor library.
|
||||
*
|
||||
* This is used to test returning a device that wasn't listed in a call to
|
||||
* eglQueryDevicesEXT.
|
||||
*/
|
||||
typedef EGLDeviceEXT (* pfn_eglTestReturnDevice) (EGLDisplay dpy, EGLint index);
|
||||
|
||||
/**
|
||||
* Changes the number of EGLDeviceEXT handles that the dummy library exposes.
|
||||
*
|
||||
* This function has to be looked up using dlsym, not eglGetProcAddress.
|
||||
*/
|
||||
typedef void (* pfn_DummySetDeviceCount) (EGLint count);
|
||||
|
||||
#endif // EGL_DUMMY_H
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
const char *DUMMY_VENDOR_NAMES[DUMMY_VENDOR_COUNT] = {
|
||||
DUMMY_VENDOR_NAME_0,
|
||||
|
@ -12,10 +14,17 @@ PFNEGLQUERYDEVICESEXTPROC ptr_eglQueryDevicesEXT;
|
|||
PFNEGLDEBUGMESSAGECONTROLKHRPROC ptr_eglDebugMessageControlKHR;
|
||||
PFNEGLQUERYDEBUGKHRPROC ptr_eglQueryDebugKHR;
|
||||
PFNEGLLABELOBJECTKHRPROC ptr_eglLabelObjectKHR;
|
||||
PFNEGLQUERYDEVICEATTRIBEXTPROC ptr_eglQueryDeviceAttribEXT;
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC ptr_eglQueryDeviceStringEXT;
|
||||
PFNEGLQUERYDISPLAYATTRIBEXTPROC ptr_eglQueryDisplayAttribEXT;
|
||||
|
||||
pfn_eglTestDispatchDisplay ptr_eglTestDispatchDisplay;
|
||||
pfn_eglTestDispatchDevice ptr_eglTestDispatchDevice;
|
||||
pfn_eglTestDispatchCurrent ptr_eglTestDispatchCurrent;
|
||||
pfn_eglTestReturnDevice ptr_eglTestReturnDevice;
|
||||
|
||||
static void *dummyVendorHandles[DUMMY_VENDOR_COUNT] = {};
|
||||
DummyVendorFunctions dummyFuncs[DUMMY_VENDOR_COUNT] = {};
|
||||
|
||||
__eglMustCastToProperFunctionPointerType loadEGLFunction(const char *name)
|
||||
{
|
||||
|
@ -31,6 +40,12 @@ void loadEGLExtensions(void)
|
|||
{
|
||||
ptr_eglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC)
|
||||
loadEGLFunction("eglQueryDevicesEXT");
|
||||
ptr_eglQueryDeviceAttribEXT = (PFNEGLQUERYDEVICEATTRIBEXTPROC)
|
||||
loadEGLFunction("eglQueryDeviceAttribEXT");
|
||||
ptr_eglQueryDeviceStringEXT = (PFNEGLQUERYDEVICESTRINGEXTPROC)
|
||||
loadEGLFunction("eglQueryDeviceStringEXT");
|
||||
ptr_eglQueryDisplayAttribEXT = (PFNEGLQUERYDISPLAYATTRIBEXTPROC)
|
||||
loadEGLFunction("eglQueryDisplayAttribEXT");
|
||||
ptr_eglDebugMessageControlKHR = (PFNEGLDEBUGMESSAGECONTROLKHRPROC)
|
||||
loadEGLFunction("eglDebugMessageControlKHR");
|
||||
ptr_eglQueryDebugKHR = (PFNEGLQUERYDEBUGKHRPROC)
|
||||
|
@ -44,5 +59,50 @@ void loadEGLExtensions(void)
|
|||
loadEGLFunction("eglTestDispatchDevice");
|
||||
ptr_eglTestDispatchCurrent = (pfn_eglTestDispatchCurrent)
|
||||
loadEGLFunction("eglTestDispatchCurrent");
|
||||
ptr_eglTestReturnDevice = (pfn_eglTestReturnDevice)
|
||||
loadEGLFunction("eglTestReturnDevice");
|
||||
}
|
||||
|
||||
void loadDummyVendorExtensions(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<DUMMY_VENDOR_COUNT; i++)
|
||||
{
|
||||
if (dummyVendorHandles[i] == NULL)
|
||||
{
|
||||
char filename[128];
|
||||
snprintf(filename, sizeof(filename), "libEGL_%s.so.0", DUMMY_VENDOR_NAMES[i]);
|
||||
dummyVendorHandles[i] = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
|
||||
if (dummyVendorHandles[i] == NULL)
|
||||
{
|
||||
printf("Failed to load %s: %s\n", filename, dlerror());
|
||||
abort();
|
||||
}
|
||||
|
||||
dummyFuncs[i].SetDeviceCount = dlsym(dummyVendorHandles[i], "DummySetDeviceCount");
|
||||
if (dummyFuncs[i].SetDeviceCount == NULL)
|
||||
{
|
||||
printf("Can't load DummySetDeviceCount from %s\n", filename);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cleanupDummyVendorExtensions(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<DUMMY_VENDOR_COUNT; i++)
|
||||
{
|
||||
if (dummyVendorHandles[i] != NULL)
|
||||
{
|
||||
dlclose(dummyVendorHandles[i]);
|
||||
dummyVendorHandles[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&dummyFuncs, 0, sizeof(dummyFuncs));
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,21 @@
|
|||
*/
|
||||
#define DUMMY_TOTAL_DEVICE_COUNT (DUMMY_VENDOR_COUNT * DUMMY_EGL_DEVICE_COUNT)
|
||||
|
||||
/**
|
||||
* Functions that are exported directly from a vendor library, rather than
|
||||
* being accessed through eglGetProcAddress.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
pfn_DummySetDeviceCount SetDeviceCount;
|
||||
} DummyVendorFunctions;
|
||||
|
||||
extern const char *DUMMY_VENDOR_NAMES[DUMMY_VENDOR_COUNT];
|
||||
|
||||
extern PFNEGLQUERYDEVICESEXTPROC ptr_eglQueryDevicesEXT;
|
||||
extern PFNEGLQUERYDEVICEATTRIBEXTPROC ptr_eglQueryDeviceAttribEXT;
|
||||
extern PFNEGLQUERYDEVICESTRINGEXTPROC ptr_eglQueryDeviceStringEXT;
|
||||
extern PFNEGLQUERYDISPLAYATTRIBEXTPROC ptr_eglQueryDisplayAttribEXT;
|
||||
extern PFNEGLDEBUGMESSAGECONTROLKHRPROC ptr_eglDebugMessageControlKHR;
|
||||
extern PFNEGLQUERYDEBUGKHRPROC ptr_eglQueryDebugKHR;
|
||||
extern PFNEGLLABELOBJECTKHRPROC ptr_eglLabelObjectKHR;
|
||||
|
@ -51,6 +63,9 @@ extern PFNEGLLABELOBJECTKHRPROC ptr_eglLabelObjectKHR;
|
|||
extern pfn_eglTestDispatchDisplay ptr_eglTestDispatchDisplay;
|
||||
extern pfn_eglTestDispatchDevice ptr_eglTestDispatchDevice;
|
||||
extern pfn_eglTestDispatchCurrent ptr_eglTestDispatchCurrent;
|
||||
extern pfn_eglTestReturnDevice ptr_eglTestReturnDevice;
|
||||
|
||||
extern DummyVendorFunctions dummyFuncs[DUMMY_VENDOR_COUNT];
|
||||
|
||||
/**
|
||||
* Loads an EGL extension function with eglGetProcAddress. If it fails, then it
|
||||
|
@ -64,4 +79,14 @@ __eglMustCastToProperFunctionPointerType loadEGLFunction(const char *name);
|
|||
*/
|
||||
void loadEGLExtensions(void);
|
||||
|
||||
/**
|
||||
* Loads the additional functions exported by the dummy vendor libraries.
|
||||
*/
|
||||
void loadDummyVendorExtensions(void);
|
||||
|
||||
/**
|
||||
* Frees up any memory allocated by loadDummyVendorExtensions.
|
||||
*/
|
||||
void cleanupDummyVendorExtensions(void);
|
||||
|
||||
#endif // EGL_TEST_UTILS_H
|
||||
|
|
|
@ -208,12 +208,29 @@ if get_option('egl')
|
|||
['test@0@.c'.format(t[0]), 'egl_test_utils.c'],
|
||||
include_directories : [inc_include],
|
||||
link_with : [libEGL, t[1]],
|
||||
dependencies : [t[2]],
|
||||
dependencies : [dep_dl, t[2]],
|
||||
),
|
||||
env : env_egl,
|
||||
suite : ['egl'],
|
||||
depends : libEGL_dummy,
|
||||
)
|
||||
endforeach
|
||||
|
||||
exe_egldeviceadd = executable(
|
||||
'egldeviceadd',
|
||||
['testegldeviceadd.c', 'egl_test_utils.c'],
|
||||
include_directories : [inc_include],
|
||||
link_with : [libEGL],
|
||||
dependencies : [dep_dl],
|
||||
)
|
||||
foreach t : [ 'querydevices', 'returndevice', 'querydisplay' ]
|
||||
test(
|
||||
'egldeviceadd (@0@)'.format(t),
|
||||
exe_egldeviceadd,
|
||||
args : [t],
|
||||
env : env_egl,
|
||||
suite : ['egl'],
|
||||
)
|
||||
endforeach
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and/or associated documentation files (the
|
||||
* "Materials"), to deal in the Materials without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
* permit persons to whom the Materials are furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* unaltered in all copies or substantial portions of the Materials.
|
||||
* Any additions, deletions, or changes to the original source files
|
||||
* must be clearly indicated in accompanying documentation.
|
||||
*
|
||||
* If only executable code is distributed, then the accompanying
|
||||
* documentation must state that "this software is based in part on the
|
||||
* work of the Khronos Group."
|
||||
*
|
||||
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dummy/EGL_dummy.h"
|
||||
#include "egl_test_utils.h"
|
||||
|
||||
#define DEVICE_ARRAY_SIZE (DUMMY_EGL_MAX_DEVICE_COUNT * DUMMY_VENDOR_COUNT)
|
||||
|
||||
EGLBoolean CheckDeviceHandles(EGLDeviceEXT *devices, EGLint count)
|
||||
{
|
||||
EGLint i, j;
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
for (j=0; j<i; j++) {
|
||||
if (devices[i] == EGL_NO_DEVICE_EXT) {
|
||||
printf("Got EGL_NO_DEVICE_EXT at index %d\n", i);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (devices[i] == devices[j]) {
|
||||
printf("Got duplicate device handles at index %d, %d\n", i, j);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common function to get a list of devices. This will check to make sure that
|
||||
* we get the number of devices that we expect, that none of them are
|
||||
* EGL_NO_DEVICE_EXT, and that there are no duplicates.
|
||||
*/
|
||||
EGLBoolean CommonGetDevices(EGLDeviceEXT *devices, EGLint expectedCount)
|
||||
{
|
||||
EGLint count = -1;
|
||||
|
||||
if (!ptr_eglQueryDevicesEXT(0, NULL, &count)) {
|
||||
printf("eglQueryDevicesEXT(count) failed\n");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (count != expectedCount) {
|
||||
printf("eglQueryDevicesEXT(count) returned the wrong count\n");
|
||||
printf("Expected %d, but got %d\n", expectedCount, count);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!ptr_eglQueryDevicesEXT(expectedCount, devices, &count)) {
|
||||
printf("eglQueryDevicesEXT(get) failed\n");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (count != expectedCount) {
|
||||
printf("eglQueryDevicesEXT(ge) returned the wrong count\n");
|
||||
printf("Expected %d, but got %d\n", expectedCount, count);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!CheckDeviceHandles(devices, count)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean CheckDeviceVendors(EGLDeviceEXT *devices, EGLint count, const char *name)
|
||||
{
|
||||
EGLint i;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
const char *str = ptr_eglTestDispatchDevice(devices[i], DUMMY_COMMAND_GET_VENDOR_NAME, 0);
|
||||
if (str == NULL) {
|
||||
printf("eglTestDispatchDevice failed at index %s/%d, error 0x%04x\n", name, i, eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (strcmp(str, name) != 0) {
|
||||
printf("Got the wrong vendor string from device at index %d\n", i);
|
||||
printf("Expected \"%s\", but got \"%s\"\n", name, str);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean TestNewDevice(EGLDeviceEXT newDevice, EGLDeviceEXT *oldDevices, EGLint oldDeviceCount)
|
||||
{
|
||||
EGLint i;
|
||||
const char *str;
|
||||
|
||||
if (newDevice == EGL_NO_DEVICE_EXT) {
|
||||
printf("New device is EGL_NO_DEVICE_EXT\n");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
// Make sure that the newly added device doesn't show up in the old list
|
||||
for (i=0; i<oldDeviceCount; i++) {
|
||||
if (oldDevices[i] == newDevice) {
|
||||
printf("New device was at index %d\n", i);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we can dispatch using the new device
|
||||
str = ptr_eglTestDispatchDevice(newDevice, DUMMY_COMMAND_GET_VENDOR_NAME, 0);
|
||||
if (str == NULL) {
|
||||
printf("eglTestDispatchDevice failed with new device, error 0x%04x\n", eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (strcmp(str, DUMMY_VENDOR_NAMES[0]) != 0) {
|
||||
printf("Got the wrong vendor string from device at index %d\n", i);
|
||||
printf("Expected \"%s\", but got \"%s\"\n", DUMMY_VENDOR_NAMES[0], str);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
EGLBoolean TestAddQueryDevices(EGLDeviceEXT *oldDevices, EGLint oldDeviceCount)
|
||||
{
|
||||
EGLDeviceEXT devices[DEVICE_ARRAY_SIZE] = {};
|
||||
EGLint deviceCount = -1;
|
||||
const EGLint expectedDeviceCount = DUMMY_EGL_DEVICE_COUNT * DUMMY_VENDOR_COUNT + 1;
|
||||
EGLDeviceEXT newDevice;
|
||||
|
||||
printf("Testing second eglQueryDevicesEXT call.\n");
|
||||
|
||||
if (!ptr_eglQueryDevicesEXT(DEVICE_ARRAY_SIZE, devices, &deviceCount)) {
|
||||
printf("eglQueryDevicesEXT (2) failed\n");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (deviceCount != expectedDeviceCount) {
|
||||
printf("eglQueryDevicesEXT returned the wrong count\n");
|
||||
printf("Expected %d, but got %d\n", expectedDeviceCount, deviceCount);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!CheckDeviceHandles(devices, deviceCount)) {
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
newDevice = devices[DUMMY_EGL_DEVICE_COUNT];
|
||||
return TestNewDevice(newDevice, oldDevices, oldDeviceCount);
|
||||
}
|
||||
|
||||
EGLBoolean TestReturnDevice(EGLDeviceEXT *oldDevices, EGLint oldDeviceCount)
|
||||
{
|
||||
EGLDisplay dpy;
|
||||
EGLint major, minor;
|
||||
EGLDeviceEXT newDevice;
|
||||
|
||||
printf("Testing vendor-provided dispatch function.\n");
|
||||
|
||||
dpy = eglGetPlatformDisplay(EGL_DUMMY_PLATFORM, (EGLNativeDisplayType) DUMMY_VENDOR_NAMES[0], NULL);
|
||||
if (dpy == EGL_NO_DISPLAY) {
|
||||
printf("eglGetPlatformDisplay failed with 0x%04x\n", eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (!eglInitialize(dpy, &major, &minor)) {
|
||||
printf("eglInitialize failed with 0x%04x\n", eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
newDevice = ptr_eglTestReturnDevice(dpy, DUMMY_EGL_DEVICE_COUNT);
|
||||
eglTerminate(dpy);
|
||||
|
||||
return TestNewDevice(newDevice, oldDevices, oldDeviceCount);
|
||||
}
|
||||
|
||||
EGLBoolean TestQueryDisplay(EGLDeviceEXT *oldDevices, EGLint oldDeviceCount)
|
||||
{
|
||||
const EGLAttrib DISPLAY_ATTRIBS[] =
|
||||
{
|
||||
EGL_DEVICE_INDEX, DUMMY_EGL_DEVICE_COUNT, EGL_NONE
|
||||
};
|
||||
EGLDisplay dpy;
|
||||
EGLint major, minor;
|
||||
EGLAttrib newDevice = -1;
|
||||
|
||||
printf("Testing eglQueryDisplayAttribEXT.\n");
|
||||
|
||||
dpy = eglGetPlatformDisplay(EGL_DUMMY_PLATFORM, (EGLNativeDisplayType) DUMMY_VENDOR_NAMES[0], DISPLAY_ATTRIBS);
|
||||
if (dpy == EGL_NO_DISPLAY) {
|
||||
printf("eglGetPlatformDisplay failed with 0x%04x\n", eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
if (!eglInitialize(dpy, &major, &minor)) {
|
||||
printf("eglInitialize failed with 0x%04x\n", eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (!ptr_eglQueryDisplayAttribEXT(dpy, EGL_DEVICE_EXT, &newDevice)) {
|
||||
printf("ptr_eglQueryDisplayAttribEXT failed with 0x%04x\n", eglGetError());
|
||||
return EGL_FALSE;
|
||||
}
|
||||
eglTerminate(dpy);
|
||||
|
||||
return TestNewDevice((EGLDeviceEXT) newDevice, oldDevices, oldDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
EGLDeviceEXT devices[DEVICE_ARRAY_SIZE] = {};
|
||||
const EGLint deviceCount = DUMMY_EGL_DEVICE_COUNT * DUMMY_VENDOR_COUNT;
|
||||
EGLint i;
|
||||
|
||||
loadEGLExtensions();
|
||||
loadDummyVendorExtensions();
|
||||
|
||||
printf("Getting initial device list.\n");
|
||||
if (!CommonGetDevices(devices, deviceCount)) {
|
||||
return 1;
|
||||
}
|
||||
// Make sure that we can dispatch using each device
|
||||
for (i=0; i<DUMMY_VENDOR_COUNT; i++) {
|
||||
if (!CheckDeviceVendors(devices + (i * DUMMY_EGL_DEVICE_COUNT),
|
||||
DUMMY_EGL_DEVICE_COUNT, DUMMY_VENDOR_NAMES[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a device to the first vendor.
|
||||
dummyFuncs[0].SetDeviceCount(DUMMY_EGL_DEVICE_COUNT + 1);
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
EGLBoolean success = EGL_FALSE;
|
||||
if (strcmp(argv[i], "querydevices") == 0) {
|
||||
success = TestAddQueryDevices(devices, deviceCount);
|
||||
} else if (strcmp(argv[i], "returndevice") == 0) {
|
||||
success = TestReturnDevice(devices, deviceCount);
|
||||
} else if (strcmp(argv[i], "querydisplay") == 0) {
|
||||
success = TestQueryDisplay(devices, deviceCount);
|
||||
} else {
|
||||
printf("Invalid test name: %s\n", argv[i]);
|
||||
}
|
||||
if (!success) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
cleanupDummyVendorExtensions();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
. $TOP_SRCDIR/tests/eglenv.sh
|
||||
|
||||
./testegldeviceadd querydevices
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
. $TOP_SRCDIR/tests/eglenv.sh
|
||||
|
||||
./testegldeviceadd querydisplay
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
. $TOP_SRCDIR/tests/eglenv.sh
|
||||
|
||||
./testegldeviceadd returndevice
|
Loading…
Reference in New Issue