Commit 055a4bab authored by Kyle Brenneman's avatar Kyle Brenneman
Browse files

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

EGL: Allow adding EGLDeviceEXT handles

See merge request !239
parents 2d69d472 288eb48c
Pipeline #454003 passed with stages
in 2 minutes and 11 seconds
......@@ -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;
/*****************************************************************************
......
......@@ -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,18 +1030,55 @@ EGLBoolean EGLAPIENTRY eglQueryDevicesEXT(EGLint max_devices,
return EGL_FALSE;
}
__eglInitDeviceList();
vendorList = __eglLoadVendors();
// 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;
}
}
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;
}
if (devices != NULL) {
EGLint i;
__eglSetLastVendor(vendor);
if (!vendor->staticDispatch.queryDisplayAttribEXT(dpy, attribute, value)) {
return EGL_FALSE;
}
*num_devices = (max_devices < __eglDeviceCount ? max_devices : __eglDeviceCount);
for (i = 0; i < *num_devices; i++) {
devices[i] = __eglDeviceList[i].handle;
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;
}
} else {
*num_devices = __eglDeviceCount;
}
return EGL_TRUE;
}
......
......@@ -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 {