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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
|
From ef4faa3bd7de045efa62c092f1bb01198fe015e8 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Tue, 9 Mar 2021 17:15:30 +0000
Subject: [PATCH] dri: preserve the original FD for driver use.
If an application uses a different GPU from the default, allow the
file descriptor (FD) for that original GPU/display to be preserved
for use by drivers. Drivers may wish to use the original FD to
allocate shared surfaces, to ensure the surface properties are
compatible with the original GPU/display (e.g. for X11 or Wayland).
This feature is only available on platforms that choose to support
it, by implementing the new getDisplayFD function in the DRI image,
and DRI2 loader extensions.
If the feature is available, drivers can obtain the original FD
by calling the getDisplayFD function in the relevant loader extension.
Drivers should check the FD is valid before use (i.e. not -1). If
the FD is valid, it may be equal to the current GPU FD if a different
GPU is not being used. The FD is owned by the platform, not the
driver, and the platform is responsible for closing it.
The feature is currently supported by the Wayland, and DRI3 based
X11 EGL and GLX platforms.
---
include/GL/internal/dri_interface.h | 26 +++++++++++++++++--
src/egl/drivers/dri2/egl_dri2.c | 12 ++++++++-
src/egl/drivers/dri2/egl_dri2.h | 1 +
src/egl/drivers/dri2/platform_wayland.c | 31 ++++++++++++++++++++--
src/egl/drivers/dri2/platform_x11.c | 3 +++
src/egl/drivers/dri2/platform_x11_dri3.c | 27 ++++++++++++++++++-
src/glx/dri3_glx.c | 33 ++++++++++++++++++++++--
src/glx/dri3_priv.h | 1 +
8 files changed, 126 insertions(+), 8 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index acd58cc..ab6a9fb 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1005,7 +1005,7 @@ struct __DRIbufferRec {
};
#define __DRI_DRI2_LOADER "DRI_DRI2Loader"
-#define __DRI_DRI2_LOADER_VERSION 5
+#define __DRI_DRI2_LOADER_VERSION 6
enum dri_loader_cap {
/* Whether the loader handles RGBA channel ordering correctly. If not,
@@ -1086,6 +1086,17 @@ struct __DRIdri2LoaderExtensionRec {
* \since 5
*/
void (*destroyLoaderImageState)(void *loaderPrivate);
+
+ /**
+ * Get the display FD
+ *
+ * Get the FD of the display device.
+ *
+ * \param loaderPrivate The last parameter of createNewScreen or
+ * createNewScreen2.
+ * \since 6
+ */
+ int (*getDisplayFD)(void *loaderPrivate);
};
/**
@@ -2032,7 +2043,7 @@ struct __DRIimageList {
};
#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
-#define __DRI_IMAGE_LOADER_VERSION 4
+#define __DRI_IMAGE_LOADER_VERSION 5
struct __DRIimageLoaderExtensionRec {
__DRIextension base;
@@ -2100,6 +2111,17 @@ struct __DRIimageLoaderExtensionRec {
* \since 4
*/
void (*destroyLoaderImageState)(void *loaderPrivate);
+
+ /**
+ * Get the display FD
+ *
+ * Get the FD of the display device.
+ *
+ * \param loaderPrivate The last parameter of createNewScreen or
+ * createNewScreen2.
+ * \since 5
+ */
+ int (*getDisplayFD)(void *loaderPrivate);
};
/**
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 3ae5cdd..b0fa686 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1360,6 +1360,16 @@ dri2_display_destroy(_EGLDisplay *disp)
break;
}
+ switch (disp->Platform) {
+ case _EGL_PLATFORM_WAYLAND:
+ case _EGL_PLATFORM_X11:
+ if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
+ close(dri2_dpy->fd_dpy);
+ break;
+ default:
+ break;
+ }
+
if (dri2_dpy->fd >= 0)
close(dri2_dpy->fd);
@@ -3471,7 +3481,7 @@ dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
if (dri2_dpy->wl_server_drm)
return EGL_FALSE;
- device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
+ device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd_dpy);
if (!device_name)
device_name = strdup(dri2_dpy->device_name);
if (!device_name)
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index e48d3d2..a5418bd 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -260,6 +260,7 @@ struct dri2_egl_display
const __DRIconfigOptionsExtension *configOptions;
const __DRImutableRenderBufferDriverExtension *mutable_render_buffer;
int fd;
+ int fd_dpy;
/* dri2_initialize/dri2_terminate increment/decrement this count, so does
* dri2_make_current (tracks if there are active contexts/surfaces). */
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index be10fc6..d651274 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -44,6 +44,7 @@
#include "loader.h"
#include "util/u_vector.h"
#include "util/anon_file.h"
+#include "util/os_file.h"
#include "eglglobals.h"
#include "kopper_interface.h"
@@ -1448,21 +1449,32 @@ dri2_wl_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
}
}
+static int
+dri2_wl_get_display_fd(void *loaderPrivate)
+{
+ _EGLDisplay *disp = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ return dri2_dpy->fd_dpy;
+}
+
static const __DRIdri2LoaderExtension dri2_loader_extension = {
- .base = { __DRI_DRI2_LOADER, 4 },
+ .base = { __DRI_DRI2_LOADER, 6 },
.getBuffers = dri2_wl_get_buffers,
.flushFrontBuffer = dri2_wl_flush_front_buffer,
.getBuffersWithFormat = dri2_wl_get_buffers_with_format,
.getCapability = dri2_wl_get_capability,
+ .getDisplayFD = dri2_wl_get_display_fd,
};
static const __DRIimageLoaderExtension image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 2 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = image_get_buffers,
.flushFrontBuffer = dri2_wl_flush_front_buffer,
.getCapability = dri2_wl_get_capability,
+ .getDisplayFD = dri2_wl_get_display_fd,
};
static void
@@ -2224,12 +2236,14 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
{
_EGLDevice *dev;
struct dri2_egl_display *dri2_dpy;
+ int fd_old;
dri2_dpy = calloc(1, sizeof *dri2_dpy);
if (!dri2_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
disp->DriverData = (void *) dri2_dpy;
if (dri2_wl_formats_init(&dri2_dpy->formats) < 0)
@@ -2303,8 +2317,20 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
goto cleanup;
}
+ fd_old = dri2_dpy->fd;
+ dri2_dpy->fd_dpy = os_dupfd_cloexec(dri2_dpy->fd);
dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
&dri2_dpy->is_different_gpu);
+ if (dri2_dpy->fd == fd_old) {
+ if (dri2_dpy->fd_dpy != -1)
+ close(dri2_dpy->fd_dpy);
+
+ dri2_dpy->fd_dpy = dri2_dpy->fd;
+ } else if (dri2_dpy->fd_dpy == -1) {
+ _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to dup display FD");
+ goto cleanup;
+ }
+
dev = _eglAddDevice(dri2_dpy->fd, false);
if (!dev) {
_eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
@@ -2868,6 +2894,7 @@ dri2_initialize_wayland_swrast(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
disp->DriverData = (void *) dri2_dpy;
if (dri2_wl_formats_init(&dri2_dpy->formats) < 0)
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 5330298..730a91d 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -1413,6 +1413,7 @@ dri2_initialize_x11_swrast(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
if (!dri2_get_xcb_connection(disp, dri2_dpy))
goto cleanup;
@@ -1497,6 +1498,7 @@ dri2_initialize_x11_dri3(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
if (!dri2_get_xcb_connection(disp, dri2_dpy))
goto cleanup;
@@ -1605,6 +1607,7 @@ dri2_initialize_x11_dri2(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
if (!dri2_get_xcb_connection(disp, dri2_dpy))
goto cleanup;
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
index 3d7c2ae..860d975 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -32,6 +32,7 @@
#include <xf86drm.h>
#include "util/macros.h"
+#include "util/os_file.h"
#include "egl_dri2.h"
#include "platform_x11_dri3.h"
@@ -431,11 +432,21 @@ dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
_eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
}
+static int
+dri3_get_display_fd(void *loaderPrivate)
+{
+ _EGLDisplay *disp = loaderPrivate;
+ struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+ return dri2_dpy->fd_dpy;
+}
+
const __DRIimageLoaderExtension dri3_image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 1 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = loader_dri3_get_buffers,
.flushFrontBuffer = dri3_flush_front_buffer,
+ .getDisplayFD = dri3_get_display_fd,
};
static EGLBoolean
@@ -554,6 +565,7 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
xcb_generic_error_t *error;
const xcb_query_extension_reply_t *extension;
+ int fd_old;
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
@@ -633,12 +645,25 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
return EGL_FALSE;
}
+ fd_old = dri2_dpy->fd;
+ dri2_dpy->fd_dpy = os_dupfd_cloexec(dri2_dpy->fd);
dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
+ if (dri2_dpy->fd == fd_old) {
+ if (dri2_dpy->fd_dpy != -1)
+ close(dri2_dpy->fd_dpy);
+
+ dri2_dpy->fd_dpy = dri2_dpy->fd;
+ } else if (dri2_dpy->fd_dpy == -1) {
+ _eglLog(_EGL_WARNING, "DRI3: failed to dup display FD");
+ close(dri2_dpy->fd);
+ return EGL_FALSE;
+ }
dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
if (!dri2_dpy->driver_name) {
_eglLog(_EGL_WARNING, "DRI3: No driver found");
close(dri2_dpy->fd);
+ close(dri2_dpy->fd_dpy);
return EGL_FALSE;
}
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 6370ca0..cf7fc61 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -77,6 +77,7 @@
#include "dri3_priv.h"
#include "loader.h"
#include "dri2.h"
+#include "util/os_file.h"
static struct dri3_drawable *
loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) {
@@ -543,6 +544,14 @@ dri3_flush_swap_buffers(__DRIdrawable *driDrawable, void *loaderPrivate)
loader_dri3_swapbuffer_barrier(draw);
}
+static int
+dri3_get_display_fd(void *loaderPrivate)
+{
+ struct dri3_screen *psc = (struct dri3_screen *)loaderPrivate;
+
+ return psc->fd_dpy;
+}
+
static void
dri_set_background_context(void *loaderPrivate)
{
@@ -562,11 +571,12 @@ dri_is_thread_safe(void *loaderPrivate)
/* The image loader extension record for DRI3
*/
static const __DRIimageLoaderExtension imageLoaderExtension = {
- .base = { __DRI_IMAGE_LOADER, 3 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = loader_dri3_get_buffers,
.flushFrontBuffer = dri3_flush_front_buffer,
.flushSwapBuffers = dri3_flush_swap_buffers,
+ .getDisplayFD = dri3_get_display_fd,
};
const __DRIuseInvalidateExtension dri3UseInvalidate = {
@@ -632,6 +642,10 @@ dri3_destroy_screen(struct glx_screen *base)
loader_dri3_close_screen(psc->driScreen);
(*psc->core->destroyScreen) (psc->driScreen);
driDestroyConfigs(psc->driver_configs);
+
+ if (psc->fd_dpy != psc->fd)
+ close(psc->fd_dpy);
+
close(psc->fd);
free(psc);
}
@@ -858,8 +872,9 @@ dri3_create_screen(int screen, struct glx_display * priv)
struct dri3_screen *psc;
__GLXDRIscreen *psp;
struct glx_config *configs = NULL, *visuals = NULL;
- char *driverName, *driverNameDisplayGPU, *tmp;
+ char *driverName = NULL, *driverNameDisplayGPU, *tmp;
int i;
+ int fd_old;
psc = calloc(1, sizeof *psc);
if (psc == NULL)
@@ -867,6 +882,7 @@ dri3_create_screen(int screen, struct glx_display * priv)
psc->fd = -1;
psc->fd_display_gpu = -1;
+ psc->fd_dpy = -1;
if (!glx_screen_init(&psc->base, screen, priv)) {
free(psc);
@@ -887,12 +903,23 @@ dri3_create_screen(int screen, struct glx_display * priv)
return NULL;
}
+ fd_old = psc->fd;
+ psc->fd_dpy = os_dupfd_cloexec(psc->fd);
psc->fd_display_gpu = fcntl(psc->fd, F_DUPFD_CLOEXEC, 3);
psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
if (!psc->is_different_gpu) {
close(psc->fd_display_gpu);
psc->fd_display_gpu = -1;
}
+ if (psc->fd == fd_old) {
+ if (psc->fd_dpy != -1)
+ close(psc->fd_dpy);
+
+ psc->fd_dpy = psc->fd;
+ } else if (psc->fd_dpy == -1) {
+ ErrorMessageF("Unable to dup the display FD");
+ goto handle_error;
+ }
driverName = loader_get_driver_for_fd(psc->fd);
if (!driverName) {
@@ -1098,6 +1125,8 @@ handle_error:
if (psc->driScreenDisplayGPU)
psc->core->destroyScreen(psc->driScreenDisplayGPU);
psc->driScreenDisplayGPU = NULL;
+ if (psc->fd_dpy >= 0 && psc->fd_dpy != psc->fd)
+ close(psc->fd_dpy);
if (psc->fd >= 0)
close(psc->fd);
if (psc->fd_display_gpu >= 0)
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
index 192238f..bac8a35 100644
--- a/src/glx/dri3_priv.h
+++ b/src/glx/dri3_priv.h
@@ -107,6 +107,7 @@ struct dri3_screen {
void *driver;
int fd;
+ int fd_dpy;
bool is_different_gpu;
bool prefer_back_buffer_reuse;
|