-
Notifications
You must be signed in to change notification settings - Fork 1
/
0044-egl-drm-add-support-for-DRI_PRIME-GPU-selection.patch
265 lines (236 loc) · 9.15 KB
/
0044-egl-drm-add-support-for-DRI_PRIME-GPU-selection.patch
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
From e446f32e8b5d7329bd67cbcab06bc0ac89ee4ca7 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 20 May 2021 14:43:29 +0100
Subject: [PATCH] egl/drm: add support for DRI_PRIME GPU selection
Add support for selecting the GPU to be used for rendering using
the DRI_PRIME environment variable. If a different GPU is selected,
a duplicate of the file descriptor for the original GPU/display is
preserved, which can be obtained by calling the getDisplayFD
function in the image loader extension.
For server side Wayland, the ability to support PRIME is
determined by checking for the PRIME import and export
capabilities on the driver file descriptor, which may no
longer support them if a different GPU from the default has
been selected. It may be that the driver can still support
PRIME; for example, by making use of the original (default)
file descriptor. The driver can indicate it supports PRIME
via the getCapabilities function in the DRI Image extension.
---
include/GL/internal/dri_interface.h | 2 ++
src/egl/drivers/dri2/egl_dri2.c | 10 ++++++++
src/egl/drivers/dri2/platform_drm.c | 19 ++++++++++-----
src/gbm/backends/dri/gbm_dri.c | 38 +++++++++++++++++++++++++----
src/gbm/backends/dri/gbm_driint.h | 8 ++++++
5 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index ab6a9fb..123349a 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1397,6 +1397,8 @@ enum __DRIChromaSiting {
*/
/*@{*/
#define __DRI_IMAGE_CAP_GLOBAL_NAMES 1
+#define __DRI_IMAGE_CAP_PRIME_IMPORT 0x2000
+#define __DRI_IMAGE_CAP_PRIME_EXPORT 0x4000
/*@}*/
/**
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index b0fa686..d0503f6 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1361,6 +1361,7 @@ dri2_display_destroy(_EGLDisplay *disp)
}
switch (disp->Platform) {
+ case _EGL_PLATFORM_DRM:
case _EGL_PLATFORM_WAYLAND:
case _EGL_PLATFORM_X11:
if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
@@ -3492,6 +3493,15 @@ dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
dri2_dpy->image->base.version >= 7 &&
dri2_dpy->image->createImageFromFds != NULL)
flags |= WAYLAND_DRM_PRIME;
+ else if (dri2_dpy->image->base.version >= 10 &&
+ dri2_dpy->image->getCapabilities != NULL) {
+ int capabilities;
+
+ capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
+ if ((capabilities & __DRI_IMAGE_CAP_PRIME_IMPORT) != 0 &&
+ (capabilities & __DRI_IMAGE_CAP_PRIME_EXPORT) != 0)
+ flags |= WAYLAND_DRM_PRIME;
+ }
dri2_dpy->wl_server_drm =
wayland_drm_init(wl_dpy, device_name,
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 4d08851..19c50c2 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -595,7 +595,7 @@ dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- return drmAuthMagic(dri2_dpy->fd, id);
+ return drmAuthMagic(dri2_dpy->fd_dpy, id);
}
static void
@@ -782,6 +782,7 @@ dri2_initialize_drm(_EGLDisplay *disp)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
dri2_dpy->fd = -1;
+ dri2_dpy->fd_dpy = -1;
disp->DriverData = (void *) dri2_dpy;
gbm = disp->PlatformDisplay;
@@ -789,16 +790,16 @@ dri2_initialize_drm(_EGLDisplay *disp)
char buf[64];
int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0);
if (n != -1 && n < sizeof(buf))
- dri2_dpy->fd = loader_open_device(buf);
- gbm = gbm_create_device(dri2_dpy->fd);
+ dri2_dpy->fd_dpy = loader_open_device(buf);
+ gbm = gbm_create_device(dri2_dpy->fd_dpy);
if (gbm == NULL) {
err = "DRI2: failed to create gbm device";
goto cleanup;
}
dri2_dpy->own_device = true;
} else {
- dri2_dpy->fd = os_dupfd_cloexec(gbm_device_get_fd(gbm));
- if (dri2_dpy->fd < 0) {
+ dri2_dpy->fd_dpy = os_dupfd_cloexec(gbm_device_get_fd(gbm));
+ if (dri2_dpy->fd_dpy < 0) {
err = "DRI2: failed to fcntl() existing gbm device";
goto cleanup;
}
@@ -810,6 +811,12 @@ dri2_initialize_drm(_EGLDisplay *disp)
goto cleanup;
}
+ if (gbm_dri_device_get_fd(dri2_dpy->gbm_dri) ==
+ gbm_device_get_fd(gbm))
+ dri2_dpy->fd = dri2_dpy->fd_dpy;
+ else
+ dri2_dpy->fd = os_dupfd_cloexec(gbm_dri_device_get_fd(dri2_dpy->gbm_dri));
+
dev = _eglAddDevice(dri2_dpy->fd, dri2_dpy->gbm_dri->software);
if (!dev) {
err = "DRI2: failed to find EGLDevice";
@@ -875,7 +882,7 @@ dri2_initialize_drm(_EGLDisplay *disp)
disp->Extensions.EXT_buffer_age = EGL_TRUE;
#ifdef HAVE_WAYLAND_PLATFORM
- dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
+ dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd_dpy);
#endif
dri2_set_WL_bind_wayland_display(disp);
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index 1759458..2b60a46 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -52,6 +52,7 @@
#include "loader.h"
#include "util/debug.h"
#include "util/macros.h"
+#include "util/os_file.h"
/* For importing wl_buffer */
#if HAVE_WAYLAND_PLATFORM
@@ -164,6 +165,14 @@ image_get_buffers(__DRIdrawable *driDrawable,
surf->dri_private, buffer_mask, buffers);
}
+static int
+dri_get_display_fd(void *loaderPrivate)
+{
+ struct gbm_dri_device *dri = loaderPrivate;
+
+ return dri->base.v0.fd;
+}
+
static void
swrast_get_drawable_info(__DRIdrawable *driDrawable,
int *x,
@@ -245,20 +254,22 @@ static const __DRIimageLookupExtension image_lookup_extension = {
};
static const __DRIdri2LoaderExtension dri2_loader_extension = {
- .base = { __DRI_DRI2_LOADER, 4 },
+ .base = { __DRI_DRI2_LOADER, 6 },
.getBuffers = dri_get_buffers,
.flushFrontBuffer = dri_flush_front_buffer,
.getBuffersWithFormat = dri_get_buffers_with_format,
.getCapability = dri_get_capability,
+ .getDisplayFD = dri_get_display_fd,
};
static const __DRIimageLoaderExtension image_loader_extension = {
- .base = { __DRI_IMAGE_LOADER, 2 },
+ .base = { __DRI_IMAGE_LOADER, 5 },
.getBuffers = image_get_buffers,
.flushFrontBuffer = dri_flush_front_buffer,
.getCapability = dri_get_capability,
+ .getDisplayFD = dri_get_display_fd,
};
static const __DRIswrastLoaderExtension swrast_loader_extension = {
@@ -431,12 +442,12 @@ dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
return -1;
if (dri->dri2->base.version >= 4) {
- dri->screen = dri->dri2->createNewScreen2(0, dri->base.v0.fd,
+ dri->screen = dri->dri2->createNewScreen2(0, dri->fd,
dri->loader_extensions,
dri->driver_extensions,
&dri->driver_configs, dri);
} else {
- dri->screen = dri->dri2->createNewScreen(0, dri->base.v0.fd,
+ dri->screen = dri->dri2->createNewScreen(0, dri->fd,
dri->loader_extensions,
&dri->driver_configs, dri);
}
@@ -503,8 +514,20 @@ static int
dri_screen_create(struct gbm_dri_device *dri)
{
char *driver_name;
+ int dup_fd, new_fd;
+ bool is_different_gpu;
- driver_name = loader_get_driver_for_fd(dri->base.v0.fd);
+ dup_fd = os_dupfd_cloexec(dri->fd);
+ if (dup_fd < 0)
+ return -1;
+
+ new_fd = loader_get_user_preferred_fd(dup_fd, &is_different_gpu);
+ if (new_fd == dup_fd)
+ close(new_fd);
+ else
+ dri->fd = new_fd;
+
+ driver_name = loader_get_driver_for_fd(dri->fd);
if (!driver_name)
return -1;
@@ -1469,6 +1492,9 @@ dri_destroy(struct gbm_device *gbm)
dlclose(dri->driver);
free(dri->driver_name);
+ if (dri->fd >= 0 && dri->fd != dri->base.v0.fd)
+ close (dri->fd);
+
free(dri);
}
@@ -1490,6 +1516,8 @@ dri_device_create(int fd, uint32_t gbm_backend_version)
if (!dri)
return NULL;
+ dri->fd = fd;
+
dri->base.v0.fd = fd;
dri->base.v0.backend_version = gbm_backend_version;
dri->base.v0.bo_create = gbm_dri_bo_create;
diff --git a/src/gbm/backends/dri/gbm_driint.h b/src/gbm/backends/dri/gbm_driint.h
index 31f6b67..3f94352 100644
--- a/src/gbm/backends/dri/gbm_driint.h
+++ b/src/gbm/backends/dri/gbm_driint.h
@@ -62,6 +62,8 @@ struct gbm_dri_visual {
struct gbm_dri_device {
struct gbm_device base;
+ int fd;
+
void *driver;
char *driver_name; /* Name of the DRI module, without the _dri suffix */
bool software; /* A software driver was loaded */
@@ -195,4 +197,10 @@ gbm_dri_bo_unmap_dumb(struct gbm_dri_bo *bo)
bo->map = NULL;
}
+static inline int
+gbm_dri_device_get_fd(struct gbm_dri_device *dri)
+{
+ return dri->fd;
+}
+
#endif