Blob Blame History Raw
From a239886e159e6609c3e298effbd0243af8d0e333 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 16 Jun 2020 11:30:11 +0200
Subject: [PATCH 4/4] screen-cast: Disable DMA buffer based screen casting for
 QXL

QXL doesn't support mmap():ing a DMA buffer allocated in mutter inside
the PipeWire stream consumer process. To make screen casting work again
on QXL, disable DMA buffer based screen casting for QXL.

Eventually, it should be the client that renegotiates the supported
buffer types, but until then we need this list.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1318
---
 src/backends/meta-screen-cast.c           | 11 ++++++
 src/backends/meta-screen-cast.h           |  2 ++
 src/backends/native/meta-backend-native.c | 41 +++++++++++++++++++++++
 src/backends/native/meta-gpu-kms.c        | 26 ++++++++++++++
 src/backends/native/meta-gpu-kms.h        |  2 ++
 5 files changed, 82 insertions(+)

diff --git a/src/backends/meta-screen-cast.c b/src/backends/meta-screen-cast.c
index 5f1ca8b5ca..268155e7b3 100644
--- a/src/backends/meta-screen-cast.c
+++ b/src/backends/meta-screen-cast.c
@@ -46,6 +46,8 @@ struct _MetaScreenCast
 
   MetaDbusSessionWatcher *session_watcher;
   MetaBackend *backend;
+
+  gboolean disable_dma_bufs;
 };
 
 static void
@@ -94,6 +96,12 @@ meta_screen_cast_get_backend (MetaScreenCast *screen_cast)
   return screen_cast->backend;
 }
 
+void
+meta_screen_cast_disable_dma_bufs (MetaScreenCast *screen_cast)
+{
+  screen_cast->disable_dma_bufs = TRUE;
+}
+
 CoglDmaBufHandle *
 meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast,
                                         int             width,
@@ -107,6 +115,9 @@ meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast,
   g_autoptr (GError) error = NULL;
   CoglDmaBufHandle *dmabuf_handle;
 
+  if (screen_cast->disable_dma_bufs)
+    return NULL;
+
   dmabuf_handle = cogl_renderer_create_dma_buf (cogl_renderer,
                                                 width, height,
                                                 &error);
diff --git a/src/backends/meta-screen-cast.h b/src/backends/meta-screen-cast.h
index fb5a38f34f..fa54be729f 100644
--- a/src/backends/meta-screen-cast.h
+++ b/src/backends/meta-screen-cast.h
@@ -50,6 +50,8 @@ GDBusConnection * meta_screen_cast_get_connection (MetaScreenCast *screen_cast);
 
 MetaBackend * meta_screen_cast_get_backend (MetaScreenCast *screen_cast);
 
+void meta_screen_cast_disable_dma_bufs (MetaScreenCast *screen_cast);
+
 CoglDmaBufHandle * meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast,
                                                            int             width,
                                                            int             height);
diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
index c473681cb0..2bf7f5e7e2 100644
--- a/src/backends/native/meta-backend-native.c
+++ b/src/backends/native/meta-backend-native.c
@@ -57,6 +57,10 @@
 #include "core/meta-border.h"
 #include "meta/main.h"
 
+#ifdef HAVE_REMOTE_DESKTOP
+#include "backends/meta-screen-cast.h"
+#endif
+
 struct _MetaBackendNative
 {
   MetaBackend parent;
@@ -327,6 +331,39 @@ meta_backend_native_create_clutter_backend (MetaBackend *backend)
   return g_object_new (META_TYPE_CLUTTER_BACKEND_NATIVE, NULL);
 }
 
+#ifdef HAVE_REMOTE_DESKTOP
+static void
+maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native)
+{
+  MetaBackend *backend = META_BACKEND (native);
+  MetaRenderer *renderer = meta_backend_get_renderer (backend);
+  MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
+  MetaGpuKms *primary_gpu;
+  const char *driver_name;
+  int i;
+  static const char *disable_dma_buf_drivers[] = {
+    "qxl",
+  };
+
+  primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native);
+  driver_name = meta_gpu_kms_get_driver_name (primary_gpu);
+
+  for (i = 0; i < G_N_ELEMENTS (disable_dma_buf_drivers); i++)
+    {
+      if (g_strcmp0 (driver_name, disable_dma_buf_drivers[i]) == 0)
+        {
+          MetaScreenCast *screen_cast = meta_backend_get_screen_cast (backend);
+
+          g_message ("The '%s' driver doesn't support DMA buffer screen sharing, disabling.",
+                     driver_name);
+
+          meta_screen_cast_disable_dma_bufs (screen_cast);
+          return;
+        }
+    }
+}
+#endif /* HAVE_REMOTE_DESKTOP */
+
 static void
 meta_backend_native_post_init (MetaBackend *backend)
 {
@@ -338,6 +375,10 @@ meta_backend_native_post_init (MetaBackend *backend)
                                                 NULL, NULL);
   clutter_evdev_set_relative_motion_filter (manager, relative_motion_filter,
                                             meta_backend_get_monitor_manager (backend));
+
+#ifdef HAVE_REMOTE_DESKTOP
+  maybe_disable_screen_cast_dma_bufs (META_BACKEND_NATIVE (backend));
+#endif
 }
 
 static MetaMonitorManager *
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index c569b948ef..93e509def5 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -66,6 +66,8 @@ struct _MetaGpuKms
   char *file_path;
   GSource *source;
 
+  char *driver_name;
+
   clockid_t clock_id;
 
   drmModeConnector **connectors;
@@ -790,6 +792,27 @@ init_outputs (MetaGpuKms       *gpu_kms,
   setup_output_clones (gpu);
 }
 
+static void
+init_info (MetaGpuKms *gpu_kms)
+{
+  drmVersion *drm_version;
+
+  drm_version = drmGetVersion (gpu_kms->fd);
+  if (!drm_version)
+    return;
+
+  gpu_kms->driver_name = g_strndup (drm_version->name,
+                                    drm_version->name_len);
+
+  drmFreeVersion (drm_version);
+}
+
+const char *
+meta_gpu_kms_get_driver_name (MetaGpuKms *gpu_kms)
+{
+  return gpu_kms->driver_name;
+}
+
 static gboolean
 meta_kms_resources_init (MetaKmsResources  *resources,
                          int                fd,
@@ -865,6 +888,7 @@ meta_gpu_kms_read_current (MetaGpu  *gpu,
   init_crtcs (gpu_kms, &resources);
   init_outputs (gpu_kms, &resources);
   init_frame_clock (gpu_kms);
+  init_info (gpu_kms);
 
   meta_kms_resources_release (&resources);
 
@@ -940,6 +964,8 @@ meta_gpu_kms_finalize (GObject *object)
 
   free_resources (gpu_kms);
 
+  g_free (gpu_kms->driver_name);
+
   G_OBJECT_CLASS (meta_gpu_kms_parent_class)->finalize (object);
 }
 
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
index 1f7a939e27..6096e58341 100644
--- a/src/backends/native/meta-gpu-kms.h
+++ b/src/backends/native/meta-gpu-kms.h
@@ -108,4 +108,6 @@ MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu
 
 void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
 
+const char * meta_gpu_kms_get_driver_name (MetaGpuKms *gpu_kms);
+
 #endif /* META_GPU_KMS_H */
-- 
2.26.2