summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2015-04-27 17:42:10 -0700
committerJasper St. Pierre <jstpierre@mecheye.net>2015-04-27 17:58:38 -0700
commit48bf807430550a6c603ecde6c87536e78f1bd25b (patch)
treede6954d647c1ff2ba801c4b469546e2c058bf978
parentc68e43a97f544b9d3a7845a3a7e1e21ebd638dec (diff)
monitor-manager-kms: Add support for underscan
-rw-r--r--src/backends/meta-monitor-manager-private.h3
-rw-r--r--src/backends/meta-monitor-manager.c24
-rw-r--r--src/backends/native/meta-monitor-manager-kms.c110
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 04ffcf4e..460c789e 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 4ebe8002..90eba480 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 a756b862..999a8980 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 */