diff options
-rw-r--r-- | src/compositor/compositor-private.h | 43 | ||||
-rw-r--r-- | src/compositor/compositor.c | 95 | ||||
-rw-r--r-- | 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 4582792d4..f40db9a05 100644 --- a/src/compositor/compositor-private.h +++ b/src/compositor/compositor-private.h @@ -21,8 +21,9 @@ struct _MetaCompositor guint stage_presented_id; guint stage_after_paint_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; guint server_time_is_monotonic_time : 1; guint no_mipmaps : 1; @@ -61,8 +62,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); void meta_compositor_flash_window (MetaCompositor *compositor, MetaWindow *window); @@ -75,4 +76,38 @@ MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (Me void meta_compositor_unmanage_window_actors (MetaCompositor *compositor); +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 6d045339c..8b2ed47a9 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -500,6 +500,30 @@ redirect_windows (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 translate_monotonic_now_us; + + server_time_ms = meta_display_get_current_time_roundtrip (display); + server_time_us = ms2us (server_time_ms); + translate_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) { @@ -508,6 +532,8 @@ meta_compositor_manage (MetaCompositor *compositor) MetaScreen *screen = display->screen; MetaBackend *backend = meta_get_backend (); + determine_server_clock_source (compositor); + meta_screen_set_cm_selection (display->screen); compositor->stage = meta_backend_get_stage (backend); @@ -1428,6 +1454,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 @@ -1443,37 +1503,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 5078624cc..1cc2db488 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -965,6 +965,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; @@ -989,9 +990,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; @@ -1972,11 +1974,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; @@ -2052,8 +2057,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; |