[mutter] DisplayConfig: Add support for interlaced modes



commit 49c5228655e5004db3d1e47e7f3837ba2015764e
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Jun 14 14:41:13 2017 +0800

    DisplayConfig: Add support for interlaced modes
    
    Differentiate between non-interlaced and interlaced modes. This is done
    by appending an "i" after the resolution part of the mode ID, and
    adding a 'is-interlaced' (b) property to the mode properties.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=765011

 src/backends/meta-monitor-config-store.c    |   26 +++++++++++++++
 src/backends/meta-monitor-manager-private.h |   24 +++++++++++++-
 src/backends/meta-monitor-manager.c         |    7 ++++
 src/backends/meta-monitor.c                 |   47 ++++++++++++++++++--------
 src/backends/meta-monitor.h                 |    3 ++
 src/org.gnome.Mutter.DisplayConfig.xml      |    1 +
 src/tests/monitor-store-unit-tests.c        |    1 +
 7 files changed, 93 insertions(+), 16 deletions(-)
---
diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c
index 6ed1943..d70cdda 100644
--- a/src/backends/meta-monitor-config-store.c
+++ b/src/backends/meta-monitor-config-store.c
@@ -53,6 +53,7 @@
  *           <width>1920</width>
  *           <height>1080</height>
  *           <rate>60.049972534179688</rate>
+ *           <flag>interlace</flag>
  *         </mode>
  *       </monitor>
  *       <transform>
@@ -135,6 +136,7 @@ typedef enum
   STATE_MONITOR_MODE_WIDTH,
   STATE_MONITOR_MODE_HEIGHT,
   STATE_MONITOR_MODE_RATE,
+  STATE_MONITOR_MODE_FLAG,
   STATE_MONITOR_UNDERSCANNING
 } ParserState;
 
@@ -384,6 +386,10 @@ handle_start_element (GMarkupParseContext  *context,
           {
             parser->state = STATE_MONITOR_MODE_RATE;
           }
+        else if (g_str_equal (element_name, "flag"))
+          {
+            parser->state = STATE_MONITOR_MODE_FLAG;
+          }
         else
           {
             g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
@@ -397,6 +403,7 @@ handle_start_element (GMarkupParseContext  *context,
     case STATE_MONITOR_MODE_WIDTH:
     case STATE_MONITOR_MODE_HEIGHT:
     case STATE_MONITOR_MODE_RATE:
+    case STATE_MONITOR_MODE_FLAG:
       {
         g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                      "Invalid mode sub element '%s'", element_name);
@@ -539,6 +546,7 @@ handle_end_element (GMarkupParseContext  *context,
     case STATE_MONITOR_MODE_WIDTH:
     case STATE_MONITOR_MODE_HEIGHT:
     case STATE_MONITOR_MODE_RATE:
+    case STATE_MONITOR_MODE_FLAG:
       {
         parser->state = STATE_MONITOR_MODE;
         return;
@@ -909,6 +917,22 @@ handle_text (GMarkupParseContext *context,
         return;
       }
 
+    case STATE_MONITOR_MODE_FLAG:
+      {
+        if (strncmp (text, "interlace", text_len) == 0)
+          {
+            parser->current_monitor_mode_spec->flags |=
+              META_CRTC_MODE_FLAG_INTERLACE;
+          }
+        else
+          {
+            g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+                         "Invalid mode flag %.*s", (int) text_len, text);
+          }
+
+        return;
+      }
+
     case STATE_MONITOR_UNDERSCANNING:
       {
         read_bool (text, text_len,
@@ -1007,6 +1031,8 @@ append_monitors (GString *buffer,
                               monitor_config->mode_spec->height);
       g_string_append_printf (buffer, "          <rate>%s</rate>\n",
                               rate_str);
+      if (monitor_config->mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE)
+        g_string_append_printf (buffer, "          <flag>interlace</flag>\n");
       g_string_append (buffer, "        </mode>\n");
       if (monitor_config->enable_underscanning)
         g_string_append (buffer, "        <underscanning>yes</underscanning>\n");
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 9972bf1..fa6c9c5 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -131,6 +131,28 @@ typedef enum
   META_CONNECTOR_TYPE_DSI = 16,
 } MetaConnectorType;
 
+/* Same as KMS mode flags and X11 randr flags */
+typedef enum
+{
+  META_CRTC_MODE_FLAG_NONE = 0,
+  META_CRTC_MODE_FLAG_PHSYNC = (1 << 0),
+  META_CRTC_MODE_FLAG_NHSYNC = (1 << 1),
+  META_CRTC_MODE_FLAG_PVSYNC = (1 << 2),
+  META_CRTC_MODE_FLAG_NVSYNC = (1 << 3),
+  META_CRTC_MODE_FLAG_INTERLACE = (1 << 4),
+  META_CRTC_MODE_FLAG_DBLSCAN = (1 << 5),
+  META_CRTC_MODE_FLAG_CSYNC = (1 << 6),
+  META_CRTC_MODE_FLAG_PCSYNC = (1 << 7),
+  META_CRTC_MODE_FLAG_NCSYNC = (1 << 8),
+  META_CRTC_MODE_FLAG_HSKEW = (1 << 9),
+  META_CRTC_MODE_FLAG_BCAST = (1 << 10),
+  META_CRTC_MODE_FLAG_PIXMUX = (1 << 11),
+  META_CRTC_MODE_FLAG_DBLCLK = (1 << 12),
+  META_CRTC_MODE_FLAG_CLKDIV2 = (1 << 13),
+
+  META_CRTC_MODE_FLAG_MASK = 0x3fff
+} MetaCrtcModeFlag;
+
 struct _MetaTileInfo
 {
   guint32 group_id;
@@ -231,7 +253,7 @@ struct _MetaCrtcMode
   int width;
   int height;
   float refresh_rate;
-  guint32 flags;
+  MetaCrtcModeFlag flags;
 
   gpointer driver_private;
   GDestroyNotify driver_notify;
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index cf01096..4966b81 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -1556,6 +1556,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
           float *supported_scales;
           int n_supported_scales;
           GVariantBuilder mode_properties_builder;
+          MetaCrtcModeFlag mode_flags;
 
           mode_id = meta_monitor_mode_get_id (monitor_mode);
           meta_monitor_mode_get_resolution (monitor_mode,
@@ -1580,6 +1581,8 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
                                    (double) supported_scales[i]);
           g_free (supported_scales);
 
+          mode_flags = meta_monitor_mode_get_flags (monitor_mode);
+
           g_variant_builder_init (&mode_properties_builder,
                                   G_VARIANT_TYPE ("a{sv}"));
           if (monitor_mode == current_mode)
@@ -1590,6 +1593,10 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
             g_variant_builder_add (&mode_properties_builder, "{sv}",
                                    "is-preferred",
                                    g_variant_new_boolean (TRUE));
+          if (mode_flags & META_CRTC_MODE_FLAG_INTERLACE)
+            g_variant_builder_add (&mode_properties_builder, "{sv}",
+                                   "is-interlaced",
+                                   g_variant_new_boolean (TRUE));
 
           g_variant_builder_add (&modes_builder, MODE_FORMAT,
                                  mode_id,
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index 672fb71..7c2ba11 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -31,6 +31,8 @@
 #define MINIMUM_SCALE_FACTOR 0.5f
 #define MAXIMUM_SCALE_FACTOR 4.0f
 
+#define HANDLED_CRTC_MODE_FLAGS (META_CRTC_MODE_FLAG_INTERLACE)
+
 typedef struct _MetaMonitorMode
 {
   char *id;
@@ -360,14 +362,17 @@ meta_monitor_class_init (MetaMonitorClass *klass)
 static char *
 generate_mode_id (MetaMonitorModeSpec *monitor_mode_spec)
 {
+  gboolean is_interlaced;
   char refresh_rate_str[G_ASCII_DTOSTR_BUF_SIZE];
 
+  is_interlaced = !!(monitor_mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE);
   g_ascii_dtostr (refresh_rate_str, G_ASCII_DTOSTR_BUF_SIZE,
                   monitor_mode_spec->refresh_rate);
 
-  return g_strdup_printf ("%dx%d@%s",
+  return g_strdup_printf ("%dx%d%s@%s",
                           monitor_mode_spec->width,
                           monitor_mode_spec->height,
+                          is_interlaced ? "i" : "",
                           refresh_rate_str);
 }
 
@@ -406,7 +411,8 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
       mode->spec = (MetaMonitorModeSpec) {
         .width = crtc_mode->width,
         .height = crtc_mode->height,
-        .refresh_rate = crtc_mode->refresh_rate
+        .refresh_rate = crtc_mode->refresh_rate,
+        .flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
       },
       mode->id = generate_mode_id (&mode->spec);
       mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
@@ -674,8 +680,8 @@ is_crtc_mode_tiled (MetaOutput   *output,
 }
 
 static MetaCrtcMode *
-find_tiled_crtc_mode (MetaOutput *output,
-                      float       refresh_rate)
+find_tiled_crtc_mode (MetaOutput   *output,
+                      MetaCrtcMode *reference_crtc_mode)
 {
   MetaCrtcMode *crtc_mode;
   unsigned int i;
@@ -691,7 +697,10 @@ find_tiled_crtc_mode (MetaOutput *output,
       if (!is_crtc_mode_tiled (output, crtc_mode))
         continue;
 
-      if (crtc_mode->refresh_rate != refresh_rate)
+      if (crtc_mode->refresh_rate != reference_crtc_mode->refresh_rate)
+        continue;
+
+      if (crtc_mode->flags != reference_crtc_mode->flags)
         continue;
 
       return crtc_mode;
@@ -702,7 +711,7 @@ find_tiled_crtc_mode (MetaOutput *output,
 
 static MetaMonitorMode *
 create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
-                           float             refresh_rate,
+                           MetaCrtcMode     *reference_crtc_mode,
                            gboolean         *out_is_preferred)
 {
   MetaMonitor *monitor = META_MONITOR (monitor_tiled);
@@ -721,7 +730,8 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
   mode->parent.spec = (MetaMonitorModeSpec) {
     .width = width,
     .height = height,
-    .refresh_rate = refresh_rate,
+    .refresh_rate = reference_crtc_mode->refresh_rate,
+    .flags = reference_crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
   };
   mode->parent.id = generate_mode_id (&mode->parent.spec);
 
@@ -732,11 +742,10 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
       MetaOutput *output = l->data;
       MetaCrtcMode *tiled_crtc_mode;
 
-      tiled_crtc_mode = find_tiled_crtc_mode (output, refresh_rate);
+      tiled_crtc_mode = find_tiled_crtc_mode (output, reference_crtc_mode);
       if (!tiled_crtc_mode)
         {
-          g_warning ("No tiled mode with refresh rate %f on %s",
-                     refresh_rate, output->name);
+          g_warning ("No tiled mode found on %s", output->name);
           meta_monitor_mode_free ((MetaMonitorMode *) mode);
           return NULL;
         }
@@ -770,14 +779,14 @@ generate_tiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
 
   for (i = 0; i < main_output->n_modes; i++)
     {
-      MetaCrtcMode *crtc_mode = main_output->modes[i];
+      MetaCrtcMode *reference_crtc_mode = main_output->modes[i];
       MetaMonitorMode *mode;
       gboolean is_preferred;
 
-      if (!is_crtc_mode_tiled (main_output, crtc_mode))
+      if (!is_crtc_mode_tiled (main_output, reference_crtc_mode))
         continue;
 
-      mode = create_tiled_monitor_mode (monitor_tiled, crtc_mode->refresh_rate,
+      mode = create_tiled_monitor_mode (monitor_tiled, reference_crtc_mode,
                                         &is_preferred);
       if (!mode)
         continue;
@@ -836,7 +845,8 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
   mode->parent.spec = (MetaMonitorModeSpec) {
     .width = crtc_mode->width,
     .height = crtc_mode->height,
-    .refresh_rate = crtc_mode->refresh_rate
+    .refresh_rate = crtc_mode->refresh_rate,
+    .flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
   };
   mode->parent.id = generate_mode_id (&mode->parent.spec);
   mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
@@ -1224,7 +1234,8 @@ meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec,
   return (monitor_mode_spec->width == other_monitor_mode_spec->width &&
           monitor_mode_spec->height == other_monitor_mode_spec->height &&
           (monitor_mode_spec->refresh_rate ==
-           other_monitor_mode_spec->refresh_rate));
+           other_monitor_mode_spec->refresh_rate) &&
+          monitor_mode_spec->flags == other_monitor_mode_spec->flags);
 }
 
 MetaMonitorMode *
@@ -1543,6 +1554,12 @@ meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode)
   return monitor_mode->spec.refresh_rate;
 }
 
+MetaCrtcModeFlag
+meta_monitor_mode_get_flags (MetaMonitorMode *monitor_mode)
+{
+  return monitor_mode->spec.flags;
+}
+
 gboolean
 meta_monitor_mode_foreach_crtc (MetaMonitor        *monitor,
                                 MetaMonitorMode    *mode,
diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h
index 7390361..fa9654b 100644
--- a/src/backends/meta-monitor.h
+++ b/src/backends/meta-monitor.h
@@ -39,6 +39,7 @@ typedef struct _MetaMonitorModeSpec
   int width;
   int height;
   float refresh_rate;
+  MetaCrtcModeFlag flags;
 } MetaMonitorModeSpec;
 
 typedef struct _MetaMonitorCrtcMode
@@ -187,6 +188,8 @@ void meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
 
 float meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode);
 
+MetaCrtcModeFlag meta_monitor_mode_get_flags (MetaMonitorMode *monitor_mode);
+
 gboolean meta_monitor_mode_foreach_crtc (MetaMonitor        *monitor,
                                          MetaMonitorMode    *mode,
                                          MetaMonitorModeFunc func,
diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml
index 30a8e97..015face 100644
--- a/src/org.gnome.Mutter.DisplayConfig.xml
+++ b/src/org.gnome.Mutter.DisplayConfig.xml
@@ -325,6 +325,7 @@
            * a{sv} properties: optional properties, including:
               - "is-current" (b): the mode is currently active mode
               - "is-preferred" (b): the mode is the preferred mode
+              - "is-interlaced" (b): the mode is an interlaced mode
        * a{sv} properties: optional properties, including:
            - "width-mm" (i): physical width of monitor in millimeters
            - "height-mm" (i): physical height of monitor in millimeters
diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c
index 18e4fa5..4e1c220 100644
--- a/src/tests/monitor-store-unit-tests.c
+++ b/src/tests/monitor-store-unit-tests.c
@@ -36,6 +36,7 @@ typedef struct _MonitorTestCaseMonitorMode
   int width;
   int height;
   float refresh_rate;
+  MetaCrtcModeFlag flags;
 } MonitorTestCaseMonitorMode;
 
 typedef struct _MonitorTestCaseMonitor


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