[cogl/wip/frame-synchronization: 220/223] Don't use g_get_monotonic_time()



commit 67bc4064ea0f63fdc3a751c4cf1df3edfeeceb2f
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Thu Jan 24 22:32:39 2013 -0500

    Don't use g_get_monotonic_time()
    
    Avoid a hard dependency on GLib and on however GLib is implementing
    g_get_monotonic_time() by directly referencing clock_gettime(CLOCK_MONOTONIC).
    
    The translation of timestamp values for unidentified types of UST is
    also removed, since it's going to have a big error, and
    glXGetSyncValues() doesn't return the *current* UST anyways - it returns
    the UST for the last frame.

 cogl/cogl-frame-info.h        |   14 +++++++-
 cogl/winsys/cogl-winsys-glx.c |   64 +++++++++++++++++++++++-----------------
 2 files changed, 49 insertions(+), 29 deletions(-)
---
diff --git a/cogl/cogl-frame-info.h b/cogl/cogl-frame-info.h
index 242e608..9ddad0c 100644
--- a/cogl/cogl-frame-info.h
+++ b/cogl/cogl-frame-info.h
@@ -88,8 +88,18 @@ int64_t cogl_frame_info_get_frame_counter (CoglFrameInfo *info);
  * Gets the presentation time for the frame. This is the time at which
  * the frame became visible to the user.
  *
- * Return value: the presentation time for the frame, in
- *  the timescale of g_get_monotonic_time().
+ * The presentation time measured in microseconds is based on a
+ * monotonic time source. The time source is not necessarily
+ * correlated with system/wall clock time and may represent the time
+ * elapsed since some undefined system event such as when the system
+ * last booted.
+ *
+ * <note>Linux kernel version less that 3.8 can result in
+ * non-monotonic timestamps being reported when using a drm based
+ * OpenGL driver. Also some buggy Mesa drivers up to 9.0.1 may also
+ * incorrectly report non-monotonic timestamps.</note>
+ *
+ * Return value: the presentation time for the frame
  * Since: 2.0
  * Stability: unstable
  */
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index fff6dfe..88acd9d 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -56,6 +56,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <fcntl.h>
+#include <time.h>
 
 #include <glib/gi18n-lib.h>
 
@@ -175,7 +176,7 @@ find_onscreen_for_xid (CoglContext *context, uint32_t xid)
 
 static void
 ensure_ust_type (CoglRenderer *renderer,
-                 GLXDrawable   drawable)
+                 GLXDrawable drawable)
 {
   CoglGLXRenderer *glx_renderer =  renderer->winsys;
   CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
@@ -183,6 +184,7 @@ ensure_ust_type (CoglRenderer *renderer,
   int64_t msc;
   int64_t sbc;
   struct timeval tv;
+  struct timespec ts;
   int64_t current_system_time;
   int64_t current_monotonic_time;
 
@@ -198,20 +200,26 @@ ensure_ust_type (CoglRenderer *renderer,
                                        &ust, &msc, &sbc))
     goto out;
 
-  /* This is the method that Xorg uses currently */
-  gettimeofday(&tv, NULL);
+  /* This is the time source that existing (buggy) linux drm drivers
+   * use */
+  gettimeofday (&tv, NULL);
   current_system_time = (tv.tv_sec * G_GINT64_CONSTANT (1000000)) + tv.tv_usec;
 
-  if (current_system_time > ust - 1000000 && current_system_time < ust + 1000000)
+  if (current_system_time > ust - 1000000 &&
+      current_system_time < ust + 1000000)
     {
       glx_renderer->ust_type = COGL_GLX_UST_IS_GETTIMEOFDAY;
       goto out;
     }
 
-  /* This is the method that would make sense for a GL implementation to use -
-   * clock_gettime (CLOCK_MONOTONIC, &ts) */
-  current_monotonic_time = g_get_monotonic_time ();
-  if (current_monotonic_time > ust - 1000000 && current_monotonic_time < ust + 1000000)
+  /* This is the time source that the newer (fixed) linux drm
+   * drivers use (Linux >= 3.8) */
+  clock_gettime (CLOCK_MONOTONIC, &ts);
+  current_monotonic_time = (ts.tv_sec * G_GINT64_CONSTANT (1000000)) +
+    (ts.tv_nsec / G_GINT64_CONSTANT (1000));
+
+  if (current_monotonic_time > ust - 1000000 &&
+      current_monotonic_time < ust + 1000000)
     {
       glx_renderer->ust_type = COGL_GLX_UST_IS_MONOTONIC_TIME;
       goto out;
@@ -231,7 +239,6 @@ ust_to_monotonic_time (CoglRenderer *renderer,
                        int64_t       ust)
 {
   CoglGLXRenderer *glx_renderer =  renderer->winsys;
-  CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
 
   ensure_ust_type (renderer, drawable);
 
@@ -243,34 +250,32 @@ ust_to_monotonic_time (CoglRenderer *renderer,
     case COGL_GLX_UST_IS_GETTIMEOFDAY:
       {
         struct timeval tv;
+        struct timespec ts;
         int64_t current_system_time;
         int64_t current_monotonic_time;
 
         gettimeofday(&tv, NULL);
+        clock_gettime (CLOCK_MONOTONIC, &ts);
         current_system_time = (tv.tv_sec * G_GINT64_CONSTANT (1000000)) + tv.tv_usec;
-        current_monotonic_time = g_get_monotonic_time ();
+        current_monotonic_time = (ts.tv_sec * G_GINT64_CONSTANT (1000000)) +
+          (ts.tv_nsec / G_GINT64_CONSTANT (1000));
 
         return ust + current_monotonic_time - current_system_time;
       }
     case COGL_GLX_UST_IS_MONOTONIC_TIME:
       return ust;
     case COGL_GLX_UST_IS_OTHER:
-      {
-        if (glx_renderer->glXGetSyncValues)
-          {
-            int64_t current_monotonic_time;
-            int64_t ust;
-            int64_t msc;
-            int64_t sbc;
-
-            glx_renderer->glXGetSyncValues (xlib_renderer->xdpy, drawable,
-                                            &ust, &msc, &sbc);
-
-            current_monotonic_time = g_get_monotonic_time ();
-            return ust + current_monotonic_time - ust;
-          }
-        break;
-      }
+      /* In this case the scale of UST is undefined so we can't easily
+       * scale to nanoseconds.
+       *
+       * For example the driver may be reporting the rdtsc CPU counter
+       * as UST values and so the scale would need to be determined
+       * empirically.
+       *
+       * Potentially we could block for a known duration within
+       * ensure_ust_type() to measure the timescale of UST but for now
+       * we just ignore unknown time sources */
+      return 0;
     }
 
   return 0;
@@ -1440,12 +1445,17 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
       else
         {
           uint32_t current_count;
+          struct timespec ts;
 
           glx_renderer->glXGetVideoSync (&current_count);
           glx_renderer->glXWaitVideoSync (2,
                                           (current_count + 1) % 2,
                                           &current_count);
-          info->presentation_time = g_get_monotonic_time ();
+
+          clock_gettime (CLOCK_MONOTONIC, &ts);
+          info->presentation_time =
+            (ts.tv_sec * G_GINT64_CONSTANT (1000000)) +
+            (ts.tv_nsec / G_GINT64_CONSTANT (1000));
         }
     }
 }



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