Commit 47bcf86d authored by bajones's avatar bajones Committed by Commit bot

Enabled detection of different refresh rates per monitor on Windows

BUG=418684

Review URL: https://codereview.chromium.org/615613002

Cr-Commit-Position: refs/heads/master@{#297277}
parent c0c002bd
...@@ -59,25 +59,35 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa { ...@@ -59,25 +59,35 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa); DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa);
}; };
class DWMVSyncProvider : public VSyncProvider { class WinVSyncProvider : public VSyncProvider {
public: public:
explicit DWMVSyncProvider() {} explicit WinVSyncProvider(gfx::AcceleratedWidget window) :
window_(window)
{
use_dwm_ = (base::win::GetVersion() >= base::win::VERSION_VISTA);
}
virtual ~DWMVSyncProvider() {} virtual ~WinVSyncProvider() {}
virtual void GetVSyncParameters(const UpdateVSyncCallback& callback) { virtual void GetVSyncParameters(const UpdateVSyncCallback& callback) {
TRACE_EVENT0("gpu", "DWMVSyncProvider::GetVSyncParameters"); TRACE_EVENT0("gpu", "WinVSyncProvider::GetVSyncParameters");
base::TimeTicks timebase;
base::TimeDelta interval;
bool dwm_active = false;
// Query the DWM timing info first if available. This will provide the most
// precise values.
if (use_dwm_) {
DWM_TIMING_INFO timing_info; DWM_TIMING_INFO timing_info;
timing_info.cbSize = sizeof(timing_info); timing_info.cbSize = sizeof(timing_info);
HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info); HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info);
if (result != S_OK) if (result == S_OK) {
return; dwm_active = true;
base::TimeTicks timebase;
// If FrameTime is not high resolution, we do not want to translate the // If FrameTime is not high resolution, we do not want to translate the
// QPC value provided by DWM into the low-resolution timebase, which // QPC value provided by DWM into the low-resolution timebase, which
// would be error prone and jittery. As a fallback, we assume the timebase // would be error prone and jittery. As a fallback, we assume the
// is zero. // timebase is zero.
if (gfx::FrameTime::TimestampsAreHighRes()) { if (gfx::FrameTime::TimestampsAreHighRes()) {
timebase = gfx::FrameTime::FromQPCValue( timebase = gfx::FrameTime::FromQPCValue(
static_cast<LONGLONG>(timing_info.qpcVBlank)); static_cast<LONGLONG>(timing_info.qpcVBlank));
...@@ -86,16 +96,51 @@ class DWMVSyncProvider : public VSyncProvider { ...@@ -86,16 +96,51 @@ class DWMVSyncProvider : public VSyncProvider {
// Swap the numerator/denominator to convert frequency to period. // Swap the numerator/denominator to convert frequency to period.
if (timing_info.rateRefresh.uiDenominator > 0 && if (timing_info.rateRefresh.uiDenominator > 0 &&
timing_info.rateRefresh.uiNumerator > 0) { timing_info.rateRefresh.uiNumerator > 0) {
base::TimeDelta interval = base::TimeDelta::FromMicroseconds( interval = base::TimeDelta::FromMicroseconds(
timing_info.rateRefresh.uiDenominator * timing_info.rateRefresh.uiDenominator *
base::Time::kMicrosecondsPerSecond / base::Time::kMicrosecondsPerSecond /
timing_info.rateRefresh.uiNumerator); timing_info.rateRefresh.uiNumerator);
}
}
}
// Double check DWM values against per-display refresh rates.
// When DWM compositing is active all displays are normalized to the
// refresh rate of the primary display, and won't composite any faster.
// If the display refresh rate is higher than the DWM reported value we will
// favor the DWM value because any additional frames produced will be
// discarded by the OS. If the display refresh rate is lower, however, we
// can use that to limit the frames we produce more intelligently.
// If DWM compositing is not active we will always use the display refresh.
HMONITOR monitor = MonitorFromWindow(window_, MONITOR_DEFAULTTONEAREST);
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
BOOL result = GetMonitorInfo(monitor, &monitor_info);
if (result) {
DEVMODE display_info;
result = EnumDisplaySettings(monitor_info.szDevice, ENUM_CURRENT_SETTINGS,
&display_info);
if (result && display_info.dmDisplayFrequency > 1) {
base::TimeDelta display_interval = base::TimeDelta::FromMicroseconds(
(1.0 / static_cast<double>(display_info.dmDisplayFrequency)) *
base::Time::kMicrosecondsPerSecond);
if (!dwm_active || display_interval > interval) {
interval = display_interval;
}
}
}
if (interval.ToInternalValue() != 0) {
callback.Run(timebase, interval); callback.Run(timebase, interval);
} }
} }
private: private:
DISALLOW_COPY_AND_ASSIGN(DWMVSyncProvider); DISALLOW_COPY_AND_ASSIGN(WinVSyncProvider);
gfx::AcceleratedWidget window_;
bool use_dwm_;
}; };
// Helper routine that does one-off initialization like determining the // Helper routine that does one-off initialization like determining the
...@@ -245,8 +290,7 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( ...@@ -245,8 +290,7 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
scoped_refptr<NativeViewGLSurfaceEGL> surface( scoped_refptr<NativeViewGLSurfaceEGL> surface(
new NativeViewGLSurfaceEGL(window)); new NativeViewGLSurfaceEGL(window));
scoped_ptr<VSyncProvider> sync_provider; scoped_ptr<VSyncProvider> sync_provider;
if (base::win::GetVersion() >= base::win::VERSION_VISTA) sync_provider.reset(new WinVSyncProvider(window));
sync_provider.reset(new DWMVSyncProvider);
if (!surface->Initialize(sync_provider.Pass())) if (!surface->Initialize(sync_provider.Pass()))
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment