Index: ui/gl/vsync_provider.cc |
diff --git a/ui/gl/vsync_provider.cc b/ui/gl/vsync_provider.cc |
index e117647c7f1434d32d7fe3bc4ea896545d6e9a59..91d64e0d04274c2e4bcf64a57ff08f5060711ed2 100644 |
--- a/ui/gl/vsync_provider.cc |
+++ b/ui/gl/vsync_provider.cc |
@@ -4,6 +4,8 @@ |
#include "ui/gl/vsync_provider.h" |
+#include <math.h> |
+ |
#include "base/logging.h" |
#include "base/time.h" |
@@ -14,6 +16,11 @@ namespace { |
const int64 kMinVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 400; |
const int64 kMaxVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 10; |
+// How much noise we'll tolerate between successive computed intervals before |
+// we think the latest computed interval is invalid (noisey due to |
+// monitor configuration change, moving a window between monitors, etc.). |
+const double kRelativeIntervalDifferenceThreshold = 0.05; |
+ |
} // namespace |
namespace gfx { |
@@ -94,32 +101,46 @@ void SyncControlVSyncProvider::GetVSyncParameters( |
timebase = base::TimeTicks::FromInternalValue(system_time); |
+ // Only need the previous calculated interval for our filtering. |
+ while (last_computed_intervals_.size() > 1) |
+ last_computed_intervals_.pop(); |
+ |
int32 numerator, denominator; |
- base::TimeDelta new_interval; |
if (GetMscRate(&numerator, &denominator)) { |
- new_interval = |
- base::TimeDelta::FromSeconds(denominator) / numerator; |
+ last_computed_intervals_.push( |
+ base::TimeDelta::FromSeconds(denominator) / numerator); |
} 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_) |
- new_interval = timebase_diff / counter_diff; |
+ last_computed_intervals_.push(timebase_diff / counter_diff); |
} |
- if (new_interval.InMicroseconds() < kMinVsyncIntervalUs || |
- new_interval.InMicroseconds() > kMaxVsyncIntervalUs) { |
- LOG(ERROR) << "Calculated bogus refresh interval of " |
- << new_interval.InMicroseconds() << " us. " |
- << "Last time base of " |
- << last_timebase_.ToInternalValue() << " us. " |
- << "Current time base of " |
- << timebase.ToInternalValue() << " us. " |
- << "Last media stream count of " |
- << last_media_stream_counter_ << ". " |
- << "Current media stream count of " |
- << media_stream_counter << "."; |
- } else { |
- last_good_interval_ = new_interval; |
+ |
+ if (last_computed_intervals_.size() == 2) { |
+ const base::TimeDelta& old_interval = last_computed_intervals_.front(); |
+ const base::TimeDelta& new_interval = last_computed_intervals_.back(); |
+ |
+ double relative_change = |
+ fabs(old_interval.InMillisecondsF() - new_interval.InMillisecondsF()) / |
+ new_interval.InMillisecondsF(); |
+ if (relative_change < kRelativeIntervalDifferenceThreshold) { |
+ if (new_interval.InMicroseconds() < kMinVsyncIntervalUs || |
+ new_interval.InMicroseconds() > kMaxVsyncIntervalUs) { |
+ LOG(FATAL) << "Calculated bogus refresh interval of " |
+ << new_interval.InMicroseconds() << " us. " |
+ << "Last time base of " |
+ << last_timebase_.ToInternalValue() << " us. " |
+ << "Current time base of " |
+ << timebase.ToInternalValue() << " us. " |
+ << "Last media stream count of " |
+ << last_media_stream_counter_ << ". " |
+ << "Current media stream count of " |
+ << media_stream_counter << "."; |
+ } else { |
+ last_good_interval_ = new_interval; |
+ } |
+ } |
} |
last_timebase_ = timebase; |