From 582b2d345abaa0e313cf16c902e602084ea59551 Mon Sep 17 00:00:00 2001 From: Erik Kurzinger Date: Tue, 23 Nov 2021 14:15:14 -0500 Subject: [PATCH] egl-wayland: retrieve DRM device name before acquiring API lock wlEglBindDisplaysHook acquires the external API lock before calling wl_eglstream_display_bind, which in turn calls wl_drm_display_bind. That function calls back into EGL to query the DRM device associated with the given EGLDisplay. Normally this is not a problem since the EGLDisplay passed to eglBindWaylandDisplayWL will be an internal EGL_PLATFORM_DEVICE handle. However, some applications, notably anything WebKit-based, will instead pass in an external EGL_PLATFORM_WAYLAND handle. This means that the eglQueryDisplayAttrib call by wl_drm_display_bind will require EGL to call back into the egl-wayland library to look up the internal handle. This is done by wlEglGetInternalHandleExport, which will attempt to acquire the external API lock a second time, which will fail. To avoid this, add a new function to wayland-drm.c which will retrieve the DRM device name for the given EGLDisplay. wlEglBindDisplaysHook will call this *before* acquiring the external API lock, and then pass it to wl_drm_display_bind via wl_eglstream_display_bind so it can be saved in the wl_eglstream_display struct. --- include/wayland-drm.h | 7 ++++++- include/wayland-eglstream-server.h | 3 ++- src/wayland-drm.c | 33 +++++++++++++++--------------- src/wayland-egldisplay.c | 8 +++++--- src/wayland-eglstream-server.c | 5 +++-- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/include/wayland-drm.h b/include/wayland-drm.h index be363c6..84d0f11 100644 --- a/include/wayland-drm.h +++ b/include/wayland-drm.h @@ -23,9 +23,14 @@ #ifndef WAYLAND_DRM_H #define WAYLAND_DRM_H +extern const char * +wl_drm_get_dev_name(const WlEglPlatformData *data, + EGLDisplay dpy); + extern EGLBoolean wl_drm_display_bind(struct wl_display *display, - struct wl_eglstream_display *wlStreamDpy); + struct wl_eglstream_display *wlStreamDpy, + const char *dev_name); extern void wl_drm_display_unbind(struct wl_eglstream_display *wlStreamDpy); diff --git a/include/wayland-eglstream-server.h b/include/wayland-eglstream-server.h index 76e772c..0f7d477 100644 --- a/include/wayland-eglstream-server.h +++ b/include/wayland-eglstream-server.h @@ -49,7 +49,8 @@ EGLBoolean wl_eglstream_display_bind(WlEglPlatformData *data, struct wl_display *wlDisplay, EGLDisplay eglDisplay, - const char *exts); + const char *exts, + const char *dev_name); /* * wl_eglstream_display_unbind() diff --git a/src/wayland-drm.c b/src/wayland-drm.c index aa6de23..a08d82f 100644 --- a/src/wayland-drm.c +++ b/src/wayland-drm.c @@ -152,37 +152,36 @@ bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) wl_resource_post_event(resource, WL_DRM_CAPABILITIES, 0); } -EGLBoolean -wl_drm_display_bind(struct wl_display *display, - struct wl_eglstream_display *wlStreamDpy) +const char * +wl_drm_get_dev_name(const WlEglPlatformData *data, + EGLDisplay dpy) { - EGLDisplay dpy = wlStreamDpy->eglDisplay; EGLDeviceEXT egl_dev; const char *dev_exts; - const char *dev_name; - if (!wlStreamDpy->data->egl.queryDisplayAttrib(dpy, - EGL_DEVICE_EXT, - (EGLAttribKHR*)&egl_dev)) { - return EGL_FALSE; + if (!data->egl.queryDisplayAttrib(dpy, EGL_DEVICE_EXT, + (EGLAttribKHR*)&egl_dev)) { + return NULL; } - - dev_exts = wlStreamDpy->data->egl.queryDeviceString(egl_dev, - EGL_EXTENSIONS); + dev_exts = data->egl.queryDeviceString(egl_dev, EGL_EXTENSIONS); if (!dev_exts) { - return EGL_FALSE; + return NULL; } if (!wlEglFindExtension("EGL_EXT_device_drm_render_node", dev_exts)) { - return EGL_FALSE; + return NULL; } - dev_name = - wlStreamDpy->data->egl.queryDeviceString(egl_dev, - EGL_DRM_RENDER_NODE_FILE_EXT); + return data->egl.queryDeviceString(egl_dev, EGL_DRM_RENDER_NODE_FILE_EXT); +} +EGLBoolean +wl_drm_display_bind(struct wl_display *display, + struct wl_eglstream_display *wlStreamDpy, + const char *dev_name) +{ if (!dev_name) { return EGL_FALSE; } diff --git a/src/wayland-egldisplay.c b/src/wayland-egldisplay.c index 8b7394a..d285bf7 100644 --- a/src/wayland-egldisplay.c +++ b/src/wayland-egldisplay.c @@ -30,6 +30,7 @@ #include "wayland-eglhandle.h" #include "wayland-eglutils.h" #include "wayland-drm-client-protocol.h" +#include "wayland-drm.h" #include #include #include @@ -70,15 +71,16 @@ EGLBoolean wlEglIsValidNativeDisplayExport(void *data, void *nativeDpy) EGLBoolean wlEglBindDisplaysHook(void *data, EGLDisplay dpy, void *nativeDpy) { - /* Retrieve extension string before taking external API lock */ - const char *exts = ((WlEglPlatformData *)data)->egl.queryString(dpy, EGL_EXTENSIONS); + /* Retrieve extension string and device name before taking external API lock */ + const char *exts = ((WlEglPlatformData *)data)->egl.queryString(dpy, EGL_EXTENSIONS), + *dev_name = wl_drm_get_dev_name(data, dpy); EGLBoolean res = EGL_FALSE; wlExternalApiLock(); res = wl_eglstream_display_bind((WlEglPlatformData *)data, (struct wl_display *)nativeDpy, - dpy, exts); + dpy, exts, dev_name); wlExternalApiUnlock(); diff --git a/src/wayland-eglstream-server.c b/src/wayland-eglstream-server.c index b1baa08..1dfd7ce 100644 --- a/src/wayland-eglstream-server.c +++ b/src/wayland-eglstream-server.c @@ -289,7 +289,8 @@ EGLBoolean wl_eglstream_display_bind(WlEglPlatformData *data, struct wl_display *wlDisplay, EGLDisplay eglDisplay, - const char *exts) + const char *exts, + const char *dev_name) { struct wl_eglstream_display *wlStreamDpy = NULL; char *env = NULL; @@ -355,7 +356,7 @@ wl_eglstream_display_bind(WlEglPlatformData *data, wl_eglstream_display_global_bind); /* Failure is not fatal */ - wl_drm_display_bind(wlDisplay, wlStreamDpy); + wl_drm_display_bind(wlDisplay, wlStreamDpy, dev_name); wl_list_insert(&wlStreamDpyList, &wlStreamDpy->link);