123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- From 4163f34fbdbc0516085ba562e0013487b408c7ab 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 | 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 888a117..2fb440f 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 c4a49ca..1df53ef 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 f8792ea..22e27b4 100644
- --- a/src/egl/drivers/dri2/egl_dri2.h
- +++ b/src/egl/drivers/dri2/egl_dri2.h
- @@ -231,6 +231,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 06272d4..b393e05 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 5ffdf13..5cf3ce2 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 e117105..0babf9f 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 db1b079..1ed6b60 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 c0e833c..b3dccf2 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 */
|