summaryrefslogtreecommitdiffstats
path: root/ui/gl
diff options
context:
space:
mode:
authorajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-01 15:40:36 +0000
committerajuma@chromium.org <ajuma@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-01 15:40:36 +0000
commita0c3fbb4d5b603835cc756fce5d75c7dbb08a3ac (patch)
treebf1278eab4fc0d35c309988f0784ff8dee16a91e /ui/gl
parente3ccc01fb64e2a9b5e4b5923754f28139a6640ad (diff)
downloadchromium_src-a0c3fbb4d5b603835cc756fce5d75c7dbb08a3ac.zip
chromium_src-a0c3fbb4d5b603835cc756fce5d75c7dbb08a3ac.tar.gz
chromium_src-a0c3fbb4d5b603835cc756fce5d75c7dbb08a3ac.tar.bz2
Send vsync timebase updates to the browser compositor
This uses the GLX_OML_sync_control extension to get vsync timebase and interval information and forward it to the browser compositor on Aura, and to the renderer compositor on non-Aura. BUG=143466 Review URL: https://chromiumcodereview.appspot.com/11195011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165389 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gl')
-rwxr-xr-xui/gl/generate_bindings.py10
-rw-r--r--ui/gl/gl_surface.cc10
-rw-r--r--ui/gl/gl_surface.h13
-rw-r--r--ui/gl/gl_surface_glx.cc89
-rw-r--r--ui/gl/gl_surface_glx.h3
5 files changed, 125 insertions, 0 deletions
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index 0090602..3bf7b37 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -1108,6 +1108,16 @@ GLX_FUNCTIONS = [
'arguments':
'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, '
'const int* attrib_list', },
+{ 'return_type': 'bool',
+ 'names': ['glXGetSyncValuesOML'],
+ 'arguments':
+ 'Display* dpy, GLXDrawable drawable, int64* ust, int64* msc, '
+ 'int64* sbc' },
+{ 'return_type': 'bool',
+ 'names': ['glXGetMscRateOML'],
+ 'arguments':
+ 'Display* dpy, GLXDrawable drawable, int32* numerator, '
+ 'int32* denominator' },
]
FUNCTION_SETS = [
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index a05eae8..832015b 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -147,6 +147,11 @@ unsigned GLSurface::GetFormat() {
return 0;
}
+bool GLSurface::GetVSyncParameters(base::TimeTicks* timebase,
+ base::TimeDelta* interval) {
+ return false;
+}
+
GLSurface* GLSurface::GetCurrent() {
return current_surface_.Pointer()->Get();
}
@@ -251,6 +256,11 @@ unsigned GLSurfaceAdapter::GetFormat() {
return surface_->GetFormat();
}
+bool GLSurfaceAdapter::GetVSyncParameters(base::TimeTicks* timebase,
+ base::TimeDelta* interval) {
+ return surface_->GetVSyncParameters(timebase, interval);
+}
+
GLSurfaceAdapter::~GLSurfaceAdapter() {}
} // namespace gfx
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index 4ecc472..56d8ae7 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -13,6 +13,11 @@
#include "ui/gfx/size.h"
#include "ui/gl/gl_export.h"
+namespace base {
+class TimeDelta;
+class TimeTicks;
+}
+
namespace gfx {
class GLContext;
@@ -102,6 +107,12 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
// Get the GL pixel format of the surface, if available.
virtual unsigned GetFormat();
+ // Get the time of the most recent screen refresh, along with the time
+ // between consecutive refreshes. Returns false when these values are
+ // unavailable.
+ virtual bool GetVSyncParameters(base::TimeTicks* timebase,
+ base::TimeDelta* interval);
+
// Create a GL surface that renders directly to a view.
static scoped_refptr<GLSurface> CreateViewGLSurface(
bool software,
@@ -153,6 +164,8 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
virtual void* GetDisplay() OVERRIDE;
virtual void* GetConfig() OVERRIDE;
virtual unsigned GetFormat() OVERRIDE;
+ virtual bool GetVSyncParameters(base::TimeTicks* timebase,
+ base::TimeDelta* interval) OVERRIDE;
GLSurface* surface() const { return surface_.get(); }
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
index f810114..a164f3f 100644
--- a/ui/gl/gl_surface_glx.cc
+++ b/ui/gl/gl_surface_glx.cc
@@ -14,6 +14,7 @@ extern "C" {
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/process_util.h"
+#include "base/time.h"
#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
#include "ui/base/x/x11_util.h"
#include "ui/gl/gl_bindings.h"
@@ -37,6 +38,12 @@ Display* g_display;
const char* g_glx_extensions = NULL;
bool g_glx_create_context_robustness_supported = false;
bool g_glx_texture_from_pixmap_supported = false;
+bool g_glx_oml_sync_control_supported = false;
+
+// Track support of glXGetMscRateOML separately from GLX_OML_sync_control as a
+// whole since on some platforms (e.g. crosbug.com/34585), glXGetMscRateOML
+// always fails even though GLX_OML_sync_control is reported as being supported.
+bool g_glx_get_msc_rate_oml_supported = false;
} // namespace
@@ -69,6 +76,10 @@ bool GLSurfaceGLX::InitializeOneOff() {
HasGLXExtension("GLX_ARB_create_context_robustness");
g_glx_texture_from_pixmap_supported =
HasGLXExtension("GLX_EXT_texture_from_pixmap");
+ g_glx_oml_sync_control_supported =
+ HasGLXExtension("GLX_OML_sync_control");
+ g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
+
initialized = true;
return true;
@@ -94,6 +105,11 @@ bool GLSurfaceGLX::IsTextureFromPixmapSupported() {
return g_glx_texture_from_pixmap_supported;
}
+// static
+bool GLSurfaceGLX::IsOMLSyncControlSupported() {
+ return g_glx_oml_sync_control_supported;
+}
+
void* GLSurfaceGLX::GetDisplay() {
return g_display;
}
@@ -224,6 +240,79 @@ bool NativeViewGLSurfaceGLX::PostSubBuffer(
return true;
}
+bool NativeViewGLSurfaceGLX::GetVSyncParameters(base::TimeTicks* timebase,
+ base::TimeDelta* interval) {
+ if (!g_glx_oml_sync_control_supported)
+ return false;
+
+ // The actual clock used for the system time returned by glXGetSyncValuesOML
+ // is unspecified. In practice, the clock used is likely to be either
+ // CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the
+ // current time according to both clocks, and assume that the returned time
+ // was produced by the clock whose current time is closest to it, subject
+ // to the restriction that the returned time must not be in the future (since
+ // it is the time of a vblank that has already occurred).
+ int64 system_time;
+ int64 media_stream_counter;
+ int64 swap_buffer_counter;
+ if (!glXGetSyncValuesOML(g_display, window_, &system_time,
+ &media_stream_counter, &swap_buffer_counter))
+ return false;
+
+ struct timespec real_time;
+ struct timespec monotonic_time;
+ clock_gettime(CLOCK_REALTIME, &real_time);
+ clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
+
+ int64 real_time_in_microseconds =
+ real_time.tv_sec * base::Time::kMicrosecondsPerSecond +
+ real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+ int64 monotonic_time_in_microseconds =
+ monotonic_time.tv_sec * base::Time::kMicrosecondsPerSecond +
+ monotonic_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+
+ if ((system_time > real_time_in_microseconds) &&
+ (system_time > monotonic_time_in_microseconds))
+ return false;
+
+ // We need the time according to CLOCK_MONOTONIC, so if we've been given
+ // a time from CLOCK_REALTIME, we need to convert.
+ bool time_conversion_needed =
+ (system_time > monotonic_time_in_microseconds) ||
+ (real_time_in_microseconds - system_time <
+ monotonic_time_in_microseconds - system_time);
+
+ if (time_conversion_needed) {
+ int64 time_difference =
+ real_time_in_microseconds - monotonic_time_in_microseconds;
+ *timebase = base::TimeTicks::FromInternalValue(
+ system_time - time_difference);
+ } else {
+ *timebase = base::TimeTicks::FromInternalValue(system_time);
+ }
+
+ // On platforms where glXGetMscRateOML doesn't work, we fall back to the
+ // assumption that we're displaying 60 frames per second.
+ const int64 kDefaultIntervalTime =
+ base::Time::kMicrosecondsPerSecond / 60;
+ int64 interval_time = kDefaultIntervalTime;
+ int32 numerator;
+ int32 denominator;
+ if (g_glx_get_msc_rate_oml_supported) {
+ if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) {
+ interval_time =
+ (base::Time::kMicrosecondsPerSecond * denominator) / numerator;
+ } else {
+ // Once glXGetMscRateOML has been found to fail, don't try again,
+ // since each failing call may spew an error message.
+ g_glx_get_msc_rate_oml_supported = false;
+ }
+ }
+
+ *interval = base::TimeDelta::FromMicroseconds(interval_time);
+ return true;
+}
+
NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
: window_(0),
config_(NULL) {
diff --git a/ui/gl/gl_surface_glx.h b/ui/gl/gl_surface_glx.h
index 0dc235c..908c2fb 100644
--- a/ui/gl/gl_surface_glx.h
+++ b/ui/gl/gl_surface_glx.h
@@ -28,6 +28,7 @@ class GL_EXPORT GLSurfaceGLX : public GLSurface {
static bool HasGLXExtension(const char* name);
static bool IsCreateContextRobustnessSupported();
static bool IsTextureFromPixmapSupported();
+ static bool IsOMLSyncControlSupported();
virtual void* GetDisplay() OVERRIDE;
@@ -58,6 +59,8 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
virtual std::string GetExtensions() OVERRIDE;
virtual void* GetConfig() OVERRIDE;
virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+ virtual bool GetVSyncParameters(base::TimeTicks* timebase,
+ base::TimeDelta* interval) OVERRIDE;
protected:
NativeViewGLSurfaceGLX();