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/atomic_sequence_num.h" |
10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 226 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
227 if (!last_args.IsValid() || | 227 if (!last_args.IsValid() || |
228 (current_begin_frame_args_.frame_time > | 228 (current_begin_frame_args_.frame_time > |
229 last_args.frame_time + | 229 last_args.frame_time + |
230 current_begin_frame_args_.interval / kDoubleTickDivisor)) { | 230 current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
231 obs->OnBeginFrame(current_begin_frame_args_); | 231 obs->OnBeginFrame(current_begin_frame_args_); |
232 } | 232 } |
233 } | 233 } |
234 } | 234 } |
235 | 235 |
236 // BeginFrameObserverAckTracker ------------------------------------------- | |
237 BeginFrameObserverAckTracker::BeginFrameObserverAckTracker() | |
238 : current_source_id_(0), | |
239 current_sequence_number_(BeginFrameArgs::kStartingFrameNumber), | |
240 observers_had_damage_(false) {} | |
241 | |
242 BeginFrameObserverAckTracker::~BeginFrameObserverAckTracker() {} | |
243 | |
244 void BeginFrameObserverAckTracker::OnBeginFrame(const BeginFrameArgs& args) { | |
245 if (current_source_id_ != args.source_id) | |
246 SourceChanged(args); | |
247 | |
248 DCHECK_GE(args.sequence_number, current_sequence_number_); | |
249 // Reset for new BeginFrame. | |
250 current_sequence_number_ = args.sequence_number; | |
251 finished_observers_.clear(); | |
252 observers_had_damage_ = false; | |
253 } | |
254 | |
255 void BeginFrameObserverAckTracker::OnObserverBeginFrame( | |
256 BeginFrameObserver* obs, | |
257 const BeginFrameArgs& args) { | |
258 if (current_source_id_ != args.source_id) | |
259 SourceChanged(args); | |
260 | |
261 DCHECK_EQ(args.sequence_number, current_sequence_number_); | |
262 // Observer may choose to drop the BeginFrame. In this case, it has finished, | |
263 // but is not considered up-to-date. | |
264 if (obs->LastUsedBeginFrameArgs().sequence_number != current_sequence_number_) | |
brianderson
2017/02/15 20:50:47
Why is this != instead of ==?
Eric Seckler
2017/02/17 19:10:01
This checks if the observer actually uses the Begi
brianderson
2017/02/17 20:49:54
Ah, I see. Instead of doing this, can we require O
Eric Seckler
2017/02/17 22:49:35
I think I'll make those changes and send out anoth
Eric Seckler
2017/02/21 12:10:57
Turns out it doesn't require much changes at this
| |
265 finished_observers_.insert(obs); | |
266 } | |
267 | |
268 void BeginFrameObserverAckTracker::SourceChanged(const BeginFrameArgs& args) { | |
269 current_source_id_ = args.source_id; | |
270 current_sequence_number_ = args.sequence_number; | |
271 | |
272 // Mark all observers invalid: We report an invalid frame until every observer | |
273 // has confirmed the frame. | |
274 for (auto& entry : latest_confirmed_sequence_numbers_) | |
275 entry.second = BeginFrameArgs::kInvalidFrameNumber; | |
276 } | |
277 | |
278 void BeginFrameObserverAckTracker::OnObserverFinishedFrame( | |
279 BeginFrameObserver* obs, | |
280 const BeginFrameAck& ack) { | |
281 if (ack.source_id != current_source_id_) | |
282 return; | |
283 | |
284 DCHECK_LE(ack.sequence_number, current_sequence_number_); | |
285 if (ack.sequence_number != current_sequence_number_) | |
286 return; | |
287 | |
288 finished_observers_.insert(obs); | |
289 observers_had_damage_ |= ack.has_damage; | |
290 | |
291 // We max() with the current value in |latest_confirmed_sequence_numbers_| to | |
292 // handle situations where an observer just started observing (again) and may | |
293 // acknowledge with an ancient latest_confirmed_sequence_number. | |
294 latest_confirmed_sequence_numbers_[obs] = | |
295 std::max(ack.latest_confirmed_sequence_number, | |
296 latest_confirmed_sequence_numbers_[obs]); | |
297 } | |
298 | |
299 void BeginFrameObserverAckTracker::OnObserverAdded(BeginFrameObserver* obs) { | |
300 observers_.insert(obs); | |
301 | |
302 // Since the observer didn't want BeginFrames before, we consider it | |
303 // up-to-date up to the last BeginFrame, except if it already handled the | |
304 // current BeginFrame. In which case, we consider it up-to-date up to the | |
305 // current one. | |
306 DCHECK_LT(BeginFrameArgs::kInvalidFrameNumber, current_sequence_number_); | |
307 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | |
308 if (last_args.IsValid() && | |
309 last_args.sequence_number == current_sequence_number_ && | |
310 last_args.source_id == current_source_id_) { | |
311 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_; | |
312 finished_observers_.insert(obs); | |
313 } else { | |
314 latest_confirmed_sequence_numbers_[obs] = current_sequence_number_ - 1; | |
315 } | |
316 } | |
317 | |
318 void BeginFrameObserverAckTracker::OnObserverRemoved(BeginFrameObserver* obs) { | |
319 observers_.erase(obs); | |
320 finished_observers_.erase(obs); | |
321 latest_confirmed_sequence_numbers_.erase(obs); | |
322 } | |
323 | |
324 bool BeginFrameObserverAckTracker::AllObserversFinishedFrame() const { | |
325 return base::STLIncludes(finished_observers_, observers_); | |
brianderson
2017/02/15 20:50:48
It looks like STLIncludes depends on std::includes
Eric Seckler
2017/02/17 19:10:01
Added the early out. I don't think we can guarante
| |
326 } | |
327 | |
328 bool BeginFrameObserverAckTracker::AnyObserversHadDamage() const { | |
329 return observers_had_damage_; | |
330 } | |
331 | |
332 uint64_t BeginFrameObserverAckTracker::LatestConfirmedSequenceNumber() const { | |
333 uint64_t latest_confirmed_sequence_number = current_sequence_number_; | |
334 for (const auto& entry : latest_confirmed_sequence_numbers_) { | |
335 latest_confirmed_sequence_number = | |
336 std::min(latest_confirmed_sequence_number, entry.second); | |
337 } | |
338 return latest_confirmed_sequence_number; | |
339 } | |
340 | |
236 // ExternalBeginFrameSource ----------------------------------------------- | 341 // ExternalBeginFrameSource ----------------------------------------------- |
237 ExternalBeginFrameSource::ExternalBeginFrameSource( | 342 ExternalBeginFrameSource::ExternalBeginFrameSource( |
238 ExternalBeginFrameSourceClient* client) | 343 ExternalBeginFrameSourceClient* client) |
239 : client_(client) { | 344 : client_(client) { |
240 DCHECK(client_); | 345 DCHECK(client_); |
241 } | 346 } |
242 | 347 |
243 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; | 348 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; |
244 | 349 |
245 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 350 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
246 DCHECK(obs); | 351 DCHECK(obs); |
247 DCHECK(observers_.find(obs) == observers_.end()); | 352 DCHECK(observers_.find(obs) == observers_.end()); |
248 | 353 |
249 bool observers_was_empty = observers_.empty(); | 354 bool observers_was_empty = observers_.empty(); |
250 observers_.insert(obs); | 355 observers_.insert(obs); |
356 ack_tracker_.OnObserverAdded(obs); | |
251 obs->OnBeginFrameSourcePausedChanged(paused_); | 357 obs->OnBeginFrameSourcePausedChanged(paused_); |
252 if (observers_was_empty) | 358 if (observers_was_empty) |
253 client_->OnNeedsBeginFrames(true); | 359 client_->OnNeedsBeginFrames(true); |
254 | 360 |
255 // Send a MISSED begin frame if necessary. | 361 // Send a MISSED begin frame if necessary. |
256 if (missed_begin_frame_args_.IsValid()) { | 362 if (missed_begin_frame_args_.IsValid()) { |
257 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); | 363 BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
258 if (!last_args.IsValid() || | 364 if (!last_args.IsValid() || |
259 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { | 365 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { |
260 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || | 366 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || |
261 (missed_begin_frame_args_.sequence_number > | 367 (missed_begin_frame_args_.sequence_number > |
262 last_args.sequence_number)); | 368 last_args.sequence_number)); |
263 obs->OnBeginFrame(missed_begin_frame_args_); | 369 obs->OnBeginFrame(missed_begin_frame_args_); |
370 ack_tracker_.OnObserverBeginFrame(obs, missed_begin_frame_args_); | |
264 } | 371 } |
265 } | 372 } |
266 } | 373 } |
267 | 374 |
268 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 375 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
269 DCHECK(obs); | 376 DCHECK(obs); |
270 DCHECK(observers_.find(obs) != observers_.end()); | 377 DCHECK(observers_.find(obs) != observers_.end()); |
271 | 378 |
272 observers_.erase(obs); | 379 observers_.erase(obs); |
380 ack_tracker_.OnObserverRemoved(obs); | |
381 MaybeFinishFrame(); | |
273 if (observers_.empty()) { | 382 if (observers_.empty()) { |
274 missed_begin_frame_args_ = BeginFrameArgs(); | 383 missed_begin_frame_args_ = BeginFrameArgs(); |
275 client_->OnNeedsBeginFrames(false); | 384 client_->OnNeedsBeginFrames(false); |
276 } | 385 } |
277 } | 386 } |
278 | 387 |
388 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, | |
389 const BeginFrameAck& ack) { | |
390 ack_tracker_.OnObserverFinishedFrame(obs, ack); | |
391 MaybeFinishFrame(); | |
392 } | |
393 | |
279 bool ExternalBeginFrameSource::IsThrottled() const { | 394 bool ExternalBeginFrameSource::IsThrottled() const { |
280 return true; | 395 return true; |
281 } | 396 } |
282 | 397 |
283 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { | 398 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { |
284 if (paused_ == paused) | 399 if (paused_ == paused) |
285 return; | 400 return; |
286 paused_ = paused; | 401 paused_ = paused; |
287 std::unordered_set<BeginFrameObserver*> observers(observers_); | 402 std::unordered_set<BeginFrameObserver*> observers(observers_); |
288 for (auto* obs : observers) | 403 for (auto* obs : observers) |
289 obs->OnBeginFrameSourcePausedChanged(paused_); | 404 obs->OnBeginFrameSourcePausedChanged(paused_); |
290 } | 405 } |
291 | 406 |
292 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { | 407 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { |
408 if (frame_active_) | |
409 FinishFrame(); | |
410 | |
411 frame_active_ = true; | |
293 missed_begin_frame_args_ = args; | 412 missed_begin_frame_args_ = args; |
294 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; | 413 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; |
414 ack_tracker_.OnBeginFrame(args); | |
295 std::unordered_set<BeginFrameObserver*> observers(observers_); | 415 std::unordered_set<BeginFrameObserver*> observers(observers_); |
296 for (auto* obs : observers) | 416 for (auto* obs : observers) { |
297 obs->OnBeginFrame(args); | 417 obs->OnBeginFrame(args); |
418 ack_tracker_.OnObserverBeginFrame(obs, args); | |
419 } | |
420 MaybeFinishFrame(); | |
421 } | |
422 | |
423 void ExternalBeginFrameSource::MaybeFinishFrame() { | |
424 if (!frame_active_ || !ack_tracker_.AllObserversFinishedFrame()) | |
425 return; | |
426 FinishFrame(); | |
427 } | |
428 | |
429 void ExternalBeginFrameSource::FinishFrame() { | |
430 frame_active_ = false; | |
431 | |
432 BeginFrameAck ack(missed_begin_frame_args_.source_id, | |
433 missed_begin_frame_args_.sequence_number, | |
434 ack_tracker_.LatestConfirmedSequenceNumber(), 0, | |
435 ack_tracker_.AnyObserversHadDamage()); | |
436 client_->OnDidFinishFrame(ack); | |
298 } | 437 } |
299 | 438 |
300 } // namespace cc | 439 } // namespace cc |
OLD | NEW |