[Mesa-dev] [PATCH 4/8] egldevice: implement eglQueryDevicesEXT using udev

Jonny Lamb jonny.lamb at collabora.co.uk
Fri Jul 24 07:19:58 PDT 2015


Enumerate udev devices by using:

  SUBSYSTEM=="drm"
  DEVTYPE=="drm_minor"
  TAG=="master-of-seat"

Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
---
 src/egl/main/eglapi.c    |   7 ++-
 src/egl/main/egldevice.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/egl/main/egldevice.h |   7 ++-
 3 files changed, 172 insertions(+), 3 deletions(-)

diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 6c1e6c7..222d3ff 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -92,6 +92,7 @@
 
 #include "eglglobals.h"
 #include "eglcontext.h"
+#include "egldevice.h"
 #include "egldisplay.h"
 #include "egltypedefs.h"
 #include "eglcurrent.h"
@@ -1850,7 +1851,11 @@ eglQueryDevicesEXT(EGLint max_devices,
                    EGLDeviceEXT *devices,
                    EGLint *num_devices)
 {
-   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
+   EGLBoolean ret;
+
+   ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices, num_devices);
+
+   RETURN_EGL_EVAL(NULL, ret);
 }
 #endif
 #endif /* HAVE_LIBUDEV */
diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c
index c79daff..56fa73c 100644
--- a/src/egl/main/egldevice.c
+++ b/src/egl/main/egldevice.c
@@ -31,20 +31,31 @@
 #include <libudev.h>
 #endif
 
+#include "eglcurrent.h"
 #include "egldevice.h"
 #include "eglglobals.h"
 #include "egllog.h"
 #include "egltypedefs.h"
 
 
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+
 typedef struct {
    /* device list */
    _EGLDevice *devices;
+   EGLBoolean got_devices;
+
+#ifdef HAVE_LIBUDEV
+   struct udev *udev;
+#endif
 
 } _EGLDeviceInfo;
 
+static EGLBoolean _eglFillDeviceList(_EGLDeviceInfo *info);
+
 static _EGLDeviceInfo *
-_eglEnsureDeviceInfo(void)
+_eglEnsureDeviceInfo(EGLBoolean get_devices)
 {
    _EGLDeviceInfo *info;
 
@@ -58,10 +69,20 @@ _eglEnsureDeviceInfo(void)
          goto out;
 
       info->devices = NULL;
+      info->got_devices = EGL_FALSE;
+
+#ifdef HAVE_LIBUDEV
+      info->udev = NULL;
+#endif
 
       _eglGlobal.DeviceInfo = info;
    }
 
+   if (get_devices && !info->got_devices) {
+      if (!_eglFillDeviceList(info))
+         info = NULL;
+   }
+
 out:
    mtx_unlock(_eglGlobal.Mutex);
 
@@ -124,6 +145,11 @@ _eglFiniDeviceInfo(void)
 {
    _EGLDeviceInfo *info;
    _EGLDevice *device_list, *device;
+#ifdef HAVE_LIBUDEV
+   UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *));
+   UDEV_SYMBOL(struct udev_device *, udev_device_unref,
+               (struct udev_device *));
+#endif
 
    /* atexit function is called with global mutex locked */
 
@@ -138,9 +164,142 @@ _eglFiniDeviceInfo(void)
       device = device_list;
       device_list = device_list->Next;
 
+#ifdef HAVE_LIBUDEV
+      if (!dlsym_failed)
+         udev_device_unref(device->Info);
+#endif
       free(device);
    }
 
+#ifdef HAVE_LIBUDEV
+   if (info->udev && !dlsym_failed)
+      udev_unref(info->udev);
+#endif
+
    free(info);
    _eglGlobal.DeviceInfo = NULL;
 }
+
+static EGLBoolean
+_eglFillDeviceList(_EGLDeviceInfo *info)
+{
+#ifdef HAVE_LIBUDEV
+   struct udev_enumerate *enumerate;
+   struct udev_list_entry *entry;
+   EGLBoolean ret = EGL_TRUE;
+   UDEV_SYMBOL(struct udev *, udev_new, (void));
+   UDEV_SYMBOL(struct udev_enumerate *, udev_enumerate_new,
+               (struct udev *));
+   UDEV_SYMBOL(int, udev_enumerate_add_match_subsystem,
+               (struct udev_enumerate *, const char *));
+   UDEV_SYMBOL(int, udev_enumerate_add_match_property,
+               (struct udev_enumerate *, const char *, const char *));
+   UDEV_SYMBOL(int, udev_enumerate_add_match_tag,
+               (struct udev_enumerate *, const char *));
+   UDEV_SYMBOL(int, udev_enumerate_scan_devices,
+               (struct udev_enumerate *));
+   UDEV_SYMBOL(struct udev_list_entry *, udev_list_entry_get_next,
+               (struct udev_list_entry *));
+   UDEV_SYMBOL(struct udev_list_entry *, udev_enumerate_get_list_entry,
+               (struct udev_enumerate *));
+   UDEV_SYMBOL(const char *, udev_list_entry_get_name,
+               (struct udev_list_entry *));
+   UDEV_SYMBOL(struct udev_device *, udev_device_new_from_syspath,
+               (struct udev *, const char *));
+   UDEV_SYMBOL(void, udev_enumerate_unref,
+               (struct udev_enumerate *));
+
+   if (dlsym_failed)
+      return EGL_FALSE;
+
+   if (!info->udev)
+      info->udev = udev_new();
+   if (!info->udev)
+      return EGL_FALSE;
+
+   enumerate = udev_enumerate_new(info->udev);
+   udev_enumerate_add_match_subsystem(enumerate, "drm");
+   udev_enumerate_add_match_property(enumerate, "DEVTYPE", "drm_minor");
+   udev_enumerate_add_match_tag(enumerate, "master-of-seat");
+   udev_enumerate_scan_devices(enumerate);
+
+   udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(enumerate)) {
+      struct udev_device *dev;
+      const char *path;
+      _EGLDevice *egl_device;
+
+      path = udev_list_entry_get_name(entry);
+      dev = udev_device_new_from_syspath(info->udev, path);
+
+      egl_device = calloc(1, sizeof(_EGLDevice));
+      if (!egl_device) {
+         ret = EGL_FALSE;
+         break;
+      }
+
+      egl_device->Info = dev;
+
+      egl_device->Next = info->devices;
+      info->devices = egl_device;
+   }
+
+   udev_enumerate_unref(enumerate);
+
+   /* only report we enumerated the devices if all callocs were successful */
+   if (ret)
+      info->got_devices = EGL_TRUE;
+
+   return ret;
+#else
+   return EGL_FALSE;
+#endif
+}
+
+/**
+ * Enumerate EGL devices.
+ */
+EGLBoolean
+_eglQueryDevicesEXT(EGLint max_devices,
+                    _EGLDevice **devices,
+                    EGLint *num_devices)
+{
+   _EGLDeviceInfo *info;
+   EGLBoolean ret = EGL_TRUE;
+   int i;
+   _EGLDevice *dev;
+
+   /* max_devices can only be bad if devices is non-NULL. num_devices must
+    * always be present. */
+   if ((devices && max_devices < 1) || !num_devices)
+      return _eglError(EGL_BAD_PARAMETER, "eglQueryDevicesEXT");
+
+   info = _eglEnsureDeviceInfo(EGL_TRUE);
+   if (!info)
+      return _eglError(EGL_BAD_ALLOC, "eglQueryDevicesEXT");
+
+   mtx_lock(_eglGlobal.Mutex);
+
+   /* work out total number of devices */
+   for (i = 0, dev = info->devices; dev; i++, dev = dev->Next)
+      ;
+
+   /* bail early if we devices is NULL */
+   if (!devices) {
+      *num_devices = i;
+      goto out;
+   }
+
+   /* create and fill devices array */
+   *num_devices = MIN(i, max_devices);
+
+   for (i = 0, dev = info->devices;
+        i < *num_devices;
+        i++, dev = dev->Next) {
+      devices[i] = dev;
+   }
+
+out:
+   mtx_unlock(_eglGlobal.Mutex);
+
+   return ret;
+}
diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h
index f8f3824..682f4b1 100644
--- a/src/egl/main/egldevice.h
+++ b/src/egl/main/egldevice.h
@@ -36,7 +36,7 @@
 struct _egl_device {
    _EGLDevice *Next;
 
-   /* TODO */
+   void *Info;
 };
 
 
@@ -44,4 +44,9 @@ extern void
 _eglFiniDeviceInfo(void);
 
 
+EGLBoolean
+_eglQueryDevicesEXT(EGLint max_devices, _EGLDevice **devices,
+                    EGLint *num_devices);
+
+
 #endif /* EGLDEVICE_INCLUDED */
-- 
2.4.6



More information about the mesa-dev mailing list