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 "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 54 void BeginFrameObserverBase::AsValueInto( | 54 void BeginFrameObserverBase::AsValueInto( |
| 55 base::trace_event::TracedValue* dict) const { | 55 base::trace_event::TracedValue* dict) const { |
| 56 dict->BeginDictionary("last_begin_frame_args_"); | 56 dict->BeginDictionary("last_begin_frame_args_"); |
| 57 last_begin_frame_args_.AsValueInto(dict); | 57 last_begin_frame_args_.AsValueInto(dict); |
| 58 dict->EndDictionary(); | 58 dict->EndDictionary(); |
| 59 dict->SetInteger("dropped_begin_frame_args_", dropped_begin_frame_args_); | 59 dict->SetInteger("dropped_begin_frame_args_", dropped_begin_frame_args_); |
| 60 } | 60 } |
| 61 | 61 |
| 62 // BeginFrameSourceBase ------------------------------------------------------ | 62 // BeginFrameSourceBase ------------------------------------------------------ |
| 63 BeginFrameSourceBase::BeginFrameSourceBase() | 63 BeginFrameSourceBase::BeginFrameSourceBase() |
| 64 : observer_(NULL), | 64 : observer_list_(), |
| 65 needs_begin_frames_(false), | 65 needs_begin_frames_(false), |
| 66 inside_as_value_into_(false) { | 66 inside_as_value_into_(false) { |
| 67 DCHECK(!observer_); | |
| 68 DCHECK_EQ(inside_as_value_into_, false); | 67 DCHECK_EQ(inside_as_value_into_, false); |
| 69 } | 68 } |
| 70 | 69 |
| 70 BeginFrameSourceBase::~BeginFrameSourceBase() {} | |
| 71 | |
| 71 bool BeginFrameSourceBase::NeedsBeginFrames() const { | 72 bool BeginFrameSourceBase::NeedsBeginFrames() const { |
| 72 return needs_begin_frames_; | 73 return needs_begin_frames_; |
| 73 } | 74 } |
| 74 | 75 |
| 75 void BeginFrameSourceBase::SetNeedsBeginFrames(bool needs_begin_frames) { | 76 void BeginFrameSourceBase::SetNeedsBeginFrames(bool needs_begin_frames) { |
| 76 DEBUG_FRAMES("BeginFrameSourceBase::SetNeedsBeginFrames", | 77 DEBUG_FRAMES("BeginFrameSourceBase::SetNeedsBeginFrames", |
| 77 "current state", | 78 "current state", |
| 78 needs_begin_frames_, | 79 needs_begin_frames_, |
| 79 "new state", | 80 "new state", |
| 80 needs_begin_frames); | 81 needs_begin_frames); |
| 81 if (needs_begin_frames_ != needs_begin_frames) { | 82 if (needs_begin_frames_ != needs_begin_frames) { |
| 82 needs_begin_frames_ = needs_begin_frames; | 83 needs_begin_frames_ = needs_begin_frames; |
| 83 OnNeedsBeginFramesChange(needs_begin_frames); | 84 OnNeedsBeginFramesChange(needs_begin_frames); |
| 84 } | 85 } |
| 85 } | 86 } |
| 86 | 87 |
| 87 void BeginFrameSourceBase::AddObserver(BeginFrameObserver* obs) { | 88 void BeginFrameSourceBase::AddObserver(BeginFrameObserver* obs) { |
| 88 DEBUG_FRAMES("BeginFrameSourceBase::AddObserver", | 89 DEBUG_FRAMES("BeginFrameSourceBase::AddObserver", "has observers?", |
| 89 "current observer", | 90 (observer_list_).might_have_observers(), "to add observer", obs); |
| 90 observer_, | 91 DCHECK(obs); |
| 91 "to add observer", | 92 DCHECK(!observer_list_.HasObserver(obs)); |
| 92 obs); | 93 observer_list_.AddObserver(obs); |
| 93 DCHECK(!observer_); | |
| 94 observer_ = obs; | |
| 95 } | 94 } |
| 96 | 95 |
| 97 void BeginFrameSourceBase::RemoveObserver(BeginFrameObserver* obs) { | 96 void BeginFrameSourceBase::RemoveObserver(BeginFrameObserver* obs) { |
| 98 DEBUG_FRAMES("BeginFrameSourceBase::RemoveObserver", | 97 DEBUG_FRAMES("BeginFrameSourceBase::RemoveObserver", "has observers?", |
| 99 "current observer", | 98 (observer_list_).might_have_observers(), "to remove observer", |
| 100 observer_, | |
| 101 "to remove observer", | |
| 102 obs); | 99 obs); |
| 103 DCHECK_EQ(observer_, obs); | 100 DCHECK(obs); |
| 104 observer_ = NULL; | 101 DCHECK(observer_list_.HasObserver(obs)); |
| 102 observer_list_.RemoveObserver(obs); | |
| 105 } | 103 } |
| 106 | 104 |
| 107 void BeginFrameSourceBase::CallOnBeginFrame(const BeginFrameArgs& args) { | 105 void BeginFrameSourceBase::CallOnBeginFrame(const BeginFrameArgs& args) { |
| 108 DEBUG_FRAMES("BeginFrameSourceBase::CallOnBeginFrame", | 106 DEBUG_FRAMES("BeginFrameSourceBase::CallOnBeginFrame", "has observers?", |
| 109 "current observer", | 107 observer_list_.might_have_observers(), "args", args.AsValue()); |
| 110 observer_, | 108 FOR_EACH_OBSERVER(BeginFrameObserver, observer_list_, OnBeginFrame(args)); |
| 111 "args", | 109 } |
| 112 args.AsValue()); | 110 |
| 113 if (observer_) { | 111 base::ObserverList<const BeginFrameObserver>::Iterator |
| 114 return observer_->OnBeginFrame(args); | 112 BeginFrameSourceBase::getConstObserverListIterator() const { |
|
brianderson
2015/09/04 19:48:18
Please pay special attention here.
| |
| 115 } | 113 // TODO(mithro): Add a const iterator on base::ObserverList which does |
| 114 // something similar to this. That should probably also DCHECK that | |
| 115 // AddObserver/RemoveObserver are never called. | |
| 116 | |
| 117 // First we use reinterpret_cast to make an base::ObserverList containing | |
| 118 // *const Observers*. This means we can only call *const* methods on the | |
| 119 // Observer. | |
| 120 const base::ObserverList<const BeginFrameObserver>* a = | |
| 121 reinterpret_cast<const base::ObserverList<const BeginFrameObserver>*>( | |
| 122 &observer_list_); | |
| 123 // As AddObserver and RemoveObserver are *not* const methods, const methods | |
| 124 // on the Observer will (most) not be able to call them. This makes it | |
| 125 // "safe" to cast away the const on the ObserverList so we can iterate over | |
| 126 // it. | |
| 127 base::ObserverList<const BeginFrameObserver>* b = | |
| 128 const_cast<base::ObserverList<const BeginFrameObserver>*>(a); | |
| 129 return base::ObserverList<const BeginFrameObserver>::Iterator(b); | |
| 116 } | 130 } |
| 117 | 131 |
| 118 // Tracing support | 132 // Tracing support |
| 119 void BeginFrameSourceBase::AsValueInto( | 133 void BeginFrameSourceBase::AsValueInto( |
| 120 base::trace_event::TracedValue* dict) const { | 134 base::trace_event::TracedValue* dict) const { |
| 121 // As the observer might try to trace the source, prevent an infinte loop | 135 // As the observer might try to trace the source, prevent an infinte loop |
| 122 // from occuring. | 136 // from occuring. |
| 123 if (inside_as_value_into_) { | 137 if (inside_as_value_into_) { |
| 124 dict->SetString("observer", "<loop detected>"); | 138 dict->SetString("observer", "<loop detected>"); |
| 125 return; | 139 return; |
| 126 } | 140 } |
| 141 base::AutoReset<bool> prevent_loops(const_cast<bool*>(&inside_as_value_into_), | |
| 142 true); | |
| 127 | 143 |
| 128 if (observer_) { | 144 dict->SetBoolean("needs_begin_frames", NeedsBeginFrames()); |
| 129 base::AutoReset<bool> prevent_loops( | 145 if (observer_list_.might_have_observers()) { |
| 130 const_cast<bool*>(&inside_as_value_into_), true); | 146 base::ObserverList<const BeginFrameObserver>::Iterator it = |
| 131 dict->BeginDictionary("observer"); | 147 getConstObserverListIterator(); |
| 132 observer_->AsValueInto(dict); | 148 const BeginFrameObserver* obs; |
| 133 dict->EndDictionary(); | 149 dict->BeginArray("observers"); |
| 134 } else { | 150 while ((obs = it.GetNext()) != NULL) { |
| 135 dict->SetString("observer", "NULL"); | 151 dict->BeginDictionary(); |
| 152 obs->AsValueInto(dict); | |
| 153 dict->EndDictionary(); | |
| 154 } | |
| 155 dict->EndArray(); | |
| 136 } | 156 } |
| 137 dict->SetBoolean("needs_begin_frames", NeedsBeginFrames()); | |
| 138 } | 157 } |
| 139 | 158 |
| 140 // BackToBackBeginFrameSource -------------------------------------------- | 159 // BackToBackBeginFrameSource -------------------------------------------- |
| 141 scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create( | 160 scoped_ptr<BackToBackBeginFrameSource> BackToBackBeginFrameSource::Create( |
| 142 base::SingleThreadTaskRunner* task_runner) { | 161 base::SingleThreadTaskRunner* task_runner) { |
| 143 return make_scoped_ptr(new BackToBackBeginFrameSource(task_runner)); | 162 return make_scoped_ptr(new BackToBackBeginFrameSource(task_runner)); |
| 144 } | 163 } |
| 145 | 164 |
| 146 BackToBackBeginFrameSource::BackToBackBeginFrameSource( | 165 BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
| 147 base::SingleThreadTaskRunner* task_runner) | 166 base::SingleThreadTaskRunner* task_runner) |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnBeginFrame", | 397 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnBeginFrame", |
| 379 "action", | 398 "action", |
| 380 "using", | 399 "using", |
| 381 "new args", | 400 "new args", |
| 382 args.AsValue()); | 401 args.AsValue()); |
| 383 CallOnBeginFrame(args); | 402 CallOnBeginFrame(args); |
| 384 } | 403 } |
| 385 | 404 |
| 386 const BeginFrameArgs BeginFrameSourceMultiplexer::LastUsedBeginFrameArgs() | 405 const BeginFrameArgs BeginFrameSourceMultiplexer::LastUsedBeginFrameArgs() |
| 387 const { | 406 const { |
| 388 if (observer_) | 407 BeginFrameArgs last; |
| 389 return observer_->LastUsedBeginFrameArgs(); | 408 |
| 390 else | 409 if (observer_list_.might_have_observers()) { |
| 391 return BeginFrameArgs(); | 410 base::ObserverList<const BeginFrameObserver>::Iterator it = |
| 411 getConstObserverListIterator(); | |
| 412 const BeginFrameObserver* obs; | |
| 413 while ((obs = it.GetNext()) != NULL) { | |
| 414 BeginFrameArgs obs_last = obs->LastUsedBeginFrameArgs(); | |
| 415 if (obs_last.frame_time > last.frame_time) | |
| 416 last = obs_last; | |
| 417 } | |
| 418 } | |
| 419 return last; | |
| 392 } | 420 } |
| 393 | 421 |
| 394 // BeginFrameSource support | 422 // BeginFrameSource support |
| 395 void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange( | 423 void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange( |
| 396 bool needs_begin_frames) { | 424 bool needs_begin_frames) { |
| 397 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange", | 425 DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange", |
| 398 "active_source", active_source_, "needs_begin_frames", | 426 "active_source", active_source_, "needs_begin_frames", |
| 399 needs_begin_frames); | 427 needs_begin_frames); |
| 400 if (active_source_) { | 428 if (active_source_) { |
| 401 active_source_->SetNeedsBeginFrames(needs_begin_frames); | 429 active_source_->SetNeedsBeginFrames(needs_begin_frames); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 412 remaining_frames); | 440 remaining_frames); |
| 413 if (active_source_) { | 441 if (active_source_) { |
| 414 active_source_->DidFinishFrame(remaining_frames); | 442 active_source_->DidFinishFrame(remaining_frames); |
| 415 } | 443 } |
| 416 } | 444 } |
| 417 | 445 |
| 418 // Tracing support | 446 // Tracing support |
| 419 void BeginFrameSourceMultiplexer::AsValueInto( | 447 void BeginFrameSourceMultiplexer::AsValueInto( |
| 420 base::trace_event::TracedValue* dict) const { | 448 base::trace_event::TracedValue* dict) const { |
| 421 dict->SetString("type", "BeginFrameSourceMultiplexer"); | 449 dict->SetString("type", "BeginFrameSourceMultiplexer"); |
| 450 BeginFrameSourceBase::AsValueInto(dict); | |
| 422 | 451 |
| 423 dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds()); | 452 dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds()); |
| 424 if (observer_) { | |
| 425 dict->BeginDictionary("last_begin_frame_args"); | |
| 426 observer_->LastUsedBeginFrameArgs().AsValueInto(dict); | |
| 427 dict->EndDictionary(); | |
| 428 } | |
| 429 | |
| 430 if (active_source_) { | 453 if (active_source_) { |
| 431 dict->BeginDictionary("active_source"); | 454 dict->BeginDictionary("active_source"); |
| 432 active_source_->AsValueInto(dict); | 455 active_source_->AsValueInto(dict); |
| 433 dict->EndDictionary(); | 456 dict->EndDictionary(); |
| 434 } else { | 457 } else { |
| 435 dict->SetString("active_source", "NULL"); | 458 dict->SetString("active_source", "NULL"); |
| 436 } | 459 } |
| 437 | 460 |
| 438 dict->BeginArray("sources"); | 461 dict->BeginArray("sources"); |
| 439 for (std::set<BeginFrameSource*>::const_iterator it = source_list_.begin(); | 462 for (std::set<BeginFrameSource*>::const_iterator it = source_list_.begin(); |
| 440 it != source_list_.end(); | 463 it != source_list_.end(); |
| 441 ++it) { | 464 ++it) { |
| 442 dict->BeginDictionary(); | 465 dict->BeginDictionary(); |
| 443 (*it)->AsValueInto(dict); | 466 (*it)->AsValueInto(dict); |
| 444 dict->EndDictionary(); | 467 dict->EndDictionary(); |
| 445 } | 468 } |
| 446 dict->EndArray(); | 469 dict->EndArray(); |
| 447 } | 470 } |
| 448 | 471 |
| 449 // protected methods | 472 // protected methods |
| 450 bool BeginFrameSourceMultiplexer::HasSource(BeginFrameSource* source) { | 473 bool BeginFrameSourceMultiplexer::HasSource(BeginFrameSource* source) { |
| 451 return (source_list_.find(source) != source_list_.end()); | 474 return (source_list_.find(source) != source_list_.end()); |
| 452 } | 475 } |
| 453 | 476 |
| 454 bool BeginFrameSourceMultiplexer::IsIncreasing(const BeginFrameArgs& args) { | 477 bool BeginFrameSourceMultiplexer::IsIncreasing(const BeginFrameArgs& args) { |
| 455 DCHECK(args.IsValid()); | 478 DCHECK(args.IsValid()); |
| 456 if (!observer_) | |
| 457 return false; | |
| 458 | 479 |
| 459 // If the last begin frame is invalid, then any new begin frame is valid. | 480 // If the last begin frame is invalid, then any new begin frame is valid. |
| 460 if (!observer_->LastUsedBeginFrameArgs().IsValid()) | 481 if (!LastUsedBeginFrameArgs().IsValid()) |
| 461 return true; | 482 return true; |
| 462 | 483 |
| 463 // Only allow new args have a *strictly bigger* frame_time value and statisfy | 484 // Only allow new args have a *strictly bigger* frame_time value and statisfy |
| 464 // minimum interval requirement. | 485 // minimum interval requirement. |
| 465 return (args.frame_time >= | 486 return (args.frame_time >= |
| 466 observer_->LastUsedBeginFrameArgs().frame_time + minimum_interval_); | 487 LastUsedBeginFrameArgs().frame_time + minimum_interval_); |
| 467 } | 488 } |
| 468 | 489 |
| 469 } // namespace cc | 490 } // namespace cc |
| OLD | NEW |