diff options
author | Owen W. Taylor <otaylor@fishsoup.net> | 2013-01-24 22:32:39 -0500 |
---|---|---|
committer | Owen W. Taylor <otaylor@fishsoup.net> | 2013-01-25 00:36:48 -0500 |
commit | 67bc4064ea0f63fdc3a751c4cf1df3edfeeceb2f (patch) | |
tree | 0aa7f47e7b0c8e62b5427ac0d79f708077675e88 | |
parent | 38ac56be4a0af4048091cfa3f7fd206a0d4db424 (diff) | |
download | cogl-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.h | 14 | ||||
-rw-r--r-- | 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 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 (¤t_count); glx_renderer->glXWaitVideoSync (2, (current_count + 1) % 2, ¤t_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)); } } } |