Merge branch 'egl-allow-adding-devices' into 'master'

EGL: Allow adding EGLDeviceEXT handles

See merge request glvnd/libglvnd!239
This commit is contained in:
Kyle Brenneman 2021-11-26 13:25:23 +00:00
commit 055a4bab62
17 changed files with 742 additions and 138 deletions

View File

@ -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;
/*****************************************************************************

View File

@ -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 {

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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" );

View File

@ -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"),

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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

278
tests/testegldeviceadd.c Normal file
View File

@ -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;
}

View File

@ -0,0 +1,5 @@
#!/bin/sh
. $TOP_SRCDIR/tests/eglenv.sh
./testegldeviceadd querydevices

View File

@ -0,0 +1,5 @@
#!/bin/sh
. $TOP_SRCDIR/tests/eglenv.sh
./testegldeviceadd querydisplay

View File

@ -0,0 +1,5 @@
#!/bin/sh
. $TOP_SRCDIR/tests/eglenv.sh
./testegldeviceadd returndevice