summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compositor/compositor-private.h43
-rw-r--r--src/compositor/compositor.c95
-rw-r--r--src/compositor/meta-window-actor.c22
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;