[Mesa-dev] [PATCH 03/10] egl: add EGL_MESA_device_software support

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


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

Add LookupDevices/FindDevice helpers, alongside their first user -
software device ;-)

This adds support to both dri2 and haiku backends.

Signed-off-by: Emil Velikov <emil.velikov at collabora.com>
---
How can we split this up for platforms that support SW and HW devices?
FindDevice on a HW device will fail, bringing the whole eglInitialize
with it.
---
 src/egl/drivers/dri2/egl_dri2.h             |  1 +
 src/egl/drivers/dri2/platform_android.c     |  9 +++
 src/egl/drivers/dri2/platform_drm.c         |  9 +++
 src/egl/drivers/dri2/platform_surfaceless.c | 10 ++-
 src/egl/drivers/dri2/platform_wayland.c     | 18 +++++
 src/egl/drivers/dri2/platform_x11.c         | 27 +++++++
 src/egl/drivers/haiku/egl_haiku.cpp         |  8 +++
 src/egl/main/egldevice.c                    | 78 ++++++++++++++++++++-
 src/egl/main/egldevice.h                    | 14 +++-
 9 files changed, 171 insertions(+), 3 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index f8001ec4b66..d57b91cf3b9 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -71,6 +71,7 @@ struct zwp_linux_dmabuf_v1;
 
 #include "eglconfig.h"
 #include "eglcontext.h"
+#include "egldevice.h"
 #include "egldisplay.h"
 #include "egldriver.h"
 #include "eglcurrent.h"
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index cc16fd8118f..cb3b8c1a93a 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -1360,6 +1360,7 @@ success:
 EGLBoolean
 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
    const char *err;
    int ret;
@@ -1390,6 +1391,14 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp)
       goto cleanup;
    }
 
+   dev = _eglFindDevice(dri2_dpy->fd, false);
+   if (!dev) {
+      err = "DRI2: failed to find EGLDevice";
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    if (!droid_load_driver(disp)) {
       err = "DRI2: failed to load driver";
       goto cleanup;
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 35bc4b5b1ac..5fc42668974 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -696,6 +696,7 @@ static const struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
 EGLBoolean
 dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
    struct gbm_device *gbm;
    const char *err;
@@ -738,6 +739,14 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
       goto cleanup;
    }
 
+   dev = _eglFindDevice(dri2_dpy->fd, false);
+   if (!dev) {
+      err = "DRI2: failed to find EGLDevice";
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    dri2_dpy->gbm_dri = gbm_dri_device(gbm);
    dri2_dpy->driver_name = strdup(dri2_dpy->gbm_dri->driver_name);
 
diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c
index bfc8fb99eab..a5e6f976ad2 100644
--- a/src/egl/drivers/dri2/platform_surfaceless.c
+++ b/src/egl/drivers/dri2/platform_surfaceless.c
@@ -317,8 +317,16 @@ surfaceless_probe_device(_EGLDisplay *dpy, bool swrast)
       }
 
       dri2_dpy->fd = fd;
-      if (dri2_load_driver_dri3(dpy))
+      if (dri2_load_driver_dri3(dpy)) {
+         _EGLDevice *dev = _eglFindDevice(dri2_dpy->fd, swrast);
+         if (!dev) {
+            dlclose(dri2_dpy->driver);
+            _eglLog(_EGL_WARNING, "DRI2: failed to find EGLDevice");
+            continue;
+         }
+         dpy->Device = dev;
          return true;
+      }
 
       close(fd);
       dri2_dpy->fd = -1;
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index dca099500a8..b4a0790dda3 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -1300,6 +1300,7 @@ dri2_wl_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
 static EGLBoolean
 dri2_initialize_wayland_drm(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
 
    loader_set_logger(_eglLog);
@@ -1319,6 +1320,14 @@ dri2_initialize_wayland_drm(_EGLDriver *drv, _EGLDisplay *disp)
       dri2_dpy->wl_dpy = disp->PlatformDisplay;
    }
 
+   dev = _eglFindDevice(dri2_dpy->fd, false);
+   if (!dev) {
+      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    dri2_dpy->wl_modifiers =
       calloc(ARRAY_SIZE(dri2_wl_visuals), sizeof(*dri2_dpy->wl_modifiers));
    if (!dri2_dpy->wl_modifiers)
@@ -1954,6 +1963,7 @@ static const __DRIextension *swrast_loader_extensions[] = {
 static EGLBoolean
 dri2_initialize_wayland_swrast(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
 
    loader_set_logger(_eglLog);
@@ -1973,6 +1983,14 @@ dri2_initialize_wayland_swrast(_EGLDriver *drv, _EGLDisplay *disp)
       dri2_dpy->wl_dpy = disp->PlatformDisplay;
    }
 
+   dev = _eglFindDevice(dri2_dpy->fd, true);
+   if (!dev) {
+      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy);
 
    dri2_dpy->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy);
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 118ce717b99..0e844962d7d 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -1274,6 +1274,7 @@ disconnect:
 static EGLBoolean
 dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
 
    dri2_dpy = calloc(1, sizeof *dri2_dpy);
@@ -1284,6 +1285,14 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_get_xcb_connection(drv, disp, dri2_dpy))
       goto cleanup;
 
+   dev = _eglFindDevice(dri2_dpy->fd, true);
+   if (!dev) {
+      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    /*
     * Every hardware driver_name is set using strdup. Doing the same in
     * here will allow is to simply free the memory at dri2_terminate().
@@ -1352,6 +1361,7 @@ static const __DRIextension *dri3_image_loader_extensions[] = {
 static EGLBoolean
 dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
 
    dri2_dpy = calloc(1, sizeof *dri2_dpy);
@@ -1365,6 +1375,14 @@ dri2_initialize_x11_dri3(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri3_x11_connect(dri2_dpy))
       goto cleanup;
 
+   dev = _eglFindDevice(dri2_dpy->fd, false);
+   if (!dev) {
+      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    if (!dri2_load_driver_dri3(disp))
       goto cleanup;
 
@@ -1450,6 +1468,7 @@ static const __DRIextension *dri2_loader_extensions[] = {
 static EGLBoolean
 dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
 {
+   _EGLDevice *dev;
    struct dri2_egl_display *dri2_dpy;
 
    dri2_dpy = calloc(1, sizeof *dri2_dpy);
@@ -1463,6 +1482,14 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_x11_connect(dri2_dpy))
       goto cleanup;
 
+   dev = _eglFindDevice(dri2_dpy->fd, false);
+   if (!dev) {
+      _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
+      goto cleanup;
+   }
+
+   disp->Device = dev;
+
    if (!dri2_load_driver(disp))
       goto cleanup;
 
diff --git a/src/egl/drivers/haiku/egl_haiku.cpp b/src/egl/drivers/haiku/egl_haiku.cpp
index 287760661e5..dfdb90185c5 100644
--- a/src/egl/drivers/haiku/egl_haiku.cpp
+++ b/src/egl/drivers/haiku/egl_haiku.cpp
@@ -207,8 +207,16 @@ extern "C"
 EGLBoolean
 init_haiku(_EGLDriver *drv, _EGLDisplay *dpy)
 {
+	_EGLDevice *dev;
 	CALLED();
 
+	dev = _eglFindDevice(-1, true);
+	if (!dev) {
+		_eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
+		return EGL_FALSE;
+	}
+	disp->Device = dev;
+
 	TRACE("Add configs\n");
 	if (!haiku_add_configs_for_visuals(dpy))
 		return EGL_FALSE;
diff --git a/src/egl/main/egldevice.c b/src/egl/main/egldevice.c
index 26ecc50b5e0..8e7116c90f4 100644
--- a/src/egl/main/egldevice.c
+++ b/src/egl/main/egldevice.c
@@ -30,6 +30,7 @@
 #include "eglcurrent.h"
 #include "egldevice.h"
 #include "eglglobals.h"
+#include "egllog.h"
 #include "egltypedefs.h"
 
 
@@ -37,6 +38,8 @@ struct _egl_device {
    _EGLDevice *Next;
 
    const char *extensions;
+
+   EGLBoolean MESA_device_software;
 };
 
 void
@@ -47,6 +50,12 @@ _eglFiniDevice(void)
    /* atexit function is called with global mutex locked */
 
    dev_list = _eglGlobal.DeviceList;
+
+   if (!dev_list)
+      return;
+
+   /* The first device is on-stack allocated SW device */
+   dev_list = dev_list->Next;
    while (dev_list) {
       /* pop list head */
       dev = dev_list;
@@ -74,6 +83,49 @@ _eglCheckDeviceHandle(EGLDeviceEXT device)
    return (cur != NULL);
 }
 
+static _EGLDevice software_device = {
+   .extensions = "EGL_MESA_device_software",
+   .MESA_device_software = EGL_TRUE,
+};
+
+/* Looks up for device in DeviceList adding if there isn't one already.
+ *
+ * For software device lookup, the fd is ignored.
+ */
+_EGLDevice *
+_eglFindDevice(int fd, bool software)
+{
+   _EGLDevice *dev;
+
+   mtx_lock(_eglGlobal.Mutex);
+   dev = _eglGlobal.DeviceList;
+   /* The first device is always software */
+   if (!dev) {
+      _eglGlobal.DeviceList = &software_device;
+      dev = _eglGlobal.DeviceList;
+   }
+
+   if (software)
+      goto out;
+
+   dev = NULL;
+
+out:
+   mtx_unlock(_eglGlobal.Mutex);
+   return dev;
+}
+
+EGLBoolean
+_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext)
+{
+   switch (ext) {
+   case _EGL_DEVICE_SOFTWARE:
+      return dev->MESA_device_software;
+   };
+   assert(0);
+   return EGL_FALSE;
+}
+
 EGLBoolean
 _eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute,
                          EGLAttrib *value)
@@ -97,6 +149,30 @@ _eglQueryDeviceStringEXT(_EGLDevice *dev, EGLint name)
    };
 }
 
+/* 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
+_eglLookupAllDevices(void)
+{
+   _EGLDevice *dev;
+   int count = 0;
+
+   dev = _eglGlobal.DeviceList;
+   /* The first device is always software */
+   if (!dev) {
+      _eglGlobal.DeviceList = &software_device;
+      dev = _eglGlobal.DeviceList;
+   }
+   count++;
+
+   return count;
+}
+
 EGLBoolean
 _eglQueryDevicesEXT(EGLint max_devices,
                     _EGLDevice **devices,
@@ -110,7 +186,7 @@ _eglQueryDevicesEXT(EGLint max_devices,
 
    mtx_lock(_eglGlobal.Mutex);
 
-   num_devs = 0;
+   num_devs = _eglLookupAllDevices();
    devs = _eglGlobal.DeviceList;
 
    /* bail early if we only care about the count */
diff --git a/src/egl/main/egldevice.h b/src/egl/main/egldevice.h
index 69bcc1572cc..945c25268e1 100644
--- a/src/egl/main/egldevice.h
+++ b/src/egl/main/egldevice.h
@@ -29,7 +29,7 @@
 #ifndef EGLDEVICE_INCLUDED
 #define EGLDEVICE_INCLUDED
 
-
+#include <stdbool.h>
 #include "egltypedefs.h"
 
 
@@ -52,6 +52,18 @@ _eglLookupDevice(EGLDeviceEXT device)
    return dev;
 }
 
+_EGLDevice *
+_eglFindDevice(int fd, bool software);
+
+enum _egl_device_extension {
+   _EGL_DEVICE_SOFTWARE,
+};
+
+typedef enum _egl_device_extension _EGLDeviceExtension;
+
+EGLBoolean
+_eglDeviceSupports(_EGLDevice *dev, _EGLDeviceExtension ext);
+
 EGLBoolean
 _eglQueryDeviceAttribEXT(_EGLDevice *dev, EGLint attribute,
                          EGLAttrib *value);
-- 
2.18.0



More information about the mesa-dev mailing list