monitor-manager-kms: Add support for underscan
This commit is contained in:
parent
c68e43a97f
commit
48bf807430
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,8 +764,9 @@ 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,
|
||||||
output_kms->dpms_prop_id, state);
|
DRM_MODE_OBJECT_CONNECTOR,
|
||||||
|
output_kms->dpms_prop_id, state);
|
||||||
|
|
||||||
if (ok < 0)
|
if (ok < 0)
|
||||||
meta_warning ("Failed to set power save mode for output %s: %s\n",
|
meta_warning ("Failed to set power save mode for output %s: %s\n",
|
||||||
@ -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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user