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); }