[mutter] monitor-manager-kms: Add support for underscan



commit 48bf807430550a6c603ecde6c87536e78f1bd25b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Apr 27 17:42:10 2015 -0700

    monitor-manager-kms: Add support for underscan

 src/backends/meta-monitor-manager-private.h    |    3 +
 src/backends/meta-monitor-manager.c            |   24 +++++-
 src/backends/native/meta-monitor-manager-kms.c |  110 +++++++++++++++++++++---
 3 files changed, 122 insertions(+), 15 deletions(-)
---
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 04ffcf4..460c789 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -160,6 +160,9 @@ struct _MetaCRTC
   gboolean is_dirty;
 
   MetaCursorReference *cursor;
+
+  gpointer driver_private;
+  GDestroyNotify driver_notify;
 };
 
 struct _MetaMonitorMode
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 4ebe800..90eba48 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -265,14 +265,29 @@ meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
 }
 
 static void
+meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs,
+                                      int       n_old_crtcs)
+{
+  int i;
+
+  for (i = 0; i < n_old_crtcs; i++)
+    {
+      if (old_crtcs[i].driver_notify)
+        old_crtcs[i].driver_notify (&old_crtcs[i]);
+    }
+
+  g_free (old_crtcs);
+}
+
+static void
 meta_monitor_manager_finalize (GObject *object)
 {
   MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
 
   meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
   meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
+  meta_monitor_manager_free_crtc_array (manager->crtcs, manager->n_crtcs);
   g_free (manager->monitor_infos);
-  g_free (manager->crtcs);
 
   G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
 }
@@ -1199,23 +1214,24 @@ meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
   MetaOutput *old_outputs;
   MetaCRTC *old_crtcs;
   MetaMonitorMode *old_modes;
-  unsigned int n_old_outputs, n_old_modes;
+  unsigned int n_old_outputs, n_old_crtcs, n_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;
   n_old_outputs = manager->n_outputs;
+  old_crtcs = manager->crtcs;
+  n_old_crtcs = manager->n_crtcs;
   old_modes = manager->modes;
   n_old_modes = manager->n_modes;
-  old_crtcs = manager->crtcs;
 
   manager->serial++;
   META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
 
   meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
   meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
-  g_free (old_crtcs);
+  meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs);
 }
 
 void
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index a756b86..999a898 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -57,6 +57,12 @@ typedef struct {
   uint32_t edid_blob_id;
 } MetaOutputKms;
 
+typedef struct {
+  uint32_t underscan_prop_id;
+  uint32_t underscan_hborder_prop_id;
+  uint32_t underscan_vborder_prop_id;
+} MetaCRTCKms;
+
 struct _MetaMonitorManagerKms
 {
   MetaMonitorManager parent_instance;
@@ -137,6 +143,12 @@ meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
   g_slice_free (drmModeModeInfo, output->driver_private);
 }
 
+static void
+meta_crtc_destroy_notify (MetaCRTC *crtc)
+{
+  g_free (crtc->driver_private);
+}
+
 static gboolean
 drm_mode_equal (gconstpointer one,
                 gconstpointer two)
@@ -181,29 +193,54 @@ drm_mode_hash (gconstpointer ptr)
 }
 
 static void
-find_properties (MetaMonitorManagerKms *manager_kms,
-                 MetaOutputKms         *output_kms)
+find_connector_properties (MetaMonitorManagerKms *manager_kms,
+                           MetaOutputKms         *output_kms)
 {
-  drmModePropertyPtr prop;
   int i;
 
   for (i = 0; i < output_kms->connector->count_props; i++)
     {
-      prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
+      drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
       if (!prop)
         continue;
 
-      if ((prop->flags & DRM_MODE_PROP_ENUM) &&
-          strcmp(prop->name, "DPMS") == 0)
+      if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0)
         output_kms->dpms_prop_id = prop->prop_id;
-      else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
-               strcmp (prop->name, "EDID") == 0)
+      else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0)
         output_kms->edid_blob_id = output_kms->connector->prop_values[i];
 
       drmModeFreeProperty (prop);
     }
 }
 
+static void
+find_crtc_properties (MetaMonitorManagerKms *manager_kms,
+                      MetaCRTC *meta_crtc)
+{
+  MetaCRTCKms *crtc_kms;
+  drmModeObjectPropertiesPtr props;
+  size_t i;
+
+  crtc_kms = meta_crtc->driver_private;
+
+  props = drmModeObjectGetProperties (manager_kms->fd, meta_crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
+  for (i = 0; i < props->count_props; i++)
+    {
+      drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, props->props[i]);
+      if (!prop)
+        continue;
+
+      if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "underscan") == 0)
+        crtc_kms->underscan_prop_id = prop->prop_id;
+      else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan hborder") == 0)
+        crtc_kms->underscan_hborder_prop_id = prop->prop_id;
+      else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan vborder") == 0)
+        crtc_kms->underscan_vborder_prop_id = prop->prop_id;
+
+      drmModeFreeProperty (prop);
+    }
+}
+
 static GBytes *
 read_output_edid (MetaMonitorManagerKms *manager_kms,
                   MetaOutput            *output)
@@ -417,6 +454,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
 
       meta_crtc = &manager->crtcs[i];
 
+      meta_crtc->driver_private = g_new (MetaCRTCKms, 1);
+      meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
+      find_crtc_properties (manager_kms, meta_crtc);
+
       meta_crtc->crtc_id = crtc->crtc_id;
       meta_crtc->rect.x = crtc->x;
       meta_crtc->rect.y = crtc->y;
@@ -567,7 +608,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
               meta_output->is_presentation = FALSE;
             }
 
-          find_properties (manager_kms, output_kms);
+          find_connector_properties (manager_kms, output_kms);
 
           edid = read_output_edid (manager_kms, meta_output);
           meta_output_parse_edid (meta_output, edid);
@@ -723,8 +764,9 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
 
       if (output_kms->dpms_prop_id != 0)
         {
-          int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
-                                               output_kms->dpms_prop_id, state);
+          int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id,
+                                             DRM_MODE_OBJECT_CONNECTOR,
+                                             output_kms->dpms_prop_id, state);
 
           if (ok < 0)
             meta_warning ("Failed to set power save mode for output %s: %s\n",
@@ -749,12 +791,55 @@ crtc_free (CoglKmsCrtc *crtc)
 }
 
 static void
+set_underscan (MetaMonitorManagerKms *manager_kms,
+               MetaOutput *output)
+{
+  if (!output->crtc)
+    return;
+
+  MetaCRTC *crtc = output->crtc;
+  MetaCRTCKms *crtc_kms = crtc->driver_private;
+  if (!crtc_kms->underscan_prop_id)
+    return;
+
+  if (output->is_underscanning)
+    {
+      drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
+                                DRM_MODE_OBJECT_CRTC,
+                                crtc_kms->underscan_prop_id, (uint64_t) 1);
+
+      if (crtc_kms->underscan_hborder_prop_id)
+        {
+          uint64_t value = crtc->current_mode->width * 0.05;
+          drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
+                                    DRM_MODE_OBJECT_CRTC,
+                                    crtc_kms->underscan_hborder_prop_id, value);
+        }
+      if (crtc_kms->underscan_vborder_prop_id)
+        {
+          uint64_t value = crtc->current_mode->height * 0.05;
+          drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
+                                    DRM_MODE_OBJECT_CRTC,
+                                    crtc_kms->underscan_vborder_prop_id, value);
+        }
+
+    }
+  else
+    {
+      drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id,
+                                DRM_MODE_OBJECT_CRTC,
+                                crtc_kms->underscan_prop_id, (uint64_t) 0);
+    }
+}
+
+static void
 meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
                                               MetaCRTCInfo       **crtcs,
                                               unsigned int         n_crtcs,
                                               MetaOutputInfo     **outputs,
                                               unsigned int         n_outputs)
 {
+  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
   ClutterBackend *backend;
   CoglContext *cogl_context;
   CoglDisplay *cogl_display;
@@ -900,6 +985,9 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
 
       output->is_primary = output_info->is_primary;
       output->is_presentation = output_info->is_presentation;
+      output->is_underscanning = output_info->is_underscanning;
+
+      set_underscan (manager_kms, output);
     }
 
   /* Disable outputs not mentioned in the list */


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