From 44a4e616658edb2a21a9612cfd3a41742a1ca427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 4 Mar 2021 19:11:12 +0100 Subject: [PATCH] compositor/x11: Notify the sync ring about frames on updates The sync ring has an API about "frames", where it is notified about the end of frames. However, its "insert wait" call is done before updates, meaning that some "insert waits" will never see the "after frame" if there was no frame drawn. This will cause mismatching in the frame counting, causing freezes in the synchronization until something else triggers an actual frame, effectively "unfreezing" the sync ring. Fix this by not only notifying the sync ring about frames when there were actual frames drawn, but also on plain updates which didn't result in a drawn frame. Related: https://gitlab.gnome.org/GNOME/mutter/-/issues/1516 Part-of: --- src/compositor/meta-compositor-x11.c | 41 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c index 27999fbae..1d0ba4c8d 100644 --- a/src/compositor/meta-compositor-x11.c +++ b/src/compositor/meta-compositor-x11.c @@ -40,6 +40,7 @@ struct _MetaCompositorX11 Window output; gulong before_update_handler_id; + gulong after_update_handler_id; gboolean frame_has_updated_xsurfaces; gboolean have_x11_sync_object; @@ -362,6 +363,22 @@ on_before_update (ClutterStage *stage, } } +static void +on_after_update (ClutterStage *stage, + ClutterStageView *stage_view, + MetaCompositor *compositor) +{ + MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); + + if (compositor_x11->frame_has_updated_xsurfaces) + { + if (compositor_x11->have_x11_sync_object) + compositor_x11->have_x11_sync_object = meta_sync_ring_after_frame (); + + compositor_x11->frame_has_updated_xsurfaces = FALSE; + } +} + static void meta_compositor_x11_before_paint (MetaCompositor *compositor, ClutterStageView *stage_view) @@ -375,25 +392,6 @@ meta_compositor_x11_before_paint (MetaCompositor *compositor, parent_class->before_paint (compositor, stage_view); } -static void -meta_compositor_x11_after_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - MetaCompositorClass *parent_class; - - if (compositor_x11->frame_has_updated_xsurfaces) - { - if (compositor_x11->have_x11_sync_object) - compositor_x11->have_x11_sync_object = meta_sync_ring_after_frame (); - - compositor_x11->frame_has_updated_xsurfaces = FALSE; - } - - parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class); - parent_class->after_paint (compositor, stage_view); -} - static void meta_compositor_x11_remove_window (MetaCompositor *compositor, MetaWindow *window) @@ -481,6 +479,9 @@ meta_compositor_x11_constructed (GObject *object) compositor_x11->before_update_handler_id = g_signal_connect (stage, "before-update", G_CALLBACK (on_before_update), compositor); + compositor_x11->after_update_handler_id = + g_signal_connect (stage, "after-update", + G_CALLBACK (on_after_update), compositor); G_OBJECT_CLASS (meta_compositor_x11_parent_class)->constructed (object); } @@ -499,6 +500,7 @@ meta_compositor_x11_dispose (GObject *object) } g_clear_signal_handler (&compositor_x11->before_update_handler_id, stage); + g_clear_signal_handler (&compositor_x11->after_update_handler_id, stage); G_OBJECT_CLASS (meta_compositor_x11_parent_class)->dispose (object); } @@ -520,7 +522,6 @@ meta_compositor_x11_class_init (MetaCompositorX11Class *klass) compositor_class->manage = meta_compositor_x11_manage; compositor_class->unmanage = meta_compositor_x11_unmanage; compositor_class->before_paint = meta_compositor_x11_before_paint; - compositor_class->after_paint = meta_compositor_x11_after_paint; compositor_class->remove_window = meta_compositor_x11_remove_window; compositor_class->monotonic_to_high_res_xserver_time = meta_compositor_x11_monotonic_to_high_res_xserver_time;