egl/drm: get compatible render-only device fd for kms-only device
authorLeandro Ribeiro <leandro.ribeiro@collabora.com>
Mon, 4 Sep 2023 16:53:12 +0000 (13:53 -0300)
committerMarge Bot <emma+marge@anholt.net>
Tue, 17 Oct 2023 20:31:13 +0000 (20:31 +0000)
Things have been working by accident for split display/render SoCs when
using the GBM platform.

The device fd given to the GBM platform may be associated with a
KMS-only device, so _eglFindDevice() should find nothing (because the
global EGLDevice list only has render-capable devices). The only thing
making it work is that we don't error out when we go through the
EGLDevice list and can't find the device we are looking for. We simply
return the last EGLDevice from the list.

This patch fixes that. Now we look for a compatible render-only device
for the KMS-only in the GBM platform.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24825>

src/egl/drivers/dri2/platform_drm.c

index 7b56a9a..37623f7 100644 (file)
@@ -562,6 +562,20 @@ static const struct dri2_egl_display_vtbl dri2_drm_display_vtbl = {
    .get_dri_drawable = dri2_surface_get_dri_drawable,
 };
 
+static int
+get_fd_render_gpu_drm(struct gbm_dri_device *gbm_dri, int fd_display_gpu)
+{
+   /* This doesn't make sense for the software case. */
+   assert(!gbm_dri->software);
+
+   /* Render-capable device, so just return the same fd. */
+   if (loader_is_device_render_capable(fd_display_gpu))
+      return fd_display_gpu;
+
+   /* Display-only device, so return a compatible render-only device. */
+   return gbm_dri->mesa->queryCompatibleRenderOnlyDeviceFd(fd_display_gpu);
+}
+
 EGLBoolean
 dri2_initialize_drm(_EGLDisplay *disp)
 {
@@ -593,30 +607,37 @@ dri2_initialize_drm(_EGLDisplay *disp)
             goto cleanup;
          }
 
-         dri2_dpy->fd_render_gpu =
+         dri2_dpy->fd_display_gpu =
             loader_open_device(drm->nodes[DRM_NODE_PRIMARY]);
       } else {
          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_render_gpu = loader_open_device(buf);
+            dri2_dpy->fd_display_gpu = loader_open_device(buf);
       }
 
-      gbm = gbm_create_device(dri2_dpy->fd_render_gpu);
+      gbm = gbm_create_device(dri2_dpy->fd_display_gpu);
       if (gbm == NULL) {
          err = "DRI2: failed to create gbm device";
          goto cleanup;
       }
       dri2_dpy->own_device = true;
    } else {
-      dri2_dpy->fd_render_gpu = os_dupfd_cloexec(gbm_device_get_fd(gbm));
-      if (dri2_dpy->fd_render_gpu < 0) {
+      dri2_dpy->fd_display_gpu = os_dupfd_cloexec(gbm_device_get_fd(gbm));
+      if (dri2_dpy->fd_display_gpu < 0) {
          err = "DRI2: failed to fcntl() existing gbm device";
          goto cleanup;
       }
    }
-   dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu;
    dri2_dpy->gbm_dri = gbm_dri_device(gbm);
+   if (!dri2_dpy->gbm_dri->software) {
+      dri2_dpy->fd_render_gpu =
+         get_fd_render_gpu_drm(dri2_dpy->gbm_dri, dri2_dpy->fd_display_gpu);
+      if (dri2_dpy->fd_render_gpu < 0) {
+         err = "DRI2: failed to get compatible render device";
+         goto cleanup;
+      }
+   }
 
    if (strcmp(gbm_device_get_backend_name(gbm), "drm") != 0) {
       err = "DRI2: gbm device using incorrect/incompatible backend";