monitor-manager-kms: Add support for underscan

This commit is contained in:
Jasper St. Pierre 2015-04-27 17:42:10 -07:00
parent c68e43a97f
commit 48bf807430
3 changed files with 122 additions and 15 deletions

View File

@ -160,6 +160,9 @@ struct _MetaCRTC
gboolean is_dirty; gboolean is_dirty;
MetaCursorReference *cursor; MetaCursorReference *cursor;
gpointer driver_private;
GDestroyNotify driver_notify;
}; };
struct _MetaMonitorMode struct _MetaMonitorMode

View File

@ -264,6 +264,21 @@ meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
g_free (old_modes); g_free (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 static void
meta_monitor_manager_finalize (GObject *object) meta_monitor_manager_finalize (GObject *object)
{ {
@ -271,8 +286,8 @@ meta_monitor_manager_finalize (GObject *object)
meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs); 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_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->monitor_infos);
g_free (manager->crtcs);
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object); 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; MetaOutput *old_outputs;
MetaCRTC *old_crtcs; MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes; 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 /* Some implementations of read_current use the existing information
* we have available, so don't free the old configuration until after * we have available, so don't free the old configuration until after
* read_current finishes. */ * read_current finishes. */
old_outputs = manager->outputs; old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs; n_old_outputs = manager->n_outputs;
old_crtcs = manager->crtcs;
n_old_crtcs = manager->n_crtcs;
old_modes = manager->modes; old_modes = manager->modes;
n_old_modes = manager->n_modes; n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
manager->serial++; manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager); META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs); meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes); 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 void

View File

@ -57,6 +57,12 @@ typedef struct {
uint32_t edid_blob_id; uint32_t edid_blob_id;
} MetaOutputKms; } MetaOutputKms;
typedef struct {
uint32_t underscan_prop_id;
uint32_t underscan_hborder_prop_id;
uint32_t underscan_vborder_prop_id;
} MetaCRTCKms;
struct _MetaMonitorManagerKms struct _MetaMonitorManagerKms
{ {
MetaMonitorManager parent_instance; MetaMonitorManager parent_instance;
@ -137,6 +143,12 @@ meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
g_slice_free (drmModeModeInfo, output->driver_private); g_slice_free (drmModeModeInfo, output->driver_private);
} }
static void
meta_crtc_destroy_notify (MetaCRTC *crtc)
{
g_free (crtc->driver_private);
}
static gboolean static gboolean
drm_mode_equal (gconstpointer one, drm_mode_equal (gconstpointer one,
gconstpointer two) gconstpointer two)
@ -181,29 +193,54 @@ drm_mode_hash (gconstpointer ptr)
} }
static void static void
find_properties (MetaMonitorManagerKms *manager_kms, find_connector_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms) MetaOutputKms *output_kms)
{ {
drmModePropertyPtr prop;
int i; int i;
for (i = 0; i < output_kms->connector->count_props; 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) if (!prop)
continue; continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) && if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0)
strcmp(prop->name, "DPMS") == 0)
output_kms->dpms_prop_id = prop->prop_id; output_kms->dpms_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_BLOB) && else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0)
strcmp (prop->name, "EDID") == 0)
output_kms->edid_blob_id = output_kms->connector->prop_values[i]; output_kms->edid_blob_id = output_kms->connector->prop_values[i];
drmModeFreeProperty (prop); 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 * static GBytes *
read_output_edid (MetaMonitorManagerKms *manager_kms, read_output_edid (MetaMonitorManagerKms *manager_kms,
MetaOutput *output) MetaOutput *output)
@ -417,6 +454,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc = &manager->crtcs[i]; 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->crtc_id = crtc->crtc_id;
meta_crtc->rect.x = crtc->x; meta_crtc->rect.x = crtc->x;
meta_crtc->rect.y = crtc->y; meta_crtc->rect.y = crtc->y;
@ -567,7 +608,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->is_presentation = FALSE; 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); edid = read_output_edid (manager_kms, meta_output);
meta_output_parse_edid (meta_output, edid); meta_output_parse_edid (meta_output, edid);
@ -723,7 +764,8 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0) if (output_kms->dpms_prop_id != 0)
{ {
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id, int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id,
DRM_MODE_OBJECT_CONNECTOR,
output_kms->dpms_prop_id, state); output_kms->dpms_prop_id, state);
if (ok < 0) if (ok < 0)
@ -748,6 +790,48 @@ crtc_free (CoglKmsCrtc *crtc)
g_slice_free (CoglKmsCrtc, crtc); g_slice_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 static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs, MetaCRTCInfo **crtcs,
@ -755,6 +839,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
unsigned int n_outputs) unsigned int n_outputs)
{ {
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
ClutterBackend *backend; ClutterBackend *backend;
CoglContext *cogl_context; CoglContext *cogl_context;
CoglDisplay *cogl_display; CoglDisplay *cogl_display;
@ -900,6 +985,9 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
output->is_primary = output_info->is_primary; output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation; 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 */ /* Disable outputs not mentioned in the list */