[mutter/wip/frame-synchronization: 118/121] Add meta_compositor_monotonic_time_to_server_time()



commit 4b332640ebc7432a23010488e7a100de71100c7f
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Mon Nov 12 14:09:38 2012 -0500

    Add meta_compositor_monotonic_time_to_server_time()
    
    Add a function to convert from g_get_monotonic_time() to a
    "high-resolution server timestamp" with microsecond precision.
    These timestamps will be used when communicating frame timing
    information to the client.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=685463

 src/compositor/compositor-private.h |    7 +++++
 src/compositor/compositor.c         |   48 +++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 0 deletions(-)
---
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 0926601..3c46443 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -25,6 +25,10 @@ struct _MetaCompositor
 
   MetaPlugin     *modal_plugin;
 
+  gint64          server_time_query_time;
+  gint64          server_time_offset;
+
+  guint           server_time_is_monotonic_time : 1;
   guint           show_redraw : 1;
   guint           debug       : 1;
   guint           no_mipmaps  : 1;
@@ -65,6 +69,9 @@ void     meta_end_modal_for_plugin   (MetaScreen       *screen,
                                       MetaPlugin       *plugin,
                                       guint32           timestamp);
 
+gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
+                                                      gint64       monotonic_time);
+
 void meta_check_end_modal (MetaScreen *screen);
 
 #endif /* META_COMPOSITOR_PRIVATE_H */
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index d0c40e6..6174e42 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -1414,3 +1414,51 @@ meta_compositor_flash_screen (MetaCompositor *compositor,
                          "signal-after::completed", flash_in_completed, flash,
                          NULL);
 }
+
+/**
+ * meta_compositor_monotonic_time_to_server_time:
+ * @display: a #MetaDisplay
+ * @monotonic_time: time in the units of g_get_monotonic_time()
+ *
+ * _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages represent time
+ * as a "high resolution server time" - this is the server time interpolated
+ * to microsecond resolution. The advantage of this time representation
+ * is that if  X server is running on the same computer as a client, and
+ * the Xserver uses 'clock_gettime(CLOCK_MONOTONIC, ...)' for the server
+ * time, the client can detect this, and all such clients will share a
+ * a time representation with high accuracy. If there is not a common
+ * time source, then the time synchronization will be less accurate.
+ */
+gint64
+meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
+                                               gint64       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 + 10000000)) /* 10 seconds */
+    {
+      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 - 1000000 &&
+          server_time_usec < current_monotonic_time + 1000000)
+        compositor->server_time_is_monotonic_time = TRUE;
+
+      compositor->server_time_offset = server_time_usec - current_monotonic_time;
+    }
+
+  if (compositor->server_time_is_monotonic_time)
+    return monotonic_time;
+  else
+    return monotonic_time + compositor->server_time_offset;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]