From 4a39a81050fe28bf506d88802b0711bd16ed7201 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Dec 13 2022 10:59:14 +0000 Subject: import mutter-3.28.3-32.el7_9 --- diff --git a/SOURCES/0001-compositor-Make-sure-_NET_WM_FRAME_DRAWN-timestamp-h.patch b/SOURCES/0001-compositor-Make-sure-_NET_WM_FRAME_DRAWN-timestamp-h.patch new file mode 100644 index 0000000..9478c79 --- /dev/null +++ b/SOURCES/0001-compositor-Make-sure-_NET_WM_FRAME_DRAWN-timestamp-h.patch @@ -0,0 +1,293 @@ +From 3c64ba81e7844a6d3bfe1d171eda5d3cb052002f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 11 Sep 2020 16:32:12 +0200 +Subject: [PATCH] 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. +--- + src/compositor/compositor-private.h | 43 +++++++++++-- + src/compositor/compositor.c | 95 +++++++++++++++++++++-------- + src/compositor/meta-window-actor.c | 22 +++++-- + 3 files changed, 123 insertions(+), 37 deletions(-) + +diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h +index 25cab92805..d4cb9bbdc2 100644 +--- a/src/compositor/compositor-private.h ++++ b/src/compositor/compositor-private.h +@@ -18,8 +18,9 @@ struct _MetaCompositor + guint pre_paint_func_id; + guint post_paint_func_id; + +- gint64 server_time_query_time; +- gint64 server_time_offset; ++ gboolean xserver_uses_monotonic_clock; ++ int64_t xserver_time_query_time_us; ++ int64_t xserver_time_offset_us; + + int glx_opcode; + guint stereo_tree_ext : 1; +@@ -62,8 +63,8 @@ void meta_end_modal_for_plugin (MetaCompositor *compositor, + MetaPlugin *plugin, + guint32 timestamp); + +-gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, +- gint64 monotonic_time); ++int64_t meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, ++ int64_t monotonic_time); + + gboolean meta_compositor_window_is_stereo (MetaScreen *screen, + Window xwindow); +@@ -79,4 +80,38 @@ MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *composito + MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor, + MetaWindow *window); + ++static inline int64_t ++us (int64_t us) ++{ ++ return us; ++} ++ ++static inline int64_t ++ms2us (int64_t ms) ++{ ++ return us (ms * 1000); ++} ++ ++static inline int64_t ++s2us (int64_t s) ++{ ++ return ms2us(s * 1000); ++} ++ ++/* ++ * This function takes a 64 bit time stamp from the monotonic clock, and clamps ++ * it to the scope of the X server clock, without losing the granularity. ++ */ ++static inline int64_t ++meta_translate_to_high_res_xserver_time (int64_t time_us) ++{ ++ int64_t us; ++ int64_t ms; ++ ++ us = time_us % 1000; ++ ms = time_us / 1000; ++ ++ return ms2us (ms & 0xffffffff) + us; ++} ++ + #endif /* META_COMPOSITOR_PRIVATE_H */ +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 799bcddf5a..d8df1df015 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -580,6 +580,30 @@ meta_compositor_select_stereo_notify (MetaScreen *screen, + } + } + ++static void ++determine_server_clock_source (MetaCompositor *compositor) ++{ ++ MetaDisplay *display = compositor->display; ++ uint32_t server_time_ms; ++ int64_t server_time_us; ++ int64_t translated_monotonic_now_us; ++ ++ server_time_ms = meta_display_get_current_time_roundtrip (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->xserver_uses_monotonic_clock = TRUE; ++ else ++ compositor->xserver_uses_monotonic_clock = FALSE; ++} ++ + void + meta_compositor_manage (MetaCompositor *compositor) + { +@@ -588,6 +612,8 @@ meta_compositor_manage (MetaCompositor *compositor) + MetaScreen *screen = display->screen; + MetaBackend *backend = meta_get_backend (); + ++ determine_server_clock_source (compositor); ++ + compositor->stereo_tree_ext = screen_has_stereo_tree_ext (screen); + + meta_screen_set_cm_selection (display->screen); +@@ -1524,6 +1550,40 @@ meta_compositor_flash_window (MetaCompositor *compositor, + clutter_actor_restore_easing_state (flash); + } + ++static int64_t ++meta_compositor_monotonic_to_high_res_xserver_time_x11 (MetaCompositor *compositor, ++ int64_t monotonic_time_us) ++{ ++ int64_t now_us; ++ ++ if (compositor->xserver_uses_monotonic_clock) ++ return meta_translate_to_high_res_xserver_time (monotonic_time_us); ++ ++ now_us = g_get_monotonic_time (); ++ ++ if (compositor->xserver_time_query_time_us == 0 || ++ now_us > (compositor->xserver_time_query_time_us + s2us (10))) ++ { ++ MetaDisplay *display = compositor->display; ++ uint32_t xserver_time_ms; ++ int64_t xserver_time_us; ++ ++ compositor->xserver_time_query_time_us = now_us; ++ ++ xserver_time_ms = meta_display_get_current_time_roundtrip (display); ++ xserver_time_us = ms2us (xserver_time_ms); ++ compositor->xserver_time_offset_us = xserver_time_us - now_us; ++ } ++ ++ return monotonic_time_us + compositor->xserver_time_offset_us; ++} ++ ++static int64_t ++meta_compositor_monotonic_to_high_res_xserver_time_server (int64_t monotonic_time_us) ++{ ++ return meta_translate_to_high_res_xserver_time (monotonic_time_us); ++} ++ + /** + * meta_compositor_monotonic_time_to_server_time: + * @display: a #MetaDisplay +@@ -1539,37 +1599,18 @@ meta_compositor_flash_window (MetaCompositor *compositor, + * time source, then the time synchronization will be less accurate. + */ + gint64 +-meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, +- gint64 monotonic_time) ++meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, ++ int64_t monotonic_time) + { +- MetaCompositor *compositor = display->compositor; +- +- if (compositor->server_time_query_time == 0 || +- (!compositor->server_time_is_monotonic_time && +- monotonic_time > compositor->server_time_query_time + 10*1000*1000)) /* 10 seconds */ ++ if (meta_is_wayland_compositor ()) + { +- guint32 server_time = meta_display_get_current_time_roundtrip (display); +- gint64 server_time_usec = (gint64)server_time * 1000; +- gint64 current_monotonic_time = g_get_monotonic_time (); +- compositor->server_time_query_time = current_monotonic_time; +- +- /* If the server time 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 (server_time_usec > current_monotonic_time - 1000*1000 && +- server_time_usec < current_monotonic_time + 1000*1000) +- compositor->server_time_is_monotonic_time = TRUE; +- +- compositor->server_time_offset = server_time_usec - current_monotonic_time; ++ return meta_compositor_monotonic_to_high_res_xserver_time_server (monotonic_time); + } +- +- if (compositor->server_time_is_monotonic_time) +- return monotonic_time; + else +- return monotonic_time + compositor->server_time_offset; ++ { ++ return meta_compositor_monotonic_to_high_res_xserver_time_x11 (compositor, ++ monotonic_time); ++ } + } + + void +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index f1f86e14b6..82dde9a2a3 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -973,6 +973,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self) + MetaWindow *window = priv->window; + MetaDisplay *display = meta_window_get_display (priv->window); + MetaLogicalMonitor *logical_monitor; ++ int64_t now_us; + int64_t current_time; + float refresh_rate; + int interval, offset; +@@ -997,9 +998,10 @@ queue_send_frame_messages_timeout (MetaWindowActor *self) + refresh_rate = 60.0f; + } + ++ now_us = g_get_monotonic_time (); + current_time = +- meta_compositor_monotonic_time_to_server_time (display, +- g_get_monotonic_time ()); ++ meta_compositor_monotonic_to_high_res_xserver_time (display->compositor, ++ now_us); + interval = (int)(1000000 / refresh_rate) * 6; + offset = MAX (0, priv->frame_drawn_time + interval - current_time) / 1000; + +@@ -2009,11 +2011,14 @@ do_send_frame_drawn (MetaWindowActor *self, FrameData *frame) + MetaWindowActorPrivate *priv = self->priv; + MetaDisplay *display = meta_window_get_display (priv->window); + Display *xdisplay = meta_display_get_xdisplay (display); ++ int64_t now_us; + + XClientMessageEvent ev = { 0, }; + +- frame->frame_drawn_time = meta_compositor_monotonic_time_to_server_time (display, +- g_get_monotonic_time ()); ++ now_us = g_get_monotonic_time (); ++ frame->frame_drawn_time = ++ meta_compositor_monotonic_to_high_res_xserver_time (display->compositor, now_us); ++ + priv->frame_drawn_time = frame->frame_drawn_time; + + ev.type = ClientMessage; +@@ -2089,8 +2094,13 @@ do_send_frame_timings (MetaWindowActor *self, + + if (presentation_time != 0) + { +- gint64 presentation_time_server = meta_compositor_monotonic_time_to_server_time (display, +- presentation_time); ++ MetaCompositor *compositor = display->compositor; ++ int64_t presentation_time_server; ++ ++ presentation_time_server = ++ meta_compositor_monotonic_to_high_res_xserver_time (compositor, ++ presentation_time); ++ + gint64 presentation_time_offset = presentation_time_server - frame->frame_drawn_time; + if (presentation_time_offset == 0) + presentation_time_offset = 1; +-- +2.35.3 + diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec index 27ac60a..4a2fb0e 100644 --- a/SPECS/mutter.spec +++ b/SPECS/mutter.spec @@ -10,7 +10,7 @@ Name: mutter Version: 3.28.3 -Release: 31%{?dist} +Release: 32%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+ @@ -177,6 +177,9 @@ Patch701: 0001-idle-monitor-NULL-check-cached-InhibitedActions-prop.patch # Fix race condition causing stuck pointer grabs (rhbz#2054507) Patch702: 0001-events-Pass-CurrentTime-to-XIAllowEvents-when-unfree.patch +# Fix _NET_WM_FRAME_DRAWN timestamps when overflow occurs (rhbz#2128996) +Patch703: 0001-compositor-Make-sure-_NET_WM_FRAME_DRAWN-timestamp-h.patch + BuildRequires: chrpath BuildRequires: pango-devel BuildRequires: startup-notification-devel @@ -332,6 +335,10 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/pkgconfig/* %changelog +* Wed Jul 27 2022 Jonas Ådahl - 3.28.3-32 +- Fix _NET_WM_FRAME_DRAWN timestamps when overflow occurs + Resolves: #2128996 + * Mon Apr 25 2022 Jonas Ådahl ) - 3.28.3-31 - Fix race condition causing stuck pointer grabs Resolves: #2054507