[mutter] monitor: Add monitor modes abstraction



commit a6f464a6000d1ec23fa8b84f477327721b197993
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Dec 14 17:22:07 2016 +0800

    monitor: Add monitor modes abstraction
    
    Add "monitor modes" abstracting the modes set on a monitor. On normal
    monitors, this directly maps to the CRTC modes, but on tiled monitors,
    a monitor mode can consist modes per tiled output.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=777732

 src/backends/meta-monitor.c |  221 ++++++++++++++++++++++++++++++++++++++-----
 src/backends/meta-monitor.h |   28 ++++++
 2 files changed, 226 insertions(+), 23 deletions(-)
---
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index 32c0fcf..9fad8b6 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -26,9 +26,18 @@
 #include "backends/meta-backend-private.h"
 #include "backends/meta-monitor-manager-private.h"
 
+typedef struct _MetaMonitorMode
+{
+  int width;
+  int height;
+  float refresh_rate;
+  MetaMonitorCrtcMode *crtc_modes;
+} MetaMonitorMode;
+
 typedef struct _MetaMonitorPrivate
 {
   GList *outputs;
+  GList *modes;
 
   /*
    * The primary or first output for this monitor, 0 if we can't figure out.
@@ -62,6 +71,9 @@ struct _MetaMonitorTiled
 
 G_DEFINE_TYPE (MetaMonitorTiled, meta_monitor_tiled, META_TYPE_MONITOR)
 
+static void
+meta_monitor_mode_free (MetaMonitorMode *mode);
+
 GList *
 meta_monitor_get_outputs (MetaMonitor *monitor)
 {
@@ -131,6 +143,7 @@ meta_monitor_finalize (GObject *object)
   MetaMonitor *monitor = META_MONITOR (object);
   MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
 
+  g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
   g_clear_pointer (&priv->outputs, g_list_free);
 }
 
@@ -147,6 +160,37 @@ meta_monitor_class_init (MetaMonitorClass *klass)
   object_class->finalize = meta_monitor_finalize;
 }
 
+static void
+meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
+{
+  MetaMonitor *monitor = META_MONITOR (monitor_normal);
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+  MetaOutput *output;
+  unsigned int i;
+
+  output = meta_monitor_get_main_output (monitor);
+  for (i = 0; i < output->n_modes; i++)
+    {
+      MetaCrtcMode *crtc_mode = output->modes[i];
+      MetaMonitorMode *mode;
+
+      mode = g_new0 (MetaMonitorMode, 1);
+      mode->width = crtc_mode->width;
+      mode->height = crtc_mode->height;
+      mode->refresh_rate = crtc_mode->refresh_rate;
+      mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
+      mode->crtc_modes[0] = (MetaMonitorCrtcMode) {
+        .x = 0,
+        .y = 0,
+        .output = output,
+        .crtc_mode = crtc_mode
+      };
+
+      monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
+    }
+}
+
 MetaMonitorNormal *
 meta_monitor_normal_new (MetaOutput *output)
 {
@@ -160,6 +204,8 @@ meta_monitor_normal_new (MetaOutput *output)
   monitor_priv->outputs = g_list_append (NULL, output);
   monitor_priv->winsys_id = output->winsys_id;
 
+  meta_monitor_normal_generate_modes (monitor_normal);
+
   return monitor_normal;
 }
 
@@ -223,6 +269,104 @@ add_tiled_monitor_outputs (MetaMonitorManager *monitor_manager,
     }
 }
 
+static void
+calculate_tile_coordinate (MetaMonitor *monitor,
+                           MetaOutput  *output,
+                           int         *out_x,
+                           int         *out_y)
+{
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+  GList *l;
+  int x = 0;
+  int y = 0;
+
+  for (l = monitor_priv->outputs; l; l = l->next)
+    {
+      MetaOutput *other_output = l->data;
+
+      if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
+          other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
+        x += other_output->tile_info.tile_w;
+      if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
+          other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
+        y += other_output->tile_info.tile_h;
+    }
+
+  *out_x = x;
+  *out_y = y;
+}
+
+static void
+meta_monitor_tiled_calculate_tiled_size (MetaMonitor *monitor,
+                                         int         *out_width,
+                                         int         *out_height)
+{
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+  GList *l;
+  int width;
+  int height;
+
+  width = 0;
+  height = 0;
+  for (l = monitor_priv->outputs; l; l = l->next)
+    {
+      MetaOutput *output = l->data;
+
+      if (output->tile_info.loc_v_tile == 0)
+        width += output->tile_info.tile_w;
+
+      if (output->tile_info.loc_h_tile == 0)
+        height += output->tile_info.tile_h;
+    }
+
+  *out_width = width;
+  *out_height = height;
+}
+
+static void
+meta_monitor_tiled_generate_modes (MetaMonitorTiled *monitor_tiled)
+{
+  MetaMonitor *monitor = META_MONITOR (monitor_tiled);
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+  MetaMonitorMode *mode;
+  GList *l;
+  int i;
+
+  mode = g_new0 (MetaMonitorMode, 1);
+  meta_monitor_tiled_calculate_tiled_size (monitor,
+                                           &mode->width, &mode->height);
+  mode->crtc_modes = g_new (MetaMonitorCrtcMode,
+                            g_list_length (monitor_priv->outputs));
+  for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
+    {
+      MetaOutput *output = l->data;
+      MetaCrtcMode *preferred_crtc_mode = output->preferred_mode;
+      int x;
+      int y;
+
+      calculate_tile_coordinate (monitor, output, &x, &y);
+
+      mode->crtc_modes[i] = (MetaMonitorCrtcMode) {
+        .x = x,
+        .y = y,
+        .output = output,
+        .crtc_mode = preferred_crtc_mode
+      };
+
+      g_warn_if_fail (mode->refresh_rate == 0.0f ||
+                      mode->refresh_rate == preferred_crtc_mode->refresh_rate);
+
+      mode->refresh_rate = preferred_crtc_mode->refresh_rate;
+    }
+
+  monitor_priv->modes = g_list_append (monitor_priv->modes, mode);
+
+  /* TODO: Add single tile modes */
+}
+
 MetaMonitorTiled *
 meta_monitor_tiled_new (MetaMonitorManager *monitor_manager,
                         MetaOutput         *output)
@@ -243,6 +387,8 @@ meta_monitor_tiled_new (MetaMonitorManager *monitor_manager,
   meta_monitor_manager_tiled_monitor_added (monitor_manager,
                                             META_MONITOR (monitor_tiled));
 
+  meta_monitor_tiled_generate_modes (monitor_tiled);
+
   return monitor_tiled;
 }
 
@@ -256,30 +402,10 @@ meta_monitor_tiled_get_main_output (MetaMonitor *monitor)
 
 static void
 meta_monitor_tiled_get_dimensions (MetaMonitor   *monitor,
-                                   int           *out_width,
-                                   int           *out_height)
+                                   int           *width,
+                                   int           *height)
 {
-  MetaMonitorPrivate *monitor_priv =
-    meta_monitor_get_instance_private (monitor);
-  GList *l;
-  int width;
-  int height;
-
-  width = 0;
-  height = 0;
-  for (l = monitor_priv->outputs; l; l = l->next)
-    {
-      MetaOutput *output = l->data;
-
-      if (output->tile_info.loc_v_tile == 0)
-        width += output->tile_info.tile_w;
-
-      if (output->tile_info.loc_h_tile == 0)
-        height += output->tile_info.tile_h;
-    }
-
-  *out_width = width;
-  *out_height = height;
+  meta_monitor_tiled_calculate_tiled_size (monitor, width, height);
 }
 
 static void
@@ -310,3 +436,52 @@ meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass)
   monitor_class->get_main_output = meta_monitor_tiled_get_main_output;
   monitor_class->get_dimensions = meta_monitor_tiled_get_dimensions;
 }
+
+static void
+meta_monitor_mode_free (MetaMonitorMode *monitor_mode)
+{
+  g_free (monitor_mode->crtc_modes);
+  g_free (monitor_mode);
+}
+
+GList *
+meta_monitor_get_modes (MetaMonitor *monitor)
+{
+  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
+
+  return priv->modes;
+}
+
+void
+meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
+                                  int             *width,
+                                  int             *height)
+{
+  *width = monitor_mode->width;
+  *height = monitor_mode->height;
+}
+
+float
+meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode)
+{
+  return monitor_mode->refresh_rate;
+}
+
+void
+meta_monitor_mode_foreach_crtc (MetaMonitor        *monitor,
+                                MetaMonitorMode    *mode,
+                                MetaMonitorModeFunc func,
+                                gpointer            user_data)
+{
+  MetaMonitorPrivate *monitor_priv =
+    meta_monitor_get_instance_private (monitor);
+  GList *l;
+  int i;
+
+  for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
+    {
+      MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
+
+      func (monitor, mode, monitor_crtc_mode, user_data);
+    }
+}
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index 50d5105..fc8511b 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -26,6 +26,21 @@
 
 #include "backends/meta-monitor-manager-private.h"
 
+typedef struct _MetaMonitorMode MetaMonitorMode;
+
+typedef struct _MetaMonitorCrtcMode
+{
+  int x;
+  int y;
+  MetaOutput *output;
+  MetaCrtcMode *crtc_mode;
+} MetaMonitorCrtcMode;
+
+typedef void (* MetaMonitorModeFunc) (MetaMonitor         *monitor,
+                                      MetaMonitorMode     *mode,
+                                      MetaMonitorCrtcMode *monitor_crtc_mode,
+                                      gpointer             user_data);
+
 #define META_TYPE_MONITOR (meta_monitor_get_type ())
 G_DECLARE_DERIVABLE_TYPE (MetaMonitor, meta_monitor, META, MONITOR, GObject)
 
@@ -74,4 +89,17 @@ const char * meta_monitor_get_product (MetaMonitor *monitor);
 
 uint32_t meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled);
 
+GList * meta_monitor_get_modes (MetaMonitor *monitor);
+
+void meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
+                                       int             *width,
+                                       int             *height);
+
+float meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode);
+
+void meta_monitor_mode_foreach_crtc (MetaMonitor        *monitor,
+                                     MetaMonitorMode    *mode,
+                                     MetaMonitorModeFunc func,
+                                     gpointer            user_data);
+
 #endif /* META_MONITOR_H */


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