summaryrefslogtreecommitdiff
path: root/src/compositor/meta-compositor-x11.c
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2020-07-08 16:53:14 +0200
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2020-10-12 14:48:21 +0000
commitbf6dde87f862bebce595d7cb35c74981a909cfe8 (patch)
treeea4de670264072a461f4a12c485e25770920a718 /src/compositor/meta-compositor-x11.c
parent53c4ebee828d883370779df07ac08be0602c9647 (diff)
downloadmutter-bf6dde87f862bebce595d7cb35c74981a909cfe8.tar.gz
compositor: Make sure _NET_WM_FRAME_DRAWN timestamp has the right scope
The timestamp sent with _NET_WM_FRAME_DRAWN should be in "high resolution X server timestamps", meaning they should have the same scope as the built in X11 32 bit unsigned integer timestamps, i.e. overflow at the same time. This was not done correctly when mutter had determined the X server used the monotonic clock, where it'd just forward the monotonic clock, confusing any client using _NET_WM_FRAME_DRAWN and friends. Fix this by 1) splitting the timestamp conversiot into an X11 case and a display server case, where the display server case simply clamps the monotonic clock, as it is assumed Xwayland is always usign the monotonic clock, and 2) if we're a X11 compositing manager, if the X server is using the monotonic clock, apply the same semantics as the display server case and always just clamp, or if not, calculate the offset every 10 seconds, and offset the monotonic clock timestamp with the calculated X server timestamp offset. This fixes an issue that would occur if mutter (or rather GNOME Shell) would have been started before a X11 timestamp overflow, after the overflow happened. In this case, GTK3 clients would get unclamped timestamps, and get very confused, resulting in frames queued several weeks into the future. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1494
Diffstat (limited to 'src/compositor/meta-compositor-x11.c')
-rw-r--r--src/compositor/meta-compositor-x11.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c
index fcd292a1f..e7da103e3 100644
--- a/src/compositor/meta-compositor-x11.c
+++ b/src/compositor/meta-compositor-x11.c
@@ -45,6 +45,10 @@ struct _MetaCompositorX11
gboolean have_x11_sync_object;
MetaWindow *unredirected_window;
+
+ gboolean xserver_uses_monotonic_clock;
+ int64_t xserver_time_query_time_us;
+ int64_t xserver_time_offset_us;
};
G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR)
@@ -102,6 +106,32 @@ meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11,
meta_x11_handle_event (xevent);
}
+static void
+determine_server_clock_source (MetaCompositorX11 *compositor_x11)
+{
+ MetaCompositor *compositor = META_COMPOSITOR (compositor_x11);
+ MetaDisplay *display = meta_compositor_get_display (compositor);
+ MetaX11Display *x11_display = display->x11_display;
+ uint32_t server_time_ms;
+ int64_t server_time_us;
+ int64_t translated_monotonic_now_us;
+
+ server_time_ms = meta_x11_display_get_current_time_roundtrip (x11_display);
+ server_time_us = ms2us (server_time_ms);
+ translated_monotonic_now_us =
+ meta_translate_to_high_res_xserver_time (g_get_monotonic_time ());
+
+ /* If the server time offset is within a second of the monotonic time, we
+ * assume that they are identical. This seems like a big margin, but we want
+ * to be as robust as possible even if the system is under load and our
+ * processing of the server response is delayed.
+ */
+ if (ABS (server_time_us - translated_monotonic_now_us) < s2us (1))
+ compositor_x11->xserver_uses_monotonic_clock = TRUE;
+ else
+ compositor_x11->xserver_uses_monotonic_clock = FALSE;
+}
+
static gboolean
meta_compositor_x11_manage (MetaCompositor *compositor,
GError **error)
@@ -135,6 +165,8 @@ meta_compositor_x11_manage (MetaCompositor *compositor,
return FALSE;
}
+ determine_server_clock_source (compositor_x11);
+
meta_x11_display_set_cm_selection (display->x11_display);
compositor_x11->output = display->x11_display->composite_overlay_window;
@@ -376,6 +408,37 @@ meta_compositor_x11_remove_window (MetaCompositor *compositor,
parent_class->remove_window (compositor, window);
}
+static int64_t
+meta_compositor_x11_monotonic_to_high_res_xserver_time (MetaCompositor *compositor,
+ int64_t monotonic_time_us)
+{
+ MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor);
+ int64_t now_us;
+
+ if (compositor_x11->xserver_uses_monotonic_clock)
+ return meta_translate_to_high_res_xserver_time (monotonic_time_us);
+
+ now_us = g_get_monotonic_time ();
+
+ if (compositor_x11->xserver_time_query_time_us == 0 ||
+ now_us > (compositor_x11->xserver_time_query_time_us + s2us (10)))
+ {
+ MetaDisplay *display = meta_compositor_get_display (compositor);
+ MetaX11Display *x11_display = display->x11_display;
+ uint32_t xserver_time_ms;
+ int64_t xserver_time_us;
+
+ compositor_x11->xserver_time_query_time_us = now_us;
+
+ xserver_time_ms =
+ meta_x11_display_get_current_time_roundtrip (x11_display);
+ xserver_time_us = ms2us (xserver_time_ms);
+ compositor_x11->xserver_time_offset_us = xserver_time_us - now_us;
+ }
+
+ return monotonic_time_us + compositor_x11->xserver_time_offset_us;
+}
+
Window
meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11)
{
@@ -443,4 +506,6 @@ meta_compositor_x11_class_init (MetaCompositorX11Class *klass)
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;
}