mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 17:10:40 -05:00
backends: Compare gpu/crtc/output configurations before applying
This spares us from visible flickering whenever an unchanged configuration is reapplied, eg. after lid open. The code in the X11 paths that did the same comparisons has been removed in favor of the generic checks. https://bugzilla.gnome.org/show_bug.cgi?id=791879
This commit is contained in:
parent
bcfac0d6dc
commit
18c85c9ffb
@ -388,4 +388,10 @@ gboolean meta_monitor_has_aspect_as_size (MetaMonitor *monitor);
|
||||
char * meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager,
|
||||
const char *vendor);
|
||||
|
||||
gboolean meta_monitor_manager_get_has_changed (MetaMonitorManager *manager,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos,
|
||||
MetaOutputInfo **output_infos,
|
||||
unsigned int n_output_infos);
|
||||
|
||||
#endif /* META_MONITOR_MANAGER_PRIVATE_H */
|
||||
|
@ -483,6 +483,158 @@ meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager)
|
||||
META_MONITOR_MANAGER_GET_CLASS (manager)->ensure_initial_config (manager);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_crtc_assignment_changed (MetaCrtc *crtc,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n_crtc_infos; i++)
|
||||
{
|
||||
MetaCrtcInfo *crtc_info = crtc_infos[i];
|
||||
unsigned int j;
|
||||
|
||||
if (crtc_info->crtc != crtc)
|
||||
continue;
|
||||
|
||||
if (crtc->current_mode != crtc_info->mode)
|
||||
return TRUE;
|
||||
|
||||
if (crtc->rect.x != crtc_info->x)
|
||||
return TRUE;
|
||||
|
||||
if (crtc->rect.y != crtc_info->y)
|
||||
return TRUE;
|
||||
|
||||
if (crtc->transform != crtc_info->transform)
|
||||
return TRUE;
|
||||
|
||||
for (j = 0; j < crtc_info->outputs->len; j++)
|
||||
{
|
||||
MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[j];
|
||||
MetaCrtc *assigned_crtc;
|
||||
|
||||
assigned_crtc = meta_output_get_assigned_crtc (output);
|
||||
if (assigned_crtc != crtc)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return crtc->current_mode != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_output_assignment_changed (MetaOutput *output,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos,
|
||||
MetaOutputInfo **output_infos,
|
||||
unsigned int n_output_infos)
|
||||
{
|
||||
MetaCrtc *assigned_crtc;
|
||||
gboolean output_is_found = FALSE;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n_output_infos; i++)
|
||||
{
|
||||
MetaOutputInfo *output_info = output_infos[i];
|
||||
|
||||
if (output_info->output != output)
|
||||
continue;
|
||||
|
||||
if (output->is_primary != output_info->is_primary)
|
||||
return TRUE;
|
||||
|
||||
if (output->is_presentation != output_info->is_presentation)
|
||||
return TRUE;
|
||||
|
||||
if (output->is_underscanning != output_info->is_underscanning)
|
||||
return TRUE;
|
||||
|
||||
output_is_found = TRUE;
|
||||
}
|
||||
|
||||
assigned_crtc = meta_output_get_assigned_crtc (output);
|
||||
|
||||
if (!output_is_found)
|
||||
return assigned_crtc != NULL;
|
||||
|
||||
for (i = 0; i < n_crtc_infos; i++)
|
||||
{
|
||||
MetaCrtcInfo *crtc_info = crtc_infos[i];
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < crtc_info->outputs->len; j++)
|
||||
{
|
||||
MetaOutput *crtc_info_output =
|
||||
((MetaOutput**) crtc_info->outputs->pdata)[j];
|
||||
|
||||
if (crtc_info_output == output &&
|
||||
crtc_info->crtc == assigned_crtc)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_assignments_changed (MetaMonitorManager *manager,
|
||||
MetaGpu *gpu,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos,
|
||||
MetaOutputInfo **output_infos,
|
||||
unsigned int n_output_infos)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaCrtc *crtc = l->data;
|
||||
|
||||
if (is_crtc_assignment_changed (crtc, crtc_infos, n_crtc_infos))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaOutput *output = l->data;
|
||||
|
||||
if (is_output_assignment_changed (output,
|
||||
crtc_infos,
|
||||
n_crtc_infos,
|
||||
output_infos,
|
||||
n_output_infos))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_manager_get_has_changed (MetaMonitorManager *manager,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos,
|
||||
MetaOutputInfo **output_infos,
|
||||
unsigned int n_output_infos)
|
||||
{
|
||||
GList *gpus;
|
||||
GList *l;
|
||||
|
||||
gpus = meta_backend_get_gpus (manager->backend);
|
||||
for (l = gpus; l; l = l->next)
|
||||
{
|
||||
if (is_assignments_changed (manager, l->data,
|
||||
crtc_infos, n_crtc_infos,
|
||||
output_infos, n_output_infos))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_monitor_manager_apply_monitors_config (MetaMonitorManager *manager,
|
||||
MetaMonitorsConfig *config,
|
||||
|
@ -77,6 +77,8 @@ struct _MetaMonitorManagerKms
|
||||
|
||||
guint hotplug_handler_id;
|
||||
guint removed_handler_id;
|
||||
|
||||
guint logical_monitors_invalid : 1;
|
||||
};
|
||||
|
||||
struct _MetaMonitorManagerKmsClass
|
||||
@ -322,6 +324,7 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager
|
||||
MetaMonitorsConfigMethod method,
|
||||
GError **error)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
GPtrArray *crtc_infos;
|
||||
GPtrArray *output_infos;
|
||||
|
||||
@ -345,6 +348,26 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!meta_monitor_manager_get_has_changed (manager,
|
||||
(MetaCrtcInfo **) crtc_infos->pdata,
|
||||
crtc_infos->len,
|
||||
(MetaOutputInfo **) output_infos->pdata,
|
||||
output_infos->len))
|
||||
{
|
||||
/* Rebuild logical monitors if invalid, i.e. after
|
||||
* meta_monitor_manager_read_current_state().
|
||||
*/
|
||||
if (manager_kms->logical_monitors_invalid)
|
||||
{
|
||||
meta_monitor_manager_rebuild (manager, config);
|
||||
manager_kms->logical_monitors_invalid = FALSE;
|
||||
}
|
||||
|
||||
g_ptr_array_free (crtc_infos, TRUE);
|
||||
g_ptr_array_free (output_infos, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
apply_crtc_assignments (manager,
|
||||
(MetaCrtcInfo **) crtc_infos->pdata,
|
||||
crtc_infos->len,
|
||||
@ -356,6 +379,7 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager
|
||||
|
||||
update_screen_size (manager, config);
|
||||
meta_monitor_manager_rebuild (manager, config);
|
||||
manager_kms->logical_monitors_invalid = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -474,6 +498,13 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
static void
|
||||
handle_hotplug_event (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
|
||||
/* read_current_state() will rebuild monitors, leaving MetaLogicalMonitors
|
||||
* with stale pointers to those. We will need to rebuild those even though
|
||||
* the configuration might not have actually changed (eg. tty switch).
|
||||
*/
|
||||
manager_kms->logical_monitors_invalid = TRUE;
|
||||
meta_monitor_manager_read_current_state (manager);
|
||||
meta_monitor_manager_on_hotplug (manager);
|
||||
}
|
||||
|
@ -240,103 +240,6 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_crtc_assignment_changed (MetaCrtc *crtc,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n_crtc_infos; i++)
|
||||
{
|
||||
MetaCrtcInfo *crtc_info = crtc_infos[i];
|
||||
unsigned int j;
|
||||
|
||||
if (crtc_info->crtc != crtc)
|
||||
continue;
|
||||
|
||||
if (crtc->current_mode != crtc_info->mode)
|
||||
return TRUE;
|
||||
|
||||
if (crtc->rect.x != crtc_info->x)
|
||||
return TRUE;
|
||||
|
||||
if (crtc->rect.y != crtc_info->y)
|
||||
return TRUE;
|
||||
|
||||
if (crtc->transform != crtc_info->transform)
|
||||
return TRUE;
|
||||
|
||||
for (j = 0; j < crtc_info->outputs->len; j++)
|
||||
{
|
||||
MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[j];
|
||||
MetaCrtc *assigned_crtc;
|
||||
|
||||
assigned_crtc = meta_output_get_assigned_crtc (output);
|
||||
if (assigned_crtc != crtc)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return crtc->current_mode != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_output_assignment_changed (MetaOutput *output,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos,
|
||||
MetaOutputInfo **output_infos,
|
||||
unsigned int n_output_infos)
|
||||
{
|
||||
MetaCrtc *assigned_crtc;
|
||||
gboolean output_is_found = FALSE;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n_output_infos; i++)
|
||||
{
|
||||
MetaOutputInfo *output_info = output_infos[i];
|
||||
|
||||
if (output_info->output != output)
|
||||
continue;
|
||||
|
||||
if (output->is_primary != output_info->is_primary)
|
||||
return TRUE;
|
||||
|
||||
if (output->is_presentation != output_info->is_presentation)
|
||||
return TRUE;
|
||||
|
||||
if (output->is_underscanning != output_info->is_underscanning)
|
||||
return TRUE;
|
||||
|
||||
output_is_found = TRUE;
|
||||
}
|
||||
|
||||
assigned_crtc = meta_output_get_assigned_crtc (output);
|
||||
|
||||
if (!output_is_found)
|
||||
return assigned_crtc != NULL;
|
||||
|
||||
for (i = 0; i < n_crtc_infos; i++)
|
||||
{
|
||||
MetaCrtcInfo *crtc_info = crtc_infos[i];
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < crtc_info->outputs->len; j++)
|
||||
{
|
||||
MetaOutput *crtc_info_output =
|
||||
((MetaOutput**) crtc_info->outputs->pdata)[j];
|
||||
|
||||
if (crtc_info_output == output &&
|
||||
crtc_info->crtc == assigned_crtc)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MetaGpu *
|
||||
meta_monitor_manager_xrandr_get_gpu (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
{
|
||||
@ -346,41 +249,6 @@ meta_monitor_manager_xrandr_get_gpu (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
return META_GPU (meta_backend_get_gpus (backend)->data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_assignments_changed (MetaMonitorManager *manager,
|
||||
MetaCrtcInfo **crtc_infos,
|
||||
unsigned int n_crtc_infos,
|
||||
MetaOutputInfo **output_infos,
|
||||
unsigned int n_output_infos)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr =
|
||||
META_MONITOR_MANAGER_XRANDR (manager);
|
||||
MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
|
||||
GList *l;
|
||||
|
||||
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaCrtc *crtc = l->data;
|
||||
|
||||
if (is_crtc_assignment_changed (crtc, crtc_infos, n_crtc_infos))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaOutput *output = l->data;
|
||||
|
||||
if (is_output_assignment_changed (output,
|
||||
crtc_infos,
|
||||
n_crtc_infos,
|
||||
output_infos,
|
||||
n_output_infos))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_crtc_assignments (MetaMonitorManager *manager,
|
||||
gboolean save_timestamp,
|
||||
@ -651,11 +519,11 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana
|
||||
* must check that our new assignment actually changes anything, otherwise
|
||||
* just update the logical state.
|
||||
*/
|
||||
if (is_assignments_changed (manager,
|
||||
(MetaCrtcInfo **) crtc_infos->pdata,
|
||||
crtc_infos->len,
|
||||
(MetaOutputInfo **) output_infos->pdata,
|
||||
output_infos->len))
|
||||
if (meta_monitor_manager_get_has_changed (manager,
|
||||
(MetaCrtcInfo **) crtc_infos->pdata,
|
||||
crtc_infos->len,
|
||||
(MetaOutputInfo **) output_infos->pdata,
|
||||
output_infos->len))
|
||||
{
|
||||
apply_crtc_assignments (manager,
|
||||
TRUE,
|
||||
|
Loading…
Reference in New Issue
Block a user