Index: ui/gl/gl_surface_win.cc |
diff --git a/ui/gl/gl_surface_win.cc b/ui/gl/gl_surface_win.cc |
index 02407a580c79f97d6384d400bd41f87c189a7344..33ba90174f9ecbfeab27bb9334e06dcf54b847a6 100644 |
--- a/ui/gl/gl_surface_win.cc |
+++ b/ui/gl/gl_surface_win.cc |
@@ -76,6 +76,19 @@ class WinVSyncProvider : public VSyncProvider { |
HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info); |
if (result == S_OK) { |
dwm_active = true; |
+ |
+ // Calculate an interval value using the rateRefresh numerator and |
+ // denominator. |
+ base::TimeDelta rate_interval; |
+ if (timing_info.rateRefresh.uiDenominator > 0 && |
+ timing_info.rateRefresh.uiNumerator > 0) { |
+ // Swap the numerator/denominator to convert frequency to period. |
+ rate_interval = base::TimeDelta::FromMicroseconds( |
+ timing_info.rateRefresh.uiDenominator * |
+ base::Time::kMicrosecondsPerSecond / |
+ timing_info.rateRefresh.uiNumerator); |
+ } |
+ |
if (gfx::FrameTime::TimestampsAreHighRes()) { |
// qpcRefreshPeriod is very accurate but noisy, and must be used with |
// a high resolution timebase to avoid frequently missing Vsync. |
@@ -83,8 +96,18 @@ class WinVSyncProvider : public VSyncProvider { |
static_cast<LONGLONG>(timing_info.qpcVBlank)); |
interval = base::TimeDelta::FromQPCValue( |
static_cast<LONGLONG>(timing_info.qpcRefreshPeriod)); |
- } else if (timing_info.rateRefresh.uiDenominator > 0 && |
- timing_info.rateRefresh.uiNumerator > 0) { |
+ // Check for interval values that are impossibly low. A 29 microsecond |
+ // interval was seen (from a qpcRefreshPeriod of 60). |
+ if (interval < base::TimeDelta::FromMilliseconds(1)) { |
+ interval = rate_interval; |
+ } |
+ // Check for the qpcRefreshPeriod interval being improbably small |
+ // compared to the rateRefresh calculated interval, as another |
+ // attempt at detecting driver bugs. |
+ if (!rate_interval.is_zero() && interval < rate_interval / 2) { |
+ interval = rate_interval; |
+ } |
+ } else { |
// If FrameTime is not high resolution, we do not want to translate |
// the QPC value provided by DWM into the low-resolution timebase, |
// which would be error prone and jittery. As a fallback, we assume |
@@ -92,12 +115,7 @@ class WinVSyncProvider : public VSyncProvider { |
// isn't noisy like qpcRefreshPeriod, instead. The fact that we don't |
// have a timebase here may lead to brief periods of jank when our |
// scheduling becomes offset from the hardware vsync. |
- |
- // Swap the numerator/denominator to convert frequency to period. |
- interval = base::TimeDelta::FromMicroseconds( |
- timing_info.rateRefresh.uiDenominator * |
- base::Time::kMicrosecondsPerSecond / |
- timing_info.rateRefresh.uiNumerator); |
+ interval = rate_interval; |
} |
} |
} |