egl: add base EGL_EXT_device_base implementation
authorEmil Velikov <emil.velikov@collabora.com>
Fri, 24 Jul 2015 14:19:55 +0000 (16:19 +0200)
committerEmil Velikov <emil.l.velikov@gmail.com>
Thu, 1 Nov 2018 00:05:43 +0000 (00:05 +0000)
Introduce the API for device query and enumeration. Those at the moment
produce nothing useful since zero devices are actually available.

That contradicts with the spec, so the extension isn't advertised just
yet.

With later commits we'll add support for software (always) and hardware
devices. Each one exposing the respective extension string.

v2:
 - fold API boilerplate into this patch
 - move _eglAddDevice, _eglDeviceSupports, _eglRefreshDeviceList to this
patch (Eric, Mathias)
 - make _eglFiniDevice the one called last

v3:
 - comment on the dummy _egl_device_extension enum entry (Eric)
 - annotate dev as MAYBE_UNUSED (Mathias)

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
Reviewed-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
src/egl/Makefile.sources
src/egl/main/eglapi.c
src/egl/main/egldevice.c [new file with mode: 0644]
src/egl/main/egldevice.h [new file with mode: 0644]
src/egl/main/egldisplay.h
src/egl/main/eglentrypoint.h
src/egl/main/eglglobals.c
src/egl/main/eglglobals.h
src/egl/main/egltypedefs.h
src/egl/meson.build

index 82f13ad3cbd2ce56fae267db31104ca96399a4a2..0cc5f1bbfeffe530f7eb871188c9c78015d54b88 100644 (file)
@@ -10,6 +10,8 @@ LIBEGL_C_FILES := \
        main/eglcurrent.c \
        main/eglcurrent.h \
        main/egldefines.h \
+       main/egldevice.c \
+       main/egldevice.h \
        main/egldisplay.c \
        main/egldisplay.h \
        main/egldriver.c \
index 57b4c77c41dd9f2da175d44ae6d9bd349380e154..3afdfd40e4a39b6d3e6cd890d3fc0fa3b2263dc6 100644 (file)
@@ -95,6 +95,7 @@
 #include "egldisplay.h"
 #include "egltypedefs.h"
 #include "eglcurrent.h"
+#include "egldevice.h"
 #include "egldriver.h"
 #include "eglsurface.h"
 #include "eglconfig.h"
@@ -2583,6 +2584,69 @@ eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set,
    _eglUnlockDisplay(disp);
 }
 
+static EGLBoolean EGLAPIENTRY
+eglQueryDeviceAttribEXT(EGLDeviceEXT device,
+                        EGLint attribute,
+                        EGLAttrib *value)
+{
+   _EGLDevice *dev = _eglLookupDevice(device);
+   EGLBoolean ret;
+
+   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
+   if (!dev)
+      RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
+
+   ret = _eglQueryDeviceAttribEXT(dev, attribute, value);
+   RETURN_EGL_EVAL(NULL, ret);
+}
+
+static const char * EGLAPIENTRY
+eglQueryDeviceStringEXT(EGLDeviceEXT device,
+                        EGLint name)
+{
+   _EGLDevice *dev = _eglLookupDevice(device);
+
+   _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
+   if (!dev)
+      RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL);
+
+   RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name));
+}
+
+static EGLBoolean EGLAPIENTRY
+eglQueryDevicesEXT(EGLint max_devices,
+                   EGLDeviceEXT *devices,
+                   EGLint *num_devices)
+{
+   EGLBoolean ret;
+
+   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
+   ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices,
+                             num_devices);
+   RETURN_EGL_EVAL(NULL, ret);
+}
+
+static EGLBoolean EGLAPIENTRY
+eglQueryDisplayAttribEXT(EGLDisplay dpy,
+                         EGLint attribute,
+                         EGLAttrib *value)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+
+   _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+
+   switch (attribute) {
+   case EGL_DEVICE_EXT:
+      *value = (EGLAttrib) disp->Device;
+      break;
+   default:
+      RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE);
+   }
+   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
+}
+
 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
 eglGetProcAddress(const char *procname)
 {
diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c
new file mode 100644 (file)
index 0000000..49c000a
--- /dev/null
@@ -0,0 +1,179 @@
+/**************************************************************************
+ *
+ * Copyright 2015, 2018 Collabora
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/macros.h"
+
+#include "eglcurrent.h"
+#include "egldevice.h"
+#include "eglglobals.h"
+#include "egltypedefs.h"
+
+
+struct _egl_device {
+   _EGLDevice *Next;
+
+   const char *extensions;
+};
+
+void
+_eglFiniDevice(void)
+{
+   _EGLDevice *dev_list, *dev;
+
+   /* atexit function is called with global mutex locked */
+
+   dev_list = _eglGlobal.DeviceList;
+   while (dev_list) {
+      /* pop list head */
+      dev = dev_list;
+      dev_list = dev_list->Next;
+
+      free(dev);
+   }
+
+   _eglGlobal.DeviceList = NULL;
+}
+
+EGLBoolean
+_eglCheckDeviceHandle(EGLDeviceEXT device)
+{
+   _EGLDevice *cur;
+
+   mtx_lock(_eglGlobal.Mutex);
+   cur = _eglGlobal.DeviceList;
+   while (cur) {
+      if (cur == (_EGLDevice *) device)
+         break;
+      cur = cur->Next;
+   }
+   mtx_unlock(_eglGlobal.Mutex);
+   return (cur != NULL);
+}
+
+/* Adds a device in DeviceList, if needed for the given fd.
+ *
+ * If a software device, the fd is ignored.
+ */
+_EGLDevice *
+_eglAddDevice(int fd, bool software)
+{
+   _EGLDevice *dev;
+
+   mtx_lock(_eglGlobal.Mutex);
+
+   dev = NULL;
+
+out:
+   mtx_unlock(_eglGlobal.Mutex);
+   return dev;
+}
+
+EGLBoolean
+_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext)
+{
+   switch (ext) {
+   default:
+      assert(0);
+      return EGL_FALSE;
+   };
+}
+
+EGLBoolean
+_eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute,
+                         EGLAttrib *value)
+{
+   switch (attribute) {
+   default:
+      _eglError(EGL_BAD_ATTRIBUTE, "eglQueryDeviceStringEXT");
+      return EGL_FALSE;
+   }
+}
+
+const char *
+_eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
+{
+   switch (name) {
+   case EGL_EXTENSIONS:
+      return dev->extensions;
+   default:
+      _eglError(EGL_BAD_PARAMETER, "eglQueryDeviceStringEXT");
+      return NULL;
+   };
+}
+
+/* Do a fresh lookup for devices.
+ *
+ * Walks through the DeviceList, discarding no longer available ones
+ * and adding new ones as applicable.
+ *
+ * Must be called with the global lock held.
+ */
+static int
+_eglRefreshDeviceList(void)
+{
+   MAYBE_UNUSED _EGLDevice *dev;
+   int count = 0;
+
+   dev = _eglGlobal.DeviceList;
+
+   return count;
+}
+
+EGLBoolean
+_eglQueryDevicesEXT(EGLint max_devices,
+                    _EGLDevice **devices,
+                    EGLint *num_devices)
+{
+   _EGLDevice *dev, *devs;
+   int i = 0, num_devs;
+
+   if ((devices && max_devices <= 0) || !num_devices)
+      return _eglError(EGL_BAD_PARAMETER, "eglQueryDevicesEXT");
+
+   mtx_lock(_eglGlobal.Mutex);
+
+   num_devs = _eglRefreshDeviceList();
+   devs = _eglGlobal.DeviceList;
+
+   /* bail early if we only care about the count */
+   if (!devices) {
+      *num_devices = num_devs;
+      goto out;
+   }
+
+   *num_devices = MIN2(num_devs, max_devices);
+
+   for (i = 0, dev = devs; i < *num_devices; i++) {
+      devices[i] = dev;
+      dev = dev->Next;
+   }
+
+out:
+   mtx_unlock(_eglGlobal.Mutex);
+
+   return EGL_TRUE;
+}
diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h
new file mode 100644 (file)
index 0000000..f8f3fdc
--- /dev/null
@@ -0,0 +1,83 @@
+/**************************************************************************
+ *
+ * Copyright 2015, 2018 Collabora
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef EGLDEVICE_INCLUDED
+#define EGLDEVICE_INCLUDED
+
+
+#include <stdbool.h>
+#include "egltypedefs.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+_eglFiniDevice(void);
+
+EGLBoolean
+_eglCheckDeviceHandle(EGLDeviceEXT device);
+
+static inline _EGLDevice *
+_eglLookupDevice(EGLDeviceEXT device)
+{
+   _EGLDevice *dev = (_EGLDevice *) device;
+   if (!_eglCheckDeviceHandle(device))
+      dev = NULL;
+   return dev;
+}
+
+_EGLDevice *
+_eglAddDevice(int fd, bool software);
+
+enum _egl_device_extension {
+   EGL_FOOBAR, /* A temporary entry, since enum with zero entries is illegal */
+};
+
+typedef enum _egl_device_extension _EGLDeviceExtension;
+
+EGLBoolean
+_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext);
+
+EGLBoolean
+_eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute,
+                         EGLAttrib *value);
+
+const char *
+_eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name);
+
+EGLBoolean
+_eglQueryDevicesEXT(EGLint max_devices, _EGLDevice **devices,
+                    EGLint *num_devices);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EGLDEVICE_INCLUDED */
index 50176bde887cb7e5571065acd4e3105b59a3401b..fae90520368dd7304aafcca18aa0c13875e04a00 100644 (file)
@@ -159,6 +159,7 @@ struct _egl_display
    _EGLPlatformType Platform; /**< The type of the platform display */
    void *PlatformDisplay;     /**< A pointer to the platform display */
 
+   _EGLDevice *Device;        /**< Device backing the display */
    _EGLDriver *Driver;        /**< Matched driver of the display */
    EGLBoolean Initialized;    /**< True if the display is initialized */
 
index 06749f6353abd903cf29c31ccc0bbf53efc535da..95a8814bcefe907bc91aabe07ae8050ac685bd80 100644 (file)
@@ -56,6 +56,10 @@ EGL_ENTRYPOINT(eglPostSubBufferNV)
 EGL_ENTRYPOINT(eglQueryAPI)
 EGL_ENTRYPOINT(eglQueryContext)
 EGL_ENTRYPOINT(eglQueryDebugKHR)
+EGL_ENTRYPOINT(eglQueryDeviceAttribEXT)
+EGL_ENTRYPOINT(eglQueryDevicesEXT)
+EGL_ENTRYPOINT(eglQueryDeviceStringEXT)
+EGL_ENTRYPOINT(eglQueryDisplayAttribEXT)
 EGL_ENTRYPOINT(eglQueryDmaBufFormatsEXT)
 EGL_ENTRYPOINT(eglQueryDmaBufModifiersEXT)
 EGL_ENTRYPOINT(eglQueryString)
index c506bd6a9db3f3a9c8ca8bfba460fbee67865ec2..ac8bb3f328a223dcf0b9f2d60eb9f3160e8fa7ef 100644 (file)
@@ -35,6 +35,7 @@
 #include "c11/threads.h"
 
 #include "eglglobals.h"
+#include "egldevice.h"
 #include "egldisplay.h"
 #include "egldriver.h"
 #include "egllog.h"
@@ -51,11 +52,12 @@ struct _egl_global _eglGlobal =
 {
    .Mutex = &_eglGlobalMutex,
    .DisplayList = NULL,
-   .NumAtExitCalls = 2,
+   .NumAtExitCalls = 3,
    .AtExitCalls = {
       /* default AtExitCalls, called in reverse order */
-      _eglUnloadDrivers, /* always called last */
-      _eglFiniDisplay
+      _eglFiniDevice, /* always called last */
+      _eglUnloadDrivers,
+      _eglFiniDisplay,
    },
 
    .ClientOnlyExtensionString =
index 6655ccab65c6b1a0a267032a857223f8b24cb534..63bea4ebc38245fe3540a71cdb8b23ce6c895162 100644 (file)
@@ -54,6 +54,8 @@ struct _egl_global
    /* the list of all displays */
    _EGLDisplay *DisplayList;
 
+   _EGLDevice *DeviceList;
+
    EGLint NumAtExitCalls;
    void (*AtExitCalls[10])(void);
 
index 19524a16c42cd1171af6c145c713290b3309c2fb..642f473c4eb411ff1beba516bd2d59fb748e988a 100644 (file)
@@ -46,6 +46,8 @@ typedef struct _egl_config _EGLConfig;
 
 typedef struct _egl_context _EGLContext;
 
+typedef struct _egl_device _EGLDevice;
+
 typedef struct _egl_display _EGLDisplay;
 
 typedef struct _egl_driver _EGLDriver;
index e11e589b94561657746676ae645f3019e8a1efba..80dbcae0fd358679d69d7814c4492c9c963b6fc4 100644 (file)
@@ -38,6 +38,8 @@ files_egl = files(
   'main/eglcurrent.c',
   'main/eglcurrent.h',
   'main/egldefines.h',
+  'main/egldevice.c',
+  'main/egldevice.h',
   'main/egldisplay.c',
   'main/egldisplay.h',
   'main/egldriver.c',