1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
From 582b2d345abaa0e313cf16c902e602084ea59551 Mon Sep 17 00:00:00 2001
From: Erik Kurzinger <ekurzinger@nvidia.com>
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 <string.h>
#include <stdlib.h>
#include <assert.h>
@@ -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);
|