summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen W. Taylor <otaylor@fishsoup.net>2013-01-24 22:32:39 -0500
committerOwen W. Taylor <otaylor@fishsoup.net>2013-01-25 00:36:48 -0500
commit67bc4064ea0f63fdc3a751c4cf1df3edfeeceb2f (patch)
tree0aa7f47e7b0c8e62b5427ac0d79f708077675e88
parent38ac56be4a0af4048091cfa3f7fd206a0d4db424 (diff)
downloadcogl-67bc4064ea0f63fdc3a751c4cf1df3edfeeceb2f.tar.gz
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.
-rw-r--r--cogl/cogl-frame-info.h14
-rw-r--r--cogl/winsys/cogl-winsys-glx.c64
2 files changed, 49 insertions, 29 deletions
diff --git a/cogl/cogl-frame-info.h b/cogl/cogl-frame-info.h
index 242e608f..9ddad0c7 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 fff6dfe5..88acd9d4 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));
}
}
}