summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2018-01-09 21:29:26 +0100
committerCarlos Garnacho <carlosg@gnome.org>2019-09-04 16:29:04 +0200
commit18c85c9ffb23186f5e1739d31df6ceaee906893e (patch)
tree553e668367ec4e2ae3506d689b1b9dae6a9f447a
parentbcfac0d6dc68fa53db69e5d553b7bd1d1b729e89 (diff)
downloadmutter-wip/carlosg/fix-open-lid-flicker.tar.gz
backends: Compare gpu/crtc/output configurations before applyingwip/carlosg/fix-open-lid-flicker
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
-rw-r--r--src/backends/meta-monitor-manager-private.h6
-rw-r--r--src/backends/meta-monitor-manager.c152
-rw-r--r--src/backends/native/meta-monitor-manager-kms.c31
-rw-r--r--src/backends/x11/meta-monitor-manager-xrandr.c142
4 files changed, 194 insertions, 137 deletions
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 20bb6b679..dd9b25259 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -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 */
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 41036ca2a..4048249fe 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -484,6 +484,158 @@ meta_monitor_manager_ensure_initial_config (MetaMonitorManager *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,
MetaMonitorsConfigMethod method,
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 26c2ddb61..a768b74f2 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -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);
}
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 8fae335f0..6e9d142f5 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -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,