From: Emil Velikov <emil.veli...@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.veli...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev