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
This commit is contained in:
Emilio Pozuelo Monfort 2018-11-12 19:46:06 +01:00 committed by Pekka Paalanen
parent f4f823f238
commit 6975c8b424

View File

@ -76,6 +76,22 @@ meta_monitor_config_manager_get_store (MetaMonitorConfigManager *config_manager)
return config_manager->config_store; return config_manager->config_store;
} }
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 static gboolean
is_crtc_assigned (MetaCrtc *crtc, is_crtc_assigned (MetaCrtc *crtc,
GPtrArray *crtc_infos) GPtrArray *crtc_infos)
@ -95,7 +111,8 @@ is_crtc_assigned (MetaCrtc *crtc,
static MetaCrtc * static MetaCrtc *
find_unassigned_crtc (MetaOutput *output, find_unassigned_crtc (MetaOutput *output,
GPtrArray *crtc_infos) GPtrArray *crtc_infos,
GArray *reserved_crtcs)
{ {
MetaCrtc *crtc; MetaCrtc *crtc;
unsigned int i; unsigned int i;
@ -104,6 +121,21 @@ find_unassigned_crtc (MetaOutput *output,
if (crtc && !is_crtc_assigned (crtc, crtc_infos)) if (crtc && !is_crtc_assigned (crtc, crtc_infos))
return crtc; 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++) for (i = 0; i < output->n_possible_crtcs; i++)
{ {
crtc = output->possible_crtcs[i]; crtc = output->possible_crtcs[i];
@ -124,6 +156,7 @@ typedef struct
MetaMonitorConfig *monitor_config; MetaMonitorConfig *monitor_config;
GPtrArray *crtc_infos; GPtrArray *crtc_infos;
GPtrArray *output_infos; GPtrArray *output_infos;
GArray *reserved_crtcs;
} MonitorAssignmentData; } MonitorAssignmentData;
static gboolean static gboolean
@ -147,7 +180,8 @@ assign_monitor_crtc (MetaMonitor *monitor,
output = monitor_crtc_mode->output; 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) if (!crtc)
{ {
MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor); MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
@ -229,6 +263,7 @@ assign_monitor_crtcs (MetaMonitorManager *manager,
MetaMonitorConfig *monitor_config, MetaMonitorConfig *monitor_config,
GPtrArray *crtc_infos, GPtrArray *crtc_infos,
GPtrArray *output_infos, GPtrArray *output_infos,
GArray *reserved_crtcs,
GError **error) GError **error)
{ {
MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec; MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
@ -262,7 +297,8 @@ assign_monitor_crtcs (MetaMonitorManager *manager,
.logical_monitor_config = logical_monitor_config, .logical_monitor_config = logical_monitor_config,
.monitor_config = monitor_config, .monitor_config = monitor_config,
.crtc_infos = crtc_infos, .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, if (!meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
assign_monitor_crtc, assign_monitor_crtc,
@ -278,6 +314,7 @@ assign_logical_monitor_crtcs (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config, MetaLogicalMonitorConfig *logical_monitor_config,
GPtrArray *crtc_infos, GPtrArray *crtc_infos,
GPtrArray *output_infos, GPtrArray *output_infos,
GArray *reserved_crtcs,
GError **error) GError **error)
{ {
GList *l; GList *l;
@ -290,7 +327,7 @@ assign_logical_monitor_crtcs (MetaMonitorManager *manager,
logical_monitor_config, logical_monitor_config,
monitor_config, monitor_config,
crtc_infos, output_infos, crtc_infos, output_infos,
error)) reserved_crtcs, error))
return FALSE; return FALSE;
} }
@ -306,12 +343,40 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager,
{ {
GPtrArray *crtc_infos; GPtrArray *crtc_infos;
GPtrArray *output_infos; GPtrArray *output_infos;
GArray *reserved_crtcs;
GList *l; GList *l;
crtc_infos = crtc_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_info_free); g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_info_free);
output_infos = output_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_info_free); 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) 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, if (!assign_logical_monitor_crtcs (manager, logical_monitor_config,
crtc_infos, output_infos, crtc_infos, output_infos,
error)) reserved_crtcs, error))
{ {
g_ptr_array_free (crtc_infos, TRUE); g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE); g_ptr_array_free (output_infos, TRUE);
g_array_free (reserved_crtcs, TRUE);
return FALSE; return FALSE;
} }
} }
g_array_free (reserved_crtcs, TRUE);
*out_crtc_infos = crtc_infos; *out_crtc_infos = crtc_infos;
*out_output_infos = output_infos; *out_output_infos = output_infos;