0050-dri-preserve-the-original-FD-for-driver-use.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. From 4163f34fbdbc0516085ba562e0013487b408c7ab Mon Sep 17 00:00:00 2001
  2. From: Brendan King <Brendan.King@imgtec.com>
  3. Date: Tue, 9 Mar 2021 17:15:30 +0000
  4. Subject: [PATCH] dri: preserve the original FD for driver use.
  5. If an application uses a different GPU from the default, allow the
  6. file descriptor (FD) for that original GPU/display to be preserved
  7. for use by drivers. Drivers may wish to use the original FD to
  8. allocate shared surfaces, to ensure the surface properties are
  9. compatible with the original GPU/display (e.g. for X11 or Wayland).
  10. This feature is only available on platforms that choose to support
  11. it, by implementing the new getDisplayFD function in the DRI image,
  12. and DRI2 loader extensions.
  13. If the feature is available, drivers can obtain the original FD
  14. by calling the getDisplayFD function in the relevant loader extension.
  15. Drivers should check the FD is valid before use (i.e. not -1). If
  16. the FD is valid, it may be equal to the current GPU FD if a different
  17. GPU is not being used. The FD is owned by the platform, not the
  18. driver, and the platform is responsible for closing it.
  19. The feature is currently supported by the Wayland, and DRI3 based
  20. X11 EGL and GLX platforms.
  21. ---
  22. include/GL/internal/dri_interface.h | 26 +++++++++++++++++--
  23. src/egl/drivers/dri2/egl_dri2.c | 10 +++++++
  24. src/egl/drivers/dri2/egl_dri2.h | 1 +
  25. src/egl/drivers/dri2/platform_wayland.c | 31 ++++++++++++++++++++--
  26. src/egl/drivers/dri2/platform_x11.c | 3 +++
  27. src/egl/drivers/dri2/platform_x11_dri3.c | 27 ++++++++++++++++++-
  28. src/glx/dri3_glx.c | 33 ++++++++++++++++++++++--
  29. src/glx/dri3_priv.h | 1 +
  30. 8 files changed, 125 insertions(+), 7 deletions(-)
  31. diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
  32. index 888a117..2fb440f 100644
  33. --- a/include/GL/internal/dri_interface.h
  34. +++ b/include/GL/internal/dri_interface.h
  35. @@ -1146,7 +1146,7 @@ struct __DRIbufferRec {
  36. };
  37. #define __DRI_DRI2_LOADER "DRI_DRI2Loader"
  38. -#define __DRI_DRI2_LOADER_VERSION 5
  39. +#define __DRI_DRI2_LOADER_VERSION 6
  40. enum dri_loader_cap {
  41. /* Whether the loader handles RGBA channel ordering correctly. If not,
  42. @@ -1227,6 +1227,17 @@ struct __DRIdri2LoaderExtensionRec {
  43. * \since 5
  44. */
  45. void (*destroyLoaderImageState)(void *loaderPrivate);
  46. +
  47. + /**
  48. + * Get the display FD
  49. + *
  50. + * Get the FD of the display device.
  51. + *
  52. + * \param loaderPrivate The last parameter of createNewScreen or
  53. + * createNewScreen2.
  54. + * \since 6
  55. + */
  56. + int (*getDisplayFD)(void *loaderPrivate);
  57. };
  58. /**
  59. @@ -2131,7 +2142,7 @@ struct __DRIimageList {
  60. };
  61. #define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
  62. -#define __DRI_IMAGE_LOADER_VERSION 4
  63. +#define __DRI_IMAGE_LOADER_VERSION 5
  64. struct __DRIimageLoaderExtensionRec {
  65. __DRIextension base;
  66. @@ -2199,6 +2210,17 @@ struct __DRIimageLoaderExtensionRec {
  67. * \since 4
  68. */
  69. void (*destroyLoaderImageState)(void *loaderPrivate);
  70. +
  71. + /**
  72. + * Get the display FD
  73. + *
  74. + * Get the FD of the display device.
  75. + *
  76. + * \param loaderPrivate The last parameter of createNewScreen or
  77. + * createNewScreen2.
  78. + * \since 5
  79. + */
  80. + int (*getDisplayFD)(void *loaderPrivate);
  81. };
  82. /**
  83. diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
  84. index c4a49ca..1df53ef 100644
  85. --- a/src/egl/drivers/dri2/egl_dri2.c
  86. +++ b/src/egl/drivers/dri2/egl_dri2.c
  87. @@ -1367,6 +1367,16 @@ dri2_display_destroy(_EGLDisplay *disp)
  88. break;
  89. }
  90. + switch (disp->Platform) {
  91. + case _EGL_PLATFORM_WAYLAND:
  92. + case _EGL_PLATFORM_X11:
  93. + if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
  94. + close(dri2_dpy->fd_dpy);
  95. + break;
  96. + default:
  97. + break;
  98. + }
  99. +
  100. if (dri2_dpy->fd >= 0)
  101. close(dri2_dpy->fd);
  102. diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
  103. index f8792ea..22e27b4 100644
  104. --- a/src/egl/drivers/dri2/egl_dri2.h
  105. +++ b/src/egl/drivers/dri2/egl_dri2.h
  106. @@ -231,6 +231,7 @@ struct dri2_egl_display
  107. const __DRIconfigOptionsExtension *configOptions;
  108. const __DRImutableRenderBufferDriverExtension *mutable_render_buffer;
  109. int fd;
  110. + int fd_dpy;
  111. /* dri2_initialize/dri2_terminate increment/decrement this count, so does
  112. * dri2_make_current (tracks if there are active contexts/surfaces). */
  113. diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
  114. index 06272d4..b393e05 100644
  115. --- a/src/egl/drivers/dri2/platform_wayland.c
  116. +++ b/src/egl/drivers/dri2/platform_wayland.c
  117. @@ -44,6 +44,7 @@
  118. #include "loader.h"
  119. #include "util/u_vector.h"
  120. #include "util/anon_file.h"
  121. +#include "util/os_file.h"
  122. #include "eglglobals.h"
  123. #include <wayland-egl-backend.h>
  124. @@ -973,21 +974,32 @@ dri2_wl_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
  125. }
  126. }
  127. +static int
  128. +dri2_wl_get_display_fd(void *loaderPrivate)
  129. +{
  130. + _EGLDisplay *disp = loaderPrivate;
  131. + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  132. +
  133. + return dri2_dpy->fd_dpy;
  134. +}
  135. +
  136. static const __DRIdri2LoaderExtension dri2_loader_extension = {
  137. - .base = { __DRI_DRI2_LOADER, 4 },
  138. + .base = { __DRI_DRI2_LOADER, 6 },
  139. .getBuffers = dri2_wl_get_buffers,
  140. .flushFrontBuffer = dri2_wl_flush_front_buffer,
  141. .getBuffersWithFormat = dri2_wl_get_buffers_with_format,
  142. .getCapability = dri2_wl_get_capability,
  143. + .getDisplayFD = dri2_wl_get_display_fd,
  144. };
  145. static const __DRIimageLoaderExtension image_loader_extension = {
  146. - .base = { __DRI_IMAGE_LOADER, 2 },
  147. + .base = { __DRI_IMAGE_LOADER, 5 },
  148. .getBuffers = image_get_buffers,
  149. .flushFrontBuffer = dri2_wl_flush_front_buffer,
  150. .getCapability = dri2_wl_get_capability,
  151. + .getDisplayFD = dri2_wl_get_display_fd,
  152. };
  153. static void
  154. @@ -1640,12 +1652,14 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
  155. {
  156. _EGLDevice *dev;
  157. struct dri2_egl_display *dri2_dpy;
  158. + int fd_old;
  159. dri2_dpy = calloc(1, sizeof *dri2_dpy);
  160. if (!dri2_dpy)
  161. return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  162. dri2_dpy->fd = -1;
  163. + dri2_dpy->fd_dpy = -1;
  164. disp->DriverData = (void *) dri2_dpy;
  165. if (disp->PlatformDisplay == NULL) {
  166. dri2_dpy->wl_dpy = wl_display_connect(NULL);
  167. @@ -1690,8 +1704,20 @@ dri2_initialize_wayland_drm(_EGLDisplay *disp)
  168. (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated))
  169. goto cleanup;
  170. + fd_old = dri2_dpy->fd;
  171. + dri2_dpy->fd_dpy = os_dupfd_cloexec(dri2_dpy->fd);
  172. dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd,
  173. &dri2_dpy->is_different_gpu);
  174. + if (dri2_dpy->fd == fd_old) {
  175. + if (dri2_dpy->fd_dpy != -1)
  176. + close(dri2_dpy->fd_dpy);
  177. +
  178. + dri2_dpy->fd_dpy = dri2_dpy->fd;
  179. + } else if (dri2_dpy->fd_dpy == -1) {
  180. + _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to dup display FD");
  181. + goto cleanup;
  182. + }
  183. +
  184. dev = _eglAddDevice(dri2_dpy->fd, false);
  185. if (!dev) {
  186. _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice");
  187. @@ -2236,6 +2262,7 @@ dri2_initialize_wayland_swrast(_EGLDisplay *disp)
  188. return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  189. dri2_dpy->fd = -1;
  190. + dri2_dpy->fd_dpy = -1;
  191. disp->DriverData = (void *) dri2_dpy;
  192. if (disp->PlatformDisplay == NULL) {
  193. dri2_dpy->wl_dpy = wl_display_connect(NULL);
  194. diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
  195. index 5ffdf13..5cf3ce2 100644
  196. --- a/src/egl/drivers/dri2/platform_x11.c
  197. +++ b/src/egl/drivers/dri2/platform_x11.c
  198. @@ -1277,6 +1277,7 @@ dri2_initialize_x11_swrast(_EGLDisplay *disp)
  199. return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  200. dri2_dpy->fd = -1;
  201. + dri2_dpy->fd_dpy = -1;
  202. if (!dri2_get_xcb_connection(disp, dri2_dpy))
  203. goto cleanup;
  204. @@ -1364,6 +1365,7 @@ dri2_initialize_x11_dri3(_EGLDisplay *disp)
  205. return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  206. dri2_dpy->fd = -1;
  207. + dri2_dpy->fd_dpy = -1;
  208. if (!dri2_get_xcb_connection(disp, dri2_dpy))
  209. goto cleanup;
  210. @@ -1472,6 +1474,7 @@ dri2_initialize_x11_dri2(_EGLDisplay *disp)
  211. return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  212. dri2_dpy->fd = -1;
  213. + dri2_dpy->fd_dpy = -1;
  214. if (!dri2_get_xcb_connection(disp, dri2_dpy))
  215. goto cleanup;
  216. diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
  217. index e117105..0babf9f 100644
  218. --- a/src/egl/drivers/dri2/platform_x11_dri3.c
  219. +++ b/src/egl/drivers/dri2/platform_x11_dri3.c
  220. @@ -32,6 +32,7 @@
  221. #include <xf86drm.h>
  222. #include "util/macros.h"
  223. +#include "util/os_file.h"
  224. #include "egl_dri2.h"
  225. #include "platform_x11_dri3.h"
  226. @@ -414,11 +415,21 @@ dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
  227. _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
  228. }
  229. +static int
  230. +dri3_get_display_fd(void *loaderPrivate)
  231. +{
  232. + _EGLDisplay *disp = loaderPrivate;
  233. + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  234. +
  235. + return dri2_dpy->fd_dpy;
  236. +}
  237. +
  238. const __DRIimageLoaderExtension dri3_image_loader_extension = {
  239. - .base = { __DRI_IMAGE_LOADER, 1 },
  240. + .base = { __DRI_IMAGE_LOADER, 5 },
  241. .getBuffers = loader_dri3_get_buffers,
  242. .flushFrontBuffer = dri3_flush_front_buffer,
  243. + .getDisplayFD = dri3_get_display_fd,
  244. };
  245. static EGLBoolean
  246. @@ -537,6 +548,7 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
  247. xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
  248. xcb_generic_error_t *error;
  249. const xcb_query_extension_reply_t *extension;
  250. + int fd_old;
  251. xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
  252. xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
  253. @@ -616,12 +628,25 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
  254. return EGL_FALSE;
  255. }
  256. + fd_old = dri2_dpy->fd;
  257. + dri2_dpy->fd_dpy = os_dupfd_cloexec(dri2_dpy->fd);
  258. dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
  259. + if (dri2_dpy->fd == fd_old) {
  260. + if (dri2_dpy->fd_dpy != -1)
  261. + close(dri2_dpy->fd_dpy);
  262. +
  263. + dri2_dpy->fd_dpy = dri2_dpy->fd;
  264. + } else if (dri2_dpy->fd_dpy == -1) {
  265. + _eglLog(_EGL_WARNING, "DRI3: failed to dup display FD");
  266. + close(dri2_dpy->fd);
  267. + return EGL_FALSE;
  268. + }
  269. dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
  270. if (!dri2_dpy->driver_name) {
  271. _eglLog(_EGL_WARNING, "DRI3: No driver found");
  272. close(dri2_dpy->fd);
  273. + close(dri2_dpy->fd_dpy);
  274. return EGL_FALSE;
  275. }
  276. diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
  277. index db1b079..1ed6b60 100644
  278. --- a/src/glx/dri3_glx.c
  279. +++ b/src/glx/dri3_glx.c
  280. @@ -77,6 +77,7 @@
  281. #include "dri3_priv.h"
  282. #include "loader.h"
  283. #include "dri2.h"
  284. +#include "util/os_file.h"
  285. static struct dri3_drawable *
  286. loader_drawable_to_dri3_drawable(struct loader_dri3_drawable *draw) {
  287. @@ -529,6 +530,14 @@ dri3_flush_swap_buffers(__DRIdrawable *driDrawable, void *loaderPrivate)
  288. loader_dri3_swapbuffer_barrier(draw);
  289. }
  290. +static int
  291. +dri3_get_display_fd(void *loaderPrivate)
  292. +{
  293. + struct dri3_screen *psc = (struct dri3_screen *)loaderPrivate;
  294. +
  295. + return psc->fd_dpy;
  296. +}
  297. +
  298. static void
  299. dri_set_background_context(void *loaderPrivate)
  300. {
  301. @@ -548,11 +557,12 @@ dri_is_thread_safe(void *loaderPrivate)
  302. /* The image loader extension record for DRI3
  303. */
  304. static const __DRIimageLoaderExtension imageLoaderExtension = {
  305. - .base = { __DRI_IMAGE_LOADER, 3 },
  306. + .base = { __DRI_IMAGE_LOADER, 5 },
  307. .getBuffers = loader_dri3_get_buffers,
  308. .flushFrontBuffer = dri3_flush_front_buffer,
  309. .flushSwapBuffers = dri3_flush_swap_buffers,
  310. + .getDisplayFD = dri3_get_display_fd,
  311. };
  312. const __DRIuseInvalidateExtension dri3UseInvalidate = {
  313. @@ -618,6 +628,10 @@ dri3_destroy_screen(struct glx_screen *base)
  314. loader_dri3_close_screen(psc->driScreen);
  315. (*psc->core->destroyScreen) (psc->driScreen);
  316. driDestroyConfigs(psc->driver_configs);
  317. +
  318. + if (psc->fd_dpy != psc->fd)
  319. + close(psc->fd_dpy);
  320. +
  321. close(psc->fd);
  322. free(psc);
  323. }
  324. @@ -842,8 +856,9 @@ dri3_create_screen(int screen, struct glx_display * priv)
  325. struct dri3_screen *psc;
  326. __GLXDRIscreen *psp;
  327. struct glx_config *configs = NULL, *visuals = NULL;
  328. - char *driverName, *driverNameDisplayGPU, *tmp;
  329. + char *driverName = NULL, *driverNameDisplayGPU, *tmp;
  330. int i;
  331. + int fd_old;
  332. psc = calloc(1, sizeof *psc);
  333. if (psc == NULL)
  334. @@ -851,6 +866,7 @@ dri3_create_screen(int screen, struct glx_display * priv)
  335. psc->fd = -1;
  336. psc->fd_display_gpu = -1;
  337. + psc->fd_dpy = -1;
  338. if (!glx_screen_init(&psc->base, screen, priv)) {
  339. free(psc);
  340. @@ -871,12 +887,23 @@ dri3_create_screen(int screen, struct glx_display * priv)
  341. return NULL;
  342. }
  343. + fd_old = psc->fd;
  344. + psc->fd_dpy = os_dupfd_cloexec(psc->fd);
  345. psc->fd_display_gpu = fcntl(psc->fd, F_DUPFD_CLOEXEC, 3);
  346. psc->fd = loader_get_user_preferred_fd(psc->fd, &psc->is_different_gpu);
  347. if (!psc->is_different_gpu) {
  348. close(psc->fd_display_gpu);
  349. psc->fd_display_gpu = -1;
  350. }
  351. + if (psc->fd == fd_old) {
  352. + if (psc->fd_dpy != -1)
  353. + close(psc->fd_dpy);
  354. +
  355. + psc->fd_dpy = psc->fd;
  356. + } else if (psc->fd_dpy == -1) {
  357. + ErrorMessageF("Unable to dup the display FD");
  358. + goto handle_error;
  359. + }
  360. driverName = loader_get_driver_for_fd(psc->fd);
  361. if (!driverName) {
  362. @@ -1049,6 +1076,8 @@ handle_error:
  363. if (psc->driScreenDisplayGPU)
  364. psc->core->destroyScreen(psc->driScreenDisplayGPU);
  365. psc->driScreenDisplayGPU = NULL;
  366. + if (psc->fd_dpy >= 0 && psc->fd_dpy != psc->fd)
  367. + close(psc->fd_dpy);
  368. if (psc->fd >= 0)
  369. close(psc->fd);
  370. if (psc->fd_display_gpu >= 0)
  371. diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
  372. index c0e833c..b3dccf2 100644
  373. --- a/src/glx/dri3_priv.h
  374. +++ b/src/glx/dri3_priv.h
  375. @@ -107,6 +107,7 @@ struct dri3_screen {
  376. void *driver;
  377. int fd;
  378. + int fd_dpy;
  379. bool is_different_gpu;
  380. /* fd for display GPU in case of prime */