|
|
6ddca0 |
From b0f3604cdb653ef133f9684adffeb6b93f6906f8 Mon Sep 17 00:00:00 2001
|
|
|
6ddca0 |
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
|
|
|
6ddca0 |
Date: Wed, 26 Jan 2022 10:51:07 +0100
|
|
|
6ddca0 |
Subject: [PATCH] compositor: Make sure _NET_WM_FRAME_DRAWN timestamp has the
|
|
|
6ddca0 |
right scope
|
|
|
6ddca0 |
|
|
|
6ddca0 |
The timestamp sent with _NET_WM_FRAME_DRAWN should be in "high
|
|
|
6ddca0 |
resolution X server timestamps", meaning they should have the same scope
|
|
|
6ddca0 |
as the built in X11 32 bit unsigned integer timestamps, i.e. overflow at
|
|
|
6ddca0 |
the same time.
|
|
|
6ddca0 |
|
|
|
6ddca0 |
This was not done correctly when mutter had determined the X server used
|
|
|
6ddca0 |
the monotonic clock, where it'd just forward the monotonic clock,
|
|
|
6ddca0 |
confusing any client using _NET_WM_FRAME_DRAWN and friends.
|
|
|
6ddca0 |
|
|
|
6ddca0 |
Fix this by 1) splitting the timestamp conversiot into an X11 case and a
|
|
|
6ddca0 |
display server case, where the display server case simply clamps the
|
|
|
6ddca0 |
monotonic clock, as it is assumed Xwayland is always usign the monotonic
|
|
|
6ddca0 |
clock, and 2) if we're a X11 compositing manager, if the X server is
|
|
|
6ddca0 |
using the monotonic clock, apply the same semantics as the display
|
|
|
6ddca0 |
server case and always just clamp, or if not, calculate the offset every
|
|
|
6ddca0 |
10 seconds, and offset the monotonic clock timestamp with the calculated
|
|
|
6ddca0 |
X server timestamp offset.
|
|
|
6ddca0 |
|
|
|
6ddca0 |
This fixes an issue that would occur if mutter (or rather GNOME Shell)
|
|
|
6ddca0 |
would have been started before a X11 timestamp overflow, after the
|
|
|
6ddca0 |
overflow happened. In this case, GTK3 clients would get unclamped
|
|
|
6ddca0 |
timestamps, and get very confused, resulting in frames queued several
|
|
|
6ddca0 |
weeks into the future.
|
|
|
6ddca0 |
---
|
|
|
6ddca0 |
src/compositor/compositor-private.h | 9 +-
|
|
|
6ddca0 |
src/compositor/compositor.c | 117 +++++++++++++++++++------
|
|
|
6ddca0 |
src/compositor/meta-window-actor-x11.c | 12 +--
|
|
|
6ddca0 |
3 files changed, 104 insertions(+), 34 deletions(-)
|
|
|
6ddca0 |
|
|
|
6ddca0 |
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
|
|
|
6ddca0 |
index f7008751215d..4588a8af7f2f 100644
|
|
|
6ddca0 |
--- a/src/compositor/compositor-private.h
|
|
|
6ddca0 |
+++ b/src/compositor/compositor-private.h
|
|
|
6ddca0 |
@@ -49,6 +49,10 @@ struct _MetaCompositor
|
|
|
6ddca0 |
|
|
|
6ddca0 |
gboolean frame_has_updated_xsurfaces;
|
|
|
6ddca0 |
gboolean have_x11_sync_object;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ gboolean xserver_uses_monotonic_clock;
|
|
|
6ddca0 |
+ int64_t xserver_time_query_time_us;
|
|
|
6ddca0 |
+ int64_t xserver_time_offset_us;
|
|
|
6ddca0 |
};
|
|
|
6ddca0 |
|
|
|
6ddca0 |
/* Wait 2ms after vblank before starting to draw next frame */
|
|
|
6ddca0 |
@@ -64,8 +68,9 @@ void meta_end_modal_for_plugin (MetaCompositor *compositor,
|
|
|
6ddca0 |
MetaPlugin *plugin,
|
|
|
6ddca0 |
guint32 timestamp);
|
|
|
6ddca0 |
|
|
|
6ddca0 |
-gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
|
|
6ddca0 |
- gint64 monotonic_time);
|
|
|
6ddca0 |
+int64_t
|
|
|
6ddca0 |
+meta_compositor_monotonic_to_high_res_xserver_time (MetaDisplay *display,
|
|
|
6ddca0 |
+ int64_t monotonic_time_us);
|
|
|
6ddca0 |
|
|
|
6ddca0 |
gboolean meta_compositor_window_is_stereo (MetaDisplay *display,
|
|
|
6ddca0 |
Window xwindow);
|
|
|
6ddca0 |
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
|
|
|
6ddca0 |
index ce2c1b8a3bc1..a3fbe5d888f9 100644
|
|
|
6ddca0 |
--- a/src/compositor/compositor.c
|
|
|
6ddca0 |
+++ b/src/compositor/compositor.c
|
|
|
6ddca0 |
@@ -88,6 +88,40 @@
|
|
|
6ddca0 |
#include "wayland/meta-wayland-private.h"
|
|
|
6ddca0 |
#endif
|
|
|
6ddca0 |
|
|
|
6ddca0 |
+static inline int64_t
|
|
|
6ddca0 |
+us (int64_t us)
|
|
|
6ddca0 |
+{
|
|
|
6ddca0 |
+ return us;
|
|
|
6ddca0 |
+}
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+static inline int64_t
|
|
|
6ddca0 |
+ms2us (int64_t ms)
|
|
|
6ddca0 |
+{
|
|
|
6ddca0 |
+ return us (ms * 1000);
|
|
|
6ddca0 |
+}
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+static inline int64_t
|
|
|
6ddca0 |
+s2us (int64_t s)
|
|
|
6ddca0 |
+{
|
|
|
6ddca0 |
+ return ms2us(s * 1000);
|
|
|
6ddca0 |
+}
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+/*
|
|
|
6ddca0 |
+ * This function takes a 64 bit time stamp from the monotonic clock, and clamps
|
|
|
6ddca0 |
+ * it to the scope of the X server clock, without losing the granularity.
|
|
|
6ddca0 |
+ */
|
|
|
6ddca0 |
+static inline int64_t
|
|
|
6ddca0 |
+meta_translate_to_high_res_xserver_time (int64_t time_us)
|
|
|
6ddca0 |
+{
|
|
|
6ddca0 |
+ int64_t us;
|
|
|
6ddca0 |
+ int64_t ms;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ us = time_us % 1000;
|
|
|
6ddca0 |
+ ms = time_us / 1000;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ return ms2us (ms & 0xffffffff) + us;
|
|
|
6ddca0 |
+}
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
static void
|
|
|
6ddca0 |
on_presented (ClutterStage *stage,
|
|
|
6ddca0 |
CoglFrameEvent event,
|
|
|
6ddca0 |
@@ -612,6 +646,37 @@ meta_compositor_select_stereo_notify (MetaDisplay *display,
|
|
|
6ddca0 |
}
|
|
|
6ddca0 |
}
|
|
|
6ddca0 |
|
|
|
6ddca0 |
+static void
|
|
|
6ddca0 |
+determine_server_clock_source (MetaCompositor *compositor)
|
|
|
6ddca0 |
+{
|
|
|
6ddca0 |
+ MetaDisplay *display = compositor->display;
|
|
|
6ddca0 |
+ MetaX11Display *x11_display = display->x11_display;
|
|
|
6ddca0 |
+ uint32_t server_time_ms;
|
|
|
6ddca0 |
+ int64_t server_time_us;
|
|
|
6ddca0 |
+ int64_t translated_monotonic_now_us;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ if (meta_is_wayland_compositor ())
|
|
|
6ddca0 |
+ {
|
|
|
6ddca0 |
+ compositor->xserver_uses_monotonic_clock = TRUE;
|
|
|
6ddca0 |
+ return;
|
|
|
6ddca0 |
+ }
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ server_time_ms = meta_x11_display_get_current_time_roundtrip (x11_display);
|
|
|
6ddca0 |
+ server_time_us = ms2us (server_time_ms);
|
|
|
6ddca0 |
+ translated_monotonic_now_us =
|
|
|
6ddca0 |
+ meta_translate_to_high_res_xserver_time (g_get_monotonic_time ());
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ /* If the server time offset is within a second of the monotonic time, we
|
|
|
6ddca0 |
+ * assume that they are identical. This seems like a big margin, but we want
|
|
|
6ddca0 |
+ * to be as robust as possible even if the system is under load and our
|
|
|
6ddca0 |
+ * processing of the server response is delayed.
|
|
|
6ddca0 |
+ */
|
|
|
6ddca0 |
+ if (ABS (server_time_us - translated_monotonic_now_us) < s2us (1))
|
|
|
6ddca0 |
+ compositor->xserver_uses_monotonic_clock = TRUE;
|
|
|
6ddca0 |
+ else
|
|
|
6ddca0 |
+ compositor->xserver_uses_monotonic_clock = FALSE;
|
|
|
6ddca0 |
+}
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
void
|
|
|
6ddca0 |
meta_compositor_manage (MetaCompositor *compositor)
|
|
|
6ddca0 |
{
|
|
|
6ddca0 |
@@ -622,6 +687,9 @@ meta_compositor_manage (MetaCompositor *compositor)
|
|
|
6ddca0 |
if (display->x11_display)
|
|
|
6ddca0 |
{
|
|
|
6ddca0 |
xdisplay = display->x11_display->xdisplay;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ determine_server_clock_source (compositor);
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
meta_x11_display_set_cm_selection (display->x11_display);
|
|
|
6ddca0 |
|
|
|
6ddca0 |
compositor->stereo_tree_ext = display_has_stereo_tree_ext (display->x11_display);
|
|
|
6ddca0 |
@@ -1593,7 +1661,7 @@ meta_compositor_flash_window (MetaCompositor *compositor,
|
|
|
6ddca0 |
}
|
|
|
6ddca0 |
|
|
|
6ddca0 |
/**
|
|
|
6ddca0 |
- * meta_compositor_monotonic_time_to_server_time:
|
|
|
6ddca0 |
+ * meta_compositor_monotonic_to_high_res_xserver_time:
|
|
|
6ddca0 |
* @display: a #MetaDisplay
|
|
|
6ddca0 |
* @monotonic_time: time in the units of g_get_monotonic_time()
|
|
|
6ddca0 |
*
|
|
|
6ddca0 |
@@ -1606,38 +1674,35 @@ meta_compositor_flash_window (MetaCompositor *compositor,
|
|
|
6ddca0 |
* a time representation with high accuracy. If there is not a common
|
|
|
6ddca0 |
* time source, then the time synchronization will be less accurate.
|
|
|
6ddca0 |
*/
|
|
|
6ddca0 |
-gint64
|
|
|
6ddca0 |
-meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
|
|
6ddca0 |
- gint64 monotonic_time)
|
|
|
6ddca0 |
+int64_t
|
|
|
6ddca0 |
+meta_compositor_monotonic_to_high_res_xserver_time (MetaDisplay *display,
|
|
|
6ddca0 |
+ int64_t monotonic_time_us)
|
|
|
6ddca0 |
{
|
|
|
6ddca0 |
MetaCompositor *compositor = display->compositor;
|
|
|
6ddca0 |
+ int64_t now_us;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ if (compositor->xserver_uses_monotonic_clock)
|
|
|
6ddca0 |
+ return meta_translate_to_high_res_xserver_time (monotonic_time_us);
|
|
|
6ddca0 |
|
|
|
6ddca0 |
- if (compositor->server_time_query_time == 0 ||
|
|
|
6ddca0 |
- (!compositor->server_time_is_monotonic_time &&
|
|
|
6ddca0 |
- monotonic_time > compositor->server_time_query_time + 10*1000*1000)) /* 10 seconds */
|
|
|
6ddca0 |
+ now_us = g_get_monotonic_time ();
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ if (compositor->xserver_time_query_time_us == 0 ||
|
|
|
6ddca0 |
+ now_us > (compositor->xserver_time_query_time_us + s2us (10)))
|
|
|
6ddca0 |
{
|
|
|
6ddca0 |
- guint32 server_time = meta_display_get_current_time_roundtrip (display);
|
|
|
6ddca0 |
- gint64 server_time_usec = (gint64)server_time * 1000;
|
|
|
6ddca0 |
- gint64 current_monotonic_time = g_get_monotonic_time ();
|
|
|
6ddca0 |
- compositor->server_time_query_time = current_monotonic_time;
|
|
|
6ddca0 |
-
|
|
|
6ddca0 |
- /* If the server time is within a second of the monotonic time,
|
|
|
6ddca0 |
- * we assume that they are identical. This seems like a big margin,
|
|
|
6ddca0 |
- * but we want to be as robust as possible even if the system
|
|
|
6ddca0 |
- * is under load and our processing of the server response is
|
|
|
6ddca0 |
- * delayed.
|
|
|
6ddca0 |
- */
|
|
|
6ddca0 |
- if (server_time_usec > current_monotonic_time - 1000*1000 &&
|
|
|
6ddca0 |
- server_time_usec < current_monotonic_time + 1000*1000)
|
|
|
6ddca0 |
- compositor->server_time_is_monotonic_time = TRUE;
|
|
|
6ddca0 |
+ MetaDisplay *display = compositor->display;
|
|
|
6ddca0 |
+ MetaX11Display *x11_display = display->x11_display;
|
|
|
6ddca0 |
+ uint32_t xserver_time_ms;
|
|
|
6ddca0 |
+ int64_t xserver_time_us;
|
|
|
6ddca0 |
|
|
|
6ddca0 |
- compositor->server_time_offset = server_time_usec - current_monotonic_time;
|
|
|
6ddca0 |
+ compositor->xserver_time_query_time_us = now_us;
|
|
|
6ddca0 |
+
|
|
|
6ddca0 |
+ xserver_time_ms =
|
|
|
6ddca0 |
+ meta_x11_display_get_current_time_roundtrip (x11_display);
|
|
|
6ddca0 |
+ xserver_time_us = ms2us (xserver_time_ms);
|
|
|
6ddca0 |
+ compositor->xserver_time_offset_us = xserver_time_us - now_us;
|
|
|
6ddca0 |
}
|
|
|
6ddca0 |
|
|
|
6ddca0 |
- if (compositor->server_time_is_monotonic_time)
|
|
|
6ddca0 |
- return monotonic_time;
|
|
|
6ddca0 |
- else
|
|
|
6ddca0 |
- return monotonic_time + compositor->server_time_offset;
|
|
|
6ddca0 |
+ return monotonic_time_us + compositor->xserver_time_offset_us;
|
|
|
6ddca0 |
}
|
|
|
6ddca0 |
|
|
|
6ddca0 |
void
|
|
|
6ddca0 |
diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c
|
|
|
6ddca0 |
index a364323fe057..2b9c25510dc9 100644
|
|
|
6ddca0 |
--- a/src/compositor/meta-window-actor-x11.c
|
|
|
6ddca0 |
+++ b/src/compositor/meta-window-actor-x11.c
|
|
|
6ddca0 |
@@ -105,8 +105,8 @@ do_send_frame_drawn (MetaWindowActorX11 *actor_x11,
|
|
|
6ddca0 |
XClientMessageEvent ev = { 0, };
|
|
|
6ddca0 |
|
|
|
6ddca0 |
frame->frame_drawn_time =
|
|
|
6ddca0 |
- meta_compositor_monotonic_time_to_server_time (display,
|
|
|
6ddca0 |
- g_get_monotonic_time ());
|
|
|
6ddca0 |
+ meta_compositor_monotonic_to_high_res_xserver_time (display,
|
|
|
6ddca0 |
+ g_get_monotonic_time ());
|
|
|
6ddca0 |
actor_x11->frame_drawn_time = frame->frame_drawn_time;
|
|
|
6ddca0 |
|
|
|
6ddca0 |
ev.type = ClientMessage;
|
|
|
6ddca0 |
@@ -147,8 +147,8 @@ do_send_frame_timings (MetaWindowActorX11 *actor_x11,
|
|
|
6ddca0 |
if (presentation_time != 0)
|
|
|
6ddca0 |
{
|
|
|
6ddca0 |
int64_t presentation_time_server =
|
|
|
6ddca0 |
- meta_compositor_monotonic_time_to_server_time (display,
|
|
|
6ddca0 |
- presentation_time);
|
|
|
6ddca0 |
+ meta_compositor_monotonic_to_high_res_xserver_time (display,
|
|
|
6ddca0 |
+ presentation_time);
|
|
|
6ddca0 |
int64_t presentation_time_offset = presentation_time_server - frame->frame_drawn_time;
|
|
|
6ddca0 |
if (presentation_time_offset == 0)
|
|
|
6ddca0 |
presentation_time_offset = 1;
|
|
|
6ddca0 |
@@ -246,8 +246,8 @@ queue_send_frame_messages_timeout (MetaWindowActorX11 *actor_x11)
|
|
|
6ddca0 |
}
|
|
|
6ddca0 |
|
|
|
6ddca0 |
current_time =
|
|
|
6ddca0 |
- meta_compositor_monotonic_time_to_server_time (display,
|
|
|
6ddca0 |
- g_get_monotonic_time ());
|
|
|
6ddca0 |
+ meta_compositor_monotonic_to_high_res_xserver_time (display,
|
|
|
6ddca0 |
+ g_get_monotonic_time ());
|
|
|
6ddca0 |
interval = (int) (1000000 / refresh_rate) * 6;
|
|
|
6ddca0 |
offset = MAX (0, actor_x11->frame_drawn_time + interval - current_time) / 1000;
|
|
|
6ddca0 |
|
|
|
6ddca0 |
--
|
|
|
6ddca0 |
2.33.1
|
|
|
6ddca0 |
|