[mutter] backends/native: React to GPU hotplug



commit ad7d6e4a37a6258a5de876a85859f7f57415dffa
Author: Emilio Pozuelo Monfort <emilio pozuelo collabora co uk>
Date:   Mon Sep 17 13:03:18 2018 +0200

    backends/native: React to GPU hotplug
    
    If a GPU is added at runtime, we should connect to it and manage
    its outputs.

 src/backends/native/meta-monitor-manager-kms.c | 74 ++++++++++++++++++++++++++
 src/backends/native/meta-renderer-native.c     | 61 +++++++++++++++++----
 2 files changed, 125 insertions(+), 10 deletions(-)
---
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 3209bff94..48b2d374d 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (C) 2013 Red Hat Inc.
+ * Copyright (C) 2018 DisplayLink (UK) Ltd.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -50,6 +51,15 @@
 
 #define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor"
 
+enum
+{
+  GPU_ADDED,
+
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
 typedef struct
 {
   GSource source;
@@ -371,6 +381,43 @@ handle_hotplug_event (MetaMonitorManager *manager)
   meta_monitor_manager_on_hotplug (manager);
 }
 
+static void
+handle_gpu_hotplug (MetaMonitorManagerKms *manager_kms,
+                    GUdevDevice           *device)
+{
+  MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
+  g_autoptr (GError) error = NULL;
+  const char *gpu_path;
+  MetaGpuKms *gpu_kms;
+  GList *gpus, *l;
+
+  gpu_path = g_udev_device_get_device_file (device);
+
+  gpus = meta_monitor_manager_get_gpus (manager);
+  for (l = gpus; l; l = l->next)
+    {
+      MetaGpuKms *gpu_kms = l->data;
+
+      if (!g_strcmp0 (gpu_path, meta_gpu_kms_get_file_path (gpu_kms)))
+        {
+          g_warning ("Failed to hotplug secondary gpu '%s': %s",
+                     gpu_path, "device already present");
+          return;
+        }
+    }
+
+  gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &error);
+  if (!gpu_kms)
+    {
+      g_warning ("Failed to hotplug secondary gpu '%s': %s",
+                 gpu_path, error->message);
+      return;
+    }
+  meta_monitor_manager_add_gpu (manager, META_GPU (gpu_kms));
+
+  g_signal_emit (manager_kms, signals[GPU_ADDED], 0, gpu_kms);
+}
+
 static void
 on_uevent (GUdevClient *client,
            const char  *action,
@@ -380,6 +427,25 @@ on_uevent (GUdevClient *client,
   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data);
   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
 
+  if (g_str_equal (action, "add") &&
+      g_udev_device_get_device_file (device) != NULL)
+    {
+      MetaBackend *backend = meta_monitor_manager_get_backend (manager);
+      MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
+      MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native);
+      const char *device_seat;
+      const char *seat_id;
+
+      device_seat = g_udev_device_get_property (device, "ID_SEAT");
+      seat_id = meta_launcher_get_seat_id (launcher);
+
+      if (!device_seat)
+        device_seat = "seat0";
+
+      if (!g_strcmp0 (seat_id, device_seat))
+        handle_gpu_hotplug (manager_kms, device);
+    }
+
   if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG"))
     return;
 
@@ -754,4 +820,12 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
   manager_class->get_capabilities = meta_monitor_manager_kms_get_capabilities;
   manager_class->get_max_screen_size = meta_monitor_manager_kms_get_max_screen_size;
   manager_class->get_default_layout_mode = meta_monitor_manager_kms_get_default_layout_mode;
+
+  signals[GPU_ADDED] =
+    g_signal_new ("gpu-added",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, META_TYPE_GPU_KMS);
 }
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index ab7a2ee40..6277dda20 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -3015,6 +3015,11 @@ meta_renderer_native_get_property (GObject    *object,
     }
 }
 
+static void
+on_gpu_added (MetaMonitorManager *monitor_manager,
+              MetaGpuKms         *gpu_kms,
+              MetaRendererNative *renderer_native);
+
 static void
 meta_renderer_native_set_property (GObject      *object,
                                    guint         prop_id,
@@ -3491,6 +3496,48 @@ meta_renderer_native_create_renderer_gpu_data (MetaRendererNative  *renderer_nat
   return NULL;
 }
 
+static gboolean
+create_renderer_gpu_data (MetaRendererNative  *renderer_native,
+                          MetaGpuKms          *gpu_kms,
+                          GError             **error)
+{
+  MetaRendererNativeGpuData *renderer_gpu_data;
+
+  renderer_gpu_data =
+    meta_renderer_native_create_renderer_gpu_data (renderer_native,
+                                                   gpu_kms,
+                                                   error);
+  if (!renderer_gpu_data)
+    return FALSE;
+
+  g_hash_table_insert (renderer_native->gpu_datas,
+                       gpu_kms,
+                       renderer_gpu_data);
+
+  return TRUE;
+}
+
+static void
+on_gpu_added (MetaMonitorManager *monitor_manager,
+              MetaGpuKms         *gpu_kms,
+              MetaRendererNative *renderer_native)
+{
+  MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager);
+  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
+  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
+  CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
+  GError *error = NULL;
+
+  if (!create_renderer_gpu_data (renderer_native, gpu_kms, &error))
+    {
+      g_warning ("on_gpu_added: could not create gpu_data for gpu %s: %s",
+                 meta_gpu_kms_get_file_path (gpu_kms), error->message);
+      g_clear_error (&error);
+    }
+
+  _cogl_winsys_egl_ensure_current (cogl_display);
+}
+
 static gboolean
 meta_renderer_native_initable_init (GInitable     *initable,
                                     GCancellable  *cancellable,
@@ -3508,18 +3555,9 @@ meta_renderer_native_initable_init (GInitable     *initable,
   for (l = gpus; l; l = l->next)
     {
       MetaGpuKms *gpu_kms = META_GPU_KMS (l->data);
-      MetaRendererNativeGpuData *renderer_gpu_data;
 
-      renderer_gpu_data =
-        meta_renderer_native_create_renderer_gpu_data (renderer_native,
-                                                       gpu_kms,
-                                                       error);
-      if (!renderer_gpu_data)
+      if (!create_renderer_gpu_data (renderer_native, gpu_kms, error))
         return FALSE;
-
-      g_hash_table_insert (renderer_native->gpu_datas,
-                           gpu_kms,
-                           renderer_gpu_data);
     }
 
   return TRUE;
@@ -3555,6 +3593,9 @@ meta_renderer_native_constructed (GObject *object)
         settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS))
     renderer_native->use_modifiers = TRUE;
 
+  g_signal_connect (renderer_native->monitor_manager_kms, "gpu-added",
+                    G_CALLBACK (on_gpu_added), renderer_native);
+
   G_OBJECT_CLASS (meta_renderer_native_parent_class)->constructed (object);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]