On Friday, 2018-08-03 13:44:19 +0100, Emil Velikov wrote: > 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)
"find()" doesn't really sounds like the function that builds the list one device at a time. How about _eglAddDevice() ? > +{ > + _EGLDevice *dev; > + > + mtx_lock(_eglGlobal.Mutex); > + dev = _eglGlobal.DeviceList; > + /* The first device is always software */ > + if (!dev) { > + _eglGlobal.DeviceList = &software_device; > + dev = _eglGlobal.DeviceList; > + } You could avoid that (duplicated) runtime logic by just putting that line in the initialisation of `_eglGlobal` > + > + 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) Same issue, "lookup()" doesn't sound like what builds the list. How about _eglRefreshDeviceList() ? > +{ > + _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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev