diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-04 23:37:57 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-04 23:37:57 +0000 |
commit | e9d46f8b56c8fdb4bf2ffab8900d53fe20a68890 (patch) | |
tree | 5e1bc0f70f8c6c77fc838fef9a942ab8c7ada5ab | |
parent | 8c43efaf1ed7bfeb03903aaae059873edd57b246 (diff) | |
download | chromium_src-e9d46f8b56c8fdb4bf2ffab8900d53fe20a68890.zip chromium_src-e9d46f8b56c8fdb4bf2ffab8900d53fe20a68890.tar.gz chromium_src-e9d46f8b56c8fdb4bf2ffab8900d53fe20a68890.tar.bz2 |
Calculate the refresh period from GLX_OML_sync_control.
glXGetSyncValuesOML gives us a count of the number of refreshes that have occurred (media stream counter). We can use this and the time between successive UST counters to measure the period of the screen refresh.
BUG=none
TEST=by hand on stumpy and alex using xrandr to force different refresh rates
Review URL: https://chromiumcodereview.appspot.com/11752002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175234 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ui/gl/gl_surface_glx.cc | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc index 07c281d..fde3df5d 100644 --- a/ui/gl/gl_surface_glx.cc +++ b/ui/gl/gl_surface_glx.cc @@ -57,7 +57,12 @@ class OMLSyncControlVSyncProvider : public gfx::NativeViewGLSurfaceGLX::VSyncProvider { public: explicit OMLSyncControlVSyncProvider(gfx::AcceleratedWidget window) - : window_(window) { + : window_(window), + last_media_stream_counter_(0) { + // On platforms where we can't get an accurate reading on the refresh + // rate we fall back to the assumption that we're displaying 60 frames + // per second. + last_good_interval_ = base::TimeDelta::FromSeconds(1) / 60; } virtual ~OMLSyncControlVSyncProvider() { } @@ -65,7 +70,6 @@ class OMLSyncControlVSyncProvider virtual void GetVSyncParameters( const GLSurface::UpdateVSyncCallback& callback) OVERRIDE { base::TimeTicks timebase; - base::TimeDelta interval; // The actual clock used for the system time returned by glXGetSyncValuesOML // is unspecified. In practice, the clock used is likely to be either @@ -113,30 +117,37 @@ class OMLSyncControlVSyncProvider 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) { + int32 numerator, denominator; if (glXGetMscRateOML(g_display, window_, &numerator, &denominator)) { - interval_time = - (base::Time::kMicrosecondsPerSecond * denominator) / numerator; + last_good_interval_ = + base::TimeDelta::FromSeconds(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; } + } else { + if (!last_timebase_.is_null()) { + base::TimeDelta timebase_diff = timebase - last_timebase_; + uint64 counter_diff = media_stream_counter - + last_media_stream_counter_; + if (counter_diff > 0 && timebase > last_timebase_) + last_good_interval_ = timebase_diff / counter_diff; + } } - interval = base::TimeDelta::FromMicroseconds(interval_time); - callback.Run(timebase, interval); + last_timebase_ = timebase; + last_media_stream_counter_ = media_stream_counter; + callback.Run(timebase, last_good_interval_); } private: XID window_; + base::TimeTicks last_timebase_; + uint64 last_media_stream_counter_; + base::TimeDelta last_good_interval_; + DISALLOW_COPY_AND_ASSIGN(OMLSyncControlVSyncProvider); }; @@ -182,7 +193,7 @@ class SGIVideoSyncProviderThreadShim vsync_lock_() { // This ensures that creation of |window_| has occured when this shim // is executing in the same process as the call to create |window_|. - XSync(::gfx::g_display, False); + XSync(g_display, False); } base::CancellationFlag* cancel_vsync_flag() { @@ -194,11 +205,10 @@ class SGIVideoSyncProviderThreadShim } void Initialize() { - DCHECK(SGIVideoSyncProviderThreadShim::g_display); + DCHECK(display_); XWindowAttributes attributes; - if (!XGetWindowAttributes(SGIVideoSyncProviderThreadShim::g_display, - window_, &attributes)) { + if (!XGetWindowAttributes(display_, window_, &attributes)) { LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << "."; return; @@ -209,7 +219,7 @@ class SGIVideoSyncProviderThreadShim int visual_info_count = 0; scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( - XGetVisualInfo(SGIVideoSyncProviderThreadShim::g_display, VisualIDMask, + XGetVisualInfo(display_, VisualIDMask, &visual_info_template, &visual_info_count)); DCHECK(visual_info_list.get()); @@ -218,17 +228,14 @@ class SGIVideoSyncProviderThreadShim return; } - context_ = glXCreateContext(SGIVideoSyncProviderThreadShim::g_display, - visual_info_list.get(), - NULL, - True); + context_ = glXCreateContext(display_, visual_info_list.get(), NULL, True); DCHECK(NULL != context_); } void Destroy() { if (context_) { - glXDestroyContext(SGIVideoSyncProviderThreadShim::g_display, context_); + glXDestroyContext(display_, context_); context_ = NULL; } delete this; @@ -243,8 +250,7 @@ class SGIVideoSyncProviderThreadShim if (!context_ || cancel_vsync_flag_.IsSet()) return; - glXMakeCurrent(SGIVideoSyncProviderThreadShim::g_display, - window_, context_); + glXMakeCurrent(display_, window_, context_); unsigned int retrace_count = 0; if (glXWaitVideoSyncSGI(1, 0, &retrace_count) != 0) @@ -253,26 +259,25 @@ class SGIVideoSyncProviderThreadShim TRACE_EVENT_INSTANT0("gpu", "vblank"); now = base::TimeTicks::HighResNow(); - glXMakeCurrent(SGIVideoSyncProviderThreadShim::g_display, 0, 0); + glXMakeCurrent(display_, 0, 0); } - const int64 kDefaultIntervalTime = - base::Time::kMicrosecondsPerSecond / 60; - base::TimeDelta interval = - base::TimeDelta::FromMicroseconds(kDefaultIntervalTime); + const base::TimeDelta kDefaultInterval = + base::TimeDelta::FromSeconds(1) / 60; - message_loop_->PostTask(FROM_HERE, base::Bind(callback, now, interval)); + message_loop_->PostTask( + FROM_HERE, base::Bind(callback, now, kDefaultInterval)); } private: - // For initialization of g_display in GLSurface::InitializeOneOff before + // For initialization of display_ in GLSurface::InitializeOneOff before // the sandbox goes up. friend class gfx::GLSurfaceGLX; virtual ~SGIVideoSyncProviderThreadShim() { } - static Display* g_display; + static Display* display_; XID window_; GLXContext context_; @@ -353,7 +358,7 @@ SGIVideoSyncThread* SGIVideoSyncThread::g_video_sync_thread = NULL; // In order to take advantage of GLX_SGI_video_sync, we need a display // for use on a separate thread. We must allocate this before the sandbox // goes up (rather than on-demand when we start the thread). -Display* SGIVideoSyncProviderThreadShim::g_display = NULL; +Display* SGIVideoSyncProviderThreadShim::display_ = NULL; } // namespace @@ -399,7 +404,7 @@ bool GLSurfaceGLX::InitializeOneOff() { HasGLXExtension("GLX_SGI_video_sync"); if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) - SGIVideoSyncProviderThreadShim::g_display = XOpenDisplay(NULL); + SGIVideoSyncProviderThreadShim::display_ = XOpenDisplay(NULL); initialized = true; return true; |