OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "cc/scheduler/begin_frame_source.h" | 5 #include "cc/scheduler/begin_frame_source.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
| 9 #include "base/atomic_sequence_num.h" |
9 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
10 #include "base/location.h" | 11 #include "base/location.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
15 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
16 #include "base/trace_event/trace_event_argument.h" | 17 #include "base/trace_event/trace_event_argument.h" |
17 #include "cc/scheduler/delay_based_time_source.h" | 18 #include "cc/scheduler/delay_based_time_source.h" |
18 #include "cc/scheduler/scheduler.h" | 19 #include "cc/scheduler/scheduler.h" |
19 | 20 |
20 namespace cc { | 21 namespace cc { |
21 | 22 |
22 namespace { | 23 namespace { |
23 // kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too | 24 // kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too |
24 // often to an observer. | 25 // often to an observer. |
25 static const double kDoubleTickDivisor = 2.0; | 26 static const double kDoubleTickDivisor = 2.0; |
26 } | 27 } |
27 | 28 |
28 // BeginFrameObserverBase ----------------------------------------------- | 29 // BeginFrameObserverBase ------------------------------------------------- |
29 BeginFrameObserverBase::BeginFrameObserverBase() | 30 BeginFrameObserverBase::BeginFrameObserverBase() |
30 : last_begin_frame_args_(), dropped_begin_frame_args_(0) { | 31 : last_begin_frame_args_(), dropped_begin_frame_args_(0) { |
31 } | 32 } |
32 | 33 |
33 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { | 34 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { |
34 return last_begin_frame_args_; | 35 return last_begin_frame_args_; |
35 } | 36 } |
| 37 |
36 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { | 38 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { |
37 DCHECK(args.IsValid()); | 39 DCHECK(args.IsValid()); |
38 DCHECK(args.frame_time >= last_begin_frame_args_.frame_time); | 40 DCHECK(args.frame_time >= last_begin_frame_args_.frame_time); |
| 41 DCHECK(args.sequence_number > last_begin_frame_args_.sequence_number || |
| 42 args.source_id != last_begin_frame_args_.source_id); |
39 bool used = OnBeginFrameDerivedImpl(args); | 43 bool used = OnBeginFrameDerivedImpl(args); |
40 if (used) { | 44 if (used) { |
41 last_begin_frame_args_ = args; | 45 last_begin_frame_args_ = args; |
42 } else { | 46 } else { |
43 ++dropped_begin_frame_args_; | 47 ++dropped_begin_frame_args_; |
44 } | 48 } |
45 } | 49 } |
46 | 50 |
| 51 // BeginFrameSource ------------------------------------------------------- |
| 52 namespace { |
| 53 static base::StaticAtomicSequenceNumber g_next_source_id; |
| 54 } // namespace |
| 55 |
| 56 BeginFrameSource::BeginFrameSource() : source_id_(g_next_source_id.GetNext()) {} |
| 57 |
| 58 uint32_t BeginFrameSource::source_id() const { |
| 59 return source_id_; |
| 60 } |
| 61 |
| 62 // StubBeginFrameSource --------------------------------------------------- |
47 bool StubBeginFrameSource::IsThrottled() const { | 63 bool StubBeginFrameSource::IsThrottled() const { |
48 return true; | 64 return true; |
49 } | 65 } |
50 | 66 |
51 // SyntheticBeginFrameSource --------------------------------------------- | 67 // SyntheticBeginFrameSource ---------------------------------------------- |
52 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; | 68 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; |
53 | 69 |
54 // BackToBackBeginFrameSource -------------------------------------------- | 70 // BackToBackBeginFrameSource --------------------------------------------- |
55 BackToBackBeginFrameSource::BackToBackBeginFrameSource( | 71 BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
56 std::unique_ptr<DelayBasedTimeSource> time_source) | 72 std::unique_ptr<DelayBasedTimeSource> time_source) |
57 : time_source_(std::move(time_source)), weak_factory_(this) { | 73 : time_source_(std::move(time_source)), |
| 74 next_sequence_number_(BeginFrameArgs::kStartingFrameNumber), |
| 75 weak_factory_(this) { |
58 time_source_->SetClient(this); | 76 time_source_->SetClient(this); |
59 // The time_source_ ticks immediately, so we SetActive(true) for a single | 77 // The time_source_ ticks immediately, so we SetActive(true) for a single |
60 // tick when we need it, and keep it as SetActive(false) otherwise. | 78 // tick when we need it, and keep it as SetActive(false) otherwise. |
61 time_source_->SetTimebaseAndInterval(base::TimeTicks(), base::TimeDelta()); | 79 time_source_->SetTimebaseAndInterval(base::TimeTicks(), base::TimeDelta()); |
62 } | 80 } |
63 | 81 |
64 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default; | 82 BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default; |
65 | 83 |
66 void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 84 void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
67 DCHECK(obs); | 85 DCHECK(obs); |
(...skipping 22 matching lines...) Expand all Loading... |
90 } | 108 } |
91 | 109 |
92 bool BackToBackBeginFrameSource::IsThrottled() const { | 110 bool BackToBackBeginFrameSource::IsThrottled() const { |
93 return false; | 111 return false; |
94 } | 112 } |
95 | 113 |
96 void BackToBackBeginFrameSource::OnTimerTick() { | 114 void BackToBackBeginFrameSource::OnTimerTick() { |
97 base::TimeTicks frame_time = time_source_->LastTickTime(); | 115 base::TimeTicks frame_time = time_source_->LastTickTime(); |
98 base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval(); | 116 base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval(); |
99 BeginFrameArgs args = BeginFrameArgs::Create( | 117 BeginFrameArgs args = BeginFrameArgs::Create( |
100 BEGINFRAME_FROM_HERE, frame_time, frame_time + default_interval, | 118 BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, frame_time, |
101 default_interval, BeginFrameArgs::NORMAL); | 119 frame_time + default_interval, default_interval, BeginFrameArgs::NORMAL); |
| 120 next_sequence_number_++; |
102 | 121 |
103 // This must happen after getting the LastTickTime() from the time source. | 122 // This must happen after getting the LastTickTime() from the time source. |
104 time_source_->SetActive(false); | 123 time_source_->SetActive(false); |
105 | 124 |
106 std::unordered_set<BeginFrameObserver*> pending_observers; | 125 std::unordered_set<BeginFrameObserver*> pending_observers; |
107 pending_observers.swap(pending_begin_frame_observers_); | 126 pending_observers.swap(pending_begin_frame_observers_); |
108 DCHECK(!pending_observers.empty()); | 127 DCHECK(!pending_observers.empty()); |
109 for (BeginFrameObserver* obs : pending_observers) | 128 for (BeginFrameObserver* obs : pending_observers) |
110 obs->OnBeginFrame(args); | 129 obs->OnBeginFrame(args); |
111 } | 130 } |
112 | 131 |
113 // DelayBasedBeginFrameSource --------------------------------------------- | 132 // DelayBasedBeginFrameSource --------------------------------------------- |
114 DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( | 133 DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( |
115 std::unique_ptr<DelayBasedTimeSource> time_source) | 134 std::unique_ptr<DelayBasedTimeSource> time_source) |
116 : time_source_(std::move(time_source)) { | 135 : time_source_(std::move(time_source)), |
| 136 next_sequence_number_(BeginFrameArgs::kStartingFrameNumber) { |
117 time_source_->SetClient(this); | 137 time_source_->SetClient(this); |
118 } | 138 } |
119 | 139 |
120 DelayBasedBeginFrameSource::~DelayBasedBeginFrameSource() = default; | 140 DelayBasedBeginFrameSource::~DelayBasedBeginFrameSource() = default; |
121 | 141 |
122 void DelayBasedBeginFrameSource::OnUpdateVSyncParameters( | 142 void DelayBasedBeginFrameSource::OnUpdateVSyncParameters( |
123 base::TimeTicks timebase, | 143 base::TimeTicks timebase, |
124 base::TimeDelta interval) { | 144 base::TimeDelta interval) { |
125 if (!authoritative_interval_.is_zero()) { | 145 if (!authoritative_interval_.is_zero()) { |
126 interval = authoritative_interval_; | 146 interval = authoritative_interval_; |
127 } else if (interval.is_zero()) { | 147 } else if (interval.is_zero()) { |
128 // TODO(brianderson): We should not be receiving 0 intervals. | 148 // TODO(brianderson): We should not be receiving 0 intervals. |
129 interval = BeginFrameArgs::DefaultInterval(); | 149 interval = BeginFrameArgs::DefaultInterval(); |
130 } | 150 } |
131 | 151 |
132 last_timebase_ = timebase; | 152 last_timebase_ = timebase; |
133 time_source_->SetTimebaseAndInterval(timebase, interval); | 153 time_source_->SetTimebaseAndInterval(timebase, interval); |
134 } | 154 } |
135 | 155 |
136 void DelayBasedBeginFrameSource::SetAuthoritativeVSyncInterval( | 156 void DelayBasedBeginFrameSource::SetAuthoritativeVSyncInterval( |
137 base::TimeDelta interval) { | 157 base::TimeDelta interval) { |
138 authoritative_interval_ = interval; | 158 authoritative_interval_ = interval; |
139 OnUpdateVSyncParameters(last_timebase_, interval); | 159 OnUpdateVSyncParameters(last_timebase_, interval); |
140 } | 160 } |
141 | 161 |
142 BeginFrameArgs DelayBasedBeginFrameSource::CreateBeginFrameArgs( | 162 BeginFrameArgs DelayBasedBeginFrameSource::CreateBeginFrameArgs( |
143 base::TimeTicks frame_time, | 163 base::TimeTicks frame_time, |
144 BeginFrameArgs::BeginFrameArgsType type) { | 164 BeginFrameArgs::BeginFrameArgsType type) { |
145 return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, | 165 uint64_t sequence_number = next_sequence_number_++; |
146 time_source_->NextTickTime(), | 166 return BeginFrameArgs::Create( |
147 time_source_->Interval(), type); | 167 BEGINFRAME_FROM_HERE, source_id(), sequence_number, frame_time, |
| 168 time_source_->NextTickTime(), time_source_->Interval(), type); |
148 } | 169 } |
149 | 170 |
150 void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 171 void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
151 DCHECK(obs); | 172 DCHECK(obs); |
152 DCHECK(observers_.find(obs) == observers_.end()); | 173 DCHECK(observers_.find(obs) == observers_.end()); |
153 | 174 |
154 observers_.insert(obs); | 175 observers_.insert(obs); |
155 obs->OnBeginFrameSourcePausedChanged(false); | 176 obs->OnBeginFrameSourcePausedChanged(false); |
156 time_source_->SetActive(true); | 177 time_source_->SetActive(true); |
157 BeginFrameArgs args = CreateBeginFrameArgs( | 178 |
158 time_source_->NextTickTime() - time_source_->Interval(), | 179 // Missed args should correspond to |current_begin_frame_args_| (particularly, |
159 BeginFrameArgs::MISSED); | 180 // have the same sequence number) if |current_begin_frame_args_| still |
| 181 // correspond to the last time the time source should have ticked. This may |
| 182 // not be the case if OnTimerTick() has never run yet, the time source was |
| 183 // inactive before AddObserver() was called, or the interval changed. In such |
| 184 // a case, we create new args with a new sequence number. |
| 185 base::TimeTicks last_or_missed_tick_time = |
| 186 time_source_->NextTickTime() - time_source_->Interval(); |
| 187 if (current_begin_frame_args_.IsValid() && |
| 188 current_begin_frame_args_.frame_time == last_or_missed_tick_time && |
| 189 current_begin_frame_args_.interval == time_source_->Interval()) { |
| 190 // Ensure that the args have the right type. |
| 191 current_begin_frame_args_.type = BeginFrameArgs::MISSED; |
| 192 } else { |
| 193 // The args are not up to date and we need to create new ones with the |
| 194 // missed tick's time and a new sequence number. |
| 195 current_begin_frame_args_ = |
| 196 CreateBeginFrameArgs(last_or_missed_tick_time, BeginFrameArgs::MISSED); |
| 197 } |
| 198 |
160 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 199 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
161 if (!last_args.IsValid() || | 200 if (!last_args.IsValid() || |
162 (args.frame_time > | 201 (current_begin_frame_args_.frame_time > |
163 last_args.frame_time + args.interval / kDoubleTickDivisor)) { | 202 last_args.frame_time + |
164 obs->OnBeginFrame(args); | 203 current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
| 204 obs->OnBeginFrame(current_begin_frame_args_); |
165 } | 205 } |
166 } | 206 } |
167 | 207 |
168 void DelayBasedBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 208 void DelayBasedBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
169 DCHECK(obs); | 209 DCHECK(obs); |
170 DCHECK(observers_.find(obs) != observers_.end()); | 210 DCHECK(observers_.find(obs) != observers_.end()); |
171 | 211 |
172 observers_.erase(obs); | 212 observers_.erase(obs); |
173 if (observers_.empty()) | 213 if (observers_.empty()) |
174 time_source_->SetActive(false); | 214 time_source_->SetActive(false); |
175 } | 215 } |
176 | 216 |
177 bool DelayBasedBeginFrameSource::IsThrottled() const { | 217 bool DelayBasedBeginFrameSource::IsThrottled() const { |
178 return true; | 218 return true; |
179 } | 219 } |
180 | 220 |
181 void DelayBasedBeginFrameSource::OnTimerTick() { | 221 void DelayBasedBeginFrameSource::OnTimerTick() { |
182 BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), | 222 current_begin_frame_args_ = CreateBeginFrameArgs(time_source_->LastTickTime(), |
183 BeginFrameArgs::NORMAL); | 223 BeginFrameArgs::NORMAL); |
184 std::unordered_set<BeginFrameObserver*> observers(observers_); | 224 std::unordered_set<BeginFrameObserver*> observers(observers_); |
185 for (auto* obs : observers) { | 225 for (auto* obs : observers) { |
186 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 226 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
187 if (!last_args.IsValid() || | 227 if (!last_args.IsValid() || |
188 (args.frame_time > | 228 (current_begin_frame_args_.frame_time > |
189 last_args.frame_time + args.interval / kDoubleTickDivisor)) | 229 last_args.frame_time + |
190 obs->OnBeginFrame(args); | 230 current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
| 231 obs->OnBeginFrame(current_begin_frame_args_); |
| 232 } |
191 } | 233 } |
192 } | 234 } |
193 | 235 |
| 236 // ExternalBeginFrameSource ----------------------------------------------- |
194 ExternalBeginFrameSource::ExternalBeginFrameSource( | 237 ExternalBeginFrameSource::ExternalBeginFrameSource( |
195 ExternalBeginFrameSourceClient* client) | 238 ExternalBeginFrameSourceClient* client) |
196 : client_(client) { | 239 : client_(client) { |
197 DCHECK(client_); | 240 DCHECK(client_); |
198 } | 241 } |
199 | 242 |
200 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; | 243 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; |
201 | 244 |
202 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 245 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
203 DCHECK(obs); | 246 DCHECK(obs); |
204 DCHECK(observers_.find(obs) == observers_.end()); | 247 DCHECK(observers_.find(obs) == observers_.end()); |
205 | 248 |
206 bool observers_was_empty = observers_.empty(); | 249 bool observers_was_empty = observers_.empty(); |
207 observers_.insert(obs); | 250 observers_.insert(obs); |
208 obs->OnBeginFrameSourcePausedChanged(paused_); | 251 obs->OnBeginFrameSourcePausedChanged(paused_); |
209 if (observers_was_empty) | 252 if (observers_was_empty) |
210 client_->OnNeedsBeginFrames(true); | 253 client_->OnNeedsBeginFrames(true); |
211 | 254 |
212 // Send a MISSED begin frame if necessary. | 255 // Send a MISSED begin frame if necessary. |
213 if (missed_begin_frame_args_.IsValid()) { | 256 if (missed_begin_frame_args_.IsValid()) { |
214 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 257 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
215 if (!last_args.IsValid() || | 258 if (!last_args.IsValid() || |
216 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { | 259 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { |
| 260 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || |
| 261 (missed_begin_frame_args_.sequence_number > |
| 262 last_args.sequence_number)); |
217 obs->OnBeginFrame(missed_begin_frame_args_); | 263 obs->OnBeginFrame(missed_begin_frame_args_); |
218 } | 264 } |
219 } | 265 } |
220 } | 266 } |
221 | 267 |
222 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 268 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
223 DCHECK(obs); | 269 DCHECK(obs); |
224 DCHECK(observers_.find(obs) != observers_.end()); | 270 DCHECK(observers_.find(obs) != observers_.end()); |
225 | 271 |
226 observers_.erase(obs); | 272 observers_.erase(obs); |
(...skipping 18 matching lines...) Expand all Loading... |
245 | 291 |
246 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { | 292 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { |
247 missed_begin_frame_args_ = args; | 293 missed_begin_frame_args_ = args; |
248 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; | 294 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; |
249 std::unordered_set<BeginFrameObserver*> observers(observers_); | 295 std::unordered_set<BeginFrameObserver*> observers(observers_); |
250 for (auto* obs : observers) | 296 for (auto* obs : observers) |
251 obs->OnBeginFrame(args); | 297 obs->OnBeginFrame(args); |
252 } | 298 } |
253 | 299 |
254 } // namespace cc | 300 } // namespace cc |
OLD | NEW |