diff --git a/src/Makefile.am b/src/Makefile.am index 02d46c4d2..a9642753e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -109,6 +109,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ backends/meta-egl.c \ backends/meta-egl.h \ backends/meta-egl-ext.h \ + backends/meta-gpu.c \ + backends/meta-gpu.h \ backends/meta-display-config-shared.h \ backends/meta-idle-monitor.c \ backends/meta-idle-monitor-private.h \ @@ -157,6 +159,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ backends/x11/meta-crtc-xrandr.h \ backends/x11/meta-cursor-renderer-x11.c \ backends/x11/meta-cursor-renderer-x11.h \ + backends/x11/meta-gpu-xrandr.c \ + backends/x11/meta-gpu-xrandr.h \ backends/x11/cm/meta-backend-x11-cm.c \ backends/x11/cm/meta-backend-x11-cm.h \ backends/x11/cm/meta-renderer-x11-cm.c \ @@ -455,6 +459,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \ backends/native/meta-cursor-renderer-native.c \ backends/native/meta-cursor-renderer-native.h \ backends/native/meta-default-modes.h \ + backends/native/meta-gpu-kms.c \ + backends/native/meta-gpu-kms.h \ backends/native/meta-idle-monitor-native.c \ backends/native/meta-idle-monitor-native.h \ backends/native/meta-input-settings-native.c \ diff --git a/src/backends/meta-crtc.c b/src/backends/meta-crtc.c index f19e6b8c3..7ca31ba39 100644 --- a/src/backends/meta-crtc.c +++ b/src/backends/meta-crtc.c @@ -25,10 +25,10 @@ G_DEFINE_TYPE (MetaCrtc, meta_crtc, G_TYPE_OBJECT) G_DEFINE_TYPE (MetaCrtcMode, meta_crtc_mode, G_TYPE_OBJECT) -MetaMonitorManager * -meta_crtc_get_monitor_manager (MetaCrtc *crtc) +MetaGpu * +meta_crtc_get_gpu (MetaCrtc *crtc) { - return crtc->monitor_manager; + return crtc->gpu; } static void diff --git a/src/backends/meta-crtc.h b/src/backends/meta-crtc.h index cb92d8dcf..2ff864c2a 100644 --- a/src/backends/meta-crtc.h +++ b/src/backends/meta-crtc.h @@ -22,7 +22,7 @@ #include -#include "backends/meta-monitor-manager-private.h" +#include "backends/meta-gpu.h" /* Same as KMS mode flags and X11 randr flags */ typedef enum _MetaCrtcModeFlag @@ -50,7 +50,7 @@ struct _MetaCrtc { GObject parent; - MetaMonitorManager *monitor_manager; + MetaGpu *gpu; glong crtc_id; MetaRectangle rect; @@ -93,6 +93,6 @@ G_DECLARE_FINAL_TYPE (MetaCrtc, meta_crtc, META, CRTC, GObject) #define META_TYPE_CRTC_MODE (meta_crtc_mode_get_type ()) G_DECLARE_FINAL_TYPE (MetaCrtcMode, meta_crtc_mode, META, CRTC_MODE, GObject) -MetaMonitorManager * meta_crtc_get_monitor_manager (MetaCrtc *crtc); +MetaGpu * meta_crtc_get_gpu (MetaCrtc *crtc); #endif /* META_CRTC_H */ diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c new file mode 100644 index 000000000..3577391e5 --- /dev/null +++ b/src/backends/meta-gpu.c @@ -0,0 +1,224 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include "backends/meta-gpu.h" + +#include "backends/meta-output.h" + +enum +{ + PROP_0, + + PROP_MONITOR_MANAGER, + + PROP_LAST +}; + +static GParamSpec *obj_props[PROP_LAST]; + +typedef struct _MetaGpuPrivate +{ + MetaMonitorManager *monitor_manager; + + GList *outputs; + GList *crtcs; + GList *modes; +} MetaGpuPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaGpu, meta_gpu, G_TYPE_OBJECT) + +gboolean +meta_gpu_has_hotplug_mode_update (MetaGpu *gpu) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + GList *l; + + for (l = priv->outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + if (output->hotplug_mode_update) + return TRUE; + } + + return FALSE; +} + +gboolean +meta_gpu_read_current (MetaGpu *gpu, + GError **error) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + gboolean ret; + GList *old_outputs; + GList *old_crtcs; + GList *old_modes; + + /* TODO: Get rid of this when objects incref:s what they need instead */ + old_outputs = priv->outputs; + old_crtcs = priv->crtcs; + old_modes = priv->modes; + + ret = META_GPU_GET_CLASS (gpu)->read_current (gpu, error); + + g_list_free_full (old_outputs, g_object_unref); + g_list_free_full (old_modes, g_object_unref); + g_list_free_full (old_crtcs, g_object_unref); + + return ret; +} + +MetaMonitorManager * +meta_gpu_get_monitor_manager (MetaGpu *gpu) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + return priv->monitor_manager; +} + +GList * +meta_gpu_get_outputs (MetaGpu *gpu) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + return priv->outputs; +} + +GList * +meta_gpu_get_crtcs (MetaGpu *gpu) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + return priv->crtcs; +} + +GList * +meta_gpu_get_modes (MetaGpu *gpu) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + return priv->modes; +} + +void +meta_gpu_take_outputs (MetaGpu *gpu, + GList *outputs) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + priv->outputs = outputs; +} + +void +meta_gpu_take_crtcs (MetaGpu *gpu, + GList *crtcs) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + priv->crtcs = crtcs; +} + +void +meta_gpu_take_modes (MetaGpu *gpu, + GList *modes) +{ + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + priv->modes = modes; +} + +static void +meta_gpu_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MetaGpu *gpu = META_GPU (object); + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + switch (prop_id) + { + case PROP_MONITOR_MANAGER: + priv->monitor_manager = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meta_gpu_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MetaGpu *gpu = META_GPU (object); + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + switch (prop_id) + { + case PROP_MONITOR_MANAGER: + g_value_set_object (value, priv->monitor_manager); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meta_gpu_finalize (GObject *object) +{ + MetaGpu *gpu = META_GPU (object); + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + g_list_free_full (priv->outputs, g_object_unref); + g_list_free_full (priv->modes, g_object_unref); + g_list_free_full (priv->crtcs, g_object_unref); + + G_OBJECT_CLASS (meta_gpu_parent_class)->finalize (object); +} + +static void +meta_gpu_init (MetaGpu *gpu) +{ +} + +static void +meta_gpu_class_init (MetaGpuClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = meta_gpu_set_property; + object_class->get_property = meta_gpu_get_property; + object_class->finalize = meta_gpu_finalize; + + obj_props[PROP_MONITOR_MANAGER] = + g_param_spec_object ("monitor-manager", + "monitor-manager", + "MetaMonitorManager", + META_TYPE_MONITOR_MANAGER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, PROP_LAST, obj_props); +} diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h new file mode 100644 index 000000000..4badcbd26 --- /dev/null +++ b/src/backends/meta-gpu.h @@ -0,0 +1,66 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_GPU_H +#define META_GPU_H + +#include + +#include "backends/meta-monitor-manager-private.h" + +#define META_TYPE_GPU (meta_gpu_get_type ()) +G_DECLARE_DERIVABLE_TYPE (MetaGpu, meta_gpu, META, GPU, GObject) + +struct _MetaGpuClass +{ + GObjectClass parent_class; + + gboolean (* read_current) (MetaGpu *gpu, + GError **error); +}; + +int meta_gpu_get_kms_fd (MetaGpu *gpu); + +const char * meta_gpu_get_kms_file_path (MetaGpu *gpu); + +gboolean meta_gpu_read_current (MetaGpu *gpu, + GError **error); + +gboolean meta_gpu_has_hotplug_mode_update (MetaGpu *gpu); + +MetaMonitorManager * meta_gpu_get_monitor_manager (MetaGpu *gpu); + +GList * meta_gpu_get_outputs (MetaGpu *gpu); + +GList * meta_gpu_get_crtcs (MetaGpu *gpu); + +GList * meta_gpu_get_modes (MetaGpu *gpu); + +void meta_gpu_take_outputs (MetaGpu *gpu, + GList *outputs); + +void meta_gpu_take_crtcs (MetaGpu *gpu, + GList *crtcs); + +void meta_gpu_take_modes (MetaGpu *gpu, + GList *modes); + +#endif /* META_GPU_H */ diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c index 8f9f8faa8..f81349e71 100644 --- a/src/backends/meta-monitor-manager-dummy.c +++ b/src/backends/meta-monitor-manager-dummy.c @@ -47,6 +47,8 @@ struct _MetaMonitorManagerDummy { MetaMonitorManager parent_instance; + MetaGpu *gpu; + gboolean is_transform_handled; }; @@ -62,6 +64,13 @@ typedef struct _MetaOutputDummy G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER); +struct _MetaGpuDummy +{ + MetaGpu parent; +}; + +G_DEFINE_TYPE (MetaGpuDummy, meta_gpu_dummy, META_TYPE_GPU) + static void meta_output_dummy_notify_destroy (MetaOutput *output); @@ -95,6 +104,8 @@ append_monitor (MetaMonitorManager *manager, GList **outputs, float scale) { + MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); + MetaGpu *gpu = manager_dummy->gpu; CrtcModeSpec mode_specs[] = { { .width = 800, @@ -141,7 +152,7 @@ append_monitor (MetaMonitorManager *manager, number = g_list_length (*outputs) + 1; - output->monitor_manager = manager; + output->gpu = gpu; output->winsys_id = number; output->name = g_strdup_printf ("LVDS%d", number); output->vendor = g_strdup ("MetaProducts Inc."); @@ -182,6 +193,8 @@ append_tiled_monitor (MetaMonitorManager *manager, GList **outputs, int scale) { + MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); + MetaGpu *gpu = manager_dummy->gpu; CrtcModeSpec mode_specs[] = { { .width = 800, @@ -218,7 +231,7 @@ append_tiled_monitor (MetaMonitorManager *manager, MetaCrtc *crtc; crtc = g_object_new (META_TYPE_CRTC, NULL); - crtc->monitor_manager = manager; + crtc->gpu = gpu; crtc->crtc_id = g_list_length (*crtcs) + i + 1; crtc->all_transforms = ALL_TRANSFORMS; new_crtcs = g_list_append (new_crtcs, crtc); @@ -246,7 +259,7 @@ append_tiled_monitor (MetaMonitorManager *manager, output = g_object_new (META_TYPE_OUTPUT, NULL); - output->monitor_manager = manager; + output->gpu = gpu; output->winsys_id = number; output->name = g_strdup_printf ("LVDS%d", number); output->vendor = g_strdup ("MetaProducts Inc."); @@ -305,6 +318,8 @@ meta_output_dummy_notify_destroy (MetaOutput *output) static void meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) { + MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); + MetaGpu *gpu = manager_dummy->gpu; unsigned int num_monitors = 1; float *monitor_scales = NULL; const char *num_monitors_str; @@ -396,9 +411,9 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) append_monitor (manager, &modes, &crtcs, &outputs, monitor_scales[i]); } - manager->modes = modes; - manager->crtcs = crtcs; - manager->outputs = outputs; + meta_gpu_take_modes (gpu, modes); + meta_gpu_take_crtcs (gpu, crtcs); + meta_gpu_take_outputs (gpu, outputs); } static void @@ -421,6 +436,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, MetaOutputInfo **outputs, unsigned int n_outputs) { + MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); GList *l; unsigned i; @@ -485,7 +501,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable CRTCs not mentioned in the list */ - for (l = manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (manager_dummy->gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -505,7 +521,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable outputs not mentioned in the list */ - for (l = manager->outputs; l; l = l->next) + for (l = meta_gpu_get_outputs (manager_dummy->gpu); l; l = l->next) { MetaOutput *output = l->data; @@ -702,7 +718,6 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass) { MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); - manager_class->read_current = meta_monitor_manager_dummy_read_current; manager_class->ensure_initial_config = meta_monitor_manager_dummy_ensure_initial_config; manager_class->apply_monitors_config = meta_monitor_manager_dummy_apply_monitors_config; manager_class->is_transform_handled = meta_monitor_manager_dummy_is_transform_handled; @@ -714,14 +729,44 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass) } static void -meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager) +meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager_dummy) { + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_dummy); const char *nested_offscreen_transform; nested_offscreen_transform = g_getenv ("MUTTER_DEBUG_NESTED_OFFSCREEN_TRANSFORM"); if (g_strcmp0 (nested_offscreen_transform, "1") == 0) - manager->is_transform_handled = FALSE; + manager_dummy->is_transform_handled = FALSE; else - manager->is_transform_handled = TRUE; + manager_dummy->is_transform_handled = TRUE; + + manager_dummy->gpu = g_object_new (META_TYPE_GPU_DUMMY, + "monitor-manager", manager, + NULL); + meta_monitor_manager_add_gpu (manager, manager_dummy->gpu); +} + +static gboolean +meta_gpu_dummy_read_current (MetaGpu *gpu, + GError **error) +{ + MetaMonitorManager *manager = meta_gpu_get_monitor_manager (gpu); + + meta_monitor_manager_dummy_read_current (manager); + + return TRUE; +} + +static void +meta_gpu_dummy_init (MetaGpuDummy *gpu_dummy) +{ +} + +static void +meta_gpu_dummy_class_init (MetaGpuDummyClass *klass) +{ + MetaGpuClass *gpu_class = META_GPU_CLASS (klass); + + gpu_class->read_current = meta_gpu_dummy_read_current; } diff --git a/src/backends/meta-monitor-manager-dummy.h b/src/backends/meta-monitor-manager-dummy.h index a9e839198..5451d72a2 100644 --- a/src/backends/meta-monitor-manager-dummy.h +++ b/src/backends/meta-monitor-manager-dummy.h @@ -24,9 +24,13 @@ #define META_MONITOR_MANAGER_DUMMY_H #include "meta-monitor-manager-private.h" +#include "backends/meta-gpu.h" #define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ()) G_DECLARE_FINAL_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META, MONITOR_MANAGER_DUMMY, MetaMonitorManager) +#define META_TYPE_GPU_DUMMY (meta_gpu_dummy_get_type ()) +G_DECLARE_FINAL_TYPE (MetaGpuDummy, meta_gpu_dummy, META, GPU_DUMMY, MetaGpu) + #endif /* META_MONITOR_MANAGER_DUMMY_H */ diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index ab6b529fd..59494db5d 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -60,6 +60,8 @@ typedef struct _MetaLogicalMonitor MetaLogicalMonitor; typedef struct _MetaMonitorMode MetaMonitorMode; +typedef struct _MetaGpu MetaGpu; + typedef struct _MetaCrtc MetaCrtc; typedef struct _MetaOutput MetaOutput; typedef struct _MetaCrtcMode MetaCrtcMode; @@ -164,14 +166,7 @@ struct _MetaMonitorManager int screen_width; int screen_height; - /* Outputs refer to physical screens, - CRTCs refer to stuff that can drive outputs - (like encoders, but less tied to the HW), - while logical_monitors refer to logical ones. - */ - GList *outputs; - GList *crtcs; - GList *modes; + GList *gpus; GList *monitors; @@ -196,8 +191,6 @@ struct _MetaMonitorManagerClass { MetaDBusDisplayConfigSkeletonClass parent_class; - void (*read_current) (MetaMonitorManager *); - char* (*get_edid_file) (MetaMonitorManager *, MetaOutput *); GBytes* (*read_edid) (MetaMonitorManager *, @@ -302,9 +295,10 @@ MetaMonitor * meta_monitor_manager_get_monitor_from_connector (MetaMonitor GList * meta_monitor_manager_get_monitors (MetaMonitorManager *manager); -GList * meta_monitor_manager_get_outputs (MetaMonitorManager *manager); +void meta_monitor_manager_add_gpu (MetaMonitorManager *manager, + MetaGpu *gpu); -GList * meta_monitor_manager_get_crtcs (MetaMonitorManager *manager); +GList * meta_monitor_manager_get_gpus (MetaMonitorManager *manager); void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager, int *width, diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index dd9d4475a..1ba007cfa 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -467,11 +467,11 @@ meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) { GList *l; - for (l = manager->outputs; l; l = l->next) + for (l = manager->gpus; l; l = l->next) { - MetaOutput *output = l->data; + MetaGpu *gpu = l->data; - if (output->hotplug_mode_update) + if (meta_gpu_has_hotplug_mode_update (gpu)) return TRUE; } @@ -747,9 +747,7 @@ meta_monitor_manager_finalize (GObject *object) { MetaMonitorManager *manager = META_MONITOR_MANAGER (object); - g_list_free_full (manager->outputs, g_object_unref); - g_list_free_full (manager->modes, g_object_unref); - g_list_free_full (manager->crtcs, g_object_unref); + g_list_free_full (manager->gpus, g_object_unref); g_list_free_full (manager->logical_monitors, g_object_unref); g_signal_handler_disconnect (manager->backend, @@ -957,23 +955,47 @@ get_connector_type_name (MetaConnectorType connector_type) } } +static GList * +combine_gpu_lists (MetaMonitorManager *manager, + GList * (*list_getter) (MetaGpu *gpu)) +{ + GList *list = NULL; + GList *l; + + for (l = manager->gpus; l; l = l->next) + { + MetaGpu *gpu = l->data; + + list = g_list_concat (list, g_list_copy (list_getter (gpu))); + } + + return list; +} + static gboolean meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, GDBusMethodInvocation *invocation) { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (skeleton); + GList *combined_modes; + GList *combined_outputs; + GList *combined_crtcs; GVariantBuilder crtc_builder, output_builder, mode_builder; GList *l; unsigned int i, j; int max_screen_width; int max_screen_height; + combined_modes = combine_gpu_lists (manager, meta_gpu_get_modes); + combined_outputs = combine_gpu_lists (manager, meta_gpu_get_outputs); + combined_crtcs = combine_gpu_lists (manager, meta_gpu_get_crtcs); + g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})")); g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiausauaua{sv})")); g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuudu)")); - for (l = manager->crtcs, i = 0; l; l = l->next, i++) + for (l = combined_crtcs, i = 0; l; l = l->next, i++) { MetaCrtc *crtc = l->data; GVariantBuilder transforms; @@ -985,7 +1007,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, g_variant_builder_add (&transforms, "u", j); if (crtc->current_mode) - current_mode_index = g_list_index (manager->modes, crtc->current_mode); + current_mode_index = g_list_index (combined_modes, crtc->current_mode); else current_mode_index = -1; g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})", @@ -1001,7 +1023,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, NULL /* properties */); } - for (l = manager->outputs; l; l = l->next) + for (l = combined_outputs; l; l = l->next) { MetaOutput *output = l->data; GVariantBuilder crtcs, modes, clones, properties; @@ -1015,7 +1037,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, MetaCrtc *possible_crtc = output->possible_crtcs[j]; unsigned possible_crtc_index; - possible_crtc_index = g_list_index (manager->crtcs, possible_crtc); + possible_crtc_index = g_list_index (combined_crtcs, possible_crtc); g_variant_builder_add (&crtcs, "u", possible_crtc_index); } @@ -1024,7 +1046,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, { unsigned mode_index; - mode_index = g_list_index (manager->modes, output->modes[j]); + mode_index = g_list_index (combined_modes, output->modes[j]); g_variant_builder_add (&modes, "u", mode_index); } @@ -1033,7 +1055,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, { unsigned int possible_clone_index; - possible_clone_index = g_list_index (manager->outputs, + possible_clone_index = g_list_index (combined_outputs, output->possible_clones[j]); g_variant_builder_add (&clones, "u", possible_clone_index); } @@ -1100,7 +1122,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, output->tile_info.tile_h)); } - crtc_index = output->crtc ? g_list_index (manager->crtcs, output->crtc) + crtc_index = output->crtc ? g_list_index (combined_crtcs, output->crtc) : -1; g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", i, /* ID */ @@ -1113,7 +1135,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, &properties); } - for (l = manager->modes, i = 0; l; l = l->next, i++) + for (l = combined_modes, i = 0; l; l = l->next, i++) { MetaCrtcMode *mode = l->data; @@ -1143,6 +1165,11 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, g_variant_builder_end (&mode_builder), max_screen_width, max_screen_height); + + g_list_free (combined_modes); + g_list_free (combined_outputs); + g_list_free (combined_crtcs); + return TRUE; } @@ -2042,6 +2069,7 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton, gint value) { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); + GList *combined_outputs; MetaOutput *output; if (serial != manager->serial) @@ -2052,14 +2080,18 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton, return TRUE; } - if (output_index >= g_list_length (manager->outputs)) + combined_outputs = combine_gpu_lists (manager, meta_gpu_get_outputs); + + if (output_index >= g_list_length (combined_outputs)) { + g_list_free (combined_outputs); g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid output id"); return TRUE; } - output = g_list_nth_data (manager->outputs, output_index); + output = g_list_nth_data (combined_outputs, output_index); + g_list_free (combined_outputs); if (value < 0 || value > 100) { @@ -2092,6 +2124,7 @@ meta_monitor_manager_handle_get_crtc_gamma (MetaDBusDisplayConfig *skeleton, { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); MetaMonitorManagerClass *klass; + GList *combined_crtcs; MetaCrtc *crtc; gsize size; unsigned short *red; @@ -2108,15 +2141,18 @@ meta_monitor_manager_handle_get_crtc_gamma (MetaDBusDisplayConfig *skeleton, return TRUE; } - if (crtc_id >= g_list_length (manager->crtcs)) + combined_crtcs = combine_gpu_lists (manager, meta_gpu_get_crtcs); + if (crtc_id >= g_list_length (combined_crtcs)) { + g_list_free (combined_crtcs); g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid crtc id"); return TRUE; } - crtc = g_list_nth_data (manager->crtcs, crtc_id); + crtc = g_list_nth_data (combined_crtcs, crtc_id); + g_list_free (combined_crtcs); klass = META_MONITOR_MANAGER_GET_CLASS (manager); if (klass->get_crtc_gamma) @@ -2156,6 +2192,7 @@ meta_monitor_manager_handle_set_crtc_gamma (MetaDBusDisplayConfig *skeleton, { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); MetaMonitorManagerClass *klass; + GList *combined_crtcs; MetaCrtc *crtc; gsize size, dummy; unsigned short *red; @@ -2171,15 +2208,19 @@ meta_monitor_manager_handle_set_crtc_gamma (MetaDBusDisplayConfig *skeleton, return TRUE; } - if (crtc_id >= g_list_length (manager->crtcs)) + combined_crtcs = combine_gpu_lists (manager, meta_gpu_get_crtcs); + + if (crtc_id >= g_list_length (combined_crtcs)) { + g_list_free (combined_crtcs); g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Invalid crtc id"); return TRUE; } - crtc = g_list_nth_data (manager->crtcs, crtc_id); + crtc = g_list_nth_data (combined_crtcs, crtc_id); + g_list_free (combined_crtcs); red_bytes = g_variant_get_data_as_bytes (red_v); green_bytes = g_variant_get_data_as_bytes (green_v); @@ -2449,16 +2490,17 @@ meta_monitor_manager_get_monitors (MetaMonitorManager *manager) return manager->monitors; } -GList * -meta_monitor_manager_get_outputs (MetaMonitorManager *manager) +void +meta_monitor_manager_add_gpu (MetaMonitorManager *manager, + MetaGpu *gpu) { - return manager->outputs; + manager->gpus = g_list_append (manager->gpus, gpu); } GList * -meta_monitor_manager_get_crtcs (MetaMonitorManager *manager) +meta_monitor_manager_get_gpus (MetaMonitorManager *manager) { - return manager->crtcs; + return manager->gpus; } void @@ -2481,28 +2523,34 @@ rebuild_monitors (MetaMonitorManager *manager) manager->monitors = NULL; } - for (l = manager->outputs; l; l = l->next) + for (l = manager->gpus; l; l = l->next) { - MetaOutput *output = l->data; + MetaGpu *gpu = l->data; + GList *k; - if (output->tile_info.group_id) + for (k = meta_gpu_get_outputs (gpu); k; k = k->next) { - if (is_main_tiled_monitor_output (output)) + MetaOutput *output = k->data; + + if (output->tile_info.group_id) { - MetaMonitorTiled *monitor_tiled; + if (is_main_tiled_monitor_output (output)) + { + MetaMonitorTiled *monitor_tiled; - monitor_tiled = meta_monitor_tiled_new (manager, output); - manager->monitors = g_list_append (manager->monitors, - monitor_tiled); + monitor_tiled = meta_monitor_tiled_new (gpu, output); + manager->monitors = g_list_append (manager->monitors, + monitor_tiled); + } } - } - else - { - MetaMonitorNormal *monitor_normal; + else + { + MetaMonitorNormal *monitor_normal; - monitor_normal = meta_monitor_normal_new (manager, output); - manager->monitors = g_list_append (manager->monitors, - monitor_normal); + monitor_normal = meta_monitor_normal_new (gpu, output); + manager->monitors = g_list_append (manager->monitors, + monitor_normal); + } } } } @@ -2543,25 +2591,23 @@ meta_monitor_manager_is_transform_handled (MetaMonitorManager *manager, void meta_monitor_manager_read_current_state (MetaMonitorManager *manager) { - GList *old_outputs; - GList *old_crtcs; - GList *old_modes; - - /* Some implementations of read_current use the existing information - * we have available, so don't free the old configuration until after - * read_current finishes. */ - old_outputs = manager->outputs; - old_crtcs = manager->crtcs; - old_modes = manager->modes; + GList *l; manager->serial++; - META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager); + + for (l = manager->gpus; l; l = l->next) + { + MetaGpu *gpu = l->data; + GError *error = NULL; + + if (!meta_gpu_read_current (gpu, &error)) + { + g_warning ("Failed to read current KMS state: %s", error->message); + g_clear_error (&error); + } + } rebuild_monitors (manager); - - g_list_free_full (old_outputs, g_object_unref); - g_list_free_full (old_modes, g_object_unref); - g_list_free_full (old_crtcs, g_object_unref); } static void diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index 340544fd6..ee850446c 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -25,6 +25,7 @@ #include "backends/meta-backend-private.h" #include "backends/meta-crtc.h" +#include "backends/meta-gpu.h" #include "backends/meta-monitor-manager-private.h" #include "backends/meta-settings-private.h" #include "backends/meta-output.h" @@ -54,7 +55,7 @@ typedef struct _MetaMonitorModeTiled typedef struct _MetaMonitorPrivate { - MetaMonitorManager *monitor_manager; + MetaGpu *gpu; GList *outputs; GList *modes; @@ -450,8 +451,8 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal) } MetaMonitorNormal * -meta_monitor_normal_new (MetaMonitorManager *monitor_manager, - MetaOutput *output) +meta_monitor_normal_new (MetaGpu *gpu, + MetaOutput *output) { MetaMonitorNormal *monitor_normal; MetaMonitor *monitor; @@ -461,7 +462,7 @@ meta_monitor_normal_new (MetaMonitorManager *monitor_manager, monitor = META_MONITOR (monitor_normal); monitor_priv = meta_monitor_get_instance_private (monitor); - monitor_priv->monitor_manager = monitor_manager; + monitor_priv->gpu = gpu; monitor_priv->outputs = g_list_append (NULL, output); monitor_priv->winsys_id = output->winsys_id; @@ -557,15 +558,15 @@ meta_monitor_get_suggested_position (MetaMonitor *monitor, } static void -add_tiled_monitor_outputs (MetaMonitorManager *monitor_manager, - MetaMonitorTiled *monitor_tiled) +add_tiled_monitor_outputs (MetaGpu *gpu, + MetaMonitorTiled *monitor_tiled) { MetaMonitorPrivate *monitor_priv = meta_monitor_get_instance_private (META_MONITOR (monitor_tiled)); GList *outputs; GList *l; - outputs = monitor_manager->outputs; + outputs = meta_gpu_get_outputs (gpu); for (l = outputs; l; l = l->next) { MetaOutput *output = l->data; @@ -1084,9 +1085,10 @@ meta_monitor_tiled_generate_modes (MetaMonitorTiled *monitor_tiled) } MetaMonitorTiled * -meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, - MetaOutput *output) +meta_monitor_tiled_new (MetaGpu *gpu, + MetaOutput *output) { + MetaMonitorManager *monitor_manager; MetaMonitorTiled *monitor_tiled; MetaMonitor *monitor; MetaMonitorPrivate *monitor_priv; @@ -1095,18 +1097,19 @@ meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, monitor = META_MONITOR (monitor_tiled); monitor_priv = meta_monitor_get_instance_private (monitor); - monitor_priv->monitor_manager = monitor_manager; + monitor_priv->gpu = gpu; monitor_tiled->tile_group_id = output->tile_info.group_id; monitor_priv->winsys_id = output->winsys_id; monitor_tiled->origin_output = output; - add_tiled_monitor_outputs (monitor_manager, monitor_tiled); + add_tiled_monitor_outputs (gpu, monitor_tiled); monitor_tiled->main_output = find_untiled_output (monitor_tiled); meta_monitor_generate_spec (monitor); + monitor_manager = meta_gpu_get_monitor_manager (gpu); meta_monitor_manager_tiled_monitor_added (monitor_manager, META_MONITOR (monitor_tiled)); @@ -1193,8 +1196,10 @@ meta_monitor_tiled_finalize (GObject *object) MetaMonitor *monitor = META_MONITOR (object); MetaMonitorPrivate *monitor_priv = meta_monitor_get_instance_private (monitor); + MetaMonitorManager *monitor_manager; - meta_monitor_manager_tiled_monitor_removed (monitor_priv->monitor_manager, + monitor_manager = meta_gpu_get_monitor_manager (monitor_priv->gpu); + meta_monitor_manager_tiled_monitor_removed (monitor_manager, monitor); G_OBJECT_CLASS (meta_monitor_tiled_parent_class)->finalize (object); diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h index 5b6f747bf..0026bb0e6 100644 --- a/src/backends/meta-monitor.h +++ b/src/backends/meta-monitor.h @@ -93,11 +93,11 @@ G_DECLARE_FINAL_TYPE (MetaMonitorTiled, meta_monitor_tiled, META, MONITOR_TILED, MetaMonitor) -MetaMonitorTiled * meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, - MetaOutput *main_output); +MetaMonitorTiled * meta_monitor_tiled_new (MetaGpu *gpu, + MetaOutput *output); -MetaMonitorNormal * meta_monitor_normal_new (MetaMonitorManager *monitor_manager, - MetaOutput *output); +MetaMonitorNormal * meta_monitor_normal_new (MetaGpu *gpu, + MetaOutput *output); MetaMonitorSpec * meta_monitor_get_spec (MetaMonitor *monitor); diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c index c3a7bd99b..62102ced3 100644 --- a/src/backends/meta-output.c +++ b/src/backends/meta-output.c @@ -23,10 +23,10 @@ G_DEFINE_TYPE (MetaOutput, meta_output, G_TYPE_OBJECT) -MetaMonitorManager * -meta_output_get_monitor_manager (MetaOutput *output) +MetaGpu * +meta_output_get_gpu (MetaOutput *output) { - return output->monitor_manager; + return output->gpu; } static void diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h index 922b0e7f0..e65826fda 100644 --- a/src/backends/meta-output.h +++ b/src/backends/meta-output.h @@ -22,7 +22,7 @@ #include -#include "backends/meta-monitor-manager-private.h" +#include "backends/meta-gpu.h" struct _MetaTileInfo { @@ -62,7 +62,7 @@ struct _MetaOutput { GObject parent; - MetaMonitorManager *monitor_manager; + MetaGpu *gpu; /* The CRTC driving this output, NULL if the output is not enabled */ MetaCrtc *crtc; @@ -119,6 +119,6 @@ struct _MetaOutput #define META_TYPE_OUTPUT (meta_output_get_type ()) G_DECLARE_FINAL_TYPE (MetaOutput, meta_output, META, OUTPUT, GObject) -MetaMonitorManager * meta_output_get_monitor_manager (MetaOutput *output); +MetaGpu * meta_output_get_gpu (MetaOutput *output); #endif /* META_OUTPUT_H */ diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index 0531452d6..d34c94ff5 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -24,7 +24,7 @@ #include "backends/native/meta-crtc-kms.h" #include "backends/meta-backend-private.h" -#include "backends/native/meta-monitor-manager-kms.h" +#include "backends/native/meta-gpu-kms.h" #define ALL_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1) #define ALL_TRANSFORMS_MASK ((1 << ALL_TRANSFORMS) - 1) @@ -57,13 +57,12 @@ void meta_crtc_kms_apply_transform (MetaCrtc *crtc) { MetaCrtcKms *crtc_kms = crtc->driver_private; - MetaMonitorManager *monitor_manager = meta_crtc_get_monitor_manager (crtc); - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); int kms_fd; MetaMonitorTransform hw_transform; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); if (crtc_kms->all_hw_transforms & (1 << crtc->transform)) hw_transform = crtc->transform; @@ -91,15 +90,14 @@ meta_crtc_kms_set_underscan (MetaCrtc *crtc, gboolean is_underscanning) { MetaCrtcKms *crtc_kms = crtc->driver_private; - MetaMonitorManager *monitor_manager = meta_crtc_get_monitor_manager (crtc); - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); int kms_fd; if (!crtc_kms->underscan_prop_id) return; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); if (is_underscanning) { @@ -136,17 +134,16 @@ meta_crtc_kms_set_underscan (MetaCrtc *crtc, } static int -find_property_index (MetaMonitorManager *monitor_manager, +find_property_index (MetaGpu *gpu, drmModeObjectPropertiesPtr props, const char *prop_name, drmModePropertyPtr *out_prop) { - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); int kms_fd; unsigned int i; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); for (i = 0; i < props->count_props; i++) { @@ -197,13 +194,13 @@ parse_transforms (MetaCrtc *crtc, } static gboolean -is_primary_plane (MetaMonitorManager *monitor_manager, +is_primary_plane (MetaGpu *gpu, drmModeObjectPropertiesPtr props) { drmModePropertyPtr prop; int idx; - idx = find_property_index (monitor_manager, props, "type", &prop); + idx = find_property_index (gpu, props, "type", &prop); if (idx < 0) return FALSE; @@ -212,19 +209,18 @@ is_primary_plane (MetaMonitorManager *monitor_manager, } static void -init_crtc_rotations (MetaCrtc *crtc, - MetaMonitorManager *monitor_manager) +init_crtc_rotations (MetaCrtc *crtc, + MetaGpu *gpu) { MetaCrtcKms *crtc_kms = crtc->driver_private; - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); int kms_fd; drmModeObjectPropertiesPtr props; drmModePlaneRes *planes; drmModePlane *drm_plane; unsigned int i; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); planes = drmModeGetPlaneResources (kms_fd); if (planes == NULL) @@ -245,12 +241,12 @@ init_crtc_rotations (MetaCrtc *crtc, drm_plane->plane_id, DRM_MODE_OBJECT_PLANE); - if (props && is_primary_plane (monitor_manager, props)) + if (props && is_primary_plane (gpu, props)) { int rotation_idx; crtc_kms->primary_plane_id = drm_plane->plane_id; - rotation_idx = find_property_index (monitor_manager, props, + rotation_idx = find_property_index (gpu, props, "rotation", &prop); if (rotation_idx >= 0) { @@ -273,15 +269,15 @@ init_crtc_rotations (MetaCrtc *crtc, } static void -find_crtc_properties (MetaCrtc *crtc, - MetaMonitorManagerKms *monitor_manager_kms) +find_crtc_properties (MetaCrtc *crtc, + MetaGpuKms *gpu_kms) { MetaCrtcKms *crtc_kms = crtc->driver_private; int kms_fd; drmModeObjectPropertiesPtr props; unsigned int i; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); props = drmModeObjectGetProperties (kms_fd, crtc->crtc_id, DRM_MODE_OBJECT_CRTC); if (!props) @@ -314,18 +310,17 @@ meta_crtc_destroy_notify (MetaCrtc *crtc) } MetaCrtc * -meta_create_kms_crtc (MetaMonitorManager *monitor_manager, - drmModeCrtc *drm_crtc, - unsigned int crtc_index) +meta_create_kms_crtc (MetaGpuKms *gpu_kms, + drmModeCrtc *drm_crtc, + unsigned int crtc_index) { - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpu *gpu = META_GPU (gpu_kms); MetaCrtc *crtc; MetaCrtcKms *crtc_kms; crtc = g_object_new (META_TYPE_CRTC, NULL); - crtc->monitor_manager = monitor_manager; + crtc->gpu = gpu; crtc->crtc_id = drm_crtc->crtc_id; crtc->rect.x = drm_crtc->x; crtc->rect.y = drm_crtc->y; @@ -340,7 +335,7 @@ meta_create_kms_crtc (MetaMonitorManager *monitor_manager, { GList *l; - for (l = monitor_manager->modes; l; l = l->next) + for (l = meta_gpu_get_modes (gpu); l; l = l->next) { MetaCrtcMode *mode = l->data; @@ -358,8 +353,8 @@ meta_create_kms_crtc (MetaMonitorManager *monitor_manager, crtc->driver_private = crtc_kms; crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify; - find_crtc_properties (crtc, monitor_manager_kms); - init_crtc_rotations (crtc, monitor_manager); + find_crtc_properties (crtc, gpu_kms); + init_crtc_rotations (crtc, gpu); return crtc; } diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h index 7abad147c..cb275f4cb 100644 --- a/src/backends/native/meta-crtc-kms.h +++ b/src/backends/native/meta-crtc-kms.h @@ -26,6 +26,8 @@ #include #include "backends/meta-crtc.h" +#include "backends/meta-gpu.h" +#include "backends/native/meta-gpu-kms.h" gboolean meta_crtc_kms_is_transform_handled (MetaCrtc *crtc, MetaMonitorTransform transform); @@ -35,8 +37,8 @@ void meta_crtc_kms_apply_transform (MetaCrtc *crtc); void meta_crtc_kms_set_underscan (MetaCrtc *crtc, gboolean is_underscanning); -MetaCrtc * meta_create_kms_crtc (MetaMonitorManager *monitor_manager, - drmModeCrtc *drm_crtc, - unsigned int crtc_index); +MetaCrtc * meta_create_kms_crtc (MetaGpuKms *gpu_kms, + drmModeCrtc *drm_crtc, + unsigned int crtc_index); #endif /* META_CRTC_KMS_H */ diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index 07af07b39..efd9b7385 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -488,6 +488,7 @@ should_have_hw_cursor (MetaCursorRenderer *renderer, { MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); + GList *gpus; CoglTexture *texture; if (priv->hw_cursor_broken) @@ -496,6 +497,10 @@ should_have_hw_cursor (MetaCursorRenderer *renderer, if (!cursor_sprite) return FALSE; + gpus = meta_monitor_manager_get_gpus (priv->monitor_manager); + if (g_list_length (gpus) != 1) + return FALSE; + if (cursor_over_transformed_logical_monitor (renderer, cursor_sprite)) return FALSE; @@ -853,24 +858,26 @@ on_monitors_changed (MetaMonitorManager *monitors, } static void -init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native, - MetaBackend *backend) +init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native) { - MetaRendererNative *renderer_native = - META_RENDERER_NATIVE (meta_backend_get_renderer (backend)); MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (priv->monitor_manager); + GList *gpus; + MetaGpuKms *gpu_kms; uint64_t width, height; struct gbm_device *gbm_device; - gbm_device = meta_renderer_native_get_gbm (renderer_native); + gpus = meta_monitor_manager_get_gpus (priv->monitor_manager); + if (g_list_length (gpus) != 1) + return; + + gpu_kms = META_GPU_KMS (gpus->data); + gbm_device = meta_gbm_device_from_gpu (gpu_kms); if (!gbm_device) return; priv->gbm = gbm_device; - priv->drm_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + priv->drm_fd = meta_gpu_kms_get_fd (gpu_kms); if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 && drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0) @@ -905,7 +912,7 @@ meta_cursor_renderer_native_new (MetaBackend *backend) priv->monitor_manager = monitor_manager; priv->hw_state_invalidated = TRUE; - init_hw_cursor_support (cursor_renderer_native, backend); + init_hw_cursor_support (cursor_renderer_native); return cursor_renderer_native; } diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c new file mode 100644 index 000000000..775ed349d --- /dev/null +++ b/src/backends/native/meta-gpu-kms.c @@ -0,0 +1,759 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "config.h" + +#include "backends/native/meta-gpu-kms.h" + +#include +#include +#include +#include +#include + +#include "backends/meta-crtc.h" +#include "backends/meta-monitor-manager-private.h" +#include "backends/meta-output.h" +#include "backends/native/meta-backend-native.h" +#include "backends/native/meta-crtc-kms.h" +#include "backends/native/meta-launcher.h" +#include "backends/native/meta-output-kms.h" +#include "backends/native/meta-default-modes.h" + +typedef struct _MetaKmsSource +{ + GSource source; + + gpointer fd_tag; + MetaGpuKms *gpu_kms; +} MetaKmsSource; + +struct _MetaGpuKms +{ + MetaGpu parent; + + int fd; + char *file_path; + GSource *source; + + drmModeConnector **connectors; + unsigned int n_connectors; + + int max_buffer_width; + int max_buffer_height; + + gboolean page_flips_not_supported; +}; + +G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU) + +static gboolean +kms_event_check (GSource *source) +{ + MetaKmsSource *kms_source = (MetaKmsSource *) source; + + return g_source_query_unix_fd (source, kms_source->fd_tag) & G_IO_IN; +} + +static gboolean +kms_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + MetaKmsSource *kms_source = (MetaKmsSource *) source; + + meta_gpu_kms_wait_for_flip (kms_source->gpu_kms); + + return G_SOURCE_CONTINUE; +} + +static GSourceFuncs kms_event_funcs = { + NULL, + kms_event_check, + kms_event_dispatch +}; + +static void +get_crtc_drm_connectors (MetaGpu *gpu, + MetaCrtc *crtc, + uint32_t **connectors, + unsigned int *n_connectors) +{ + GArray *connectors_array = g_array_new (FALSE, FALSE, sizeof (uint32_t)); + GList *l; + + for (l = meta_gpu_get_outputs (gpu); l; l = l->next) + { + MetaOutput *output = l->data; + + if (output->crtc == crtc) + g_array_append_val (connectors_array, output->winsys_id); + } + + *n_connectors = connectors_array->len; + *connectors = (uint32_t *) g_array_free (connectors_array, FALSE); +} + +gboolean +meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms, + MetaCrtc *crtc, + int x, + int y, + uint32_t fb_id) +{ + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + int kms_fd = meta_gpu_kms_get_fd (gpu_kms); + uint32_t *connectors; + unsigned int n_connectors; + drmModeModeInfo *mode; + + get_crtc_drm_connectors (gpu, crtc, &connectors, &n_connectors); + + if (connectors) + mode = crtc->current_mode->driver_private; + else + mode = NULL; + + if (drmModeSetCrtc (kms_fd, + crtc->crtc_id, + fb_id, + x, y, + connectors, n_connectors, + mode) != 0) + { + g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name); + return FALSE; + } + + g_free (connectors); + + return TRUE; +} + +static void +invoke_flip_closure (GClosure *flip_closure) +{ + GValue param = G_VALUE_INIT; + + g_value_init (¶m, G_TYPE_POINTER); + g_value_set_pointer (¶m, flip_closure); + g_closure_invoke (flip_closure, NULL, 1, ¶m, NULL); + g_closure_unref (flip_closure); +} + +gboolean +meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, + MetaCrtc *crtc) +{ + MetaGpu *gpu = META_GPU (gpu_kms); + MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); + GList *l; + gboolean connected_crtc_found; + + if (monitor_manager->power_save_mode != META_POWER_SAVE_ON) + return FALSE; + + connected_crtc_found = FALSE; + for (l = meta_gpu_get_outputs (gpu); l; l = l->next) + { + MetaOutput *output = l->data; + + if (output->crtc == crtc) + { + connected_crtc_found = TRUE; + break; + } + } + + if (!connected_crtc_found) + return FALSE; + + return TRUE; +} + +gboolean +meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms, + MetaCrtc *crtc, + int x, + int y, + uint32_t fb_id, + GClosure *flip_closure, + gboolean *fb_in_use) +{ + MetaGpu *gpu = META_GPU (gpu_kms); + MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); + uint32_t *connectors; + unsigned int n_connectors; + int ret = -1; + + g_assert (meta_crtc_get_gpu (crtc) == gpu); + g_assert (monitor_manager->power_save_mode == META_POWER_SAVE_ON); + + get_crtc_drm_connectors (gpu, crtc, &connectors, &n_connectors); + g_assert (n_connectors > 0); + + if (!gpu_kms->page_flips_not_supported) + { + int kms_fd = meta_gpu_kms_get_fd (gpu_kms); + + ret = drmModePageFlip (kms_fd, + crtc->crtc_id, + fb_id, + DRM_MODE_PAGE_FLIP_EVENT, + flip_closure); + if (ret != 0 && ret != -EACCES) + { + g_warning ("Failed to flip: %s", strerror (-ret)); + gpu_kms->page_flips_not_supported = TRUE; + } + } + + if (gpu_kms->page_flips_not_supported) + { + if (meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id)) + { + *fb_in_use = TRUE; + return FALSE; + } + } + + if (ret != 0) + return FALSE; + + *fb_in_use = TRUE; + g_closure_ref (flip_closure); + + return TRUE; +} + +static void +page_flip_handler (int fd, + unsigned int frame, + unsigned int sec, + unsigned int usec, + void *user_data) +{ + GClosure *flip_closure = user_data; + + invoke_flip_closure (flip_closure); +} + +void +meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms) +{ + drmEventContext evctx; + + if (gpu_kms->page_flips_not_supported) + return; + + memset (&evctx, 0, sizeof evctx); + evctx.version = DRM_EVENT_CONTEXT_VERSION; + evctx.page_flip_handler = page_flip_handler; + drmHandleEvent (gpu_kms->fd, &evctx); +} + +void +meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms, + int *max_width, + int *max_height) +{ + *max_width = gpu_kms->max_buffer_width; + *max_height = gpu_kms->max_buffer_height; +} + +int +meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms) +{ + return gpu_kms->fd; +} + +const char * +meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms) +{ + return gpu_kms->file_path; +} + +void +meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms, + uint64_t state) +{ + GList *l; + + for (l = meta_gpu_get_outputs (META_GPU (gpu_kms)); l; l = l->next) + { + MetaOutput *output = l->data; + + meta_output_kms_set_power_save_mode (output, state); + } +} + +static void +free_resources (MetaGpuKms *gpu_kms) +{ + unsigned i; + + for (i = 0; i < gpu_kms->n_connectors; i++) + drmModeFreeConnector (gpu_kms->connectors[i]); + + g_free (gpu_kms->connectors); +} + +static int +compare_outputs (gconstpointer one, + gconstpointer two) +{ + const MetaOutput *o_one = one, *o_two = two; + + return strcmp (o_one->name, o_two->name); +} + +static void +meta_crtc_mode_destroy_notify (MetaCrtcMode *mode) +{ + g_slice_free (drmModeModeInfo, mode->driver_private); +} + +gboolean +meta_drm_mode_equal (const drmModeModeInfo *one, + const drmModeModeInfo *two) +{ + return (one->clock == two->clock && + one->hdisplay == two->hdisplay && + one->hsync_start == two->hsync_start && + one->hsync_end == two->hsync_end && + one->htotal == two->htotal && + one->hskew == two->hskew && + one->vdisplay == two->vdisplay && + one->vsync_start == two->vsync_start && + one->vsync_end == two->vsync_end && + one->vtotal == two->vtotal && + one->vscan == two->vscan && + one->vrefresh == two->vrefresh && + one->flags == two->flags && + one->type == two->type && + strncmp (one->name, two->name, DRM_DISPLAY_MODE_LEN) == 0); +} + +static guint +drm_mode_hash (gconstpointer ptr) +{ + const drmModeModeInfo *mode = ptr; + guint hash = 0; + + /* + * We don't include the name in the hash because it's generally + * derived from the other fields (hdisplay, vdisplay and flags) + */ + + hash ^= mode->clock; + hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end; + hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end; + hash ^= mode->vrefresh; + hash ^= mode->flags ^ mode->type; + + return hash; +} + +MetaCrtcMode * +meta_gpu_kms_get_mode_from_drm_mode (MetaGpuKms *gpu_kms, + const drmModeModeInfo *drm_mode) +{ + MetaGpu *gpu = META_GPU (gpu_kms); + GList *l; + + for (l = meta_gpu_get_modes (gpu); l; l = l->next) + { + MetaCrtcMode *mode = l->data; + + if (meta_drm_mode_equal (drm_mode, mode->driver_private)) + return mode; + } + + g_assert_not_reached (); + return NULL; +} + +float +meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode) +{ + float refresh = 0.0; + + if (mode->htotal > 0 && mode->vtotal > 0) + { + /* Calculate refresh rate in milliHz first for extra precision. */ + refresh = (mode->clock * 1000000LL) / mode->htotal; + refresh += (mode->vtotal / 2); + refresh /= mode->vtotal; + if (mode->vscan > 1) + refresh /= mode->vscan; + refresh /= 1000.0; + } + return refresh; +} + +static MetaCrtcMode * +create_mode (const drmModeModeInfo *drm_mode, + long mode_id) +{ + MetaCrtcMode *mode; + + mode = g_object_new (META_TYPE_CRTC_MODE, NULL); + mode->mode_id = mode_id; + mode->name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN); + mode->width = drm_mode->hdisplay; + mode->height = drm_mode->vdisplay; + mode->flags = drm_mode->flags; + mode->refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); + mode->driver_private = g_slice_dup (drmModeModeInfo, drm_mode); + mode->driver_notify = (GDestroyNotify) meta_crtc_mode_destroy_notify; + + return mode; +} + +static MetaOutput * +find_output_by_id (GList *outputs, + glong id) +{ + GList *l; + + for (l = outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + if (output->winsys_id == id) + return output; + } + + return NULL; +} + +static void +setup_output_clones (MetaGpu *gpu) +{ + GList *l; + + for (l = meta_gpu_get_outputs (gpu); l; l = l->next) + { + MetaOutput *output = l->data; + GList *k; + + for (k = meta_gpu_get_outputs (gpu); k; k = k->next) + { + MetaOutput *other_output = k->data; + + if (other_output == output) + continue; + + if (meta_output_kms_can_clone (output, other_output)) + { + output->n_possible_clones++; + output->possible_clones = g_renew (MetaOutput *, + output->possible_clones, + output->n_possible_clones); + output->possible_clones[output->n_possible_clones - 1] = + other_output; + } + } + } +} + +static void +init_connectors (MetaGpuKms *gpu_kms, + drmModeRes *resources) +{ + unsigned int i; + + gpu_kms->n_connectors = resources->count_connectors; + gpu_kms->connectors = g_new (drmModeConnector *, gpu_kms->n_connectors); + for (i = 0; i < gpu_kms->n_connectors; i++) + { + drmModeConnector *drm_connector; + + drm_connector = drmModeGetConnector (gpu_kms->fd, + resources->connectors[i]); + gpu_kms->connectors[i] = drm_connector; + } +} + +static void +init_modes (MetaGpuKms *gpu_kms, + drmModeRes *resources) +{ + MetaGpu *gpu = META_GPU (gpu_kms); + GHashTable *modes_table; + GList *modes; + GHashTableIter iter; + drmModeModeInfo *drm_mode; + unsigned int i; + long mode_id; + + /* + * Gather all modes on all connected connectors. + */ + modes_table = g_hash_table_new (drm_mode_hash, (GEqualFunc) meta_drm_mode_equal); + for (i = 0; i < gpu_kms->n_connectors; i++) + { + drmModeConnector *drm_connector; + + drm_connector = gpu_kms->connectors[i]; + if (drm_connector && drm_connector->connection == DRM_MODE_CONNECTED) + { + unsigned int j; + + for (j = 0; j < (unsigned int) drm_connector->count_modes; j++) + g_hash_table_add (modes_table, &drm_connector->modes[j]); + } + } + + modes = NULL; + + g_hash_table_iter_init (&iter, modes_table); + mode_id = 0; + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &drm_mode)) + { + MetaCrtcMode *mode; + + mode = create_mode (drm_mode, (long) mode_id); + modes = g_list_append (modes, mode); + + mode_id++; + } + + g_hash_table_destroy (modes_table); + + for (i = 0; i < G_N_ELEMENTS (meta_default_drm_mode_infos); i++) + { + MetaCrtcMode *mode; + + mode = create_mode (&meta_default_drm_mode_infos[i], (long) mode_id); + modes = g_list_append (modes, mode); + + mode_id++; + } + + meta_gpu_take_modes (gpu, modes); +} + +static void +init_crtcs (MetaGpuKms *gpu_kms, + MetaKmsResources *resources) +{ + MetaGpu *gpu = META_GPU (gpu_kms); + GList *crtcs; + unsigned int i; + + crtcs = NULL; + + for (i = 0; i < (unsigned int) resources->resources->count_crtcs; i++) + { + drmModeCrtc *drm_crtc; + MetaCrtc *crtc; + + drm_crtc = drmModeGetCrtc (gpu_kms->fd, + resources->resources->crtcs[i]); + + crtc = meta_create_kms_crtc (gpu_kms, drm_crtc, i); + + drmModeFreeCrtc (drm_crtc); + + crtcs = g_list_append (crtcs, crtc); + } + + meta_gpu_take_crtcs (gpu, crtcs); +} + +static void +init_outputs (MetaGpuKms *gpu_kms, + MetaKmsResources *resources) +{ + MetaGpu *gpu = META_GPU (gpu_kms); + GList *old_outputs; + GList *outputs; + unsigned int i; + + old_outputs = meta_gpu_get_outputs (gpu); + + outputs = NULL; + + for (i = 0; i < gpu_kms->n_connectors; i++) + { + drmModeConnector *connector; + + connector = gpu_kms->connectors[i]; + + if (connector && connector->connection == DRM_MODE_CONNECTED) + { + MetaOutput *output; + MetaOutput *old_output; + + old_output = find_output_by_id (old_outputs, connector->connector_id); + output = meta_create_kms_output (gpu_kms, connector, resources, + old_output); + outputs = g_list_prepend (outputs, output); + } + } + + + /* Sort the outputs for easier handling in MetaMonitorConfig */ + outputs = g_list_sort (outputs, compare_outputs); + meta_gpu_take_outputs (gpu, outputs); + + setup_output_clones (gpu); +} + +static void +meta_kms_resources_init (MetaKmsResources *resources, + int fd) +{ + drmModeRes *drm_resources; + unsigned int i; + + drm_resources = drmModeGetResources (fd); + resources->resources = drm_resources; + + resources->n_encoders = (unsigned int) drm_resources->count_encoders; + resources->encoders = g_new (drmModeEncoder *, resources->n_encoders); + for (i = 0; i < resources->n_encoders; i++) + resources->encoders[i] = drmModeGetEncoder (fd, drm_resources->encoders[i]); +} + +static void +meta_kms_resources_release (MetaKmsResources *resources) +{ + unsigned int i; + + for (i = 0; i < resources->n_encoders; i++) + drmModeFreeEncoder (resources->encoders[i]); + g_free (resources->encoders); + + drmModeFreeResources (resources->resources); +} + +static gboolean +meta_gpu_kms_read_current (MetaGpu *gpu, + GError **error) +{ + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); + MetaMonitorManager *monitor_manager = + meta_gpu_get_monitor_manager (gpu); + MetaKmsResources resources; + + meta_kms_resources_init (&resources, gpu_kms->fd); + + gpu_kms->max_buffer_width = resources.resources->max_width; + gpu_kms->max_buffer_height = resources.resources->max_height; + + monitor_manager->power_save_mode = META_POWER_SAVE_ON; + + /* Note: we must not free the public structures (output, crtc, monitor + mode and monitor info) here, they must be kept alive until the API + users are done with them after we emit monitors-changed, and thus + are freed by the platform-independent layer. */ + free_resources (gpu_kms); + + init_connectors (gpu_kms, resources.resources); + init_modes (gpu_kms, resources.resources); + init_crtcs (gpu_kms, &resources); + init_outputs (gpu_kms, &resources); + + meta_kms_resources_release (&resources); + + return TRUE; +} + +MetaGpuKms * +meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms, + const char *kms_file_path, + GError **error) +{ + MetaMonitorManager *monitor_manager = + META_MONITOR_MANAGER (monitor_manager_kms); + MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager); + MetaLauncher *launcher = + meta_backend_native_get_launcher (META_BACKEND_NATIVE (backend)); + GSource *source; + MetaKmsSource *kms_source; + MetaGpuKms *gpu_kms; + int kms_fd; + + kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error); + if (kms_fd == -1) + return FALSE; + + gpu_kms = g_object_new (META_TYPE_GPU_KMS, + "monitor-manager", monitor_manager_kms, + NULL); + + gpu_kms->fd = kms_fd; + gpu_kms->file_path = g_strdup (kms_file_path); + + drmSetClientCap (gpu_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + + source = g_source_new (&kms_event_funcs, sizeof (MetaKmsSource)); + kms_source = (MetaKmsSource *) source; + kms_source->fd_tag = g_source_add_unix_fd (source, + gpu_kms->fd, + G_IO_IN | G_IO_ERR); + kms_source->gpu_kms = gpu_kms; + + gpu_kms->source = source; + g_source_attach (gpu_kms->source, NULL); + + return gpu_kms; +} + +static void +meta_gpu_kms_finalize (GObject *object) +{ + MetaGpuKms *gpu_kms = META_GPU_KMS (object); + MetaMonitorManager *monitor_manager = + meta_gpu_get_monitor_manager (META_GPU (gpu_kms)); + MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager); + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native); + + if (gpu_kms->fd != -1) + meta_launcher_close_restricted (launcher, gpu_kms->fd); + g_clear_pointer (&gpu_kms->file_path, g_free); + + g_source_destroy (gpu_kms->source); + + free_resources (gpu_kms); + + G_OBJECT_CLASS (meta_gpu_kms_parent_class)->finalize (object); +} + +static void +meta_gpu_kms_init (MetaGpuKms *gpu_kms) +{ + gpu_kms->fd = -1; +} + +static void +meta_gpu_kms_class_init (MetaGpuKmsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaGpuClass *gpu_class = META_GPU_CLASS (klass); + + object_class->finalize = meta_gpu_kms_finalize; + + gpu_class->read_current = meta_gpu_kms_read_current; +} diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h new file mode 100644 index 000000000..001fc95b4 --- /dev/null +++ b/src/backends/native/meta-gpu-kms.h @@ -0,0 +1,86 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_GPU_KMS_H +#define META_GPU_KMS_H + +#include +#include +#include + +#include "backends/meta-gpu.h" +#include "backends/native/meta-monitor-manager-kms.h" + +#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ()) +G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu) + +typedef struct _MetaKmsResources +{ + drmModeRes *resources; + drmModeEncoder **encoders; + unsigned int n_encoders; +} MetaKmsResources; + +typedef void (*MetaKmsFlipCallback) (void *user_data); + +MetaGpuKms * meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms, + const char *kms_file_path, + GError **error); + +gboolean meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms, + MetaCrtc *crtc, + int x, + int y, + uint32_t fb_id); + +gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, + MetaCrtc *crtc); + +gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms, + MetaCrtc *crtc, + int x, + int y, + uint32_t fb_id, + GClosure *flip_closure, + gboolean *fb_in_use); + +void meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms); + +int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms); + +const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms); + +void meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms, + int *max_width, + int *max_height); + +void meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms, + uint64_t state); + +MetaCrtcMode * meta_gpu_kms_get_mode_from_drm_mode (MetaGpuKms *gpu_kms, + const drmModeModeInfo *drm_mode); + +gboolean meta_drm_mode_equal (const drmModeModeInfo *one, + const drmModeModeInfo *two); + +float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode); + +#endif /* META_GPU_KMS_H */ diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 73ddfcc19..1f20106c3 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -32,6 +32,7 @@ #include "meta-backend-private.h" #include "meta-renderer-native.h" #include "meta-crtc-kms.h" +#include "meta-gpu-kms.h" #include "meta-output-kms.h" #include @@ -49,8 +50,6 @@ #include -#include "meta-default-modes.h" - #define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor" typedef struct @@ -65,20 +64,10 @@ struct _MetaMonitorManagerKms { MetaMonitorManager parent_instance; - int fd; - char *file_path; - MetaKmsSource *source; - - drmModeConnector **connectors; - unsigned int n_connectors; + MetaGpuKms *primary_gpu; GUdevClient *udev; guint uevent_handler_id; - - gboolean page_flips_not_supported; - - int max_buffer_width; - int max_buffer_height; }; struct _MetaMonitorManagerKmsClass @@ -94,378 +83,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaMonitorManagerKms, meta_monitor_manager_kms, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)) -int -meta_monitor_manager_kms_get_fd (MetaMonitorManagerKms *manager_kms) -{ - return manager_kms->fd; -} - -const char * -meta_monitor_manager_kms_get_file_path (MetaMonitorManagerKms *manager_kms) -{ - return manager_kms->file_path; -} - -static void -free_resources (MetaMonitorManagerKms *manager_kms) -{ - unsigned i; - - for (i = 0; i < manager_kms->n_connectors; i++) - drmModeFreeConnector (manager_kms->connectors[i]); - - g_free (manager_kms->connectors); -} - -static int -compare_outputs (gconstpointer one, - gconstpointer two) -{ - const MetaOutput *o_one = one, *o_two = two; - - return strcmp (o_one->name, o_two->name); -} - -static void -meta_monitor_mode_destroy_notify (MetaCrtcMode *mode) -{ - g_slice_free (drmModeModeInfo, mode->driver_private); -} - -gboolean -meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two) -{ - return (one->clock == two->clock && - one->hdisplay == two->hdisplay && - one->hsync_start == two->hsync_start && - one->hsync_end == two->hsync_end && - one->htotal == two->htotal && - one->hskew == two->hskew && - one->vdisplay == two->vdisplay && - one->vsync_start == two->vsync_start && - one->vsync_end == two->vsync_end && - one->vtotal == two->vtotal && - one->vscan == two->vscan && - one->vrefresh == two->vrefresh && - one->flags == two->flags && - one->type == two->type && - strncmp (one->name, two->name, DRM_DISPLAY_MODE_LEN) == 0); -} - -static guint -drm_mode_hash (gconstpointer ptr) -{ - const drmModeModeInfo *mode = ptr; - guint hash = 0; - - /* We don't include the name in the hash because it's generally - derived from the other fields (hdisplay, vdisplay and flags) - */ - - hash ^= mode->clock; - hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end; - hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end; - hash ^= mode->vrefresh; - hash ^= mode->flags ^ mode->type; - - return hash; -} - -MetaCrtcMode * -meta_monitor_manager_kms_get_mode_from_drm_mode (MetaMonitorManagerKms *manager_kms, - const drmModeModeInfo *drm_mode) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); - GList *l; - - for (l = manager->modes; l; l = l->next) - { - MetaCrtcMode *mode = l->data; - - if (meta_drm_mode_equal (drm_mode, mode->driver_private)) - return mode; - } - - g_assert_not_reached (); - return NULL; -} - -float -meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode) -{ - float refresh = 0.0; - - if (mode->htotal > 0 && mode->vtotal > 0) - { - /* Calculate refresh rate in milliHz first for extra precision. */ - refresh = (mode->clock * 1000000LL) / mode->htotal; - refresh += (mode->vtotal / 2); - refresh /= mode->vtotal; - if (mode->vscan > 1) - refresh /= mode->vscan; - refresh /= 1000.0; - } - return refresh; -} - -static MetaCrtcMode * -create_mode (const drmModeModeInfo *drm_mode, - long mode_id) -{ - MetaCrtcMode *mode; - - mode = g_object_new (META_TYPE_CRTC_MODE, NULL); - mode->mode_id = mode_id; - mode->name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN); - mode->width = drm_mode->hdisplay; - mode->height = drm_mode->vdisplay; - mode->flags = drm_mode->flags; - mode->refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - mode->driver_private = g_slice_dup (drmModeModeInfo, drm_mode); - mode->driver_notify = (GDestroyNotify) meta_monitor_mode_destroy_notify; - - return mode; -} - -static MetaOutput * -find_output_by_id (GList *outputs, - glong id) -{ - GList *l; - - for (l = outputs; l; l = l->next) - { - MetaOutput *output = l->data; - - if (output->winsys_id == id) - return output; - } - - return NULL; -} - -static void -setup_output_clones (MetaMonitorManager *manager) -{ - GList *l; - - for (l = manager->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - GList *k; - - for (k = manager->outputs; k; k = k->next) - { - MetaOutput *other_output = k->data; - - if (other_output == output) - continue; - - if (meta_output_kms_can_clone (output, other_output)) - { - output->n_possible_clones++; - output->possible_clones = g_renew (MetaOutput *, - output->possible_clones, - output->n_possible_clones); - output->possible_clones[output->n_possible_clones - 1] = - other_output; - } - } - } -} - -static void -init_connectors (MetaMonitorManager *manager, - drmModeRes *resources) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); - unsigned int i; - - manager_kms->n_connectors = resources->count_connectors; - manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors); - for (i = 0; i < manager_kms->n_connectors; i++) - { - drmModeConnector *drm_connector; - - drm_connector = drmModeGetConnector (manager_kms->fd, - resources->connectors[i]); - manager_kms->connectors[i] = drm_connector; - } -} - -static void -init_modes (MetaMonitorManager *manager, - drmModeRes *resources) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); - GHashTable *modes; - GHashTableIter iter; - drmModeModeInfo *drm_mode; - unsigned int i; - long mode_id; - - /* - * Gather all modes on all connected connectors. - */ - modes = g_hash_table_new (drm_mode_hash, (GEqualFunc) meta_drm_mode_equal); - for (i = 0; i < manager_kms->n_connectors; i++) - { - drmModeConnector *drm_connector; - - drm_connector = manager_kms->connectors[i]; - if (drm_connector && drm_connector->connection == DRM_MODE_CONNECTED) - { - unsigned int j; - - for (j = 0; j < (unsigned int) drm_connector->count_modes; j++) - g_hash_table_add (modes, &drm_connector->modes[j]); - } - } - - manager->modes = NULL; - - g_hash_table_iter_init (&iter, modes); - mode_id = 0; - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &drm_mode)) - { - MetaCrtcMode *mode; - - mode = create_mode (drm_mode, (long) mode_id); - manager->modes = g_list_append (manager->modes, mode); - - mode_id++; - } - - g_hash_table_destroy (modes); - - for (i = 0; i < G_N_ELEMENTS (meta_default_drm_mode_infos); i++) - { - MetaCrtcMode *mode; - - mode = create_mode (&meta_default_drm_mode_infos[i], (long) mode_id); - manager->modes = g_list_append (manager->modes, mode); - - mode_id++; - } -} - -static void -init_crtcs (MetaMonitorManager *manager, - MetaKmsResources *resources) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); - unsigned int i; - - manager->crtcs = NULL; - - for (i = 0; i < (unsigned int) resources->resources->count_crtcs; i++) - { - drmModeCrtc *drm_crtc; - MetaCrtc *crtc; - - drm_crtc = drmModeGetCrtc (manager_kms->fd, - resources->resources->crtcs[i]); - - crtc = meta_create_kms_crtc (manager, drm_crtc, i); - - drmModeFreeCrtc (drm_crtc); - - manager->crtcs = g_list_append (manager->crtcs, crtc); - } -} - -static void -init_outputs (MetaMonitorManager *manager, - MetaKmsResources *resources) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); - GList *old_outputs; - unsigned int i; - - old_outputs = manager->outputs; - - manager->outputs = NULL; - - for (i = 0; i < manager_kms->n_connectors; i++) - { - drmModeConnector *connector; - - connector = manager_kms->connectors[i]; - - if (connector && connector->connection == DRM_MODE_CONNECTED) - { - MetaOutput *output; - MetaOutput *old_output; - - old_output = find_output_by_id (old_outputs, connector->connector_id); - output = meta_create_kms_output (manager, connector, resources, old_output); - manager->outputs = g_list_prepend (manager->outputs, output); - } - } - - - /* Sort the outputs for easier handling in MetaMonitorConfig */ - manager->outputs = g_list_sort (manager->outputs, compare_outputs); - - setup_output_clones (manager); -} - -static void -meta_kms_resources_init (MetaKmsResources *resources, - int fd) -{ - drmModeRes *drm_resources; - unsigned int i; - - drm_resources = drmModeGetResources (fd); - resources->resources = drm_resources; - - resources->n_encoders = (unsigned int) drm_resources->count_encoders; - resources->encoders = g_new (drmModeEncoder *, resources->n_encoders); - for (i = 0; i < resources->n_encoders; i++) - resources->encoders[i] = drmModeGetEncoder (fd, drm_resources->encoders[i]); -} - -static void -meta_kms_resources_release (MetaKmsResources *resources) -{ - unsigned int i; - - for (i = 0; i < resources->n_encoders; i++) - drmModeFreeEncoder (resources->encoders[i]); - g_free (resources->encoders); - - drmModeFreeResources (resources->resources); -} - -static void -meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); - MetaKmsResources resources; - - meta_kms_resources_init (&resources, manager_kms->fd); - - manager_kms->max_buffer_width = resources.resources->max_width; - manager_kms->max_buffer_height = resources.resources->max_height; - - manager->power_save_mode = META_POWER_SAVE_ON; - - /* Note: we must not free the public structures (output, crtc, monitor - mode and monitor info) here, they must be kept alive until the API - users are done with them after we emit monitors-changed, and thus - are freed by the platform-independent layer. */ - free_resources (manager_kms); - - init_connectors (manager, resources.resources); - init_modes (manager, resources.resources); - init_crtcs (manager, &resources); - init_outputs (manager, &resources); - - meta_kms_resources_release (&resources); -} - static GBytes * meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager, MetaOutput *output) @@ -497,11 +114,11 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, return; } - for (l = manager->outputs; l; l = l->next) + for (l = manager->gpus; l; l = l->next) { - MetaOutput *output = l->data; + MetaGpuKms *gpu_kms = l->data; - meta_output_kms_set_power_save_mode (output, state); + meta_gpu_kms_set_power_save_mode (gpu_kms, state); } } @@ -579,23 +196,29 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE, because they weren't seen in the first loop) */ - for (l = manager->crtcs; l; l = l->next) + for (l = manager->gpus; l; l = l->next) { - MetaCrtc *crtc = l->data; + MetaGpu *gpu = l->data; + GList *k; - crtc->logical_monitor = NULL; - - if (crtc->is_dirty) + for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) { - crtc->is_dirty = FALSE; - continue; - } + MetaCrtc *crtc = k->data; - crtc->rect.x = 0; - crtc->rect.y = 0; - crtc->rect.width = 0; - crtc->rect.height = 0; - crtc->current_mode = NULL; + crtc->logical_monitor = NULL; + + if (crtc->is_dirty) + { + crtc->is_dirty = FALSE; + continue; + } + + crtc->rect.x = 0; + crtc->rect.y = 0; + crtc->rect.width = 0; + crtc->rect.height = 0; + crtc->current_mode = NULL; + } } for (i = 0; i < n_outputs; i++) @@ -611,18 +234,24 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable outputs not mentioned in the list */ - for (l = manager->outputs; l; l = l->next) + for (l = manager->gpus; l; l = l->next) { - MetaOutput *output = l->data; + MetaGpu *gpu = l->data; + GList *k; - if (output->is_dirty) + for (k = meta_gpu_get_outputs (gpu); k; k = k->next) { - output->is_dirty = FALSE; - continue; - } + MetaOutput *output = k->data; - output->crtc = NULL; - output->is_primary = FALSE; + if (output->is_dirty) + { + output->is_dirty = FALSE; + continue; + } + + output->crtc = NULL; + output->is_primary = FALSE; + } } } @@ -707,17 +336,18 @@ meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager, unsigned short **green, unsigned short **blue) { - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu)); drmModeCrtc *kms_crtc; - kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id); + kms_crtc = drmModeGetCrtc (kms_fd, crtc->crtc_id); *size = kms_crtc->gamma_size; *red = g_new (unsigned short, *size); *green = g_new (unsigned short, *size); *blue = g_new (unsigned short, *size); - drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue); + drmModeCrtcGetGamma (kms_fd, crtc->crtc_id, *size, *red, *green, *blue); drmModeFreeCrtc (kms_crtc); } @@ -730,9 +360,10 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager, unsigned short *green, unsigned short *blue) { - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + int kms_fd = meta_gpu_kms_get_fd (META_GPU_KMS (gpu)); - drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue); + drmModeCrtcSetGamma (kms_fd, crtc->crtc_id, size, red, green, blue); } static void @@ -757,32 +388,6 @@ on_uevent (GUdevClient *client, handle_hotplug_event (manager); } -static gboolean -kms_event_check (GSource *source) -{ - MetaKmsSource *kms_source = (MetaKmsSource *) source; - - return g_source_query_unix_fd (source, kms_source->fd_tag) & G_IO_IN; -} - -static gboolean -kms_event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaKmsSource *kms_source = (MetaKmsSource *) source; - - meta_monitor_manager_kms_wait_for_flip (kms_source->manager_kms); - - return G_SOURCE_CONTINUE; -} - -static GSourceFuncs kms_event_funcs = { - NULL, - kms_event_check, - kms_event_dispatch -}; - static void meta_monitor_manager_kms_connect_uevent_handler (MetaMonitorManagerKms *manager_kms) { @@ -815,182 +420,6 @@ meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms) handle_hotplug_event (manager); } -static void -get_crtc_connectors (MetaMonitorManager *manager, - MetaCrtc *crtc, - uint32_t **connectors, - unsigned int *n_connectors) -{ - GArray *connectors_array = g_array_new (FALSE, FALSE, sizeof (uint32_t)); - GList *l; - - for (l = manager->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - - if (output->crtc == crtc) - g_array_append_val (connectors_array, output->winsys_id); - } - - *n_connectors = connectors_array->len; - *connectors = (uint32_t *) g_array_free (connectors_array, FALSE); -} - -gboolean -meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms, - MetaCrtc *crtc, - int x, - int y, - uint32_t fb_id) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); - uint32_t *connectors; - unsigned int n_connectors; - drmModeModeInfo *mode; - - get_crtc_connectors (manager, crtc, &connectors, &n_connectors); - - if (connectors) - mode = crtc->current_mode->driver_private; - else - mode = NULL; - - if (drmModeSetCrtc (manager_kms->fd, - crtc->crtc_id, - fb_id, - x, y, - connectors, n_connectors, - mode) != 0) - { - g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name); - return FALSE; - } - - g_free (connectors); - - return TRUE; -} - -static void -invoke_flip_closure (GClosure *flip_closure) -{ - GValue param = G_VALUE_INIT; - - g_value_init (¶m, G_TYPE_POINTER); - g_value_set_pointer (¶m, flip_closure); - g_closure_invoke (flip_closure, NULL, 1, ¶m, NULL); - g_closure_unref (flip_closure); -} - -gboolean -meta_monitor_manager_kms_is_crtc_active (MetaMonitorManagerKms *manager_kms, - MetaCrtc *crtc) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); - GList *l; - gboolean connected_crtc_found; - - if (manager->power_save_mode != META_POWER_SAVE_ON) - return FALSE; - - connected_crtc_found = FALSE; - for (l = manager->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - - if (output->crtc == crtc) - { - connected_crtc_found = TRUE; - break; - } - } - - if (!connected_crtc_found) - return FALSE; - - return TRUE; -} - -gboolean -meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms, - MetaCrtc *crtc, - int x, - int y, - uint32_t fb_id, - GClosure *flip_closure, - gboolean *fb_in_use) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); - uint32_t *connectors; - unsigned int n_connectors; - int ret = -1; - - g_assert (manager->power_save_mode == META_POWER_SAVE_ON); - - get_crtc_connectors (manager, crtc, &connectors, &n_connectors); - g_assert (n_connectors > 0); - - if (!manager_kms->page_flips_not_supported) - { - ret = drmModePageFlip (manager_kms->fd, - crtc->crtc_id, - fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - flip_closure); - if (ret != 0 && ret != -EACCES) - { - g_warning ("Failed to flip: %s", strerror (-ret)); - manager_kms->page_flips_not_supported = TRUE; - } - } - - if (manager_kms->page_flips_not_supported) - { - if (meta_monitor_manager_kms_apply_crtc_mode (manager_kms, - crtc, - x, y, - fb_id)) - { - *fb_in_use = TRUE; - return FALSE; - } - } - - if (ret != 0) - return FALSE; - - *fb_in_use = TRUE; - g_closure_ref (flip_closure); - - return TRUE; -} - -static void -page_flip_handler (int fd, - unsigned int frame, - unsigned int sec, - unsigned int usec, - void *data) -{ - GClosure *flip_closure = data; - - invoke_flip_closure (flip_closure); -} - -void -meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms) -{ - drmEventContext evctx; - - if (manager_kms->page_flips_not_supported) - return; - - memset (&evctx, 0, sizeof evctx); - evctx.version = DRM_EVENT_CONTEXT_VERSION; - evctx.page_flip_handler = page_flip_handler; - drmHandleEvent (manager_kms->fd, &evctx); -} - static gboolean meta_monitor_manager_kms_is_transform_handled (MetaMonitorManager *manager, MetaCrtc *crtc, @@ -1046,16 +475,8 @@ meta_monitor_manager_kms_get_capabilities (MetaMonitorManager *manager) META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; - switch (meta_renderer_native_get_mode (renderer_native)) - { - case META_RENDERER_NATIVE_MODE_GBM: - capabilities |= META_MONITOR_MANAGER_CAPABILITY_MIRRORING; - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - break; -#endif - } + if (meta_renderer_native_supports_mirroring (renderer_native)) + capabilities |= META_MONITOR_MANAGER_CAPABILITY_MIRRORING; return capabilities; } @@ -1070,8 +491,8 @@ meta_monitor_manager_kms_get_max_screen_size (MetaMonitorManager *manager, if (meta_is_stage_views_enabled ()) return FALSE; - *max_width = manager_kms->max_buffer_width; - *max_height = manager_kms->max_buffer_height; + meta_gpu_kms_get_max_buffer_size (manager_kms->primary_gpu, + max_width, max_height); return TRUE; } @@ -1093,6 +514,12 @@ meta_monitor_manager_kms_get_default_layout_mode (MetaMonitorManager *manager) return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; } +MetaGpuKms * +meta_monitor_manager_kms_get_primary_gpu (MetaMonitorManagerKms *manager_kms) +{ + return manager_kms->primary_gpu; +} + static guint count_devices_with_connectors (const char *seat_id, GList *devices) @@ -1256,64 +683,34 @@ out: } static gboolean -open_primary_gpu (MetaMonitorManagerKms *manager_kms, - int *fd_out, - char **kms_file_path_out, - GError **error) +meta_monitor_manager_kms_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) { - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native); - g_autofree char *path = NULL; - int fd; + MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable); + const char *subsystems[2] = { "drm", NULL }; + g_autofree char *primary_gpu_path; - path = get_primary_gpu_path (manager_kms); - if (!path) + manager_kms->udev = g_udev_client_new (subsystems); + + primary_gpu_path = get_primary_gpu_path (manager_kms); + if (!primary_gpu_path) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Could not find drm kms device"); return FALSE; } - fd = meta_launcher_open_restricted (launcher, path, error); - if (fd == -1) + manager_kms->primary_gpu = meta_gpu_kms_new (manager_kms, + primary_gpu_path, + error); + if (!manager_kms->primary_gpu) return FALSE; - *fd_out = fd; - *kms_file_path_out = g_steal_pointer (&path); - - return TRUE; -} - -static gboolean -meta_monitor_manager_kms_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable); - GSource *source; - const char *subsystems[2] = { "drm", NULL }; - - manager_kms->udev = g_udev_client_new (subsystems); - - if (!open_primary_gpu (manager_kms, - &manager_kms->fd, - &manager_kms->file_path, - error)) - return FALSE; - - drmSetClientCap (manager_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); - meta_monitor_manager_kms_connect_uevent_handler (manager_kms); - source = g_source_new (&kms_event_funcs, sizeof (MetaKmsSource)); - manager_kms->source = (MetaKmsSource *) source; - manager_kms->source->fd_tag = g_source_add_unix_fd (source, - manager_kms->fd, - G_IO_IN | G_IO_ERR); - manager_kms->source->manager_kms = manager_kms; - g_source_attach (source, NULL); + meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms), + META_GPU (manager_kms->primary_gpu)); return TRUE; } @@ -1334,29 +731,9 @@ meta_monitor_manager_kms_dispose (GObject *object) G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object); } -static void -meta_monitor_manager_kms_finalize (GObject *object) -{ - MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object); - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaLauncher *launcher = meta_backend_native_get_launcher (backend_native); - - if (manager_kms->fd != -1) - meta_launcher_close_restricted (launcher, manager_kms->fd); - g_clear_pointer (&manager_kms->file_path, g_free); - - free_resources (manager_kms); - g_source_destroy ((GSource *) manager_kms->source); - - G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object); -} - static void meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms) { - manager_kms->fd = -1; } static void @@ -1366,9 +743,7 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = meta_monitor_manager_kms_dispose; - object_class->finalize = meta_monitor_manager_kms_finalize; - manager_class->read_current = meta_monitor_manager_kms_read_current; manager_class->read_edid = meta_monitor_manager_kms_read_edid; manager_class->ensure_initial_config = meta_monitor_manager_kms_ensure_initial_config; manager_class->apply_monitors_config = meta_monitor_manager_kms_apply_monitors_config; diff --git a/src/backends/native/meta-monitor-manager-kms.h b/src/backends/native/meta-monitor-manager-kms.h index e4e71b157..fea5b63f1 100644 --- a/src/backends/native/meta-monitor-manager-kms.h +++ b/src/backends/native/meta-monitor-manager-kms.h @@ -28,53 +28,17 @@ #include "meta-monitor-manager-private.h" +typedef struct _MetaGpuKms MetaGpuKms; + #define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ()) G_DECLARE_FINAL_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META, MONITOR_MANAGER_KMS, MetaMonitorManager) -typedef struct _MetaKmsResources -{ - drmModeRes *resources; - drmModeEncoder **encoders; - unsigned int n_encoders; -} MetaKmsResources; - -typedef void (*MetaKmsFlipCallback) (void *user_data); - -int meta_monitor_manager_kms_get_fd (MetaMonitorManagerKms *manager_kms); - -const char * meta_monitor_manager_kms_get_file_path (MetaMonitorManagerKms *manager_kms); - -gboolean meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two); - -MetaCrtcMode * meta_monitor_manager_kms_get_mode_from_drm_mode (MetaMonitorManagerKms *manager_kms, - const drmModeModeInfo *drm_mode); - -gboolean meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms, - MetaCrtc *crtc, - int x, - int y, - uint32_t fb_id); - -gboolean meta_monitor_manager_kms_is_crtc_active (MetaMonitorManagerKms *manager_kms, - MetaCrtc *crtc); - -gboolean meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms, - MetaCrtc *crtc, - int x, - int y, - uint32_t fb_id, - GClosure *flip_closure, - gboolean *fb_in_use); - -void meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms); +MetaGpuKms * meta_monitor_manager_kms_get_primary_gpu (MetaMonitorManagerKms *manager_kms); void meta_monitor_manager_kms_pause (MetaMonitorManagerKms *manager_kms); void meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms); -float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode); - #endif /* META_MONITOR_MANAGER_KMS_H */ diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index faa843234..544eb9593 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -30,7 +30,6 @@ #include "backends/meta-crtc.h" #include "backends/native/meta-crtc-kms.h" #include "backends/native/meta-default-modes.h" -#include "backends/native/meta-monitor-manager-kms.h" #define SYNC_TOLERANCE 0.01 /* 1 percent */ @@ -77,16 +76,14 @@ meta_output_kms_set_power_save_mode (MetaOutput *output, uint64_t state) { MetaOutputKms *output_kms = output->driver_private; - MetaMonitorManager *monitor_manager = - meta_output_get_monitor_manager (output); - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpu *gpu = meta_output_get_gpu (output); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); if (output_kms->dpms_prop_id != 0) { int fd; - fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + fd = meta_gpu_kms_get_fd (gpu_kms); if (drmModeObjectSetProperty (fd, output->winsys_id, DRM_MODE_OBJECT_CONNECTOR, output_kms->dpms_prop_id, state) < 0) @@ -113,14 +110,14 @@ meta_output_kms_can_clone (MetaOutput *output, } static drmModePropertyBlobPtr -read_edid_blob (MetaMonitorManagerKms *monitor_manager_kms, - uint32_t edid_blob_id, - GError **error) +read_edid_blob (MetaGpuKms *gpu_kms, + uint32_t edid_blob_id, + GError **error) { int fd; drmModePropertyBlobPtr edid_blob = NULL; - fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + fd = meta_gpu_kms_get_fd (gpu_kms); edid_blob = drmModeGetPropertyBlob (fd, edid_blob_id); if (!edid_blob) { @@ -133,16 +130,16 @@ read_edid_blob (MetaMonitorManagerKms *monitor_manager_kms, } static GBytes * -read_output_edid (MetaMonitorManagerKms *monitor_manager_kms, - MetaOutput *output, - GError **error) +read_output_edid (MetaGpuKms *gpu_kms, + MetaOutput *output, + GError **error) { MetaOutputKms *output_kms = output->driver_private; drmModePropertyBlobPtr edid_blob; g_assert (output_kms->edid_blob_id != 0); - edid_blob = read_edid_blob (monitor_manager_kms, output_kms->edid_blob_id, error); + edid_blob = read_edid_blob (gpu_kms, output_kms->edid_blob_id, error); if (!edid_blob) return NULL; @@ -159,8 +156,8 @@ read_output_edid (MetaMonitorManagerKms *monitor_manager_kms, } static gboolean -output_get_tile_info (MetaMonitorManagerKms *monitor_manager_kms, - MetaOutput *output) +output_get_tile_info (MetaGpuKms *gpu_kms, + MetaOutput *output) { MetaOutputKms *output_kms = output->driver_private; int fd; @@ -169,7 +166,7 @@ output_get_tile_info (MetaMonitorManagerKms *monitor_manager_kms, if (output_kms->tile_blob_id == 0) return FALSE; - fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + fd = meta_gpu_kms_get_fd (gpu_kms); tile_blob = drmModeGetPropertyBlob (fd, output_kms->tile_blob_id); if (!tile_blob) { @@ -211,17 +208,15 @@ GBytes * meta_output_kms_read_edid (MetaOutput *output) { MetaOutputKms *output_kms = output->driver_private; - MetaMonitorManager *monitor_manager = - meta_output_get_monitor_manager (output); - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpu *gpu = meta_output_get_gpu (output); + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); GError *error = NULL; GBytes *edid; if (output_kms->edid_blob_id == 0) return NULL; - edid = read_output_edid (monitor_manager_kms, output, &error); + edid = read_output_edid (gpu_kms, output, &error); if (!edid) { g_warning ("Failed to read EDID from '%s': %s", @@ -234,14 +229,14 @@ meta_output_kms_read_edid (MetaOutput *output) } static void -find_connector_properties (MetaMonitorManagerKms *monitor_manager_kms, - MetaOutputKms *output_kms) +find_connector_properties (MetaGpuKms *gpu_kms, + MetaOutputKms *output_kms) { drmModeConnector *connector = output_kms->connector; int fd; int i; - fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + fd = meta_gpu_kms_get_fd (gpu_kms); output_kms->hotplug_mode_update = 0; output_kms->suggested_x = -1; @@ -327,8 +322,8 @@ meta_output_destroy_notify (MetaOutput *output) } static void -add_common_modes (MetaOutput *output, - MetaMonitorManagerKms *monitor_manager_kms) +add_common_modes (MetaOutput *output, + MetaGpuKms *gpu_kms) { GPtrArray *array; unsigned i; @@ -365,8 +360,8 @@ add_common_modes (MetaOutput *output, refresh_rate > max_refresh_rate) continue; - crtc_mode = meta_monitor_manager_kms_get_mode_from_drm_mode (monitor_manager_kms, - drm_mode); + crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms, + drm_mode); g_ptr_array_add (array, crtc_mode); } @@ -397,8 +392,8 @@ compare_modes (const void *one, } static void -init_output_modes (MetaOutput *output, - MetaMonitorManagerKms *monitor_manager_kms) +init_output_modes (MetaOutput *output, + MetaGpuKms *gpu_kms) { MetaOutputKms *output_kms = output->driver_private; unsigned int i; @@ -412,9 +407,7 @@ init_output_modes (MetaOutput *output, MetaCrtcMode *crtc_mode; drm_mode = &output_kms->connector->modes[i]; - crtc_mode = - meta_monitor_manager_kms_get_mode_from_drm_mode (monitor_manager_kms, - drm_mode); + crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms, drm_mode); output->modes[i] = crtc_mode; if (output_kms->connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) output->preferred_mode = output->modes[i]; @@ -425,13 +418,12 @@ init_output_modes (MetaOutput *output, } MetaOutput * -meta_create_kms_output (MetaMonitorManager *monitor_manager, - drmModeConnector *connector, - MetaKmsResources *resources, - MetaOutput *old_output) +meta_create_kms_output (MetaGpuKms *gpu_kms, + drmModeConnector *connector, + MetaKmsResources *resources, + MetaOutput *old_output) { - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); + MetaGpu *gpu = META_GPU (gpu_kms); MetaOutput *output; MetaOutputKms *output_kms; GArray *crtcs; @@ -447,7 +439,7 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, output->driver_private = output_kms; output->driver_notify = (GDestroyNotify) meta_output_destroy_notify; - output->monitor_manager = monitor_manager; + output->gpu = gpu; output->winsys_id = connector->connector_id; output->name = make_output_name (connector); output->width_mm = connector->mmWidth; @@ -477,16 +469,16 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, } output_kms->connector = connector; - find_connector_properties (monitor_manager_kms, output_kms); + find_connector_properties (gpu_kms, output_kms); - init_output_modes (output, monitor_manager_kms); + init_output_modes (output, gpu_kms); /* FIXME: MSC feature bit? */ /* Presume that if the output supports scaling, then we have * a panel fitter capable of adjusting any mode to suit. */ if (output_kms->has_scaling) - add_common_modes (output, monitor_manager_kms); + add_common_modes (output, gpu_kms); qsort (output->modes, output->n_modes, sizeof (MetaCrtcMode *), compare_modes); @@ -494,7 +486,7 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, output_kms->n_encoders = connector->count_encoders; output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders); - fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + fd = meta_gpu_kms_get_fd (gpu_kms); crtc_mask = ~(unsigned int) 0; for (i = 0; i < output_kms->n_encoders; i++) @@ -516,7 +508,7 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc*)); - for (l = monitor_manager->crtcs, i = 0; l; l = l->next, i++) + for (l = meta_gpu_get_crtcs (gpu), i = 0; l; l = l->next, i++) { if (crtc_mask & (1 << i)) { @@ -531,7 +523,7 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0) { - for (l = monitor_manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -566,7 +558,7 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, { GError *error = NULL; - edid = read_output_edid (monitor_manager_kms, output, &error); + edid = read_output_edid (gpu_kms, output, &error); if (!edid) { g_warning ("Failed to read EDID blob from %s: %s", @@ -585,7 +577,7 @@ meta_create_kms_output (MetaMonitorManager *monitor_manager, /* MetaConnectorType matches DRM's connector types */ output->connector_type = (MetaConnectorType) connector->connector_type; - output_get_tile_info (monitor_manager_kms, output); + output_get_tile_info (gpu_kms, output); /* FIXME: backlight is a very driver specific thing unfortunately, every DDX does its own thing, and the dumb KMS API does not include it. diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h index 84ec17ad4..ca811b92b 100644 --- a/src/backends/native/meta-output-kms.h +++ b/src/backends/native/meta-output-kms.h @@ -23,7 +23,7 @@ #define META_OUTPUT_KMS_H #include "backends/meta-output.h" -#include "backends/native/meta-monitor-manager-kms.h" +#include "backends/native/meta-gpu-kms.h" void meta_output_kms_set_underscan (MetaOutput *output); @@ -35,9 +35,9 @@ gboolean meta_output_kms_can_clone (MetaOutput *output, GBytes * meta_output_kms_read_edid (MetaOutput *output); -MetaOutput * meta_create_kms_output (MetaMonitorManager *monitor_manager, - drmModeConnector *connector, - MetaKmsResources *resources, - MetaOutput *old_output); +MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms, + drmModeConnector *connector, + MetaKmsResources *resources, + MetaOutput *old_output); #endif /* META_OUTPUT_KMS_H */ diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index c85f3fe82..866d06645 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -54,6 +54,7 @@ #include "backends/meta-logical-monitor.h" #include "backends/meta-output.h" #include "backends/meta-renderer-view.h" +#include "backends/native/meta-gpu-kms.h" #include "backends/native/meta-monitor-manager-kms.h" #include "backends/native/meta-renderer-native.h" #include "cogl/cogl.h" @@ -74,8 +75,31 @@ enum static GParamSpec *obj_props[PROP_LAST]; +typedef struct _MetaRendererNativeGpuData +{ + MetaRendererNative *renderer_native; + + struct { + struct gbm_device *device; + } gbm; + +#ifdef HAVE_EGL_DEVICE + struct { + EGLDeviceEXT device; + + gboolean no_egl_output_drm_flip_event; + } egl; +#endif + + MetaRendererNativeMode mode; + + gboolean no_add_fb2; +} MetaRendererNativeGpuData; + typedef struct _MetaOnscreenNative { + MetaGpuKms *gpu_kms; + struct { struct gbm_surface *surface; uint32_t current_fb_id; @@ -115,28 +139,14 @@ struct _MetaRendererNative MetaMonitorManagerKms *monitor_manager_kms; - MetaRendererNativeMode mode; - EGLDisplay egl_display; - struct { - struct gbm_device *device; - } gbm; - -#ifdef HAVE_EGL_DEVICE - struct { - EGLDeviceEXT device; - - gboolean no_egl_output_drm_flip_event; - } egl; -#endif + GHashTable *gpu_datas; CoglClosure *swap_notify_idle; int64_t frame_counter; gboolean pending_unset_disabled_crtcs; - - gboolean no_add_fb2; }; static void @@ -151,6 +161,58 @@ G_DEFINE_TYPE_WITH_CODE (MetaRendererNative, static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; static const CoglWinsysVtable *parent_vtable; +static void +meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data) +{ + g_free (renderer_gpu_data); +} + +static MetaRendererNativeGpuData * +meta_renderer_native_get_gpu_data (MetaRendererNative *renderer_native, + MetaGpuKms *gpu_kms) +{ + return g_hash_table_lookup (renderer_native->gpu_datas, gpu_kms); +} + +static MetaRendererNative * +meta_renderer_native_from_onscreen (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglRenderer *cogl_renderer = framebuffer->context->display->renderer; + CoglRendererEGL *egl_renderer = cogl_renderer->winsys; + + return egl_renderer->platform; +} + +static MetaRendererNative * +meta_renderer_native_from_gpu (MetaGpuKms *gpu_kms) +{ + MetaMonitorManager *monitor_manager = + meta_gpu_get_monitor_manager (META_GPU (gpu_kms)); + MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager); + + return META_RENDERER_NATIVE (meta_backend_get_renderer (backend)); +} + +struct gbm_device * +meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms) +{ + MetaRendererNative *renderer_native = + meta_renderer_native_from_gpu (gpu_kms); + MetaRendererNativeGpuData *renderer_gpu_data; + + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + gpu_kms); + + return renderer_gpu_data->gbm.device; +} + +static MetaRendererNativeGpuData * +meta_create_renderer_native_gpu_data (MetaGpuKms *gpu_kms) +{ + return g_new0 (MetaRendererNativeGpuData, 1); +} + static void meta_renderer_native_disconnect (CoglRenderer *cogl_renderer) { @@ -220,15 +282,10 @@ free_current_bo (CoglOnscreen *onscreen) { CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; - CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context; - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *egl_renderer = cogl_renderer->winsys; - MetaRendererNative *renderer_native = egl_renderer->platform; - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; int kms_fd; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); if (onscreen_native->gbm.current_fb_id) { @@ -318,9 +375,15 @@ meta_renderer_native_add_egl_config_attributes (CoglDisplay *cogl_disp { CoglRendererEGL *egl_renderer = cogl_display->renderer->winsys; MetaRendererNative *renderer_native = egl_renderer->platform; + MetaMonitorManagerKms *monitor_manager_kms = + renderer_native->monitor_manager_kms; + MetaGpuKms *primary_gpu = + meta_monitor_manager_kms_get_primary_gpu (monitor_manager_kms); + MetaRendererNativeGpuData *primary_renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, primary_gpu); int i = 0; - switch (renderer_native->mode) + switch (primary_renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: attributes[i++] = EGL_SURFACE_TYPE; @@ -461,18 +524,22 @@ on_crtc_flipped (GClosure *closure, CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); onscreen_native->pending_flips--; if (onscreen_native->pending_flips == 0) { + MetaRendererNative *renderer_native = + meta_renderer_native_from_onscreen (onscreen); + MetaRendererNativeGpuData *renderer_gpu_data; + onscreen_native->pending_queue_swap_notify = FALSE; meta_onscreen_native_queue_swap_notify (onscreen); - switch (renderer_native->mode) + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + onscreen_native->gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: meta_onscreen_native_swap_drm_fb (onscreen); @@ -494,20 +561,21 @@ flip_closure_destroyed (MetaRendererView *view) CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; + MetaRendererNative *renderer_native = + meta_renderer_native_from_onscreen (onscreen); + MetaRendererNativeGpuData *renderer_gpu_data; - switch (renderer_native->mode) + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: if (onscreen_native->gbm.next_fb_id) { - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; int kms_fd; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); drmModeRmFB (kms_fd, onscreen_native->gbm.next_fb_id); gbm_surface_release_buffer (onscreen_native->gbm.surface, onscreen_native->gbm.next_bo); @@ -533,10 +601,12 @@ flip_closure_destroyed (MetaRendererView *view) #ifdef HAVE_EGL_DEVICE static gboolean -flip_egl_stream (MetaRendererNative *renderer_native, - MetaOnscreenNative *onscreen_native, +flip_egl_stream (MetaOnscreenNative *onscreen_native, GClosure *flip_closure) { + MetaRendererNative *renderer_native = + meta_renderer_native_from_gpu (onscreen_native->gpu_kms); + MetaRendererNativeGpuData *renderer_gpu_data; MetaBackend *backend = meta_get_backend (); MetaEgl *egl = meta_backend_get_egl (backend); ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); @@ -547,7 +617,10 @@ flip_egl_stream (MetaRendererNative *renderer_native, EGLAttrib *acquire_attribs; GError *error = NULL; - if (renderer_native->egl.no_egl_output_drm_flip_event) + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + onscreen_native->gpu_kms); + if (renderer_gpu_data->egl.no_egl_output_drm_flip_event) return FALSE; acquire_attribs = (EGLAttrib[]) { @@ -567,7 +640,7 @@ flip_egl_stream (MetaRendererNative *renderer_native, { g_warning ("Failed to flip EGL stream (%s), relying on clock from " "now on", error->message); - renderer_native->egl.no_egl_output_drm_flip_event = TRUE; + renderer_gpu_data->egl.no_egl_output_drm_flip_event = TRUE; } g_error_free (error); return FALSE; @@ -587,34 +660,32 @@ meta_onscreen_native_flip_crtc (MetaOnscreenNative *onscreen_native, int y, gboolean *fb_in_use) { - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; + MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); + MetaRendererNativeGpuData *renderer_gpu_data; - if (!meta_monitor_manager_kms_is_crtc_active (monitor_manager_kms, - crtc)) + if (!meta_gpu_kms_is_crtc_active (gpu_kms, crtc)) { *fb_in_use = FALSE; return; } - switch (renderer_native->mode) + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - if (meta_monitor_manager_kms_flip_crtc (monitor_manager_kms, - crtc, - x, y, - onscreen_native->gbm.next_fb_id, - flip_closure, - fb_in_use)) + if (meta_gpu_kms_flip_crtc (gpu_kms, + crtc, + x, y, + onscreen_native->gbm.next_fb_id, + flip_closure, + fb_in_use)) onscreen_native->pending_flips++; break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - if (flip_egl_stream (renderer_native, - onscreen_native, + if (flip_egl_stream (onscreen_native, flip_closure)) onscreen_native->pending_flips++; *fb_in_use = TRUE; @@ -625,7 +696,7 @@ meta_onscreen_native_flip_crtc (MetaOnscreenNative *onscreen_native, typedef struct _SetCrtcFbData { - MetaMonitorManagerKms *monitor_manager_kms; + MetaGpuKms *gpu_kms; MetaLogicalMonitor *logical_monitor; uint32_t fb_id; } SetCrtcFbData; @@ -636,31 +707,28 @@ set_crtc_fb (MetaLogicalMonitor *logical_monitor, gpointer user_data) { SetCrtcFbData *data = user_data; - MetaMonitorManagerKms *monitor_manager_kms = data->monitor_manager_kms; + MetaGpuKms *gpu_kms = data->gpu_kms; int x, y; x = crtc->rect.x - logical_monitor->rect.x; y = crtc->rect.y - logical_monitor->rect.y; - meta_monitor_manager_kms_apply_crtc_mode (monitor_manager_kms, - crtc, - x, y, - data->fb_id); + meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, data->fb_id); } static void meta_onscreen_native_set_crtc_modes (MetaOnscreenNative *onscreen_native) { - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; + MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); + MetaRendererNativeGpuData *renderer_gpu_data; MetaRendererView *view = onscreen_native->view; uint32_t fb_id = 0; MetaLogicalMonitor *logical_monitor; - switch (renderer_native->mode) + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: fb_id = onscreen_native->gbm.next_fb_id; @@ -678,7 +746,7 @@ meta_onscreen_native_set_crtc_modes (MetaOnscreenNative *onscreen_native) if (logical_monitor) { SetCrtcFbData data = { - .monitor_manager_kms = monitor_manager_kms, + .gpu_kms = gpu_kms, .fb_id = fb_id }; @@ -688,20 +756,16 @@ meta_onscreen_native_set_crtc_modes (MetaOnscreenNative *onscreen_native) } else { - MetaMonitorManager *monitor_manager = - META_MONITOR_MANAGER (monitor_manager_kms); - GList *crtcs; GList *l; - crtcs = meta_monitor_manager_get_crtcs (monitor_manager); - for (l = crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (META_GPU (gpu_kms)); l; l = l->next) { MetaCrtc *crtc = l->data; - meta_monitor_manager_kms_apply_crtc_mode (monitor_manager_kms, - crtc, - crtc->rect.x, crtc->rect.y, - fb_id); + meta_gpu_kms_apply_crtc_mode (gpu_kms, + crtc, + crtc->rect.x, crtc->rect.y, + fb_id); } } } @@ -736,13 +800,9 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen) { CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; + MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); MetaRendererView *view = onscreen_native->view; - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = framebuffer->context; - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *egl_renderer = cogl_renderer->winsys; - MetaRendererNative *renderer_native = egl_renderer->platform; GClosure *flip_closure; MetaLogicalMonitor *logical_monitor; gboolean fb_in_use = FALSE; @@ -780,13 +840,9 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen) } else { - MetaMonitorManager *monitor_manager = - META_MONITOR_MANAGER (renderer_native->monitor_manager_kms); - GList *crtcs; GList *l; - crtcs = meta_monitor_manager_get_crtcs (monitor_manager); - for (l = crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (META_GPU (gpu_kms)); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -804,7 +860,11 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen) */ if (fb_in_use && onscreen_native->pending_flips == 0) { - switch (renderer_native->mode) + MetaRendererNativeGpuData *renderer_gpu_data; + + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: meta_onscreen_native_swap_drm_fb (onscreen); @@ -826,14 +886,9 @@ gbm_get_next_fb_id (CoglOnscreen *onscreen, struct gbm_bo **out_next_bo, uint32_t *out_next_fb_id) { - CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context; - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *egl_renderer = cogl_renderer->winsys; - MetaRendererNative *renderer_native = egl_renderer->platform; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; uint32_t handle, stride; struct gbm_bo *next_bo; uint32_t next_fb_id; @@ -845,7 +900,7 @@ gbm_get_next_fb_id (CoglOnscreen *onscreen, stride = gbm_bo_get_stride (next_bo); handle = gbm_bo_get_handle (next_bo).u32; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); if (drmModeAddFB (kms_fd, cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen)), @@ -877,8 +932,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, MetaRendererNative *renderer_native = egl_renderer->platform; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; + MetaRendererNativeGpuData *renderer_gpu_data; CoglFrameInfo *frame_info; frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos); @@ -889,13 +944,15 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, * animation earlier due to the animation being driven by some other monitor. */ while (onscreen_native->pending_flips) - meta_monitor_manager_kms_wait_for_flip (monitor_manager_kms); + meta_gpu_kms_wait_for_flip (gpu_kms); parent_vtable->onscreen_swap_buffers_with_damage (onscreen, rectangles, n_rectangles); - switch (renderer_native->mode) + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: g_warn_if_fail (onscreen_native->gbm.next_bo == NULL && @@ -933,6 +990,11 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context, CoglRenderer *cogl_renderer = cogl_context->display->renderer; CoglRendererEGL *egl_renderer = cogl_renderer->winsys; MetaRendererNative *renderer_native = egl_renderer->platform; + MetaMonitorManagerKms *monitor_manager_kms = + renderer_native->monitor_manager_kms; + MetaGpuKms *primary_gpu = + meta_monitor_manager_kms_get_primary_gpu (monitor_manager_kms); + MetaRendererNativeGpuData *primary_renderer_gpu_data; #endif COGL_FLAGS_SET (cogl_context->features, @@ -949,7 +1011,9 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context, TRUE); #ifdef HAVE_EGL_DEVICE - if (renderer_native->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE) + primary_renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, primary_gpu); + if (primary_renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE) COGL_FLAGS_SET (cogl_context->features, COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL, TRUE); #endif @@ -958,7 +1022,7 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context, } static gboolean -meta_renderer_native_create_surface_gbm (MetaRendererNative *renderer_native, +meta_renderer_native_create_surface_gbm (MetaOnscreenNative *onscreen_native, int width, int height, struct gbm_surface **gbm_surface, @@ -972,11 +1036,16 @@ meta_renderer_native_create_surface_gbm (MetaRendererNative *renderer_native, CoglDisplay *cogl_display = cogl_context->display; CoglDisplayEGL *egl_display = cogl_display->winsys; CoglRendererEGL *egl_renderer = cogl_display->renderer->winsys; + MetaRendererNative *renderer_native = egl_renderer->platform; + MetaRendererNativeGpuData *renderer_gpu_data; struct gbm_surface *new_gbm_surface; EGLNativeWindowType egl_native_window; EGLSurface new_egl_surface; - new_gbm_surface = gbm_surface_create (renderer_native->gbm.device, + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + onscreen_native->gpu_kms); + new_gbm_surface = gbm_surface_create (renderer_gpu_data->gbm.device, width, height, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | @@ -1110,14 +1179,14 @@ meta_renderer_native_create_surface_egl_device (MetaRendererNative *renderer_nat } static gboolean -init_dumb_fb (MetaRendererNative *renderer_native, - MetaOnscreenNative *onscreen_native, +init_dumb_fb (MetaOnscreenNative *onscreen_native, int width, int height, GError **error) { - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaRendererNativeGpuData *renderer_gpu_data; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; + MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); struct drm_mode_create_dumb create_arg; struct drm_mode_destroy_dumb destroy_arg; struct drm_mode_map_dumb map_arg; @@ -1125,7 +1194,7 @@ init_dumb_fb (MetaRendererNative *renderer_native, void *map; int kms_fd; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); create_arg = (struct drm_mode_create_dumb) { .bpp = 32, /* RGBX8888 */ @@ -1141,7 +1210,10 @@ init_dumb_fb (MetaRendererNative *renderer_native, goto err_ioctl; } - if (!renderer_native->no_add_fb2) + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + onscreen_native->gpu_kms); + if (!renderer_gpu_data->no_add_fb2) { uint32_t handles[4] = { create_arg.handle, }; uint32_t pitches[4] = { create_arg.pitch, }; @@ -1154,11 +1226,11 @@ init_dumb_fb (MetaRendererNative *renderer_native, { g_warning ("drmModeAddFB2 failed (%s), falling back to drmModeAddFB", g_strerror (errno)); - renderer_native->no_add_fb2 = TRUE; + renderer_gpu_data->no_add_fb2 = TRUE; } } - if (renderer_native->no_add_fb2) + if (renderer_gpu_data->no_add_fb2) { if (drmModeAddFB (kms_fd, width, height, 24 /* depth of RGBX8888 */, @@ -1221,11 +1293,9 @@ err_ioctl: } static void -release_dumb_fb (MetaRendererNative *renderer_native, - MetaOnscreenNative *onscreen_native) +release_dumb_fb (MetaOnscreenNative *onscreen_native) { - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; struct drm_mode_destroy_dumb destroy_arg; int kms_fd; @@ -1236,7 +1306,7 @@ release_dumb_fb (MetaRendererNative *renderer_native, onscreen_native->egl.dumb_fb.map_size); onscreen_native->egl.dumb_fb.map = NULL; - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); drmModeRmFB (kms_fd, onscreen_native->egl.dumb_fb.fb_id); @@ -1291,6 +1361,7 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen, MetaRendererNative *renderer_native = egl_renderer->platform; CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; + MetaRendererNativeGpuData *renderer_gpu_data; struct gbm_surface *gbm_surface; EGLSurface egl_surface; int width; @@ -1313,10 +1384,13 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen, if (width == 0 || height == 0) return TRUE; - switch (renderer_native->mode) + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + onscreen_native->gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - if (!meta_renderer_native_create_surface_gbm (renderer_native, + if (!meta_renderer_native_create_surface_gbm (onscreen_native, width, height, &gbm_surface, &egl_surface, @@ -1328,8 +1402,7 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen, break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - if (!init_dumb_fb (renderer_native, onscreen_native, - width, height, error)) + if (!init_dumb_fb (onscreen_native, width, height, error)) return FALSE; view = onscreen_native->view; @@ -1361,6 +1434,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaRendererNative *renderer_native = egl_renderer->platform; MetaOnscreenNative *onscreen_native; + MetaRendererNativeGpuData *renderer_gpu_data; /* If we never successfully allocated then there's nothing to do */ if (egl_onscreen == NULL) @@ -1374,7 +1448,10 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) egl_onscreen->egl_surface = EGL_NO_SURFACE; } - switch (renderer_native->mode) + renderer_gpu_data = + meta_renderer_native_get_gpu_data (renderer_native, + onscreen_native->gpu_kms); + switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: /* flip state takes a reference on the onscreen so there should @@ -1391,7 +1468,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - release_dumb_fb (renderer_native, onscreen_native); + release_dumb_fb (onscreen_native); if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR) { MetaBackend *backend = meta_get_backend (); @@ -1422,16 +1499,32 @@ _cogl_winsys_egl_vtable = { .context_init = meta_renderer_native_init_egl_context }; -MetaRendererNativeMode -meta_renderer_native_get_mode (MetaRendererNative *renderer_native) +gboolean +meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native) { - return renderer_native->mode; -} + MetaMonitorManager *monitor_manager = + META_MONITOR_MANAGER (renderer_native->monitor_manager_kms); + GList *l; -struct gbm_device * -meta_renderer_native_get_gbm (MetaRendererNative *renderer_native) -{ - return renderer_native->gbm.device; + for (l = monitor_manager->gpus; l; l = l->next) + { + MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); + MetaRendererNativeGpuData *renderer_gpu_data; + + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, + gpu_kms); + switch (renderer_gpu_data->mode) + { + case META_RENDERER_NATIVE_MODE_GBM: + break; +#ifdef HAVE_EGL_DEVICE + case META_RENDERER_NATIVE_MODE_EGL_DEVICE: + return FALSE; +#endif + } + } + + return TRUE; } void @@ -1456,13 +1549,15 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) } static CoglOnscreen * -meta_renderer_native_create_onscreen (MetaRendererNative *renderer, - CoglContext *context, - MetaMonitorTransform transform, - gint view_width, - gint view_height) +meta_renderer_native_create_onscreen (MetaGpuKms *gpu_kms, + CoglContext *context, + MetaMonitorTransform transform, + gint view_width, + gint view_height) { CoglOnscreen *onscreen; + CoglOnscreenEGL *egl_onscreen; + MetaOnscreenNative *onscreen_native; gint width, height; GError *error = NULL; @@ -1489,6 +1584,10 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer, return NULL; } + egl_onscreen = onscreen->winsys; + onscreen_native = egl_onscreen->platform; + onscreen_native->gpu_kms = gpu_kms; + return onscreen; } @@ -1543,13 +1642,12 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native, if (width != view_layout.width || height != view_layout.height) { - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (stage_view); CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); CoglOnscreenEGL *egl_onscreen = onscreen->winsys; MetaOnscreenNative *onscreen_native = egl_onscreen->platform; + MetaGpuKms *gpu_kms = onscreen_native->gpu_kms; CoglDisplayEGL *egl_display = cogl_display->winsys; struct gbm_surface *new_surface; EGLSurface new_egl_surface; @@ -1560,11 +1658,11 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native, * to swap the current buffer. */ while (onscreen_native->gbm.next_fb_id != 0) - meta_monitor_manager_kms_wait_for_flip (monitor_manager_kms); + meta_gpu_kms_wait_for_flip (gpu_kms); /* Need to drop the GBM surface and create a new one */ - if (!meta_renderer_native_create_surface_gbm (renderer_native, + if (!meta_renderer_native_create_surface_gbm (onscreen_native, width, height, &new_surface, &new_egl_surface, @@ -1677,13 +1775,18 @@ meta_onscreen_native_set_view (CoglOnscreen *onscreen, MetaRendererView * meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native) { + MetaMonitorManagerKms *monitor_manager_kms = + renderer_native->monitor_manager_kms; MetaMonitorManager *monitor_manager = - META_MONITOR_MANAGER (renderer_native->monitor_manager_kms); - CoglOnscreen *onscreen = NULL; - MetaBackend *backend = meta_get_backend (); + META_MONITOR_MANAGER (monitor_manager_kms); + MetaGpuKms *primary_gpu = + meta_monitor_manager_kms_get_primary_gpu (monitor_manager_kms); + 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); + CoglContext *cogl_context = + clutter_backend_get_cogl_context (clutter_backend); cairo_rectangle_int_t view_layout = { 0 }; + CoglOnscreen *onscreen; MetaRendererView *view; GError *error = NULL; @@ -1691,7 +1794,7 @@ meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native) &view_layout.width, &view_layout.height); - onscreen = meta_renderer_native_create_onscreen (renderer_native, + onscreen = meta_renderer_native_create_onscreen (primary_gpu, cogl_context, META_MONITOR_TRANSFORM_NORMAL, view_layout.width, @@ -1748,11 +1851,16 @@ meta_renderer_native_create_view (MetaRenderer *renderer, MetaLogicalMonitor *logical_monitor) { MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); + MetaMonitorManagerKms *monitor_manager_kms = + renderer_native->monitor_manager_kms; MetaMonitorManager *monitor_manager = - META_MONITOR_MANAGER (renderer_native->monitor_manager_kms); - MetaBackend *backend = meta_get_backend (); + META_MONITOR_MANAGER (monitor_manager_kms); + MetaGpuKms *primary_gpu = + meta_monitor_manager_kms_get_primary_gpu (monitor_manager_kms); + 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); + CoglContext *cogl_context = + clutter_backend_get_cogl_context (clutter_backend); CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); CoglDisplayEGL *egl_display = cogl_display->winsys; CoglOnscreenEGL *egl_onscreen; @@ -1774,7 +1882,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, width = roundf (logical_monitor->rect.width * scale); height = roundf (logical_monitor->rect.height * scale); - onscreen = meta_renderer_native_create_onscreen (META_RENDERER_NATIVE (renderer), + onscreen = meta_renderer_native_create_onscreen (primary_gpu, cogl_context, view_transform, width, @@ -1784,7 +1892,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, if (view_transform != META_MONITOR_TRANSFORM_NORMAL) { - offscreen = meta_renderer_native_create_offscreen (META_RENDERER_NATIVE (renderer), + offscreen = meta_renderer_native_create_offscreen (renderer_native, cogl_context, view_transform, width, @@ -1833,24 +1941,25 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native) if (renderer_native->pending_unset_disabled_crtcs) { - MetaBackend *backend = meta_get_backend (); MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerKms *monitor_manager_kms = - META_MONITOR_MANAGER_KMS (monitor_manager); - GList *crtcs; + META_MONITOR_MANAGER (renderer_native->monitor_manager_kms); GList *l; - crtcs = meta_monitor_manager_get_crtcs (monitor_manager); - for (l = crtcs; l; l = l->next) + for (l = meta_monitor_manager_get_gpus (monitor_manager); l; l = l->next) { - MetaCrtc *crtc = l->data; + MetaGpu *gpu = l->data; + MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); + GList *k; - if (crtc->current_mode) - continue; + for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) + { + MetaCrtc *crtc = k->data; - meta_monitor_manager_kms_apply_crtc_mode (monitor_manager_kms, - crtc, 0, 0, 0); + if (crtc->current_mode) + continue; + + meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, 0, 0, 0); + } } renderer_native->pending_unset_disabled_crtcs = FALSE; @@ -1901,27 +2010,21 @@ meta_renderer_native_set_property (GObject *object, } } -static void -meta_renderer_native_finalize (GObject *object) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); - - g_clear_pointer (&renderer_native->gbm.device, gbm_device_destroy); - - G_OBJECT_CLASS (meta_renderer_native_parent_class)->finalize (object); -} - -static gboolean -init_gbm (MetaRendererNative *renderer_native, - GError **error) +static MetaRendererNativeGpuData * +create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native, + MetaGpuKms *gpu_kms, + GError **error) { MetaMonitorManagerKms *monitor_manager_kms = renderer_native->monitor_manager_kms; - MetaBackend *backend = meta_get_backend (); + MetaMonitorManager *monitor_manager = + META_MONITOR_MANAGER (monitor_manager_kms); + MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager); MetaEgl *egl = meta_backend_get_egl (backend); struct gbm_device *gbm_device; EGLDisplay egl_display; int kms_fd; + MetaRendererNativeGpuData *renderer_gpu_data; if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, "EGL_MESA_platform_gbm", @@ -1930,10 +2033,10 @@ init_gbm (MetaRendererNative *renderer_native, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Missing extension for GBM renderer: EGL_KHR_platform_gbm"); - return FALSE; + return NULL; } - kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + kms_fd = meta_gpu_kms_get_fd (gpu_kms); gbm_device = gbm_create_device (kms_fd); if (!gbm_device) @@ -1941,7 +2044,7 @@ init_gbm (MetaRendererNative *renderer_native, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Failed to create gbm device: %s", g_strerror (errno)); - return FALSE; + return NULL; } egl_display = meta_egl_get_platform_display (egl, @@ -1950,14 +2053,17 @@ init_gbm (MetaRendererNative *renderer_native, if (egl_display == EGL_NO_DISPLAY) { gbm_device_destroy (gbm_device); - return FALSE; + return NULL; } - renderer_native->egl_display = egl_display; - renderer_native->gbm.device = gbm_device; - renderer_native->mode = META_RENDERER_NATIVE_MODE_GBM; + renderer_gpu_data = meta_create_renderer_native_gpu_data (gpu_kms); + renderer_gpu_data->renderer_native = renderer_native; + renderer_gpu_data->gbm.device = gbm_device; + renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_GBM; - return TRUE; + renderer_native->egl_display = egl_display; + + return renderer_gpu_data; } #ifdef HAVE_EGL_DEVICE @@ -1983,11 +2089,10 @@ get_drm_device_file (MetaEgl *egl, } static EGLDeviceEXT -find_egl_device (MetaRendererNative *renderer_native, - GError **error) +find_egl_device (MetaRendererNative *renderer_native, + MetaGpuKms *gpu_kms, + GError **error) { - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; MetaBackend *backend = meta_get_backend (); MetaEgl *egl = meta_backend_get_egl (backend); char **missing_extensions; @@ -2026,7 +2131,7 @@ find_egl_device (MetaRendererNative *renderer_native, return EGL_NO_DEVICE_EXT; } - kms_file_path = meta_monitor_manager_kms_get_file_path (monitor_manager_kms); + kms_file_path = meta_gpu_kms_get_file_path (gpu_kms); device = EGL_NO_DEVICE_EXT; for (i = 0; i < num_devices; i++) @@ -2060,15 +2165,14 @@ find_egl_device (MetaRendererNative *renderer_native, } static EGLDisplay -get_egl_device_display (MetaRendererNative *renderer_native, - EGLDeviceEXT egl_device, - GError **error) +get_egl_device_display (MetaRendererNative *renderer_native, + MetaGpuKms *gpu_kms, + EGLDeviceEXT egl_device, + GError **error) { MetaBackend *backend = meta_get_backend (); MetaEgl *egl = meta_backend_get_egl (backend); - MetaMonitorManagerKms *monitor_manager_kms = - renderer_native->monitor_manager_kms; - int kms_fd = meta_monitor_manager_kms_get_fd (monitor_manager_kms); + int kms_fd = meta_gpu_kms_get_fd (gpu_kms); EGLint platform_attribs[] = { EGL_DRM_MASTER_FD_EXT, kms_fd, EGL_NONE @@ -2080,34 +2184,37 @@ get_egl_device_display (MetaRendererNative *renderer_native, error); } -static gboolean -init_egl_device (MetaRendererNative *renderer_native, - GError **error) +static MetaRendererNativeGpuData * +create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native, + MetaGpuKms *gpu_kms, + GError **error) { MetaBackend *backend = meta_get_backend (); MetaEgl *egl = meta_backend_get_egl (backend); char **missing_extensions; EGLDeviceEXT egl_device; EGLDisplay egl_display; + MetaRendererNativeGpuData *renderer_gpu_data; if (!meta_is_stage_views_enabled()) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "EGLDevice requires stage views enabled"); - return FALSE; + return NULL; } - egl_device = find_egl_device (renderer_native, error); + egl_device = find_egl_device (renderer_native, gpu_kms, error); if (egl_device == EGL_NO_DEVICE_EXT) - return FALSE; + return NULL; - egl_display = get_egl_device_display (renderer_native, egl_device, error); + egl_display = get_egl_device_display (renderer_native, gpu_kms, + egl_device, error); if (egl_display == EGL_NO_DISPLAY) - return FALSE; + return NULL; if (!meta_egl_initialize (egl, egl_display, error)) - return FALSE; + return NULL; if (!meta_egl_has_extensions (egl, egl_display, @@ -2130,23 +2237,26 @@ init_egl_device (MetaRendererNative *renderer_native, missing_extensions_str); g_free (missing_extensions_str); g_free (missing_extensions); - return FALSE; + return NULL; } - renderer_native->egl_display = egl_display; - renderer_native->egl.device = egl_device; - renderer_native->mode = META_RENDERER_NATIVE_MODE_EGL_DEVICE; + renderer_gpu_data = meta_create_renderer_native_gpu_data (gpu_kms); + renderer_gpu_data->renderer_native = renderer_native; + renderer_gpu_data->egl.device = egl_device; + renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_EGL_DEVICE; - return TRUE; + renderer_native->egl_display = egl_display; + + return renderer_gpu_data; } #endif /* HAVE_EGL_DEVICE */ -static gboolean -meta_renderer_native_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) +static MetaRendererNativeGpuData * +meta_renderer_native_create_renderer_gpu_data (MetaRendererNative *renderer_native, + MetaGpuKms *gpu_kms, + GError **error) { - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (initable); + MetaRendererNativeGpuData *renderer_gpu_data; GError *gbm_error = NULL; #ifdef HAVE_EGL_DEVICE GError *egl_device_error = NULL; @@ -2158,16 +2268,22 @@ meta_renderer_native_initable_init (GInitable *initable, * we'll fall back to GBM (which will always succeed as it has a software * rendering fallback) */ - if (init_egl_device (renderer_native, &egl_device_error)) - return TRUE; + renderer_gpu_data = create_renderer_gpu_data_egl_device (renderer_native, + gpu_kms, + &egl_device_error); + if (renderer_gpu_data) + return renderer_gpu_data; #endif - if (init_gbm (renderer_native, &gbm_error)) + renderer_gpu_data = create_renderer_gpu_data_gbm (renderer_native, + gpu_kms, + &gbm_error); + if (renderer_gpu_data) { #ifdef HAVE_EGL_DEVICE g_error_free (egl_device_error); #endif - return TRUE; + return renderer_gpu_data; } g_set_error (error, G_IO_ERROR, @@ -2188,7 +2304,45 @@ meta_renderer_native_initable_init (GInitable *initable, g_error_free (egl_device_error); #endif - return FALSE; + return NULL; +} + +static gboolean +meta_renderer_native_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + MetaRendererNative *renderer_native = META_RENDERER_NATIVE (initable); + MetaMonitorManagerKms *monitor_manager_kms = + renderer_native->monitor_manager_kms; + MetaMonitorManager *monitor_manager = + META_MONITOR_MANAGER (monitor_manager_kms); + GList *gpus; + MetaGpuKms *gpu_kms; + MetaRendererNativeGpuData *renderer_gpu_data; + + gpus = meta_monitor_manager_get_gpus (monitor_manager); + if (g_list_length (gpus) != 1) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Renderer only supports single GPU configurations"); + return FALSE; + } + + gpu_kms = META_GPU_KMS (gpus->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 @@ -2197,9 +2351,23 @@ initable_iface_init (GInitableIface *initable_iface) initable_iface->init = meta_renderer_native_initable_init; } +static void +meta_renderer_native_finalize (GObject *object) +{ + MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); + + g_hash_table_destroy (renderer_native->gpu_datas); + + G_OBJECT_CLASS (meta_renderer_native_parent_class)->finalize (object); +} + static void meta_renderer_native_init (MetaRendererNative *renderer_native) { + renderer_native->gpu_datas = + g_hash_table_new_full (NULL, NULL, + NULL, + (GDestroyNotify) meta_renderer_native_gpu_data_free); } static void diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h index ef774cc28..a006dcbe7 100644 --- a/src/backends/native/meta-renderer-native.h +++ b/src/backends/native/meta-renderer-native.h @@ -25,10 +25,12 @@ #ifndef META_RENDERER_NATIVE_H #define META_RENDERER_NATIVE_H +#include #include #include #include "backends/meta-renderer.h" +#include "backends/native/meta-gpu-kms.h" #include "backends/native/meta-monitor-manager-kms.h" #define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ()) @@ -47,9 +49,9 @@ typedef enum _MetaRendererNativeMode MetaRendererNative * meta_renderer_native_new (MetaMonitorManagerKms *monitor_manager_kms, GError **error); -MetaRendererNativeMode meta_renderer_native_get_mode (MetaRendererNative *renderer_native); +struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms); -struct gbm_device * meta_renderer_native_get_gbm (MetaRendererNative *renderer_native); +gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native); void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native); diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c index f59c9e2b9..403d04289 100644 --- a/src/backends/x11/meta-crtc-xrandr.c +++ b/src/backends/x11/meta-crtc-xrandr.c @@ -39,6 +39,9 @@ #include #include +#include "backends/meta-crtc.h" +#include "backends/x11/meta-crtc-xrandr.h" +#include "backends/x11/meta-gpu-xrandr.h" #include "backends/x11/meta-monitor-manager-xrandr.h" #define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1) @@ -55,7 +58,9 @@ meta_crtc_xrandr_set_config (MetaCrtc *crtc, int n_outputs, xcb_timestamp_t *out_timestamp) { - MetaMonitorManager *monitor_manager = meta_crtc_get_monitor_manager (crtc); + MetaGpu *gpu = meta_crtc_get_gpu (crtc); + MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); + MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); MetaMonitorManagerXrandr *monitor_manager_xrandr = META_MONITOR_MANAGER_XRANDR (monitor_manager); Display *xdisplay; @@ -68,8 +73,7 @@ meta_crtc_xrandr_set_config (MetaCrtc *crtc, xdisplay = meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); xcb_conn = XGetXCBConnection (xdisplay); - resources = - meta_monitor_manager_xrandr_get_resources (monitor_manager_xrandr); + resources = meta_gpu_xrandr_get_resources (gpu_xrandr); config_timestamp = resources->configTimestamp; cookie = xcb_randr_set_crtc_config (xcb_conn, xrandr_crtc, @@ -168,17 +172,18 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation) } MetaCrtc * -meta_create_xrandr_crtc (MetaMonitorManager *monitor_manager, +meta_create_xrandr_crtc (MetaGpuXrandr *gpu_xrandr, XRRCrtcInfo *xrandr_crtc, RRCrtc crtc_id, XRRScreenResources *resources) { MetaCrtc *crtc; unsigned int i; + GList *modes; crtc = g_object_new (META_TYPE_CRTC, NULL); - crtc->monitor_manager = monitor_manager; + crtc->gpu = META_GPU (gpu_xrandr); crtc->crtc_id = crtc_id; crtc->rect.x = xrandr_crtc->x; crtc->rect.y = xrandr_crtc->y; @@ -190,11 +195,12 @@ meta_create_xrandr_crtc (MetaMonitorManager *monitor_manager, crtc->all_transforms = meta_monitor_transform_from_xrandr_all (xrandr_crtc->rotations); + modes = meta_gpu_get_modes (crtc->gpu); for (i = 0; i < (unsigned int) resources->nmode; i++) { if (resources->modes[i].id == xrandr_crtc->mode) { - crtc->current_mode = g_list_nth_data (monitor_manager->modes, i); + crtc->current_mode = g_list_nth_data (modes, i); break; } } diff --git a/src/backends/x11/meta-crtc-xrandr.h b/src/backends/x11/meta-crtc-xrandr.h index e74bf8adc..d38a09a55 100644 --- a/src/backends/x11/meta-crtc-xrandr.h +++ b/src/backends/x11/meta-crtc-xrandr.h @@ -26,6 +26,7 @@ #include #include "backends/meta-crtc.h" +#include "backends/x11/meta-gpu-xrandr.h" gboolean meta_crtc_xrandr_set_config (MetaCrtc *crtc, xcb_randr_crtc_t xrandr_crtc, @@ -38,7 +39,7 @@ gboolean meta_crtc_xrandr_set_config (MetaCrtc *crtc, int n_outputs, xcb_timestamp_t *out_timestamp); -MetaCrtc * meta_create_xrandr_crtc (MetaMonitorManager *monitor_manager, +MetaCrtc * meta_create_xrandr_crtc (MetaGpuXrandr *gpu_xrandr, XRRCrtcInfo *xrandr_crtc, RRCrtc crtc_id, XRRScreenResources *resources); diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c new file mode 100644 index 000000000..14b46d530 --- /dev/null +++ b/src/backends/x11/meta-gpu-xrandr.c @@ -0,0 +1,296 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2001, 2002 Havoc Pennington + * Copyright (C) 2002, 2003 Red Hat Inc. + * Some ICCCM manager selection code derived from fvwm2, + * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team + * Copyright (C) 2003 Rob Adams + * Copyright (C) 2004-2006 Elijah Newren + * Copyright (C) 2013-2017 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "config.h" + +#include "backends/x11/meta-gpu-xrandr.h" + +#include +#include +#include + +#include "backends/meta-output.h" +#include "backends/x11/meta-crtc-xrandr.h" +#include "backends/x11/meta-monitor-manager-xrandr.h" +#include "backends/x11/meta-output-xrandr.h" + +struct _MetaGpuXrandr +{ + MetaGpu parent; + + XRRScreenResources *resources; + + int max_screen_width; + int max_screen_height; +}; + +G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU) + +XRRScreenResources * +meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr) +{ + return gpu_xrandr->resources; +} + +void +meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr, + int *max_width, + int *max_height) +{ + *max_width = gpu_xrandr->max_screen_width; + *max_height = gpu_xrandr->max_screen_height; +} + +static int +compare_outputs (const void *one, + const void *two) +{ + const MetaOutput *o_one = one, *o_two = two; + + return strcmp (o_one->name, o_two->name); +} + +static char * +get_xmode_name (XRRModeInfo *xmode) +{ + int width = xmode->width; + int height = xmode->height; + + return g_strdup_printf ("%dx%d", width, height); +} + +static gboolean +meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) +{ + MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); + MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); + MetaMonitorManagerXrandr *monitor_manager_xrandr = + META_MONITOR_MANAGER_XRANDR (monitor_manager); + Display *xdisplay = + meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); + XRRScreenResources *resources; + RROutput primary_output; + unsigned int i, j; + GList *l; + int min_width, min_height; + Screen *screen; + BOOL dpms_capable, dpms_enabled; + CARD16 dpms_state; + GList *outputs = NULL; + GList *modes = NULL; + GList *crtcs = NULL; + + if (gpu_xrandr->resources) + XRRFreeScreenResources (gpu_xrandr->resources); + gpu_xrandr->resources = NULL; + + dpms_capable = DPMSCapable (xdisplay); + + if (dpms_capable && + DPMSInfo (xdisplay, &dpms_state, &dpms_enabled) && + dpms_enabled) + { + switch (dpms_state) + { + case DPMSModeOn: + monitor_manager->power_save_mode = META_POWER_SAVE_ON; + break; + case DPMSModeStandby: + monitor_manager->power_save_mode = META_POWER_SAVE_STANDBY; + break; + case DPMSModeSuspend: + monitor_manager->power_save_mode = META_POWER_SAVE_SUSPEND; + break; + case DPMSModeOff: + monitor_manager->power_save_mode = META_POWER_SAVE_OFF; + break; + default: + monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; + break; + } + } + else + { + monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; + } + + XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay), + &min_width, + &min_height, + &gpu_xrandr->max_screen_width, + &gpu_xrandr->max_screen_height); + + screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay)); + /* This is updated because we called XRRUpdateConfiguration. */ + monitor_manager->screen_width = WidthOfScreen (screen); + monitor_manager->screen_height = HeightOfScreen (screen); + + resources = XRRGetScreenResourcesCurrent (xdisplay, + DefaultRootWindow (xdisplay)); + if (!resources) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to retrieve Xrandr screen resources"); + return FALSE; + } + + gpu_xrandr->resources = resources; + + outputs = NULL; + modes = NULL; + crtcs = NULL; + + for (i = 0; i < (unsigned)resources->nmode; i++) + { + XRRModeInfo *xmode = &resources->modes[i]; + MetaCrtcMode *mode; + + mode = g_object_new (META_TYPE_CRTC_MODE, NULL); + + mode->mode_id = xmode->id; + mode->width = xmode->width; + mode->height = xmode->height; + mode->refresh_rate = (xmode->dotClock / + ((float)xmode->hTotal * xmode->vTotal)); + mode->flags = xmode->modeFlags; + mode->name = get_xmode_name (xmode); + + modes = g_list_append (modes, mode); + } + meta_gpu_take_modes (gpu, modes); + + for (i = 0; i < (unsigned)resources->ncrtc; i++) + { + XRRCrtcInfo *xrandr_crtc; + RRCrtc crtc_id; + MetaCrtc *crtc; + + crtc_id = resources->crtcs[i]; + xrandr_crtc = XRRGetCrtcInfo (xdisplay, + resources, crtc_id); + crtc = meta_create_xrandr_crtc (gpu_xrandr, + xrandr_crtc, crtc_id, resources); + XRRFreeCrtcInfo (xrandr_crtc); + + crtcs = g_list_append (crtcs, crtc); + } + + meta_gpu_take_crtcs (gpu, crtcs); + + primary_output = XRRGetOutputPrimary (xdisplay, + DefaultRootWindow (xdisplay)); + + for (i = 0; i < (unsigned)resources->noutput; i++) + { + RROutput output_id; + XRROutputInfo *xrandr_output; + + output_id = resources->outputs[i]; + xrandr_output = XRRGetOutputInfo (xdisplay, + resources, output_id); + if (!xrandr_output) + continue; + + if (xrandr_output->connection != RR_Disconnected) + { + MetaOutput *output; + + output = meta_create_xrandr_output (gpu_xrandr, + xrandr_output, + output_id, + primary_output); + if (output) + outputs = g_list_prepend (outputs, output); + } + + XRRFreeOutputInfo (xrandr_output); + } + + /* Sort the outputs for easier handling in MetaMonitorConfig */ + outputs = g_list_sort (outputs, compare_outputs); + + meta_gpu_take_outputs (gpu, outputs); + + /* Now fix the clones */ + for (l = outputs; l; l = l->next) + { + MetaOutput *output = l->data; + GList *k; + + for (j = 0; j < output->n_possible_clones; j++) + { + RROutput clone = GPOINTER_TO_INT (output->possible_clones[j]); + + for (k = outputs; k; k = k->next) + { + MetaOutput *possible_clone = k->data; + + if (clone == (XID) possible_clone->winsys_id) + { + output->possible_clones[j] = possible_clone; + break; + } + } + } + } + + return TRUE; +} + +MetaGpuXrandr * +meta_gpu_xrandr_new (MetaMonitorManagerXrandr *monitor_manager_xrandr) +{ + return g_object_new (META_TYPE_GPU_XRANDR, + "monitor-manager", monitor_manager_xrandr, + NULL); +} + +static void +meta_gpu_xrandr_finalize (GObject *object) +{ + MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (object); + + g_clear_pointer (&gpu_xrandr->resources, + XRRFreeScreenResources); + + G_OBJECT_CLASS (meta_gpu_xrandr_parent_class)->finalize (object); +} + +static void +meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr) +{ +} + +static void +meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaGpuClass *gpu_class = META_GPU_CLASS (klass); + + object_class->finalize = meta_gpu_xrandr_finalize; + + gpu_class->read_current = meta_gpu_xrandr_read_current; +} diff --git a/src/backends/x11/meta-gpu-xrandr.h b/src/backends/x11/meta-gpu-xrandr.h new file mode 100644 index 000000000..aad49d09b --- /dev/null +++ b/src/backends/x11/meta-gpu-xrandr.h @@ -0,0 +1,42 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_GPU_XRANDR_H +#define META_GPU_XRANDR_H + +#include +#include + +#include "backends/meta-gpu.h" +#include "backends/x11/meta-monitor-manager-xrandr.h" + +#define META_TYPE_GPU_XRANDR (meta_gpu_xrandr_get_type ()) +G_DECLARE_FINAL_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META, GPU_XRANDR, MetaGpu) + +XRRScreenResources * meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr); + +void meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr, + int *max_width, + int *max_height); + +MetaGpuXrandr * meta_gpu_xrandr_new (MetaMonitorManagerXrandr *monitor_manager_xrandr); + +#endif /* META_GPU_XRANDR_H */ diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c index 995ec636a..70713f4b4 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c @@ -45,6 +45,7 @@ #include "backends/meta-logical-monitor.h" #include "backends/meta-output.h" #include "backends/x11/meta-crtc-xrandr.h" +#include "backends/x11/meta-gpu-xrandr.h" #include "backends/x11/meta-output-xrandr.h" /* Look for DPI_FALLBACK in: @@ -57,19 +58,22 @@ struct _MetaMonitorManagerXrandr MetaMonitorManager parent_instance; Display *xdisplay; - XRRScreenResources *resources; int rr_event_base; int rr_error_base; gboolean has_randr15; + /* + * The X server deals with multiple GPUs for us, soe just see what the X + * server gives us as one single GPU, even though it may actually be backed + * by multiple. + */ + MetaGpu *gpu; + xcb_timestamp_t last_xrandr_set_timestamp; #ifdef HAVE_XRANDR15 GHashTable *tiled_monitor_atoms; #endif /* HAVE_XRANDR15 */ - - int max_screen_width; - int max_screen_height; }; struct _MetaMonitorManagerXrandrClass @@ -94,194 +98,12 @@ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xran return manager_xrandr->xdisplay; } -XRRScreenResources * -meta_monitor_manager_xrandr_get_resources (MetaMonitorManagerXrandr *manager_xrandr) -{ - return manager_xrandr->resources; -} - gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr) { return manager_xrandr->has_randr15; } -static int -compare_outputs (const void *one, - const void *two) -{ - const MetaOutput *o_one = one, *o_two = two; - - return strcmp (o_one->name, o_two->name); -} - -static char * -get_xmode_name (XRRModeInfo *xmode) -{ - int width = xmode->width; - int height = xmode->height; - - return g_strdup_printf ("%dx%d", width, height); -} - -static void -meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - XRRScreenResources *resources; - RROutput primary_output; - unsigned int i, j; - GList *l; - int min_width, min_height; - Screen *screen; - BOOL dpms_capable, dpms_enabled; - CARD16 dpms_state; - - if (manager_xrandr->resources) - XRRFreeScreenResources (manager_xrandr->resources); - manager_xrandr->resources = NULL; - - dpms_capable = DPMSCapable (manager_xrandr->xdisplay); - - if (dpms_capable && - DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) && - dpms_enabled) - { - switch (dpms_state) - { - case DPMSModeOn: - manager->power_save_mode = META_POWER_SAVE_ON; - break; - case DPMSModeStandby: - manager->power_save_mode = META_POWER_SAVE_STANDBY; - break; - case DPMSModeSuspend: - manager->power_save_mode = META_POWER_SAVE_SUSPEND; - break; - case DPMSModeOff: - manager->power_save_mode = META_POWER_SAVE_OFF; - break; - default: - manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; - break; - } - } - else - { - manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; - } - - XRRGetScreenSizeRange (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay), - &min_width, - &min_height, - &manager_xrandr->max_screen_width, - &manager_xrandr->max_screen_height); - - screen = ScreenOfDisplay (manager_xrandr->xdisplay, - DefaultScreen (manager_xrandr->xdisplay)); - /* This is updated because we called RRUpdateConfiguration below */ - manager->screen_width = WidthOfScreen (screen); - manager->screen_height = HeightOfScreen (screen); - - resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay)); - if (!resources) - return; - - manager_xrandr->resources = resources; - manager->outputs = NULL; - manager->modes = NULL; - manager->crtcs = NULL; - - for (i = 0; i < (unsigned)resources->nmode; i++) - { - XRRModeInfo *xmode = &resources->modes[i]; - MetaCrtcMode *mode; - - mode = g_object_new (META_TYPE_CRTC_MODE, NULL); - - mode->mode_id = xmode->id; - mode->width = xmode->width; - mode->height = xmode->height; - mode->refresh_rate = (xmode->dotClock / - ((float)xmode->hTotal * xmode->vTotal)); - mode->flags = xmode->modeFlags; - mode->name = get_xmode_name (xmode); - - manager->modes = g_list_append (manager->modes, mode); - } - - for (i = 0; i < (unsigned)resources->ncrtc; i++) - { - XRRCrtcInfo *xrandr_crtc; - RRCrtc crtc_id; - MetaCrtc *crtc; - - crtc_id = resources->crtcs[i]; - xrandr_crtc = XRRGetCrtcInfo (manager_xrandr->xdisplay, - resources, crtc_id); - crtc = meta_create_xrandr_crtc (manager, xrandr_crtc, crtc_id, resources); - XRRFreeCrtcInfo (xrandr_crtc); - - manager->crtcs = g_list_append (manager->crtcs, crtc); - } - - primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay)); - - for (i = 0; i < (unsigned)resources->noutput; i++) - { - RROutput output_id; - XRROutputInfo *xrandr_output; - - output_id = resources->outputs[i]; - xrandr_output = XRRGetOutputInfo (manager_xrandr->xdisplay, - resources, output_id); - if (!xrandr_output) - continue; - - if (xrandr_output->connection != RR_Disconnected) - { - MetaOutput *output; - - output = meta_create_xrandr_output (manager, - xrandr_output, - output_id, - primary_output); - if (output) - manager->outputs = g_list_prepend (manager->outputs, output); - } - - XRRFreeOutputInfo (xrandr_output); - } - - /* Sort the outputs for easier handling in MetaMonitorConfig */ - manager->outputs = g_list_sort (manager->outputs, compare_outputs); - - /* Now fix the clones */ - for (l = manager->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - GList *k; - - for (j = 0; j < output->n_possible_clones; j++) - { - RROutput clone = GPOINTER_TO_INT (output->possible_clones[j]); - - for (k = manager->outputs; k; k = k->next) - { - MetaOutput *possible_clone = k->data; - - if (clone == (XID) possible_clone->winsys_id) - { - output->possible_clones[j] = possible_clone; - break; - } - } - } - } -} - static GBytes * meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager, MetaOutput *output) @@ -469,9 +291,11 @@ is_assignments_changed (MetaMonitorManager *manager, MetaOutputInfo **output_infos, unsigned int n_output_infos) { + MetaMonitorManagerXrandr *manager_xrandr = + META_MONITOR_MANAGER_XRANDR (manager); GList *l; - for (l = manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (manager_xrandr->gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -479,7 +303,7 @@ is_assignments_changed (MetaMonitorManager *manager, return TRUE; } - for (l = manager->outputs; l; l = l->next) + for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next) { MetaOutput *output = l->data; @@ -564,7 +388,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable CRTCs not mentioned in the list */ - for (l = manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (manager_xrandr->gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -684,7 +508,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable outputs not mentioned in the list */ - for (l = manager->outputs; l; l = l->next) + for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next) { MetaOutput *output = l->data; @@ -1038,8 +862,8 @@ meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager, MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - *max_width = manager_xrandr->max_screen_width; - *max_height = manager_xrandr->max_screen_height; + meta_gpu_xrandr_get_max_screen_size (META_GPU_XRANDR (manager_xrandr->gpu), + max_width, max_height); return TRUE; } @@ -1061,6 +885,9 @@ meta_monitor_manager_xrandr_constructed (GObject *object) manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend); + manager_xrandr->gpu = META_GPU (meta_gpu_xrandr_new (manager_xrandr)); + meta_monitor_manager_add_gpu (manager, manager_xrandr->gpu); + if (!XRRQueryExtension (manager_xrandr->xdisplay, &manager_xrandr->rr_event_base, &manager_xrandr->rr_error_base)) @@ -1099,9 +926,7 @@ meta_monitor_manager_xrandr_finalize (GObject *object) { MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object); - if (manager_xrandr->resources) - XRRFreeScreenResources (manager_xrandr->resources); - manager_xrandr->resources = NULL; + g_clear_object (&manager_xrandr->gpu); g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); @@ -1122,7 +947,6 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) object_class->finalize = meta_monitor_manager_xrandr_finalize; object_class->constructed = meta_monitor_manager_xrandr_constructed; - manager_class->read_current = meta_monitor_manager_xrandr_read_current; manager_class->read_edid = meta_monitor_manager_xrandr_read_edid; manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config; manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config; @@ -1150,6 +974,8 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra XEvent *event) { MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); + MetaGpuXrandr *gpu_xrandr; + XRRScreenResources *resources; gboolean is_hotplug; gboolean is_our_configuration; @@ -1160,10 +986,11 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra meta_monitor_manager_read_current_state (manager); + gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu); + resources = meta_gpu_xrandr_get_resources (gpu_xrandr); - is_hotplug = (manager_xrandr->resources->timestamp < - manager_xrandr->resources->configTimestamp); - is_our_configuration = (manager_xrandr->resources->timestamp == + is_hotplug = resources->timestamp < resources->configTimestamp; + is_our_configuration = (resources->timestamp == manager_xrandr->last_xrandr_set_timestamp); if (is_hotplug) { diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h index b898b1a50..f09cbfd83 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.h +++ b/src/backends/x11/meta-monitor-manager-xrandr.h @@ -33,8 +33,6 @@ G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr); -XRRScreenResources * meta_monitor_manager_xrandr_get_resources (MetaMonitorManagerXrandr *manager_xrandr); - gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr); gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager, diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c index 608c6b673..48c8fbbb7 100644 --- a/src/backends/x11/meta-output-xrandr.c +++ b/src/backends/x11/meta-output-xrandr.c @@ -48,8 +48,8 @@ static Display * xdisplay_from_output (MetaOutput *output) { - MetaMonitorManager *monitor_manager = - meta_output_get_monitor_manager (output); + MetaGpu *gpu = meta_output_get_gpu (output); + MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); MetaMonitorManagerXrandr *monitor_manager_xrandr = META_MONITOR_MANAGER_XRANDR (monitor_manager); @@ -607,8 +607,8 @@ output_get_connector_type (MetaOutput *output) static void output_get_tile_info (MetaOutput *output) { - MetaMonitorManager *monitor_manager = - meta_output_get_monitor_manager (output); + MetaGpu *gpu = meta_output_get_gpu (output); + MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); MetaMonitorManagerXrandr *monitor_manager_xrandr = META_MONITOR_MANAGER_XRANDR (monitor_manager); Display *xdisplay = xdisplay_from_output (output); @@ -646,10 +646,10 @@ output_get_tile_info (MetaOutput *output) static void -output_get_modes (MetaMonitorManager *monitor_manager, - MetaOutput *output, - XRROutputInfo *xrandr_output) +output_get_modes (MetaOutput *output, + XRROutputInfo *xrandr_output) { + MetaGpu *gpu = meta_output_get_gpu (output); unsigned int i; unsigned int n_actual_modes; @@ -660,7 +660,7 @@ output_get_modes (MetaMonitorManager *monitor_manager, { GList *l; - for (l = monitor_manager->modes; l; l = l->next) + for (l = meta_gpu_get_modes (gpu); l; l = l->next) { MetaCrtcMode *mode = l->data; @@ -678,10 +678,10 @@ output_get_modes (MetaMonitorManager *monitor_manager, } static void -output_get_crtcs (MetaMonitorManager *monitor_manager, - MetaOutput *output, - XRROutputInfo *xrandr_output) +output_get_crtcs (MetaOutput *output, + XRROutputInfo *xrandr_output) { + MetaGpu *gpu = meta_output_get_gpu (output); unsigned int i; unsigned int n_actual_crtcs; GList *l; @@ -691,7 +691,7 @@ output_get_crtcs (MetaMonitorManager *monitor_manager, n_actual_crtcs = 0; for (i = 0; i < (unsigned int) xrandr_output->ncrtc; i++) { - for (l = monitor_manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -706,7 +706,7 @@ output_get_crtcs (MetaMonitorManager *monitor_manager, output->n_possible_crtcs = n_actual_crtcs; output->crtc = NULL; - for (l = monitor_manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -719,17 +719,17 @@ output_get_crtcs (MetaMonitorManager *monitor_manager, } MetaOutput * -meta_create_xrandr_output (MetaMonitorManager *monitor_manager, - XRROutputInfo *xrandr_output, - RROutput output_id, - RROutput primary_output) +meta_create_xrandr_output (MetaGpuXrandr *gpu_xrandr, + XRROutputInfo *xrandr_output, + RROutput output_id, + RROutput primary_output) { MetaOutput *output; GBytes *edid; unsigned int i; output = g_object_new (META_TYPE_OUTPUT, NULL); - output->monitor_manager = monitor_manager; + output->gpu = META_GPU (gpu_xrandr); output->winsys_id = output_id; output->name = g_strdup (xrandr_output->name); @@ -746,8 +746,8 @@ meta_create_xrandr_output (MetaMonitorManager *monitor_manager, output->connector_type = output_get_connector_type (output); output_get_tile_info (output); - output_get_modes (monitor_manager, output, xrandr_output); - output_get_crtcs (monitor_manager, output, xrandr_output); + output_get_modes (output, xrandr_output); + output_get_crtcs (output, xrandr_output); output->n_possible_clones = xrandr_output->nclone; output->possible_clones = g_new0 (MetaOutput *, diff --git a/src/backends/x11/meta-output-xrandr.h b/src/backends/x11/meta-output-xrandr.h index 3a263a4fd..6c97b8486 100644 --- a/src/backends/x11/meta-output-xrandr.h +++ b/src/backends/x11/meta-output-xrandr.h @@ -25,6 +25,7 @@ #include #include "backends/meta-output.h" +#include "backends/x11/meta-gpu-xrandr.h" #include "backends/x11/meta-monitor-manager-xrandr.h" void meta_output_xrandr_apply_mode (MetaOutput *output); @@ -34,9 +35,9 @@ void meta_output_xrandr_change_backlight (MetaOutput *output, GBytes * meta_output_xrandr_read_edid (MetaOutput *output); -MetaOutput * meta_create_xrandr_output (MetaMonitorManager *monitor_manager, - XRROutputInfo *xrandr_output, - RROutput output_id, - RROutput primary_output); +MetaOutput * meta_create_xrandr_output (MetaGpuXrandr *gpu_xrandr, + XRROutputInfo *xrandr_output, + RROutput output_id, + RROutput primary_output); #endif /* META_OUTPUT_XRANDR */ diff --git a/src/tests/headless-start-test.c b/src/tests/headless-start-test.c index 2e356c0e7..29a4f002d 100644 --- a/src/tests/headless-start-test.c +++ b/src/tests/headless-start-test.c @@ -57,10 +57,16 @@ meta_test_headless_start (void) MetaBackend *backend = meta_get_backend (); MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); + GList *gpus; + MetaGpu *gpu; - g_assert_null (monitor_manager->modes); - g_assert_null (monitor_manager->outputs); - g_assert_null (monitor_manager->crtcs); + gpus = meta_monitor_manager_get_gpus (monitor_manager); + g_assert_cmpint ((int) g_list_length (gpus), ==, 1); + + gpu = gpus->data; + g_assert_null (meta_gpu_get_modes (gpu)); + g_assert_null (meta_gpu_get_outputs (gpu)); + g_assert_null (meta_gpu_get_crtcs (gpu)); g_assert_null (monitor_manager->monitors); g_assert_null (monitor_manager->logical_monitors); diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c index 44187ee2e..5e1c56ec3 100644 --- a/src/tests/meta-monitor-manager-test.c +++ b/src/tests/meta-monitor-manager-test.c @@ -23,6 +23,7 @@ #include "backends/meta-backend-private.h" #include "backends/meta-crtc.h" +#include "backends/meta-gpu.h" #include "backends/meta-monitor-config-manager.h" #include "backends/meta-output.h" @@ -30,6 +31,8 @@ struct _MetaMonitorManagerTest { MetaMonitorManager parent; + MetaGpu *gpu; + gboolean is_lid_closed; gboolean handles_transforms; @@ -41,6 +44,13 @@ struct _MetaMonitorManagerTest G_DEFINE_TYPE (MetaMonitorManagerTest, meta_monitor_manager_test, META_TYPE_MONITOR_MANAGER) +struct _MetaGpuTest +{ + MetaGpu parent; +}; + +G_DEFINE_TYPE (MetaGpuTest, meta_gpu_test, META_TYPE_GPU) + static MetaMonitorTestSetup *_initial_test_setup = NULL; void @@ -49,6 +59,12 @@ meta_monitor_manager_test_init_test_setup (MetaMonitorTestSetup *test_setup) _initial_test_setup = test_setup; } +MetaGpu * +meta_monitor_manager_test_get_gpu (MetaMonitorManagerTest *manager_test) +{ + return manager_test->gpu; +} + void meta_monitor_manager_test_emulate_hotplug (MetaMonitorManagerTest *manager_test, MetaMonitorTestSetup *test_setup) @@ -91,20 +107,24 @@ static void meta_monitor_manager_test_read_current (MetaMonitorManager *manager) { MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager); + MetaGpu *gpu = manager_test->gpu; GList *l; g_assert (manager_test->test_setup); for (l = manager_test->test_setup->outputs; l; l = l->next) - META_OUTPUT (l->data)->monitor_manager = manager; + META_OUTPUT (l->data)->gpu = gpu; for (l = manager_test->test_setup->crtcs; l; l = l->next) - META_CRTC (l->data)->monitor_manager = manager; + META_CRTC (l->data)->gpu = gpu; - manager->modes = manager_test->test_setup->modes; + meta_gpu_take_modes (manager_test->gpu, + manager_test->test_setup->modes); - manager->crtcs = manager_test->test_setup->crtcs; + meta_gpu_take_crtcs (manager_test->gpu, + manager_test->test_setup->crtcs); - manager->outputs = manager_test->test_setup->outputs; + meta_gpu_take_outputs (manager_test->gpu, + manager_test->test_setup->outputs); } static gboolean @@ -139,6 +159,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, MetaOutputInfo **outputs, unsigned int n_outputs) { + MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager); GList *l; unsigned int i; @@ -204,7 +225,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable CRTCs not mentioned in the list */ - for (l = manager->crtcs; l; l = l->next) + for (l = meta_gpu_get_crtcs (manager_test->gpu); l; l = l->next) { MetaCrtc *crtc = l->data; @@ -224,7 +245,7 @@ apply_crtc_assignments (MetaMonitorManager *manager, } /* Disable outputs not mentioned in the list */ - for (l = manager->outputs; l; l = l->next) + for (l = meta_gpu_get_outputs (manager_test->gpu); l; l = l->next) { MetaOutput *output = l->data; @@ -453,11 +474,18 @@ meta_monitor_manager_test_dispose (GObject *object) static void meta_monitor_manager_test_init (MetaMonitorManagerTest *manager_test) { + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_test); + g_assert (_initial_test_setup); manager_test->handles_transforms = TRUE; manager_test->test_setup = _initial_test_setup; + + manager_test->gpu = g_object_new (META_TYPE_GPU_TEST, + "monitor-manager", manager, + NULL); + meta_monitor_manager_add_gpu (manager, manager_test->gpu); } static void @@ -468,7 +496,6 @@ meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass) object_class->dispose = meta_monitor_manager_test_dispose; - manager_class->read_current = meta_monitor_manager_test_read_current; manager_class->is_lid_closed = meta_monitor_manager_test_is_lid_closed; manager_class->ensure_initial_config = meta_monitor_manager_test_ensure_initial_config; manager_class->apply_monitors_config = meta_monitor_manager_test_apply_monitors_config; @@ -481,3 +508,27 @@ meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass) manager_class->get_max_screen_size = meta_monitor_manager_test_get_max_screen_size; manager_class->get_default_layout_mode = meta_monitor_manager_test_get_default_layout_mode; } + +static gboolean +meta_gpu_test_read_current (MetaGpu *gpu, + GError **error) +{ + MetaMonitorManager *manager = meta_gpu_get_monitor_manager (gpu); + + meta_monitor_manager_test_read_current (manager); + + return TRUE; +} + +static void +meta_gpu_test_init (MetaGpuTest *gpu_test) +{ +} + +static void +meta_gpu_test_class_init (MetaGpuTestClass *klass) +{ + MetaGpuClass *gpu_class = META_GPU_CLASS (klass); + + gpu_class->read_current = meta_gpu_test_read_current; +} diff --git a/src/tests/meta-monitor-manager-test.h b/src/tests/meta-monitor-manager-test.h index 1d3b2e362..29dfa82a2 100644 --- a/src/tests/meta-monitor-manager-test.h +++ b/src/tests/meta-monitor-manager-test.h @@ -20,6 +20,7 @@ #ifndef META_MONITOR_MANAGER_TEST_H #define META_MONITOR_MANAGER_TEST_H +#include "backends/meta-gpu.h" #include "backends/meta-monitor-manager-private.h" typedef struct _MetaMonitorTestSetup @@ -38,8 +39,13 @@ typedef struct _MetaOutputTest G_DECLARE_FINAL_TYPE (MetaMonitorManagerTest, meta_monitor_manager_test, META, MONITOR_MANAGER_TEST, MetaMonitorManager) +#define META_TYPE_GPU_TEST (meta_gpu_test_get_type ()) +G_DECLARE_FINAL_TYPE (MetaGpuTest, meta_gpu_test, META, GPU_TEST, MetaGpu) + void meta_monitor_manager_test_init_test_setup (MetaMonitorTestSetup *test_setup); +MetaGpu * meta_monitor_manager_test_get_gpu (MetaMonitorManagerTest *manager_test); + void meta_monitor_manager_test_emulate_hotplug (MetaMonitorManagerTest *manager_test, MetaMonitorTestSetup *test_setup); diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c index 9baa1777b..4683ce098 100644 --- a/src/tests/monitor-unit-tests.c +++ b/src/tests/monitor-unit-tests.c @@ -368,9 +368,12 @@ static MetaOutput * output_from_winsys_id (MetaMonitorManager *monitor_manager, long winsys_id) { + MetaMonitorManagerTest *monitor_manager_test = + META_MONITOR_MANAGER_TEST (monitor_manager); + MetaGpu *gpu = meta_monitor_manager_test_get_gpu (monitor_manager_test); GList *l; - for (l = monitor_manager->outputs; l; l = l->next) + for (l = meta_gpu_get_outputs (gpu); l; l = l->next) { MetaOutput *output = l->data; @@ -402,17 +405,22 @@ check_monitor_mode (MetaMonitor *monitor, output = output_from_winsys_id (monitor_manager, data->expect_crtc_mode_iter->output); + g_assert (monitor_crtc_mode->output == output); + expect_crtc_mode_index = data->expect_crtc_mode_iter->crtc_mode; if (expect_crtc_mode_index == -1) - crtc_mode = NULL; + { + crtc_mode = NULL; + } else - crtc_mode = g_list_nth_data (monitor_manager->modes, - expect_crtc_mode_index); + { + MetaGpu *gpu = meta_output_get_gpu (output); - g_assert (monitor_crtc_mode->output == output); + crtc_mode = g_list_nth_data (meta_gpu_get_modes (gpu), + expect_crtc_mode_index); + } g_assert (monitor_crtc_mode->crtc_mode == crtc_mode); - if (crtc_mode) { float refresh_rate; @@ -607,6 +615,7 @@ check_monitor_configuration (MonitorTestCase *test_case) meta_backend_get_monitor_manager (backend); MetaMonitorManagerTest *monitor_manager_test = META_MONITOR_MANAGER_TEST (monitor_manager); + MetaGpu *gpu = meta_monitor_manager_test_get_gpu (monitor_manager_test); int tiled_monitor_count; GList *monitors; GList *crtcs; @@ -620,10 +629,10 @@ check_monitor_configuration (MonitorTestCase *test_case) g_assert_cmpint (monitor_manager->screen_height, ==, test_case->expect.screen_height); - g_assert_cmpint ((int) g_list_length (monitor_manager->outputs), + g_assert_cmpint ((int) g_list_length (meta_gpu_get_outputs (gpu)), ==, test_case->expect.n_outputs); - g_assert_cmpint ((int) g_list_length (monitor_manager->crtcs), + g_assert_cmpint ((int) g_list_length (meta_gpu_get_crtcs (gpu)), ==, test_case->expect.n_crtcs); @@ -789,7 +798,7 @@ check_monitor_configuration (MonitorTestCase *test_case) } g_assert_cmpint (n_logical_monitors, ==, i); - crtcs = meta_monitor_manager_get_crtcs (monitor_manager); + crtcs = meta_gpu_get_crtcs (gpu); for (l = crtcs, i = 0; l; l = l->next, i++) { MetaCrtc *crtc = l->data; @@ -805,7 +814,7 @@ check_monitor_configuration (MonitorTestCase *test_case) int crtc_x, crtc_y; expected_current_mode = - g_list_nth_data (monitor_manager->modes, + g_list_nth_data (meta_gpu_get_modes (gpu), test_case->expect.crtcs[i].current_mode); g_assert (crtc->current_mode == expected_current_mode);