[Mesa-dev] [PATCH 04/10] egl: add EGL_EXT_device_drm support

Emil Velikov emil.l.velikov at gmail.com
Fri Aug 3 12:44:20 UTC 2018


From: Emil Velikov <emil.velikov at collabora.com>

Add implementation based around the drmDevice API. As such it's only
available only when building with libdrm. With the latter already a
requirement when using !SW code paths in the platform code.

Note: the current code will work if a device is hot-plugged. Yet
hot-unplugged is not implemented, since I have no ways of testing it.

Signed-off-by: Emil Velikov <emil.velikov at collabora.com>
---
 src/egl/main/egldevice.c | 97 ++++++++++++++++++++++++++++++++++++++++
 src/egl/main/egldevice.h |  1 +
 2 files changed, 98 insertions(+)

diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c
index 8e7116c90f4..36f913adcac 100644
--- a/src/egl/main/egldevice.c
+++ b/src/egl/main/egldevice.c
@@ -25,6 +25,9 @@
  *
  **************************************************************************/
 
+#ifdef HAVE_LIBDRM
+#include <xf86drm.h>
+#endif
 #include "util/macros.h"
 
 #include "eglcurrent.h"
@@ -40,6 +43,11 @@ struct _egl_device {
    const char *extensions;
 
    EGLBoolean MESA_device_software;
+   EGLBoolean EXT_device_drm;
+
+#ifdef HAVE_LIBDRM
+   drmDevicePtr device;
+#endif
 };
 
 void
@@ -61,6 +69,9 @@ _eglFiniDevice(void)
       dev = dev_list;
       dev_list = dev_list->Next;
 
+#ifdef HAVE_LIBDRM
+      drmFreeDevice(&dev->device);
+#endif
       free(dev);
    }
 
@@ -88,6 +99,53 @@ static _EGLDevice software_device = {
    .MESA_device_software = EGL_TRUE,
 };
 
+#ifdef HAVE_LIBDRM
+/*
+ * Negative value on error, zero if newly added, one if already in list.
+ */
+static int
+_eglAddDRMDevice(drmDevicePtr device, _EGLDevice **out_dev)
+{
+   _EGLDevice *dev;
+
+   if ((device->available_nodes & 1 << DRM_NODE_PRIMARY) == 0)
+      return -1;
+
+   dev = _eglGlobal.DeviceList;
+
+   /* Compare against the second device onward.
+    * As said elsewhere - first one is always software.
+    */
+
+   while (dev->Next) {
+      dev = dev->Next;
+
+      if (drmDevicesEqual(device, dev->device) != 0) {
+         if (out_dev)
+            *out_dev = dev;
+         return 1;
+      }
+   }
+
+   dev->Next = calloc(1, sizeof(_EGLDevice));
+   if (!dev->Next) {
+      if (out_dev)
+         *out_dev = NULL;
+      return -1;
+   }
+
+   dev = dev->Next;
+   dev->extensions = "EGL_EXT_device_drm";
+   dev->EXT_device_drm = EGL_TRUE;
+   dev->device = device;
+
+   if (out_dev)
+      *out_dev = dev;
+
+   return 0;
+}
+#endif
+
 /* Looks up for device in DeviceList adding if there isn't one already.
  *
  * For software device lookup, the fd is ignored.
@@ -108,7 +166,21 @@ _eglFindDevice(int fd, bool software)
    if (software)
       goto out;
 
+#ifdef HAVE_LIBDRM
+   drmDevicePtr device;
+
+   if (drmGetDevice2(fd, 0, &device) != 0) {
+      dev = NULL;
+      goto out;
+   }
+
+   /* Device is not added - error or already present */
+   if (_eglAddDRMDevice(device, &dev) != 0)
+      drmFreeDevice(&device);
+#else
+   _eglLog(_EGL_FATAL, "Driver bug: Built without libdrm, yet looking for HW device");
    dev = NULL;
+#endif
 
 out:
    mtx_unlock(_eglGlobal.Mutex);
@@ -121,6 +193,8 @@ _eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext)
    switch (ext) {
    case _EGL_DEVICE_SOFTWARE:
       return dev->MESA_device_software;
+   case _EGL_DEVICE_DRM:
+      return dev->EXT_device_drm;
    };
    assert(0);
    return EGL_FALSE;
@@ -143,6 +217,12 @@ _eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
    switch (name) {
    case EGL_EXTENSIONS:
       return dev->extensions;
+#ifdef HAVE_LIBDRM
+   case EGL_DRM_DEVICE_FILE_EXT:
+      if (_eglDeviceSupports(dev, _EGL_DEVICE_DRM))
+         return dev->device->nodes[DRM_NODE_PRIMARY];
+      /* fall through */
+#endif
    default:
       _eglError(EGL_BAD_PARAMETER, "eglQueryDeviceStringEXT");
       return NULL;
@@ -170,6 +250,23 @@ _eglLookupAllDevices(void)
    }
    count++;
 
+#ifdef HAVE_LIBDRM
+   drmDevicePtr devices[64];
+   int num_devs, ret;
+
+   num_devs = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
+   for (int i = 0; i < num_devs; i++) {
+      ret = _eglAddDRMDevice(devices[i], NULL);
+
+      /* Device is not added - error or already present */
+      if (ret != 0)
+         drmFreeDevice(&devices[i]);
+
+      if (ret >= 0)
+         count++;
+   }
+#endif
+
    return count;
 }
 
diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h
index 945c25268e1..61f88df6b24 100644
--- a/src/egl/main/egldevice.h
+++ b/src/egl/main/egldevice.h
@@ -57,6 +57,7 @@ _eglFindDevice(int fd, bool software);
 
 enum _egl_device_extension {
    _EGL_DEVICE_SOFTWARE,
+   _EGL_DEVICE_DRM,
 };
 
 typedef enum _egl_device_extension _EGLDeviceExtension;
-- 
2.18.0



More information about the mesa-dev mailing list