Chromium Code Reviews| 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" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
| 17 #include "base/trace_event/trace_event_argument.h" | 17 #include "base/trace_event/trace_event_argument.h" |
| 18 #include "cc/scheduler/delay_based_time_source.h" | 18 #include "cc/scheduler/delay_based_time_source.h" |
| 19 #include "cc/scheduler/scheduler.h" | 19 #include "cc/scheduler/scheduler.h" |
| 20 | 20 |
| 21 namespace cc { | 21 namespace cc { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 // kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too | 24 // kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too |
| 25 // often to an observer. | 25 // often to an observer. |
| 26 static const double kDoubleTickDivisor = 2.0; | 26 static const double kDoubleTickDivisor = 2.0; |
| 27 } | 27 } |
| 28 | 28 |
| 29 // BeginFrameObserverBase ------------------------------------------------- | 29 // BeginFrameObserverBase ------------------------------------------------- |
| 30 BeginFrameObserverBase::BeginFrameObserverBase() | 30 BeginFrameObserverBase::BeginFrameObserverBase() = default; |
| 31 : last_begin_frame_args_(), dropped_begin_frame_args_(0) { | 31 |
| 32 } | 32 BeginFrameObserverBase::~BeginFrameObserverBase() = default; |
| 33 | 33 |
| 34 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { | 34 const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { |
| 35 return last_begin_frame_args_; | 35 return last_begin_frame_args_; |
| 36 } | 36 } |
| 37 | 37 |
| 38 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { | 38 void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { |
| 39 DCHECK(args.IsValid()); | 39 DCHECK(args.IsValid()); |
| 40 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 || | 41 DCHECK(args.sequence_number > last_begin_frame_args_.sequence_number || |
| 42 args.source_id != last_begin_frame_args_.source_id) | 42 args.source_id != last_begin_frame_args_.source_id) |
| 43 << "current " << args.AsValue()->ToString() << ", last " | 43 << "current " << args.AsValue()->ToString() << ", last " |
| 44 << last_begin_frame_args_.AsValue()->ToString(); | 44 << last_begin_frame_args_.AsValue()->ToString(); |
| 45 bool used = OnBeginFrameDerivedImpl(args); | 45 bool used = OnBeginFrameDerivedImpl(args); |
| 46 if (used) { | 46 if (used) { |
| 47 last_begin_frame_args_ = args; | 47 last_begin_frame_args_ = args; |
| 48 } else { | 48 } else { |
| 49 ++dropped_begin_frame_args_; | 49 ++dropped_begin_frame_args_; |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 void BeginFrameObserverBase::AsValueInto( | |
| 54 base::trace_event::TracedValue* state) const { | |
| 55 state->SetInteger("dropped_begin_frame_args", dropped_begin_frame_args_); | |
| 56 | |
| 57 state->BeginDictionary("last_begin_frame_args"); | |
| 58 last_begin_frame_args_.AsValueInto(state); | |
| 59 state->EndDictionary(); | |
| 60 } | |
| 61 | |
| 53 // BeginFrameSource ------------------------------------------------------- | 62 // BeginFrameSource ------------------------------------------------------- |
| 54 namespace { | 63 namespace { |
| 55 static base::StaticAtomicSequenceNumber g_next_source_id; | 64 static base::StaticAtomicSequenceNumber g_next_source_id; |
| 56 } // namespace | 65 } // namespace |
| 57 | 66 |
| 58 BeginFrameSource::BeginFrameSource() : source_id_(g_next_source_id.GetNext()) {} | 67 BeginFrameSource::BeginFrameSource() : source_id_(g_next_source_id.GetNext()) {} |
| 59 | 68 |
| 60 uint32_t BeginFrameSource::source_id() const { | 69 BeginFrameSource::~BeginFrameSource() = default; |
| 61 return source_id_; | 70 |
| 71 void BeginFrameSource::AsValueInto( | |
| 72 base::trace_event::TracedValue* state) const { | |
| 73 state->SetInteger("source_id", source_id_); | |
| 62 } | 74 } |
| 63 | 75 |
| 64 // StubBeginFrameSource --------------------------------------------------- | 76 // StubBeginFrameSource --------------------------------------------------- |
| 65 bool StubBeginFrameSource::IsThrottled() const { | 77 bool StubBeginFrameSource::IsThrottled() const { |
| 66 return true; | 78 return true; |
| 67 } | 79 } |
| 68 | 80 |
| 69 // SyntheticBeginFrameSource ---------------------------------------------- | 81 // SyntheticBeginFrameSource ---------------------------------------------- |
| 70 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; | 82 SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; |
| 71 | 83 |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 if (!last_args.IsValid() || | 246 if (!last_args.IsValid() || |
| 235 (current_begin_frame_args_.frame_time > | 247 (current_begin_frame_args_.frame_time > |
| 236 last_args.frame_time + | 248 last_args.frame_time + |
| 237 current_begin_frame_args_.interval / kDoubleTickDivisor)) { | 249 current_begin_frame_args_.interval / kDoubleTickDivisor)) { |
| 238 obs->OnBeginFrame(current_begin_frame_args_); | 250 obs->OnBeginFrame(current_begin_frame_args_); |
| 239 } | 251 } |
| 240 } | 252 } |
| 241 } | 253 } |
| 242 | 254 |
| 243 // BeginFrameObserverAckTracker ------------------------------------------- | 255 // BeginFrameObserverAckTracker ------------------------------------------- |
| 244 BeginFrameObserverAckTracker::BeginFrameObserverAckTracker() | 256 BeginFrameObserverAckTracker::BeginFrameObserverAckTracker() = default; |
| 245 : current_source_id_(0), | |
| 246 current_sequence_number_(BeginFrameArgs::kStartingFrameNumber), | |
| 247 observers_had_damage_(false) {} | |
| 248 | 257 |
| 249 BeginFrameObserverAckTracker::~BeginFrameObserverAckTracker() {} | 258 BeginFrameObserverAckTracker::~BeginFrameObserverAckTracker() = default; |
| 250 | 259 |
| 251 void BeginFrameObserverAckTracker::OnBeginFrame(const BeginFrameArgs& args) { | 260 void BeginFrameObserverAckTracker::OnBeginFrame(const BeginFrameArgs& args) { |
| 252 if (current_source_id_ != args.source_id) | 261 if (current_source_id_ != args.source_id) |
| 253 SourceChanged(args); | 262 SourceChanged(args); |
| 254 | 263 |
| 255 DCHECK_GE(args.sequence_number, current_sequence_number_); | 264 DCHECK_GE(args.sequence_number, current_sequence_number_); |
| 256 // Reset for new BeginFrame. | 265 // Reset for new BeginFrame. |
| 257 current_sequence_number_ = args.sequence_number; | 266 current_sequence_number_ = args.sequence_number; |
| 258 finished_observers_.clear(); | 267 finished_observers_.clear(); |
| 259 observers_had_damage_ = false; | 268 observers_had_damage_ = false; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 | 336 |
| 328 uint64_t BeginFrameObserverAckTracker::LatestConfirmedSequenceNumber() const { | 337 uint64_t BeginFrameObserverAckTracker::LatestConfirmedSequenceNumber() const { |
| 329 uint64_t latest_confirmed_sequence_number = current_sequence_number_; | 338 uint64_t latest_confirmed_sequence_number = current_sequence_number_; |
| 330 for (const auto& entry : latest_confirmed_sequence_numbers_) { | 339 for (const auto& entry : latest_confirmed_sequence_numbers_) { |
| 331 latest_confirmed_sequence_number = | 340 latest_confirmed_sequence_number = |
| 332 std::min(latest_confirmed_sequence_number, entry.second); | 341 std::min(latest_confirmed_sequence_number, entry.second); |
| 333 } | 342 } |
| 334 return latest_confirmed_sequence_number; | 343 return latest_confirmed_sequence_number; |
| 335 } | 344 } |
| 336 | 345 |
| 346 void BeginFrameObserverAckTracker::AsValueInto( | |
| 347 base::trace_event::TracedValue* state) const { | |
| 348 base::SmallMap<std::map<BeginFrameObserver*, uint64_t>, 4> | |
| 349 latest_confirmed_sequence_numbers_; | |
| 350 state->SetInteger("current_source_id", current_source_id_); | |
| 351 state->SetInteger("current_sequence_number", current_sequence_number_); | |
| 352 state->SetInteger("num_observers", observers_.size()); | |
| 353 state->SetInteger("num_finished_observers", finished_observers_.size()); | |
| 354 state->SetBoolean("observers_had_damage", observers_had_damage_); | |
| 355 | |
| 356 state->BeginArray("latest_confirmed_sequence_numbers"); | |
| 357 for (const auto& kv : latest_confirmed_sequence_numbers_) { | |
| 358 state->AppendInteger(kv.second); | |
| 359 } | |
| 360 state->EndArray(); | |
| 361 } | |
| 362 | |
| 337 // ExternalBeginFrameSource ----------------------------------------------- | 363 // ExternalBeginFrameSource ----------------------------------------------- |
| 338 ExternalBeginFrameSource::ExternalBeginFrameSource( | 364 ExternalBeginFrameSource::ExternalBeginFrameSource( |
| 339 ExternalBeginFrameSourceClient* client) | 365 ExternalBeginFrameSourceClient* client) |
| 340 : client_(client) { | 366 : client_(client) { |
| 341 DCHECK(client_); | 367 DCHECK(client_); |
| 342 } | 368 } |
| 343 | 369 |
| 344 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; | 370 ExternalBeginFrameSource::~ExternalBeginFrameSource() = default; |
| 345 | 371 |
| 372 void ExternalBeginFrameSource::AsValueInto( | |
| 373 base::trace_event::TracedValue* state) const { | |
| 374 BeginFrameSource::AsValueInto(state); | |
| 375 | |
| 376 state->SetBoolean("paused", paused_); | |
| 377 state->SetBoolean("frame_active", frame_active_); | |
| 378 state->SetInteger("num_observers", observers_.size()); | |
| 379 | |
| 380 state->BeginDictionary("last_begin_frame_args"); | |
| 381 last_begin_frame_args_.AsValueInto(state); | |
| 382 state->EndDictionary(); | |
| 383 | |
| 384 state->BeginDictionary("ack_tracker_state"); | |
| 385 ack_tracker_.AsValueInto(state); | |
| 386 state->EndDictionary(); | |
| 387 } | |
| 388 | |
| 346 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { | 389 void ExternalBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| 347 DCHECK(obs); | 390 DCHECK(obs); |
| 348 DCHECK(observers_.find(obs) == observers_.end()); | 391 DCHECK(observers_.find(obs) == observers_.end()); |
| 349 | 392 |
| 350 bool observers_was_empty = observers_.empty(); | 393 bool observers_was_empty = observers_.empty(); |
| 351 observers_.insert(obs); | 394 observers_.insert(obs); |
| 352 ack_tracker_.OnObserverAdded(obs); | 395 ack_tracker_.OnObserverAdded(obs); |
| 353 obs->OnBeginFrameSourcePausedChanged(paused_); | 396 obs->OnBeginFrameSourcePausedChanged(paused_); |
| 354 if (observers_was_empty) | 397 if (observers_was_empty) |
| 355 client_->OnNeedsBeginFrames(true); | 398 client_->OnNeedsBeginFrames(true); |
| 356 | 399 |
| 357 // Send a MISSED begin frame if necessary. | 400 // Send a MISSED begin frame if necessary. |
| 358 if (missed_begin_frame_args_.IsValid()) { | 401 if (last_begin_frame_args_.IsValid()) { |
| 359 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | 402 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); |
| 360 if (!last_args.IsValid() || | 403 if (!last_args.IsValid() || |
| 361 (missed_begin_frame_args_.frame_time > last_args.frame_time)) { | 404 (last_begin_frame_args_.frame_time > last_args.frame_time)) { |
| 362 DCHECK((missed_begin_frame_args_.source_id != last_args.source_id) || | 405 DCHECK( |
| 363 (missed_begin_frame_args_.sequence_number > | 406 (last_begin_frame_args_.source_id != last_args.source_id) || |
| 364 last_args.sequence_number)) | 407 (last_begin_frame_args_.sequence_number > last_args.sequence_number)) |
| 365 << "current " << missed_begin_frame_args_.AsValue()->ToString() | 408 << "current " << last_begin_frame_args_.AsValue()->ToString() |
| 366 << ", last " << last_args.AsValue()->ToString(); | 409 << ", last " << last_args.AsValue()->ToString(); |
| 367 obs->OnBeginFrame(missed_begin_frame_args_); | 410 BeginFrameArgs missed_args = last_begin_frame_args_; |
| 411 missed_args.type = BeginFrameArgs::MISSED; | |
| 412 obs->OnBeginFrame(missed_args); | |
| 368 } | 413 } |
| 369 } | 414 } |
| 370 } | 415 } |
| 371 | 416 |
| 372 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { | 417 void ExternalBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
| 373 DCHECK(obs); | 418 DCHECK(obs); |
| 374 DCHECK(observers_.find(obs) != observers_.end()); | 419 DCHECK(observers_.find(obs) != observers_.end()); |
| 375 | 420 |
| 376 observers_.erase(obs); | 421 observers_.erase(obs); |
| 377 ack_tracker_.OnObserverRemoved(obs); | 422 ack_tracker_.OnObserverRemoved(obs); |
| 378 MaybeFinishFrame(); | 423 MaybeFinishFrame(); |
| 379 if (observers_.empty()) { | 424 if (observers_.empty()) { |
| 380 missed_begin_frame_args_ = BeginFrameArgs(); | 425 last_begin_frame_args_ = BeginFrameArgs(); |
| 381 client_->OnNeedsBeginFrames(false); | 426 client_->OnNeedsBeginFrames(false); |
| 382 } | 427 } |
| 383 } | 428 } |
| 384 | 429 |
| 385 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, | 430 void ExternalBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, |
| 386 const BeginFrameAck& ack) { | 431 const BeginFrameAck& ack) { |
| 387 ack_tracker_.OnObserverFinishedFrame(obs, ack); | 432 ack_tracker_.OnObserverFinishedFrame(obs, ack); |
| 388 MaybeFinishFrame(); | 433 MaybeFinishFrame(); |
| 389 } | 434 } |
| 390 | 435 |
| 391 bool ExternalBeginFrameSource::IsThrottled() const { | 436 bool ExternalBeginFrameSource::IsThrottled() const { |
| 392 return true; | 437 return true; |
| 393 } | 438 } |
| 394 | 439 |
| 395 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { | 440 void ExternalBeginFrameSource::OnSetBeginFrameSourcePaused(bool paused) { |
| 396 if (paused_ == paused) | 441 if (paused_ == paused) |
| 397 return; | 442 return; |
| 398 paused_ = paused; | 443 paused_ = paused; |
| 399 std::unordered_set<BeginFrameObserver*> observers(observers_); | 444 std::unordered_set<BeginFrameObserver*> observers(observers_); |
| 400 for (auto* obs : observers) | 445 for (auto* obs : observers) |
| 401 obs->OnBeginFrameSourcePausedChanged(paused_); | 446 obs->OnBeginFrameSourcePausedChanged(paused_); |
| 402 } | 447 } |
| 403 | 448 |
| 404 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { | 449 void ExternalBeginFrameSource::OnBeginFrame(const BeginFrameArgs& args) { |
| 405 if (frame_active_) | 450 if (frame_active_) |
| 406 FinishFrame(); | 451 FinishFrame(); |
| 407 | 452 |
| 408 frame_active_ = true; | 453 frame_active_ = true; |
| 409 missed_begin_frame_args_ = args; | 454 last_begin_frame_args_ = args; |
|
sunnyps
2017/04/14 23:24:11
NOTE: I don't set type to MISSED here because I wa
| |
| 410 missed_begin_frame_args_.type = BeginFrameArgs::MISSED; | |
| 411 ack_tracker_.OnBeginFrame(args); | 455 ack_tracker_.OnBeginFrame(args); |
| 412 std::unordered_set<BeginFrameObserver*> observers(observers_); | 456 std::unordered_set<BeginFrameObserver*> observers(observers_); |
| 413 for (auto* obs : observers) { | 457 for (auto* obs : observers) { |
| 414 // It is possible that the source in which |args| originate changes, or that | 458 // It is possible that the source in which |args| originate changes, or that |
| 415 // our hookup to this source changes, so we have to check for continuity. | 459 // our hookup to this source changes, so we have to check for continuity. |
| 416 // See also https://crbug.com/690127 for what may happen without this check. | 460 // See also https://crbug.com/690127 for what may happen without this check. |
| 417 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); | 461 const BeginFrameArgs& last_args = obs->LastUsedBeginFrameArgs(); |
| 418 if (!last_args.IsValid() || (args.frame_time > last_args.frame_time)) { | 462 if (!last_args.IsValid() || (args.frame_time > last_args.frame_time)) { |
| 419 DCHECK((args.source_id != last_args.source_id) || | 463 DCHECK((args.source_id != last_args.source_id) || |
| 420 (args.sequence_number > last_args.sequence_number)) | 464 (args.sequence_number > last_args.sequence_number)) |
| 421 << "current " << args.AsValue()->ToString() << ", last " | 465 << "current " << args.AsValue()->ToString() << ", last " |
| 422 << last_args.AsValue()->ToString(); | 466 << last_args.AsValue()->ToString(); |
| 423 obs->OnBeginFrame(args); | 467 obs->OnBeginFrame(args); |
| 424 } | 468 } |
| 425 } | 469 } |
| 426 MaybeFinishFrame(); | 470 MaybeFinishFrame(); |
| 427 } | 471 } |
| 428 | 472 |
| 429 void ExternalBeginFrameSource::MaybeFinishFrame() { | 473 void ExternalBeginFrameSource::MaybeFinishFrame() { |
| 430 if (!frame_active_ || !ack_tracker_.AllObserversFinishedFrame()) | 474 if (!frame_active_ || !ack_tracker_.AllObserversFinishedFrame()) |
| 431 return; | 475 return; |
| 432 FinishFrame(); | 476 FinishFrame(); |
| 433 } | 477 } |
| 434 | 478 |
| 435 void ExternalBeginFrameSource::FinishFrame() { | 479 void ExternalBeginFrameSource::FinishFrame() { |
| 436 frame_active_ = false; | 480 frame_active_ = false; |
| 437 | 481 |
| 438 BeginFrameAck ack(missed_begin_frame_args_.source_id, | 482 BeginFrameAck ack(last_begin_frame_args_.source_id, |
| 439 missed_begin_frame_args_.sequence_number, | 483 last_begin_frame_args_.sequence_number, |
| 440 ack_tracker_.LatestConfirmedSequenceNumber(), | 484 ack_tracker_.LatestConfirmedSequenceNumber(), |
| 441 ack_tracker_.AnyObserversHadDamage()); | 485 ack_tracker_.AnyObserversHadDamage()); |
| 442 client_->OnDidFinishFrame(ack); | 486 client_->OnDidFinishFrame(ack); |
| 443 } | 487 } |
| 444 | 488 |
| 445 } // namespace cc | 489 } // namespace cc |
| OLD | NEW |