Files
fml13v01-buildroot/package/mesa3d/0050-dri-preserve-the-original-FD-for-driver-use.patch
T
2022-08-16 17:38:05 +08:00

434 lines
14 KiB
Diff

From db015d5fd0ded075e759677c047c581151bb1b52 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 50/67] 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 | 10 +++++++
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, 125 insertions(+), 7 deletions(-)
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 888a117d56e..2fb440feb50 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1146,7 +1146,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,
@@ -1227,6 +1227,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);
};
/**
@@ -2131,7 +2142,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;
@@ -2199,6 +2210,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 c4a49cae592..1df53ef011c 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1367,6 +1367,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);
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 141df1b1732..af03caee623 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -230,6 +230,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 06272d4081e..b393e058770 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 <wayland-egl-backend.h>
@@ -973,21 +974,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
@@ -1640,12 +1652,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 (disp->PlatformDisplay == NULL) {
dri2_dpy->wl_dpy = wl_display_connect(NULL);
@@ -1690,8 +1704,20 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
(roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated))
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");
@@ -2236,6 +2262,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 (disp->PlatformDisplay == NULL) {
dri2_dpy->wl_dpy = wl_display_connect(NULL);
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 5ffdf132184..5cf3ce2a369 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -1277,6 +1277,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;
@@ -1364,6 +1365,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;
@@ -1472,6 +1474,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 e117105fcb6..0babf9f867e 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"
@@ -414,11 +415,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
@@ -537,6 +548,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);
@@ -616,12 +628,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 db1b079663f..1ed6b60ffe8 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) {
@@ -529,6 +530,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)
{
@@ -548,11 +557,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 = {
@@ -618,6 +628,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);
}
@@ -842,8 +856,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)
@@ -851,6 +866,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);
@@ -871,12 +887,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) {
@@ -1049,6 +1076,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 c0e833c16ef..b3dccf28c06 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;
/* fd for display GPU in case of prime */
--
2.25.1