0053-egl-drm-add-support-for-DRI_PRIME-GPU-selection.patch 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. From f92304242d7656cf296e978eb9e4a5fc09050b75 Mon Sep 17 00:00:00 2001
  2. From: Brendan King <Brendan.King@imgtec.com>
  3. Date: Thu, 20 May 2021 14:43:29 +0100
  4. Subject: [PATCH] egl/drm: add support for DRI_PRIME GPU selection
  5. Add support for selecting the GPU to be used for rendering using
  6. the DRI_PRIME environment variable. If a different GPU is selected,
  7. a duplicate of the file descriptor for the original GPU/display is
  8. preserved, which can be obtained by calling the getDisplayFD
  9. function in the image loader extension.
  10. For server side Wayland, the ability to support PRIME is
  11. determined by checking for the PRIME import and export
  12. capabilities on the driver file descriptor, which may no
  13. longer support them if a different GPU from the default has
  14. been selected. It may be that the driver can still support
  15. PRIME; for example, by making use of the original (default)
  16. file descriptor. The driver can indicate it supports PRIME
  17. via the getCapabilities function in the DRI Image extension.
  18. ---
  19. include/GL/internal/dri_interface.h | 2 ++
  20. src/egl/drivers/dri2/egl_dri2.c | 10 ++++++++
  21. src/egl/drivers/dri2/platform_drm.c | 19 ++++++++++-----
  22. src/gbm/backends/dri/gbm_dri.c | 38 +++++++++++++++++++++++++----
  23. src/gbm/backends/dri/gbm_driint.h | 8 ++++++
  24. 5 files changed, 66 insertions(+), 11 deletions(-)
  25. diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
  26. index 2fb440f..080d191 100644
  27. --- a/include/GL/internal/dri_interface.h
  28. +++ b/include/GL/internal/dri_interface.h
  29. @@ -1548,6 +1548,8 @@ enum __DRIChromaSiting {
  30. */
  31. /*@{*/
  32. #define __DRI_IMAGE_CAP_GLOBAL_NAMES 1
  33. +#define __DRI_IMAGE_CAP_PRIME_IMPORT 0x2000
  34. +#define __DRI_IMAGE_CAP_PRIME_EXPORT 0x4000
  35. /*@}*/
  36. /**
  37. diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
  38. index 1df53ef..ec4ac60 100644
  39. --- a/src/egl/drivers/dri2/egl_dri2.c
  40. +++ b/src/egl/drivers/dri2/egl_dri2.c
  41. @@ -1368,6 +1368,7 @@ dri2_display_destroy(_EGLDisplay *disp)
  42. }
  43. switch (disp->Platform) {
  44. + case _EGL_PLATFORM_DRM:
  45. case _EGL_PLATFORM_WAYLAND:
  46. case _EGL_PLATFORM_X11:
  47. if (dri2_dpy->fd_dpy >= 0 && dri2_dpy->fd_dpy != dri2_dpy->fd)
  48. @@ -3943,6 +3944,15 @@ dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy)
  49. dri2_dpy->image->base.version >= 7 &&
  50. dri2_dpy->image->createImageFromFds != NULL)
  51. flags |= WAYLAND_DRM_PRIME;
  52. + else if (dri2_dpy->image->base.version >= 10 &&
  53. + dri2_dpy->image->getCapabilities != NULL) {
  54. + int capabilities;
  55. +
  56. + capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
  57. + if ((capabilities & __DRI_IMAGE_CAP_PRIME_IMPORT) != 0 &&
  58. + (capabilities & __DRI_IMAGE_CAP_PRIME_EXPORT) != 0)
  59. + flags |= WAYLAND_DRM_PRIME;
  60. + }
  61. dri2_dpy->wl_server_drm =
  62. wayland_drm_init(wl_dpy, device_name,
  63. diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
  64. index 258e8b6..f160ad1 100644
  65. --- a/src/egl/drivers/dri2/platform_drm.c
  66. +++ b/src/egl/drivers/dri2/platform_drm.c
  67. @@ -595,7 +595,7 @@ dri2_drm_authenticate(_EGLDisplay *disp, uint32_t id)
  68. {
  69. struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  70. - return drmAuthMagic(dri2_dpy->fd, id);
  71. + return drmAuthMagic(dri2_dpy->fd_dpy, id);
  72. }
  73. static void
  74. @@ -782,6 +782,7 @@ dri2_initialize_drm(_EGLDisplay *disp)
  75. return _eglError(EGL_BAD_ALLOC, "eglInitialize");
  76. dri2_dpy->fd = -1;
  77. + dri2_dpy->fd_dpy = -1;
  78. disp->DriverData = (void *) dri2_dpy;
  79. gbm = disp->PlatformDisplay;
  80. @@ -789,16 +790,16 @@ dri2_initialize_drm(_EGLDisplay *disp)
  81. char buf[64];
  82. int n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, 0);
  83. if (n != -1 && n < sizeof(buf))
  84. - dri2_dpy->fd = loader_open_device(buf);
  85. - gbm = gbm_create_device(dri2_dpy->fd);
  86. + dri2_dpy->fd_dpy = loader_open_device(buf);
  87. + gbm = gbm_create_device(dri2_dpy->fd_dpy);
  88. if (gbm == NULL) {
  89. err = "DRI2: failed to create gbm device";
  90. goto cleanup;
  91. }
  92. dri2_dpy->own_device = true;
  93. } else {
  94. - dri2_dpy->fd = os_dupfd_cloexec(gbm_device_get_fd(gbm));
  95. - if (dri2_dpy->fd < 0) {
  96. + dri2_dpy->fd_dpy = os_dupfd_cloexec(gbm_device_get_fd(gbm));
  97. + if (dri2_dpy->fd_dpy < 0) {
  98. err = "DRI2: failed to fcntl() existing gbm device";
  99. goto cleanup;
  100. }
  101. @@ -810,6 +811,12 @@ dri2_initialize_drm(_EGLDisplay *disp)
  102. goto cleanup;
  103. }
  104. + if (gbm_dri_device_get_fd(dri2_dpy->gbm_dri) ==
  105. + gbm_device_get_fd(gbm))
  106. + dri2_dpy->fd = dri2_dpy->fd_dpy;
  107. + else
  108. + dri2_dpy->fd = os_dupfd_cloexec(gbm_dri_device_get_fd(dri2_dpy->gbm_dri));
  109. +
  110. dev = _eglAddDevice(dri2_dpy->fd, dri2_dpy->gbm_dri->software);
  111. if (!dev) {
  112. err = "DRI2: failed to find EGLDevice";
  113. @@ -872,7 +879,7 @@ dri2_initialize_drm(_EGLDisplay *disp)
  114. disp->Extensions.EXT_buffer_age = EGL_TRUE;
  115. #ifdef HAVE_WAYLAND_PLATFORM
  116. - dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
  117. + dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd_dpy);
  118. #endif
  119. dri2_set_WL_bind_wayland_display(disp);
  120. diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
  121. index 5acb15b..c1586f4 100644
  122. --- a/src/gbm/backends/dri/gbm_dri.c
  123. +++ b/src/gbm/backends/dri/gbm_dri.c
  124. @@ -51,6 +51,7 @@
  125. #include "loader.h"
  126. #include "util/debug.h"
  127. #include "util/macros.h"
  128. +#include "util/os_file.h"
  129. /* For importing wl_buffer */
  130. #if HAVE_WAYLAND_PLATFORM
  131. @@ -141,6 +142,14 @@ image_get_buffers(__DRIdrawable *driDrawable,
  132. surf->dri_private, buffer_mask, buffers);
  133. }
  134. +static int
  135. +dri_get_display_fd(void *loaderPrivate)
  136. +{
  137. + struct gbm_dri_device *dri = loaderPrivate;
  138. +
  139. + return dri->base.v0.fd;
  140. +}
  141. +
  142. static void
  143. swrast_get_drawable_info(__DRIdrawable *driDrawable,
  144. int *x,
  145. @@ -220,20 +229,22 @@ static const __DRIimageLookupExtension image_lookup_extension = {
  146. };
  147. static const __DRIdri2LoaderExtension dri2_loader_extension = {
  148. - .base = { __DRI_DRI2_LOADER, 4 },
  149. + .base = { __DRI_DRI2_LOADER, 6 },
  150. .getBuffers = dri_get_buffers,
  151. .flushFrontBuffer = dri_flush_front_buffer,
  152. .getBuffersWithFormat = dri_get_buffers_with_format,
  153. .getCapability = dri_get_capability,
  154. + .getDisplayFD = dri_get_display_fd,
  155. };
  156. static const __DRIimageLoaderExtension image_loader_extension = {
  157. - .base = { __DRI_IMAGE_LOADER, 2 },
  158. + .base = { __DRI_IMAGE_LOADER, 5 },
  159. .getBuffers = image_get_buffers,
  160. .flushFrontBuffer = dri_flush_front_buffer,
  161. .getCapability = dri_get_capability,
  162. + .getDisplayFD = dri_get_display_fd,
  163. };
  164. static const __DRIswrastLoaderExtension swrast_loader_extension = {
  165. @@ -398,12 +409,12 @@ dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name)
  166. return -1;
  167. if (dri->dri2->base.version >= 4) {
  168. - dri->screen = dri->dri2->createNewScreen2(0, dri->base.v0.fd,
  169. + dri->screen = dri->dri2->createNewScreen2(0, dri->fd,
  170. dri->loader_extensions,
  171. dri->driver_extensions,
  172. &dri->driver_configs, dri);
  173. } else {
  174. - dri->screen = dri->dri2->createNewScreen(0, dri->base.v0.fd,
  175. + dri->screen = dri->dri2->createNewScreen(0, dri->fd,
  176. dri->loader_extensions,
  177. &dri->driver_configs, dri);
  178. }
  179. @@ -470,8 +481,20 @@ static int
  180. dri_screen_create(struct gbm_dri_device *dri)
  181. {
  182. char *driver_name;
  183. + int dup_fd, new_fd;
  184. + bool is_different_gpu;
  185. - driver_name = loader_get_driver_for_fd(dri->base.v0.fd);
  186. + dup_fd = os_dupfd_cloexec(dri->fd);
  187. + if (dup_fd < 0)
  188. + return -1;
  189. +
  190. + new_fd = loader_get_user_preferred_fd(dup_fd, &is_different_gpu);
  191. + if (new_fd == dup_fd)
  192. + close(new_fd);
  193. + else
  194. + dri->fd = new_fd;
  195. +
  196. + driver_name = loader_get_driver_for_fd(dri->fd);
  197. if (!driver_name)
  198. return -1;
  199. @@ -1424,6 +1447,9 @@ dri_destroy(struct gbm_device *gbm)
  200. dlclose(dri->driver);
  201. free(dri->driver_name);
  202. + if (dri->fd >= 0 && dri->fd != dri->base.v0.fd)
  203. + close (dri->fd);
  204. +
  205. free(dri);
  206. }
  207. @@ -1445,6 +1471,8 @@ dri_device_create(int fd, uint32_t gbm_backend_version)
  208. if (!dri)
  209. return NULL;
  210. + dri->fd = fd;
  211. +
  212. dri->base.v0.fd = fd;
  213. dri->base.v0.backend_version = gbm_backend_version;
  214. dri->base.v0.bo_create = gbm_dri_bo_create;
  215. diff --git a/src/gbm/backends/dri/gbm_driint.h b/src/gbm/backends/dri/gbm_driint.h
  216. index 9e77ba5..e33a96e 100644
  217. --- a/src/gbm/backends/dri/gbm_driint.h
  218. +++ b/src/gbm/backends/dri/gbm_driint.h
  219. @@ -61,6 +61,8 @@ struct gbm_dri_visual {
  220. struct gbm_dri_device {
  221. struct gbm_device base;
  222. + int fd;
  223. +
  224. void *driver;
  225. char *driver_name; /* Name of the DRI module, without the _dri suffix */
  226. bool software; /* A software driver was loaded */
  227. @@ -191,4 +193,10 @@ gbm_dri_bo_unmap_dumb(struct gbm_dri_bo *bo)
  228. bo->map = NULL;
  229. }
  230. +static inline int
  231. +gbm_dri_device_get_fd(struct gbm_dri_device *dri)
  232. +{
  233. + return dri->fd;
  234. +}
  235. +
  236. #endif