OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/vsync_provider.h" | 5 #include "ui/gl/vsync_provider.h" |
6 | 6 |
| 7 #include <math.h> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "base/time.h" | 10 #include "base/time.h" |
9 | 11 |
10 namespace { | 12 namespace { |
11 | 13 |
12 // These constants define a reasonable range for a calculated refresh interval. | 14 // These constants define a reasonable range for a calculated refresh interval. |
13 // Calculating refreshes out of this range will be considered a fatal error. | 15 // Calculating refreshes out of this range will be considered a fatal error. |
14 const int64 kMinVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 400; | 16 const int64 kMinVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 400; |
15 const int64 kMaxVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 10; | 17 const int64 kMaxVsyncIntervalUs = base::Time::kMicrosecondsPerSecond / 10; |
16 | 18 |
| 19 // How much noise we'll tolerate between successive computed intervals before |
| 20 // we think the latest computed interval is invalid (noisey due to |
| 21 // monitor configuration change, moving a window between monitors, etc.). |
| 22 const double kRelativeIntervalDifferenceThreshold = 0.05; |
| 23 |
17 } // namespace | 24 } // namespace |
18 | 25 |
19 namespace gfx { | 26 namespace gfx { |
20 | 27 |
21 VSyncProvider::VSyncProvider() { | 28 VSyncProvider::VSyncProvider() { |
22 } | 29 } |
23 | 30 |
24 VSyncProvider::~VSyncProvider() { | 31 VSyncProvider::~VSyncProvider() { |
25 } | 32 } |
26 | 33 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 if (system_time > monotonic_time_in_microseconds) { | 94 if (system_time > monotonic_time_in_microseconds) { |
88 system_time -= interval_in_microseconds; | 95 system_time -= interval_in_microseconds; |
89 media_stream_counter--; | 96 media_stream_counter--; |
90 } | 97 } |
91 if (monotonic_time_in_microseconds - system_time > | 98 if (monotonic_time_in_microseconds - system_time > |
92 base::Time::kMicrosecondsPerSecond) | 99 base::Time::kMicrosecondsPerSecond) |
93 return; | 100 return; |
94 | 101 |
95 timebase = base::TimeTicks::FromInternalValue(system_time); | 102 timebase = base::TimeTicks::FromInternalValue(system_time); |
96 | 103 |
| 104 // Only need the previous calculated interval for our filtering. |
| 105 while (last_computed_intervals_.size() > 1) |
| 106 last_computed_intervals_.pop(); |
| 107 |
97 int32 numerator, denominator; | 108 int32 numerator, denominator; |
98 base::TimeDelta new_interval; | |
99 if (GetMscRate(&numerator, &denominator)) { | 109 if (GetMscRate(&numerator, &denominator)) { |
100 new_interval = | 110 last_computed_intervals_.push( |
101 base::TimeDelta::FromSeconds(denominator) / numerator; | 111 base::TimeDelta::FromSeconds(denominator) / numerator); |
102 } else if (!last_timebase_.is_null()) { | 112 } else if (!last_timebase_.is_null()) { |
103 base::TimeDelta timebase_diff = timebase - last_timebase_; | 113 base::TimeDelta timebase_diff = timebase - last_timebase_; |
104 uint64 counter_diff = media_stream_counter - | 114 uint64 counter_diff = media_stream_counter - |
105 last_media_stream_counter_; | 115 last_media_stream_counter_; |
106 if (counter_diff > 0 && timebase > last_timebase_) | 116 if (counter_diff > 0 && timebase > last_timebase_) |
107 new_interval = timebase_diff / counter_diff; | 117 last_computed_intervals_.push(timebase_diff / counter_diff); |
108 } | 118 } |
109 if (new_interval.InMicroseconds() < kMinVsyncIntervalUs || | 119 |
110 new_interval.InMicroseconds() > kMaxVsyncIntervalUs) { | 120 if (last_computed_intervals_.size() == 2) { |
111 LOG(ERROR) << "Calculated bogus refresh interval of " | 121 const base::TimeDelta& old_interval = last_computed_intervals_.front(); |
112 << new_interval.InMicroseconds() << " us. " | 122 const base::TimeDelta& new_interval = last_computed_intervals_.back(); |
113 << "Last time base of " | 123 |
114 << last_timebase_.ToInternalValue() << " us. " | 124 double relative_change = |
115 << "Current time base of " | 125 fabs(old_interval.InMillisecondsF() - new_interval.InMillisecondsF()) / |
116 << timebase.ToInternalValue() << " us. " | 126 new_interval.InMillisecondsF(); |
117 << "Last media stream count of " | 127 if (relative_change < kRelativeIntervalDifferenceThreshold) { |
118 << last_media_stream_counter_ << ". " | 128 if (new_interval.InMicroseconds() < kMinVsyncIntervalUs || |
119 << "Current media stream count of " | 129 new_interval.InMicroseconds() > kMaxVsyncIntervalUs) { |
120 << media_stream_counter << "."; | 130 LOG(FATAL) << "Calculated bogus refresh interval of " |
121 } else { | 131 << new_interval.InMicroseconds() << " us. " |
122 last_good_interval_ = new_interval; | 132 << "Last time base of " |
| 133 << last_timebase_.ToInternalValue() << " us. " |
| 134 << "Current time base of " |
| 135 << timebase.ToInternalValue() << " us. " |
| 136 << "Last media stream count of " |
| 137 << last_media_stream_counter_ << ". " |
| 138 << "Current media stream count of " |
| 139 << media_stream_counter << "."; |
| 140 } else { |
| 141 last_good_interval_ = new_interval; |
| 142 } |
| 143 } |
123 } | 144 } |
124 | 145 |
125 last_timebase_ = timebase; | 146 last_timebase_ = timebase; |
126 last_media_stream_counter_ = media_stream_counter; | 147 last_media_stream_counter_ = media_stream_counter; |
127 callback.Run(timebase, last_good_interval_); | 148 callback.Run(timebase, last_good_interval_); |
128 #endif // defined(OS_LINUX) | 149 #endif // defined(OS_LINUX) |
129 } | 150 } |
130 | 151 |
131 } // namespace gfx | 152 } // namespace gfx |
OLD | NEW |