Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1088)

Side by Side Diff: cc/scheduler/begin_frame_source.cc

Issue 1026233002: cc: Making BeginFrameSources support multiple BeginFrameObservers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding tests. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 {
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698