summaryrefslogtreecommitdiff
path: root/src/backends
diff options
context:
space:
mode:
authorEmilio Pozuelo Monfort <emilio.pozuelo@collabora.co.uk>2018-11-12 19:46:06 +0100
committerPekka Paalanen <pekka.paalanen@collabora.com>2019-02-21 17:23:38 +0200
commit6975c8b4245acab029c019910c0966f62bc5665c (patch)
treec73bb55166f8245e35a1046c44011f975632384e /src/backends
parentf4f823f2380b94e97f7d7952bae200ab7e791699 (diff)
downloadmutter-6975c8b4245acab029c019910c0966f62bc5665c.tar.gz
monitor-config-manager: respect other outputs' CRTC
We should not only take the old CRTC for an output whenever possible, but we should also assign one that is 'free', i.e. one that another monitor (to be processed after this one) isn't using, so that that monitor can use the same CRTC. https://gitlab.gnome.org/GNOME/mutter/issues/373
Diffstat (limited to 'src/backends')
-rw-r--r--src/backends/meta-monitor-config-manager.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index 335c3f34b..771c57fc1 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -77,6 +77,22 @@ meta_monitor_config_manager_get_store (MetaMonitorConfigManager *config_manager)
}
static gboolean
+is_crtc_reserved (MetaCrtc *crtc,
+ GArray *reserved_crtcs)
+{
+ unsigned int i;
+
+ for (i = 0; i < reserved_crtcs->len; i++)
+ {
+ glong id = g_array_index (reserved_crtcs, glong, i);
+ if (id == crtc->crtc_id)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
is_crtc_assigned (MetaCrtc *crtc,
GPtrArray *crtc_infos)
{
@@ -95,7 +111,8 @@ is_crtc_assigned (MetaCrtc *crtc,
static MetaCrtc *
find_unassigned_crtc (MetaOutput *output,
- GPtrArray *crtc_infos)
+ GPtrArray *crtc_infos,
+ GArray *reserved_crtcs)
{
MetaCrtc *crtc;
unsigned int i;
@@ -104,6 +121,21 @@ find_unassigned_crtc (MetaOutput *output,
if (crtc && !is_crtc_assigned (crtc, crtc_infos))
return crtc;
+ /* then try to assign a CRTC that wasn't used */
+ for (i = 0; i < output->n_possible_crtcs; i++)
+ {
+ crtc = output->possible_crtcs[i];
+
+ if (is_crtc_assigned (crtc, crtc_infos))
+ continue;
+
+ if (is_crtc_reserved (crtc, reserved_crtcs))
+ continue;
+
+ return crtc;
+ }
+
+ /* finally just give a CRTC that we haven't assigned */
for (i = 0; i < output->n_possible_crtcs; i++)
{
crtc = output->possible_crtcs[i];
@@ -124,6 +156,7 @@ typedef struct
MetaMonitorConfig *monitor_config;
GPtrArray *crtc_infos;
GPtrArray *output_infos;
+ GArray *reserved_crtcs;
} MonitorAssignmentData;
static gboolean
@@ -147,7 +180,8 @@ assign_monitor_crtc (MetaMonitor *monitor,
output = monitor_crtc_mode->output;
- crtc = find_unassigned_crtc (output, data->crtc_infos);
+ crtc = find_unassigned_crtc (output, data->crtc_infos, data->reserved_crtcs);
+
if (!crtc)
{
MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
@@ -229,6 +263,7 @@ assign_monitor_crtcs (MetaMonitorManager *manager,
MetaMonitorConfig *monitor_config,
GPtrArray *crtc_infos,
GPtrArray *output_infos,
+ GArray *reserved_crtcs,
GError **error)
{
MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
@@ -262,7 +297,8 @@ assign_monitor_crtcs (MetaMonitorManager *manager,
.logical_monitor_config = logical_monitor_config,
.monitor_config = monitor_config,
.crtc_infos = crtc_infos,
- .output_infos = output_infos
+ .output_infos = output_infos,
+ .reserved_crtcs = reserved_crtcs
};
if (!meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
assign_monitor_crtc,
@@ -278,6 +314,7 @@ assign_logical_monitor_crtcs (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config,
GPtrArray *crtc_infos,
GPtrArray *output_infos,
+ GArray *reserved_crtcs,
GError **error)
{
GList *l;
@@ -290,7 +327,7 @@ assign_logical_monitor_crtcs (MetaMonitorManager *manager,
logical_monitor_config,
monitor_config,
crtc_infos, output_infos,
- error))
+ reserved_crtcs, error))
return FALSE;
}
@@ -306,12 +343,40 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager,
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
+ GArray *reserved_crtcs;
GList *l;
crtc_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_info_free);
output_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_info_free);
+ reserved_crtcs = g_array_new (FALSE, FALSE, sizeof (glong));
+
+ for (l = config->logical_monitor_configs; l; l = l->next)
+ {
+ MetaLogicalMonitorConfig *logical_monitor_config = l->data;
+ GList *k;
+
+ for (k = logical_monitor_config->monitor_configs; k; k = k->next)
+ {
+ MetaMonitorConfig *monitor_config = k->data;
+ MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
+ MetaMonitor *monitor;
+ GList *o;
+
+ monitor = meta_monitor_manager_get_monitor_from_spec (manager, monitor_spec);
+
+ for (o = meta_monitor_get_outputs (monitor); o; o = o->next)
+ {
+ MetaOutput *output = o->data;
+ MetaCrtc *crtc;
+
+ crtc = meta_output_get_assigned_crtc (output);
+ if (crtc)
+ g_array_append_val (reserved_crtcs, crtc->crtc_id);
+ }
+ }
+ }
for (l = config->logical_monitor_configs; l; l = l->next)
{
@@ -319,14 +384,17 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager,
if (!assign_logical_monitor_crtcs (manager, logical_monitor_config,
crtc_infos, output_infos,
- error))
+ reserved_crtcs, error))
{
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
+ g_array_free (reserved_crtcs, TRUE);
return FALSE;
}
}
+ g_array_free (reserved_crtcs, TRUE);
+
*out_crtc_infos = crtc_infos;
*out_output_infos = output_infos;