diff options
22 files changed, 728 insertions, 584 deletions
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc index d96ef4e..5447086 100644 --- a/cc/scheduler/begin_frame_source.cc +++ b/cc/scheduler/begin_frame_source.cc @@ -10,6 +10,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/scheduler/delay_based_time_source.h" @@ -17,12 +18,18 @@ namespace cc { +namespace { +// kDoubleTickDivisor prevents the SyntheticBFS from sending BeginFrames too +// often to an observer. +static const double kDoubleTickDivisor = 2.0; +} + // BeginFrameObserverBase ----------------------------------------------- BeginFrameObserverBase::BeginFrameObserverBase() : last_begin_frame_args_(), dropped_begin_frame_args_(0) { } -const BeginFrameArgs BeginFrameObserverBase::LastUsedBeginFrameArgs() const { +const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { return last_begin_frame_args_; } void BeginFrameObserverBase::OnBeginFrame(const BeginFrameArgs& args) { @@ -51,69 +58,49 @@ void BeginFrameObserverBase::AsValueInto( // BeginFrameSourceBase ------------------------------------------------------ BeginFrameSourceBase::BeginFrameSourceBase() - : observer_(NULL), - needs_begin_frames_(false), - paused_(false), - inside_as_value_into_(false) { - DCHECK(!observer_); - DCHECK_EQ(inside_as_value_into_, false); -} - -bool BeginFrameSourceBase::NeedsBeginFrames() const { - return needs_begin_frames_; -} - -void BeginFrameSourceBase::SetNeedsBeginFrames(bool needs_begin_frames) { - DEBUG_FRAMES("BeginFrameSourceBase::SetNeedsBeginFrames", - "current state", - needs_begin_frames_, - "new state", - needs_begin_frames); - if (needs_begin_frames_ != needs_begin_frames) { - needs_begin_frames_ = needs_begin_frames; - OnNeedsBeginFramesChange(needs_begin_frames); - } -} + : paused_(false), inside_as_value_into_(false) {} + +BeginFrameSourceBase::~BeginFrameSourceBase() {} void BeginFrameSourceBase::AddObserver(BeginFrameObserver* obs) { - DEBUG_FRAMES("BeginFrameSourceBase::AddObserver", - "current observer", - observer_, - "to add observer", - obs); - DCHECK(!observer_); - observer_ = obs; - if (observer_) - return observer_->OnBeginFrameSourcePausedChanged(paused_); + DEBUG_FRAMES("BeginFrameSourceBase::AddObserver", "num observers", + observers_.size(), "to add observer", obs); + DCHECK(obs); + DCHECK(observers_.find(obs) == observers_.end()) + << "AddObserver cannot be called with an observer that was already added"; + bool observers_was_empty = observers_.empty(); + observers_.insert(obs); + if (observers_was_empty) + OnNeedsBeginFramesChanged(true); + obs->OnBeginFrameSourcePausedChanged(paused_); } void BeginFrameSourceBase::RemoveObserver(BeginFrameObserver* obs) { - DEBUG_FRAMES("BeginFrameSourceBase::RemoveObserver", - "current observer", - observer_, - "to remove observer", - obs); - DCHECK_EQ(observer_, obs); - observer_ = NULL; + DEBUG_FRAMES("BeginFrameSourceBase::RemoveObserver", "num observers", + observers_.size(), "removed observer", obs); + DCHECK(obs); + DCHECK(observers_.find(obs) != observers_.end()) + << "RemoveObserver cannot be called with an observer that wasn't added"; + observers_.erase(obs); + if (observers_.empty()) + OnNeedsBeginFramesChanged(false); } void BeginFrameSourceBase::CallOnBeginFrame(const BeginFrameArgs& args) { - DEBUG_FRAMES("BeginFrameSourceBase::CallOnBeginFrame", - "current observer", - observer_, - "args", - args.AsValue()); - if (observer_) { - return observer_->OnBeginFrame(args); - } + DEBUG_FRAMES("BeginFrameSourceBase::CallOnBeginFrame", "num observers", + observers_.size(), "args", args.AsValue()); + std::set<BeginFrameObserver*> observers(observers_); + for (auto& it : observers) + it->OnBeginFrame(args); } void BeginFrameSourceBase::SetBeginFrameSourcePaused(bool paused) { if (paused_ == paused) return; paused_ = paused; - if (observer_) - return observer_->OnBeginFrameSourcePausedChanged(paused_); + std::set<BeginFrameObserver*> observers(observers_); + for (auto& it : observers) + it->OnBeginFrameSourcePausedChanged(paused_); } // Tracing support @@ -126,16 +113,17 @@ void BeginFrameSourceBase::AsValueInto( return; } - if (observer_) { + { base::AutoReset<bool> prevent_loops( const_cast<bool*>(&inside_as_value_into_), true); - dict->BeginDictionary("observer"); - observer_->AsValueInto(dict); - dict->EndDictionary(); - } else { - dict->SetString("observer", "NULL"); + dict->BeginArray("observers"); + for (const auto& it : observers_) { + dict->BeginDictionary(); + it->AsValueInto(dict); + dict->EndDictionary(); + } + dict->EndArray(); } - dict->SetBoolean("needs_begin_frames", NeedsBeginFrames()); } // BackToBackBeginFrameSource -------------------------------------------- @@ -148,11 +136,8 @@ BackToBackBeginFrameSource::BackToBackBeginFrameSource( base::SingleThreadTaskRunner* task_runner) : BeginFrameSourceBase(), task_runner_(task_runner), - send_begin_frame_posted_(false), weak_factory_(this) { DCHECK(task_runner); - DCHECK_EQ(needs_begin_frames_, false); - DCHECK_EQ(send_begin_frame_posted_, false); } BackToBackBeginFrameSource::~BackToBackBeginFrameSource() { @@ -162,26 +147,33 @@ base::TimeTicks BackToBackBeginFrameSource::Now() { return base::TimeTicks::Now(); } -void BackToBackBeginFrameSource::OnNeedsBeginFramesChange( - bool needs_begin_frames) { - if (!needs_begin_frames) - return; +// BeginFrameSourceBase support +void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { + DCHECK(observers_.empty()) + << "BackToBackBeginFrameSource only supports a single observer"; + BeginFrameSourceBase::AddObserver(obs); +} - if (send_begin_frame_posted_) - return; +void BackToBackBeginFrameSource::OnNeedsBeginFramesChanged( + bool needs_begin_frames) { + if (needs_begin_frames) { + PostBeginFrame(); + } else { + begin_frame_task_.Cancel(); + } +} - send_begin_frame_posted_ = true; - task_runner_->PostTask(FROM_HERE, - base::Bind(&BackToBackBeginFrameSource::BeginFrame, - weak_factory_.GetWeakPtr())); +void BackToBackBeginFrameSource::PostBeginFrame() { + DCHECK(needs_begin_frames()); + begin_frame_task_.Reset(base::Bind(&BackToBackBeginFrameSource::BeginFrame, + weak_factory_.GetWeakPtr())); + task_runner_->PostTask(FROM_HERE, begin_frame_task_.callback()); } void BackToBackBeginFrameSource::BeginFrame() { - send_begin_frame_posted_ = false; - - if (!needs_begin_frames_) - return; - + DCHECK(needs_begin_frames()); + DCHECK(!begin_frame_task_.IsCancelled()); + begin_frame_task_.Cancel(); base::TimeTicks now = Now(); BeginFrameArgs args = BeginFrameArgs::Create( BEGINFRAME_FROM_HERE, now, now + BeginFrameArgs::DefaultInterval(), @@ -189,12 +181,10 @@ void BackToBackBeginFrameSource::BeginFrame() { CallOnBeginFrame(args); } -// BeginFrameSource support - void BackToBackBeginFrameSource::DidFinishFrame(size_t remaining_frames) { - if (remaining_frames == 0) { - OnNeedsBeginFramesChange(NeedsBeginFrames()); - } + BeginFrameSourceBase::DidFinishFrame(remaining_frames); + if (needs_begin_frames() && remaining_frames == 0) + PostBeginFrame(); } // Tracing support @@ -202,7 +192,6 @@ void BackToBackBeginFrameSource::AsValueInto( base::trace_event::TracedValue* dict) const { dict->SetString("type", "BackToBackBeginFrameSource"); BeginFrameSourceBase::AsValueInto(dict); - dict->SetBoolean("send_begin_frame_posted_", send_begin_frame_posted_); } // SyntheticBeginFrameSource --------------------------------------------- @@ -217,13 +206,10 @@ scoped_ptr<SyntheticBeginFrameSource> SyntheticBeginFrameSource::Create( SyntheticBeginFrameSource::SyntheticBeginFrameSource( scoped_ptr<DelayBasedTimeSource> time_source) : BeginFrameSourceBase(), time_source_(std::move(time_source)) { - time_source_->SetActive(false); time_source_->SetClient(this); } -SyntheticBeginFrameSource::~SyntheticBeginFrameSource() { - time_source_->SetActive(false); -} +SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {} void SyntheticBeginFrameSource::OnUpdateVSyncParameters( base::TimeTicks new_vsync_timebase, @@ -234,26 +220,42 @@ void SyntheticBeginFrameSource::OnUpdateVSyncParameters( BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs( base::TimeTicks frame_time, BeginFrameArgs::BeginFrameArgsType type) { - base::TimeTicks deadline = time_source_->NextTickTime(); - return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline, + return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, + time_source_->NextTickTime(), time_source_->Interval(), type); } -// DelayBasedTimeSourceClient support -void SyntheticBeginFrameSource::OnTimerTick() { - CallOnBeginFrame(CreateBeginFrameArgs(time_source_->LastTickTime(), - BeginFrameArgs::NORMAL)); +// BeginFrameSource support +void SyntheticBeginFrameSource::AddObserver(BeginFrameObserver* obs) { + BeginFrameSourceBase::AddObserver(obs); + BeginFrameArgs args = CreateBeginFrameArgs( + time_source_->NextTickTime() - time_source_->Interval(), + BeginFrameArgs::MISSED); + BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); + if (!last_args.IsValid() || + (args.frame_time > + last_args.frame_time + args.interval / kDoubleTickDivisor)) { + obs->OnBeginFrame(args); + } } -// BeginFrameSourceBase support -void SyntheticBeginFrameSource::OnNeedsBeginFramesChange( +void SyntheticBeginFrameSource::OnNeedsBeginFramesChanged( bool needs_begin_frames) { - base::TimeTicks missed_tick_time = - time_source_->SetActive(needs_begin_frames); - if (!missed_tick_time.is_null()) { - DCHECK(needs_begin_frames); - CallOnBeginFrame( - CreateBeginFrameArgs(missed_tick_time, BeginFrameArgs::MISSED)); + time_source_->SetActive(needs_begin_frames); +} + +// DelayBasedTimeSourceClient support +void SyntheticBeginFrameSource::OnTimerTick() { + BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), + BeginFrameArgs::NORMAL); + std::set<BeginFrameObserver*> observers(observers_); + for (auto& it : observers) { + BeginFrameArgs last_args = it->LastUsedBeginFrameArgs(); + if (!last_args.IsValid() || + (args.frame_time > + last_args.frame_time + args.interval / kDoubleTickDivisor)) { + it->OnBeginFrame(args); + } } } @@ -275,24 +277,18 @@ scoped_ptr<BeginFrameSourceMultiplexer> BeginFrameSourceMultiplexer::Create() { BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer() : BeginFrameSourceBase(), - minimum_interval_(base::TimeDelta()), - active_source_(NULL), - source_list_() { -} + active_source_(nullptr), + inside_add_observer_(false) {} BeginFrameSourceMultiplexer::BeginFrameSourceMultiplexer( base::TimeDelta minimum_interval) : BeginFrameSourceBase(), - minimum_interval_(minimum_interval), - active_source_(NULL), - source_list_() { -} + active_source_(nullptr), + inside_add_observer_(false) {} BeginFrameSourceMultiplexer::~BeginFrameSourceMultiplexer() { - if (active_source_) { - active_source_->SetNeedsBeginFrames(false); + if (active_source_ && needs_begin_frames()) active_source_->RemoveObserver(this); - } } void BeginFrameSourceMultiplexer::SetMinimumInterval( @@ -337,29 +333,18 @@ void BeginFrameSourceMultiplexer::SetActiveSource( "to become active", new_source); - DCHECK(HasSource(new_source) || new_source == NULL); + DCHECK(HasSource(new_source) || new_source == nullptr); - bool needs_begin_frames = NeedsBeginFrames(); - if (active_source_) { - if (needs_begin_frames) - SetNeedsBeginFrames(false); + if (active_source_ == new_source) + return; - // Technically we shouldn't need to remove observation, but this prevents - // the case where SetNeedsBeginFrames message gets to the source after a - // message has already been sent. + if (active_source_ && needs_begin_frames()) active_source_->RemoveObserver(this); - active_source_ = NULL; - } - DCHECK(!active_source_); + active_source_ = new_source; - if (active_source_) { + if (active_source_ && needs_begin_frames()) active_source_->AddObserver(this); - - if (needs_begin_frames) { - SetNeedsBeginFrames(true); - } - } } const BeginFrameSource* BeginFrameSourceMultiplexer::ActiveSource() { @@ -381,42 +366,50 @@ void BeginFrameSourceMultiplexer::OnBeginFrame(const BeginFrameArgs& args) { "using", "new args", args.AsValue()); + last_begin_frame_args_ = args; CallOnBeginFrame(args); } -const BeginFrameArgs BeginFrameSourceMultiplexer::LastUsedBeginFrameArgs() +const BeginFrameArgs& BeginFrameSourceMultiplexer::LastUsedBeginFrameArgs() const { - if (observer_) - return observer_->LastUsedBeginFrameArgs(); - else - return BeginFrameArgs(); + return last_begin_frame_args_; } void BeginFrameSourceMultiplexer::OnBeginFrameSourcePausedChanged(bool paused) { - BeginFrameSourceBase::SetBeginFrameSourcePaused(paused); -} - -// BeginFrameSource support -void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange( - bool needs_begin_frames) { - DEBUG_FRAMES("BeginFrameSourceMultiplexer::OnNeedsBeginFramesChange", - "active_source", active_source_, "needs_begin_frames", - needs_begin_frames); - if (active_source_) { - active_source_->SetNeedsBeginFrames(needs_begin_frames); - } else { - DCHECK(!needs_begin_frames); + if (paused_ == paused) + return; + paused_ = paused; + if (!inside_add_observer_) { + std::set<BeginFrameObserver*> observers(observers_); + for (auto& it : observers) + it->OnBeginFrameSourcePausedChanged(paused); } } +// BeginFrameSource support void BeginFrameSourceMultiplexer::DidFinishFrame(size_t remaining_frames) { DEBUG_FRAMES("BeginFrameSourceMultiplexer::DidFinishFrame", "active_source", active_source_, "remaining_frames", remaining_frames); - if (active_source_) { + if (active_source_) active_source_->DidFinishFrame(remaining_frames); +} + +void BeginFrameSourceMultiplexer::AddObserver(BeginFrameObserver* obs) { + base::AutoReset<bool> reset(&inside_add_observer_, true); + BeginFrameSourceBase::AddObserver(obs); +} + +void BeginFrameSourceMultiplexer::OnNeedsBeginFramesChanged( + bool needs_begin_frames) { + if (!active_source_) + return; + if (needs_begin_frames) { + active_source_->AddObserver(this); + } else { + active_source_->RemoveObserver(this); } } @@ -426,11 +419,10 @@ void BeginFrameSourceMultiplexer::AsValueInto( dict->SetString("type", "BeginFrameSourceMultiplexer"); dict->SetInteger("minimum_interval_us", minimum_interval_.InMicroseconds()); - if (observer_) { - dict->BeginDictionary("last_begin_frame_args"); - observer_->LastUsedBeginFrameArgs().AsValueInto(dict); - dict->EndDictionary(); - } + + dict->BeginDictionary("last_begin_frame_args"); + last_begin_frame_args_.AsValueInto(dict); + dict->EndDictionary(); if (active_source_) { dict->BeginDictionary("active_source"); @@ -458,17 +450,15 @@ bool BeginFrameSourceMultiplexer::HasSource(BeginFrameSource* source) { bool BeginFrameSourceMultiplexer::IsIncreasing(const BeginFrameArgs& args) { DCHECK(args.IsValid()); - if (!observer_) - return false; // If the last begin frame is invalid, then any new begin frame is valid. - if (!observer_->LastUsedBeginFrameArgs().IsValid()) + if (!last_begin_frame_args_.IsValid()) return true; // Only allow new args have a *strictly bigger* frame_time value and statisfy // minimum interval requirement. return (args.frame_time >= - observer_->LastUsedBeginFrameArgs().frame_time + minimum_interval_); + last_begin_frame_args_.frame_time + minimum_interval_); } } // namespace cc diff --git a/cc/scheduler/begin_frame_source.h b/cc/scheduler/begin_frame_source.h index a77d546..0850884 100644 --- a/cc/scheduler/begin_frame_source.h +++ b/cc/scheduler/begin_frame_source.h @@ -58,7 +58,7 @@ class CC_EXPORT BeginFrameObserver { // These requirements are designed to allow chaining and nesting of // BeginFrameObservers which filter the incoming BeginFrame messages while // preventing "double dropping" and other bad side effects. - virtual const BeginFrameArgs LastUsedBeginFrameArgs() const = 0; + virtual const BeginFrameArgs& LastUsedBeginFrameArgs() const = 0; virtual void OnBeginFrameSourcePausedChanged(bool paused) = 0; @@ -85,7 +85,7 @@ class CC_EXPORT BeginFrameObserverBase : public BeginFrameObserver { // OnBeginFrameDerivedImpl and updates the last_begin_frame_args_ value on // true. void OnBeginFrame(const BeginFrameArgs& args) override; - const BeginFrameArgs LastUsedBeginFrameArgs() const override; + const BeginFrameArgs& LastUsedBeginFrameArgs() const override; // Outputs last_begin_frame_args_ void AsValueInto(base::trace_event::TracedValue* dict) const override; @@ -115,21 +115,14 @@ class CC_EXPORT BeginFrameSource { public: virtual ~BeginFrameSource() {} - // SetNeedsBeginFrames is the on/off "switch" for the BeginFrameSource. When - // set to false no more BeginFrame messages should be sent to observer. - virtual bool NeedsBeginFrames() const = 0; - virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0; - // DidFinishFrame provides back pressure to a frame source about frame // processing (rather than toggling SetNeedsBeginFrames every frame). It is // used by systems like the BackToBackFrameSource to make sure only one frame // is pending at a time. virtual void DidFinishFrame(size_t remaining_frames) = 0; - // Add/Remove an observer from the source. - // *At the moment* only a single observer can be added to the source, however - // in the future this may be extended to allow multiple observers. - // If making this change, please use base::ObserverList to do so. + // Add/Remove an observer from the source. When no observers are added the BFS + // should shut down its timers, disable vsync, etc. virtual void AddObserver(BeginFrameObserver* obs) = 0; virtual void RemoveObserver(BeginFrameObserver* obs) = 0; @@ -150,14 +143,12 @@ class CC_EXPORT BeginFrameSource { // in their own AsValueInto implementation. class CC_EXPORT BeginFrameSourceBase : public BeginFrameSource { public: - ~BeginFrameSourceBase() override {} + ~BeginFrameSourceBase() override; // BeginFrameSource - bool NeedsBeginFrames() const final; - void SetNeedsBeginFrames(bool needs_begin_frames) final; void DidFinishFrame(size_t remaining_frames) override {} - void AddObserver(BeginFrameObserver* obs) final; - void RemoveObserver(BeginFrameObserver* obs) final; + void AddObserver(BeginFrameObserver* obs) override; + void RemoveObserver(BeginFrameObserver* obs) override; void SetClientReady() override {} // Tracing support - Recommend (but not required) to call this implementation @@ -172,12 +163,13 @@ class CC_EXPORT BeginFrameSourceBase : public BeginFrameSource { void CallOnBeginFrame(const BeginFrameArgs& args); void SetBeginFrameSourcePaused(bool paused); - // This method should be overridden if you want to change some behaviour on - // needs_begin_frames change. - virtual void OnNeedsBeginFramesChange(bool needs_begin_frames) {} + // This notifies that the subclass that it must turn on or off its mechnanism + // for producing BeginFrames. + virtual void OnNeedsBeginFramesChanged(bool needs_begin_frames) {} + + bool needs_begin_frames() const { return !observers_.empty(); } - BeginFrameObserver* observer_; - bool needs_begin_frames_; + std::set<BeginFrameObserver*> observers_; bool paused_; private: @@ -197,6 +189,10 @@ class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSourceBase { // BeginFrameSource void DidFinishFrame(size_t remaining_frames) override; + // BeginFrameSourceBase + void AddObserver(BeginFrameObserver* obs) override; + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override; + // Tracing void AsValueInto(base::trace_event::TracedValue* dict) const override; @@ -206,12 +202,9 @@ class CC_EXPORT BackToBackBeginFrameSource : public BeginFrameSourceBase { virtual base::TimeTicks Now(); // Now overridable for testing base::SingleThreadTaskRunner* task_runner_; + base::CancelableClosure begin_frame_task_; - bool send_begin_frame_posted_; - - // BeginFrameSourceBase - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; - + void PostBeginFrame(); void BeginFrame(); private: @@ -233,6 +226,10 @@ class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSourceBase, void OnUpdateVSyncParameters(base::TimeTicks new_vsync_timebase, base::TimeDelta new_vsync_interval); + // BeginFrameSourceBase + void AddObserver(BeginFrameObserver* obs) override; + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override; + // Tracing void AsValueInto(base::trace_event::TracedValue* dict) const override; @@ -246,9 +243,6 @@ class CC_EXPORT SyntheticBeginFrameSource : public BeginFrameSourceBase, BeginFrameArgs CreateBeginFrameArgs(base::TimeTicks frame_time, BeginFrameArgs::BeginFrameArgsType type); - // BeginFrameSourceBase - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; - scoped_ptr<DelayBasedTimeSource> time_source_; private: @@ -276,14 +270,13 @@ class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceBase, // calls to preserve the monotonicity of the BeginFrameArgs when switching // sources. void OnBeginFrame(const BeginFrameArgs& args) override; - const BeginFrameArgs LastUsedBeginFrameArgs() const override; + const BeginFrameArgs& LastUsedBeginFrameArgs() const override; void OnBeginFrameSourcePausedChanged(bool paused) override; - // BeginFrameSource - void DidFinishFrame(size_t remaining_frames) override; - // BeginFrameSourceBase - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; + void DidFinishFrame(size_t remaining_frames) override; + void AddObserver(BeginFrameObserver* obs) override; + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override; // Tracing void AsValueInto(base::trace_event::TracedValue* dict) const override; @@ -300,6 +293,9 @@ class CC_EXPORT BeginFrameSourceMultiplexer : public BeginFrameSourceBase, BeginFrameSource* active_source_; std::set<BeginFrameSource*> source_list_; + BeginFrameArgs last_begin_frame_args_; + bool inside_add_observer_; + private: DISALLOW_COPY_AND_ASSIGN(BeginFrameSourceMultiplexer); }; diff --git a/cc/scheduler/begin_frame_source_unittest.cc b/cc/scheduler/begin_frame_source_unittest.cc index 4591559c..16640ee 100644 --- a/cc/scheduler/begin_frame_source_unittest.cc +++ b/cc/scheduler/begin_frame_source_unittest.cc @@ -14,6 +14,7 @@ #include "testing/gtest/include/gtest/gtest.h" using testing::Mock; +using testing::StrictMock; namespace cc { namespace { @@ -78,28 +79,32 @@ TEST(BeginFrameSourceBaseTest, ObserverManipulation) { EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false); source.AddObserver(&obs); - EXPECT_EQ(&obs, source.GetObserver()); + EXPECT_TRUE(source.has_observers()); #ifndef NDEBUG - // Adding an observer when an observer already exists should DCHECK fail. - EXPECT_DEATH({ source.AddObserver(&otherObs); }, ""); + // Adding an observer when it already exists should DCHECK fail. + EXPECT_DEATH({ source.AddObserver(&obs); }, ""); // Removing wrong observer should DCHECK fail. EXPECT_DEATH({ source.RemoveObserver(&otherObs); }, ""); // Removing an observer when there is no observer should DCHECK fail. - EXPECT_DEATH({ - source.RemoveObserver(&obs); - source.RemoveObserver(&obs); - }, - ""); + EXPECT_DEATH( + { + source.RemoveObserver(&obs); + source.RemoveObserver(&obs); + }, + ""); #endif + source.RemoveObserver(&obs); + EXPECT_FALSE(source.has_observers()); EXPECT_BEGIN_FRAME_SOURCE_PAUSED(otherObs, false); source.AddObserver(&otherObs); - EXPECT_EQ(&otherObs, source.GetObserver()); + EXPECT_TRUE(source.has_observers()); source.RemoveObserver(&otherObs); + EXPECT_FALSE(source.has_observers()); } TEST(BeginFrameSourceBaseTest, Observer) { @@ -123,15 +128,6 @@ TEST(BeginFrameSourceBaseTest, NoObserver) { SEND_BEGIN_FRAME_DROP(source, 100, 200, 300); } -TEST(BeginFrameSourceBaseTest, NeedsBeginFrames) { - FakeBeginFrameSource source; - EXPECT_FALSE(source.NeedsBeginFrames()); - source.SetNeedsBeginFrames(true); - EXPECT_TRUE(source.NeedsBeginFrames()); - source.SetNeedsBeginFrames(false); - EXPECT_FALSE(source.NeedsBeginFrames()); -} - TEST(BeginFrameSourceBaseTest, SetBeginFrameSourcePaused) { FakeBeginFrameSource source; MockBeginFrameObserver obs; @@ -144,6 +140,38 @@ TEST(BeginFrameSourceBaseTest, SetBeginFrameSourcePaused) { source.SetBeginFrameSourcePaused(false); } +TEST(BeginFrameSourceBaseTest, MultipleObservers) { + FakeBeginFrameSource source; + StrictMock<MockBeginFrameObserver> obs1, obs2; + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false); + source.AddObserver(&obs1); + + EXPECT_BEGIN_FRAME_USED(obs1, 100, 200, 100); + SEND_BEGIN_FRAME_USED(source, 100, 200, 100); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false); + source.AddObserver(&obs2); + + EXPECT_BEGIN_FRAME_USED(obs1, 200, 300, 100); + EXPECT_BEGIN_FRAME_USED(obs2, 200, 300, 100); + SEND_BEGIN_FRAME_USED(source, 200, 300, 100); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, true); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, true); + source.SetBeginFrameSourcePaused(true); + + source.RemoveObserver(&obs1); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false); + source.SetBeginFrameSourcePaused(false); + + EXPECT_BEGIN_FRAME_USED(obs2, 300, 400, 100); + SEND_BEGIN_FRAME_USED(source, 300, 400, 100); + + source.RemoveObserver(&obs2); +} + class LoopingBeginFrameObserver : public BeginFrameObserverBase { public: BeginFrameSource* source_; @@ -212,12 +240,9 @@ class BackToBackBeginFrameSourceTest : public ::testing::Test { now_src_->Advance(base::TimeDelta::FromMicroseconds(1000)); task_runner_ = make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_.get(), false)); - task_runner_->SetRunTaskLimit(1); source_ = TestBackToBackBeginFrameSource::Create(now_src_.get(), task_runner_.get()); obs_ = make_scoped_ptr(new ::testing::StrictMock<MockBeginFrameObserver>()); - EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); - source_->AddObserver(obs_.get()); } void TearDown() override { obs_.reset(); } @@ -229,94 +254,106 @@ const int64_t BackToBackBeginFrameSourceTest::kDeadline = const int64_t BackToBackBeginFrameSourceTest::kInterval = BeginFrameArgs::DefaultInterval().ToInternalValue(); -TEST_F(BackToBackBeginFrameSourceTest, SetNeedsBeginFramesSendsBeginFrame) { - EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); +TEST_F(BackToBackBeginFrameSourceTest, AddObserverSendsBeginFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_TRUE(task_runner_->HasPendingTasks()); - task_runner_->RunUntilIdle(); + EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); + task_runner_->RunPendingTasks(); EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } TEST_F(BackToBackBeginFrameSourceTest, - DidFinishFrameThenSetNeedsBeginFramesProducesNoFrame) { + DidFinishFrameThenRemoveObserverProducesNoFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); - source_->SetNeedsBeginFrames(false); + source_->RemoveObserver(obs_.get()); source_->DidFinishFrame(0); EXPECT_FALSE(task_runner_->HasPendingTasks()); } TEST_F(BackToBackBeginFrameSourceTest, - SetNeedsBeginFramesThenDidFinishFrameProducesNoFrame) { + RemoveObserverThenDidFinishFrameProducesNoFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); - source_->SetNeedsBeginFrames(false); + source_->RemoveObserver(obs_.get()); EXPECT_TRUE(task_runner_->HasPendingTasks()); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } TEST_F(BackToBackBeginFrameSourceTest, - DidFinishFrameThenTogglingSetNeedsBeginFramesProducesCorrectFrame) { + TogglingObserverThenDidFinishFrameProducesCorrectFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); + source_->RemoveObserver(obs_.get()); - source_->SetNeedsBeginFrames(false); now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); - source_->DidFinishFrame(0); - now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); - source_->SetNeedsBeginFrames(false); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); - source_->SetNeedsBeginFrames(true); + source_->DidFinishFrame(0); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); EXPECT_BEGIN_FRAME_USED(*obs_, 1130, 1130 + kDeadline, kInterval); EXPECT_TRUE(task_runner_->HasPendingTasks()); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } TEST_F(BackToBackBeginFrameSourceTest, - TogglingSetNeedsBeginFramesThenDidFinishFrameProducesCorrectFrame) { + DidFinishFrameThenTogglingObserverProducesCorrectFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); - source_->SetNeedsBeginFrames(false); - now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); - source_->SetNeedsBeginFrames(true); + source_->RemoveObserver(obs_.get()); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); + now_src_->Advance(base::TimeDelta::FromMicroseconds(10)); EXPECT_BEGIN_FRAME_USED(*obs_, 1130, 1130 + kDeadline, kInterval); EXPECT_TRUE(task_runner_->HasPendingTasks()); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } -TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameNeedsBeginFrameFalse) { - source_->SetNeedsBeginFrames(false); +TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameNoObserver) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); + source_->RemoveObserver(obs_.get()); source_->DidFinishFrame(0); EXPECT_FALSE(task_runner_->RunPendingTasks()); } TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameRemainingFrames) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); @@ -330,33 +367,35 @@ TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameRemainingFrames) { EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); source_->DidFinishFrame(0); EXPECT_EQ(base::TimeDelta(), task_runner_->DelayToNextTaskTime()); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) { - source_->SetNeedsBeginFrames(true); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); source_->DidFinishFrame(0); source_->DidFinishFrame(0); EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); source_->DidFinishFrame(0); source_->DidFinishFrame(0); EXPECT_BEGIN_FRAME_USED(*obs_, 1200, 1200 + kDeadline, kInterval); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); - source_->SetNeedsBeginFrames(true); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); now_src_->Advance(base::TimeDelta::FromMicroseconds(100)); source_->DidFinishFrame(0); @@ -364,7 +403,7 @@ TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) { EXPECT_BEGIN_FRAME_USED(*obs_, 1150, 1150 + kDeadline, kInterval); EXPECT_TRUE(task_runner_->HasPendingTasks()); - task_runner_->RunUntilIdle(); + task_runner_->RunPendingTasks(); } // SyntheticBeginFrameSource testing ------------------------------------------ @@ -384,26 +423,24 @@ class SyntheticBeginFrameSourceTest : public ::testing::Test { now_src_.get(), task_runner_.get(), base::TimeDelta::FromMicroseconds(10000)); obs_ = make_scoped_ptr(new MockBeginFrameObserver()); - EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); - source_->AddObserver(obs_.get()); } void TearDown() override { obs_.reset(); } }; TEST_F(SyntheticBeginFrameSourceTest, - SetNeedsBeginFramesCallsOnBeginFrameWithMissedTick) { + AddObserverCallsOnBeginFrameWithMissedTick) { now_src_->Advance(base::TimeDelta::FromMicroseconds(9010)); - EXPECT_CALL((*obs_), OnBeginFrame(CreateBeginFrameArgsForTesting( - BEGINFRAME_FROM_HERE, 10000, 20000, 10000, - BeginFrameArgs::MISSED))); - source_->SetNeedsBeginFrames(true); // Should cause the last tick to be sent + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 10000, 20000, 10000); + source_->AddObserver(obs_.get()); // Should cause the last tick to be sent // No tasks should need to be run for this to occur. } -TEST_F(SyntheticBeginFrameSourceTest, - SetNeedsBeginFramesCallsCausesOnBeginFrame) { - source_->SetNeedsBeginFrames(true); +TEST_F(SyntheticBeginFrameSourceTest, AddObserverCallsCausesOnBeginFrame) { + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 10000, 10000); + source_->AddObserver(obs_.get()); EXPECT_EQ(10000, task_runner_->NextTaskTime().ToInternalValue()); EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); @@ -414,20 +451,24 @@ TEST_F(SyntheticBeginFrameSourceTest, TEST_F(SyntheticBeginFrameSourceTest, BasicOperation) { task_runner_->SetAutoAdvanceNowToPendingTasks(true); - source_->SetNeedsBeginFrames(true); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 10000, 10000); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); EXPECT_BEGIN_FRAME_USED(*obs_, 20000, 30000, 10000); EXPECT_BEGIN_FRAME_USED(*obs_, 30000, 40000, 10000); task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(30001)); - source_->SetNeedsBeginFrames(false); + source_->RemoveObserver(obs_.get()); // No new frames.... task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(60000)); } TEST_F(SyntheticBeginFrameSourceTest, VSyncChanges) { task_runner_->SetAutoAdvanceNowToPendingTasks(true); - source_->SetNeedsBeginFrames(true); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(*obs_, false); + EXPECT_BEGIN_FRAME_USED_MISSED(*obs_, 0, 10000, 10000); + source_->AddObserver(obs_.get()); EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); EXPECT_BEGIN_FRAME_USED(*obs_, 20000, 30000, 10000); @@ -444,6 +485,87 @@ TEST_F(SyntheticBeginFrameSourceTest, VSyncChanges) { task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(60000)); } +TEST_F(SyntheticBeginFrameSourceTest, MultipleObservers) { + StrictMock<MockBeginFrameObserver> obs1, obs2; + + // now_src_ starts off at 1000. + task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(9010)); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false); + EXPECT_BEGIN_FRAME_USED_MISSED(obs1, 10000, 20000, 10000); + source_->AddObserver(&obs1); // Should cause the last tick to be sent + // No tasks should need to be run for this to occur. + + EXPECT_BEGIN_FRAME_USED(obs1, 20000, 30000, 10000); + task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(10000)); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false); + EXPECT_BEGIN_FRAME_USED_MISSED(obs2, 20000, 30000, 10000); + source_->AddObserver(&obs2); // Should cause the last tick to be sent + // No tasks should need to be run for this to occur. + + EXPECT_BEGIN_FRAME_USED(obs1, 30000, 40000, 10000); + EXPECT_BEGIN_FRAME_USED(obs2, 30000, 40000, 10000); + task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(10000)); + + source_->RemoveObserver(&obs1); + + EXPECT_BEGIN_FRAME_USED(obs2, 40000, 50000, 10000); + task_runner_->RunForPeriod(base::TimeDelta::FromMicroseconds(10000)); + + source_->RemoveObserver(&obs2); + task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(50000)); + EXPECT_FALSE(task_runner_->HasPendingTasks()); +} + +TEST_F(SyntheticBeginFrameSourceTest, DoubleTick) { + StrictMock<MockBeginFrameObserver> obs; + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false); + EXPECT_BEGIN_FRAME_USED_MISSED(obs, 0, 10000, 10000); + source_->AddObserver(&obs); + + source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(5000), + base::TimeDelta::FromInternalValue(10000)); + now_src_->Advance(base::TimeDelta::FromInternalValue(4000)); + + // No begin frame received. + task_runner_->RunPendingTasks(); + + // Begin frame received. + source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(10000), + base::TimeDelta::FromInternalValue(10000)); + now_src_->Advance(base::TimeDelta::FromInternalValue(5000)); + EXPECT_BEGIN_FRAME_USED(obs, 10000, 20000, 10000); + task_runner_->RunPendingTasks(); +} + +TEST_F(SyntheticBeginFrameSourceTest, DoubleTickMissedFrame) { + StrictMock<MockBeginFrameObserver> obs; + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false); + EXPECT_BEGIN_FRAME_USED_MISSED(obs, 0, 10000, 10000); + source_->AddObserver(&obs); + source_->RemoveObserver(&obs); + + source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(5000), + base::TimeDelta::FromInternalValue(10000)); + now_src_->Advance(base::TimeDelta::FromInternalValue(4000)); + + // No missed frame received. + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false); + source_->AddObserver(&obs); + source_->RemoveObserver(&obs); + + // Missed frame received. + source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(10000), + base::TimeDelta::FromInternalValue(10000)); + now_src_->Advance(base::TimeDelta::FromInternalValue(5000)); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false); + EXPECT_BEGIN_FRAME_USED_MISSED(obs, 10000, 20000, 10000); + source_->AddObserver(&obs); + source_->RemoveObserver(&obs); +} + // BeginFrameSourceMultiplexer testing ----------------------------------- class BeginFrameSourceMultiplexerTest : public ::testing::Test { protected: @@ -511,33 +633,100 @@ TEST_F(BeginFrameSourceMultiplexerTest, SourcesManipulation) { mux_->RemoveSource(source1_); } -TEST_F(BeginFrameSourceMultiplexerTest, NeedsBeginFrames) { +TEST_F(BeginFrameSourceMultiplexerTest, SwitchActiveSource) { + mux_->AddSource(source1_); + mux_->AddSource(source2_); + + EXPECT_FALSE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); + + MockBeginFrameObserver obs; + mux_->AddObserver(&obs); + + mux_->SetActiveSource(source1_); + EXPECT_TRUE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); + + mux_->SetActiveSource(source2_); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_TRUE(source2_->has_observers()); +} + +TEST_F(BeginFrameSourceMultiplexerTest, SingleObserver) { mux_->AddSource(source1_); mux_->AddSource(source2_); mux_->SetActiveSource(source1_); - EXPECT_EQ(source1_->NeedsBeginFrames(), false); - EXPECT_EQ(source2_->NeedsBeginFrames(), false); - // Check SetNeedsFrames works - mux_->SetNeedsBeginFrames(true); - EXPECT_EQ(source1_->NeedsBeginFrames(), true); - EXPECT_EQ(source2_->NeedsBeginFrames(), false); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); - mux_->SetNeedsBeginFrames(false); - EXPECT_EQ(source1_->NeedsBeginFrames(), false); - EXPECT_EQ(source2_->NeedsBeginFrames(), false); + MockBeginFrameObserver obs; + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, false); + mux_->AddObserver(&obs); + EXPECT_TRUE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); + + EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 100); + SEND_BEGIN_FRAME_USED(*source1_, 100, 200, 100); + SEND_BEGIN_FRAME_DROP(*source2_, 150, 250, 100); - // Checking that switching the source makes SetNeedsFrames on the - // subsources correctly. - mux_->SetNeedsBeginFrames(true); + mux_->RemoveObserver(&obs); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); +} +TEST_F(BeginFrameSourceMultiplexerTest, MultipleObservers) { + mux_->AddSource(source1_); + mux_->AddSource(source2_); mux_->SetActiveSource(source1_); - EXPECT_EQ(source1_->NeedsBeginFrames(), true); - EXPECT_EQ(source2_->NeedsBeginFrames(), false); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); + + StrictMock<MockBeginFrameObserver> obs1, obs2; + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false); + mux_->AddObserver(&obs1); + EXPECT_TRUE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); + + EXPECT_BEGIN_FRAME_USED(obs1, 100, 200, 100); + SEND_BEGIN_FRAME_USED(*source1_, 100, 200, 100); + SEND_BEGIN_FRAME_DROP(*source2_, 200, 300, 100); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false); + mux_->AddObserver(&obs2); + + EXPECT_BEGIN_FRAME_USED(obs1, 300, 400, 100); + EXPECT_BEGIN_FRAME_USED(obs2, 300, 400, 100); + SEND_BEGIN_FRAME_USED(*source1_, 300, 400, 100); + SEND_BEGIN_FRAME_DROP(*source2_, 400, 500, 100); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, true); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, true); + source1_->SetBeginFrameSourcePaused(true); + + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs1, false); + EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs2, false); mux_->SetActiveSource(source2_); - EXPECT_EQ(source1_->NeedsBeginFrames(), false); - EXPECT_EQ(source2_->NeedsBeginFrames(), true); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_TRUE(source2_->has_observers()); + + EXPECT_BEGIN_FRAME_USED(obs1, 600, 700, 100); + EXPECT_BEGIN_FRAME_USED(obs2, 600, 700, 100); + SEND_BEGIN_FRAME_DROP(*source1_, 500, 600, 100); + SEND_BEGIN_FRAME_USED(*source2_, 600, 700, 100); + + mux_->RemoveObserver(&obs1); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_TRUE(source2_->has_observers()); + + EXPECT_BEGIN_FRAME_USED(obs2, 800, 900, 100); + SEND_BEGIN_FRAME_DROP(*source1_, 700, 800, 100); + SEND_BEGIN_FRAME_USED(*source2_, 800, 900, 100); + + mux_->RemoveObserver(&obs2); + EXPECT_FALSE(source1_->has_observers()); + EXPECT_FALSE(source2_->has_observers()); } TEST_F(BeginFrameSourceMultiplexerTest, BeginFramesSimple) { diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc index 8e633ef..bc9c762 100644 --- a/cc/scheduler/delay_based_time_source.cc +++ b/cc/scheduler/delay_based_time_source.cc @@ -19,11 +19,6 @@ namespace cc { namespace { -// kDoubleTickDivisor prevents ticks from running within the specified -// fraction of an interval. This helps account for jitter in the timebase as -// well as quick timer reactivation. -static const int kDoubleTickDivisor = 2; - // kIntervalChangeThreshold is the fraction of the interval that will trigger an // immediate interval change. kPhaseChangeThreshold is the fraction of the // interval that will trigger an immediate phase change. If the changes are @@ -53,32 +48,21 @@ DelayBasedTimeSource::DelayBasedTimeSource( DelayBasedTimeSource::~DelayBasedTimeSource() {} -base::TimeTicks DelayBasedTimeSource::SetActive(bool active) { +void DelayBasedTimeSource::SetActive(bool active) { TRACE_EVENT1("cc", "DelayBasedTimeSource::SetActive", "active", active); if (active == active_) - return base::TimeTicks(); + return; active_ = active; - if (!active_) { + if (active_) { + PostNextTickTask(Now()); + } else { + last_tick_time_ = base::TimeTicks(); next_tick_time_ = base::TimeTicks(); tick_closure_.Cancel(); - return base::TimeTicks(); - } - - ResetTickTask(Now()); - - // Determine if there was a tick that was missed while not active. - base::TimeTicks last_tick_time_if_always_active = next_tick_time_ - interval_; - base::TimeTicks last_tick_time_threshold = - last_tick_time_ + interval_ / kDoubleTickDivisor; - if (last_tick_time_if_always_active > last_tick_time_threshold) { - last_tick_time_ = last_tick_time_if_always_active; - return last_tick_time_; } - - return base::TimeTicks(); } base::TimeDelta DelayBasedTimeSource::Interval() const { @@ -134,7 +118,7 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, if (interval_change > kIntervalChangeThreshold) { TRACE_EVENT_INSTANT0("cc", "DelayBasedTimeSource::IntervalChanged", TRACE_EVENT_SCOPE_THREAD); - ResetTickTask(Now()); + PostNextTickTask(Now()); return; } @@ -150,7 +134,7 @@ void DelayBasedTimeSource::SetTimebaseAndInterval(base::TimeTicks timebase, phase_change < (1.0 - kPhaseChangeThreshold)) { TRACE_EVENT_INSTANT0("cc", "DelayBasedTimeSource::PhaseChanged", TRACE_EVENT_SCOPE_THREAD); - ResetTickTask(Now()); + PostNextTickTask(Now()); return; } } @@ -213,37 +197,15 @@ base::TimeTicks DelayBasedTimeSource::Now() const { // is not reset. // now=37 tick_target=16.667 new_target=50.000 --> // tick(), PostDelayedTask(floor(50.000-37)) --> PostDelayedTask(13) -base::TimeTicks DelayBasedTimeSource::NextTickTarget( - base::TimeTicks now) const { - base::TimeTicks next_tick_target = - now.SnappedToNextTick(timebase_, interval_); - DCHECK(now <= next_tick_target) - << "now = " << now.ToInternalValue() - << "; new_tick_target = " << next_tick_target.ToInternalValue() - << "; new_interval = " << interval_.InMicroseconds() - << "; new_timbase = " << timebase_.ToInternalValue(); - - // Avoid double ticks when: - // 1) Turning off the timer and turning it right back on. - // 2) Jittery data is passed to SetTimebaseAndInterval(). - if (next_tick_target - last_tick_time_ <= interval_ / kDoubleTickDivisor) - next_tick_target += interval_; - - return next_tick_target; -} - void DelayBasedTimeSource::PostNextTickTask(base::TimeTicks now) { - next_tick_time_ = NextTickTarget(now); - DCHECK(next_tick_time_ >= now); - // Post another task *before* the tick and update state - base::TimeDelta delay = next_tick_time_ - now; - task_runner_->PostDelayedTask(FROM_HERE, tick_closure_.callback(), delay); -} - -void DelayBasedTimeSource::ResetTickTask(base::TimeTicks now) { + next_tick_time_ = now.SnappedToNextTick(timebase_, interval_); + if (next_tick_time_ == now) + next_tick_time_ += interval_; + DCHECK_GT(next_tick_time_, now); tick_closure_.Reset(base::Bind(&DelayBasedTimeSource::OnTimerTick, weak_factory_.GetWeakPtr())); - PostNextTickTask(now); + task_runner_->PostDelayedTask(FROM_HERE, tick_closure_.callback(), + next_tick_time_ - now); } std::string DelayBasedTimeSource::TypeString() const { diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h index 7f97a91..1300661 100644 --- a/cc/scheduler/delay_based_time_source.h +++ b/cc/scheduler/delay_based_time_source.h @@ -49,8 +49,7 @@ class CC_EXPORT DelayBasedTimeSource { base::TimeDelta Interval() const; - // Returns the time for the last missed tick. - base::TimeTicks SetActive(bool active); + void SetActive(bool active); bool Active() const; // Get the last and next tick times. NextTickTime() returns null when @@ -69,8 +68,6 @@ class CC_EXPORT DelayBasedTimeSource { virtual std::string TypeString() const; private: - base::TimeTicks NextTickTarget(base::TimeTicks now) const; - void PostNextTickTask(base::TimeTicks now); void ResetTickTask(base::TimeTicks now); diff --git a/cc/scheduler/delay_based_time_source_unittest.cc b/cc/scheduler/delay_based_time_source_unittest.cc index 5e224e6..a905fed 100644 --- a/cc/scheduler/delay_based_time_source_unittest.cc +++ b/cc/scheduler/delay_based_time_source_unittest.cc @@ -123,7 +123,7 @@ TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenSlightlyAfterRequestedTime) { } // At 60Hz, when the tick returns at exactly 2*interval after the requested next -// time, make sure a 0ms next delay is posted. +// time, make sure we don't tick unnecessarily. TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenExactlyTwiceAfterRequestedTime) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = @@ -141,7 +141,7 @@ TEST(DelayBasedTimeSourceTest, timer->SetNow(timer->Now() + 2 * Interval()); task_runner->RunPendingTasks(); - EXPECT_EQ(0, task_runner->NextPendingTaskDelay().InMilliseconds()); + EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds()); } // At 60Hz, when the tick returns at 2*interval and a bit after the requested @@ -189,39 +189,6 @@ TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenHalfAfterRequestedTime) { EXPECT_EQ(8, task_runner->NextPendingTaskDelay().InMilliseconds()); } -// If the timebase and interval are updated with a jittery source, we want to -// make sure we do not double tick. -TEST(DelayBasedTimeSourceTest, SaneHandlingOfJitteryTimebase) { - scoped_refptr<base::TestSimpleTaskRunner> task_runner = - new base::TestSimpleTaskRunner; - FakeDelayBasedTimeSourceClient client; - scoped_ptr<FakeDelayBasedTimeSource> timer = - FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); - timer->SetClient(&client); - timer->SetActive(true); - // Run the first tick. - task_runner->RunPendingTasks(); - - EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds()); - - // Jitter timebase ~1ms late - timer->SetNow(timer->Now() + Interval()); - timer->SetTimebaseAndInterval( - timer->Now() + base::TimeDelta::FromMilliseconds(1), Interval()); - task_runner->RunPendingTasks(); - - // Without double tick prevention, NextPendingTaskDelay would be 1. - EXPECT_EQ(17, task_runner->NextPendingTaskDelay().InMilliseconds()); - - // Jitter timebase ~1ms early - timer->SetNow(timer->Now() + Interval()); - timer->SetTimebaseAndInterval( - timer->Now() - base::TimeDelta::FromMilliseconds(1), Interval()); - task_runner->RunPendingTasks(); - - EXPECT_EQ(15, task_runner->NextPendingTaskDelay().InMilliseconds()); -} - TEST(DelayBasedTimeSourceTest, HandlesSignificantTimebaseChangesImmediately) { scoped_refptr<base::TestSimpleTaskRunner> task_runner = new base::TestSimpleTaskRunner; @@ -249,7 +216,7 @@ TEST(DelayBasedTimeSourceTest, HandlesSignificantTimebaseChangesImmediately) { timer->SetTimebaseAndInterval(timer->Now() + jitter, Interval()); EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled. - EXPECT_EQ(16 + 7, task_runner->NextPendingTaskDelay().InMilliseconds()); + EXPECT_EQ(7, task_runner->NextPendingTaskDelay().InMilliseconds()); // Tick, then shift timebase by -7ms. timer->SetNow(timer->Now() + Interval() + jitter); @@ -345,7 +312,7 @@ TEST(DelayBasedTimeSourceTest, JitteryRuntimeWithFutureTimebases) { timer->SetTimebaseAndInterval(future_timebase, Interval()); timer->SetNow(timer->Now() + Interval() - jitter1); task_runner->RunPendingTasks(); - EXPECT_EQ(17, task_runner->NextPendingTaskDelay().InMilliseconds()); + EXPECT_EQ(1, task_runner->NextPendingTaskDelay().InMilliseconds()); // Tick with 0ms of jitter future_timebase += Interval(); @@ -376,7 +343,7 @@ TEST(DelayBasedTimeSourceTest, JitteryRuntimeWithFutureTimebases) { timer->SetTimebaseAndInterval(future_timebase, Interval()); timer->SetNow(timer->Now() + Interval() - jitter8); task_runner->RunPendingTasks(); - EXPECT_EQ(24, task_runner->NextPendingTaskDelay().InMilliseconds()); + EXPECT_EQ(8, task_runner->NextPendingTaskDelay().InMilliseconds()); // Tick with 0ms of jitter future_timebase += Interval(); @@ -407,7 +374,7 @@ TEST(DelayBasedTimeSourceTest, JitteryRuntimeWithFutureTimebases) { timer->SetTimebaseAndInterval(future_timebase, Interval()); timer->SetNow(timer->Now() + Interval() - jitter15); task_runner->RunPendingTasks(); - EXPECT_EQ(31, task_runner->NextPendingTaskDelay().InMilliseconds()); + EXPECT_EQ(15, task_runner->NextPendingTaskDelay().InMilliseconds()); // Tick with 0ms of jitter future_timebase += Interval(); @@ -509,21 +476,5 @@ TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateAfterNextTickTime) { EXPECT_EQ(13, task_runner->NextPendingTaskDelay().InMilliseconds()); } -TEST(DelayBasedTimeSourceTest, TestReturnValueWhenTimerIsDeActivated) { - scoped_refptr<base::TestSimpleTaskRunner> task_runner = - new base::TestSimpleTaskRunner; - FakeDelayBasedTimeSourceClient client; - scoped_ptr<FakeDelayBasedTimeSource> timer = - FakeDelayBasedTimeSource::Create(Interval(), task_runner.get()); - timer->SetClient(&client); - - timer->SetActive(true); - task_runner->RunPendingTasks(); - - // SetActive should return empty TimeTicks when the timer is deactivated. - base::TimeTicks missed_tick_time = timer->SetActive(false); - EXPECT_TRUE(missed_tick_time.is_null()); -} - } // namespace } // namespace cc diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index f6dfccb..39dcc08 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc @@ -63,6 +63,7 @@ Scheduler::Scheduler( synthetic_frame_source_(std::move(synthetic_frame_source)), unthrottled_frame_source_(std::move(unthrottled_frame_source)), frame_source_(BeginFrameSourceMultiplexer::Create()), + observing_frame_source_(false), throttle_frame_production_(false), compositor_timing_history_(std::move(compositor_timing_history)), begin_impl_frame_deadline_mode_( @@ -84,7 +85,6 @@ Scheduler::Scheduler( begin_impl_frame_deadline_closure_ = base::Bind( &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); - frame_source_->AddObserver(this); frame_source_->AddSource(primary_frame_source()); primary_frame_source()->SetClientReady(); @@ -95,8 +95,8 @@ Scheduler::Scheduler( } Scheduler::~Scheduler() { - if (frame_source_->NeedsBeginFrames()) - frame_source_->SetNeedsBeginFrames(false); + if (observing_frame_source_) + frame_source_->RemoveObserver(this); frame_source_->SetActiveSource(nullptr); } @@ -247,7 +247,7 @@ void Scheduler::DidLoseOutputSurface() { void Scheduler::DidCreateAndInitializeOutputSurface() { TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); - DCHECK(!frame_source_->NeedsBeginFrames()); + DCHECK(!observing_frame_source_); DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); compositor_timing_history_->DidSwapBuffersReset(); state_machine_.DidCreateAndInitializeOutputSurface(); @@ -278,16 +278,18 @@ void Scheduler::BeginImplFrameNotExpectedSoon() { void Scheduler::SetupNextBeginFrameIfNeeded() { // Never call SetNeedsBeginFrames if the frame source already has the right // value. - if (frame_source_->NeedsBeginFrames() != state_machine_.BeginFrameNeeded()) { + if (observing_frame_source_ != state_machine_.BeginFrameNeeded()) { if (state_machine_.BeginFrameNeeded()) { - // Call SetNeedsBeginFrames(true) as soon as possible. - frame_source_->SetNeedsBeginFrames(true); + // Call AddObserver as soon as possible. + observing_frame_source_ = true; + frame_source_->AddObserver(this); devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, true); } else if (state_machine_.begin_impl_frame_state() == SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { - // Call SetNeedsBeginFrames(false) in between frames only. - frame_source_->SetNeedsBeginFrames(false); + // Call RemoveObserver in between frames only. + observing_frame_source_ = false; + frame_source_->RemoveObserver(this); BeginImplFrameNotExpectedSoon(); devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, false); @@ -344,8 +346,7 @@ bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { bool should_defer_begin_frame = !begin_retro_frame_args_.empty() || - !begin_retro_frame_task_.IsCancelled() || - !frame_source_->NeedsBeginFrames() || + !begin_retro_frame_task_.IsCancelled() || !observing_frame_source_ || (state_machine_.begin_impl_frame_state() != SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); @@ -447,7 +448,7 @@ void Scheduler::PostBeginRetroFrameIfNeeded() { "Scheduler::PostBeginRetroFrameIfNeeded", "state", AsValue()); - if (!frame_source_->NeedsBeginFrames()) + if (!observing_frame_source_) return; if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) @@ -807,8 +808,7 @@ void Scheduler::AsValueInto(base::trace_event::TracedValue* state) const { (last_vsync_timebase_ - base::TimeTicks()).InMillisecondsF()); state->SetDouble("estimated_parent_draw_time_ms", estimated_parent_draw_time_.InMillisecondsF()); - state->SetBoolean("last_set_needs_begin_frame_", - frame_source_->NeedsBeginFrames()); + state->SetBoolean("observing_frame_source", observing_frame_source_); state->SetInteger("begin_retro_frame_args", static_cast<int>(begin_retro_frame_args_.size())); state->SetBoolean("begin_retro_frame_task", diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 61a0ea8..61575ec 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h @@ -167,6 +167,7 @@ class CC_EXPORT Scheduler : public BeginFrameObserverBase { scoped_ptr<BackToBackBeginFrameSource> unthrottled_frame_source_; scoped_ptr<BeginFrameSourceMultiplexer> frame_source_; + bool observing_frame_source_; bool throttle_frame_production_; base::TimeDelta authoritative_vsync_interval_; diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 9a30c34..4da406f 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc @@ -72,9 +72,7 @@ class FakeSchedulerClient : public SchedulerClient { void set_scheduler(TestScheduler* scheduler) { scheduler_ = scheduler; } - bool needs_begin_frames() { - return scheduler_->frame_source().NeedsBeginFrames(); - } + bool needs_begin_frames() { return scheduler_->begin_frames_expected(); } int num_draws() const { return num_draws_; } int num_actions_() const { return static_cast<int>(actions_.size()); } const char* Action(int i) const { return actions_[i]; } @@ -220,22 +218,22 @@ class FakeExternalBeginFrameSource : public BeginFrameSourceBase { : client_(client) {} ~FakeExternalBeginFrameSource() override {} - void OnNeedsBeginFramesChange(bool needs_begin_frames) override { - if (needs_begin_frames) { - client_->PushAction("SetNeedsBeginFrames(true)"); - } else { - client_->PushAction("SetNeedsBeginFrames(false)"); - } + void AddObserver(BeginFrameObserver* obs) override { + client_->PushAction("AddObserver(this)"); + BeginFrameSourceBase::AddObserver(obs); + } + + void RemoveObserver(BeginFrameObserver* obs) override { + client_->PushAction("RemoveObserver(this)"); + BeginFrameSourceBase::RemoveObserver(obs); } + // TODO(sunnyps): Use using CallOnBeginFrame, SetBeginFrameSourcePaused. void TestOnBeginFrame(const BeginFrameArgs& args) { return CallOnBeginFrame(args); } - void SetPaused(bool paused) { - DCHECK(observer_); - observer_->OnBeginFrameSourcePausedChanged(paused); - } + void SetPaused(bool paused) { SetBeginFrameSourcePaused(paused); } private: FakeSchedulerClient* client_; @@ -313,7 +311,7 @@ class SchedulerTest : public testing::Test { // Check the client doesn't have any actions queued when calling this // function. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); // Start the initial output surface creation. scheduler_->SetVisible(true); @@ -325,7 +323,7 @@ class SchedulerTest : public testing::Test { // We don't see anything happening until the first impl frame. scheduler_->DidCreateAndInitializeOutputSurface(); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); @@ -369,7 +367,7 @@ class SchedulerTest : public testing::Test { EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); } - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); client_->Reset(); } @@ -389,7 +387,7 @@ class SchedulerTest : public testing::Test { // it will be already in the task queue. if (scheduler_->settings().use_external_begin_frame_source && scheduler_->FrameProductionThrottled()) { - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); SendNextBeginFrame(); } @@ -455,8 +453,8 @@ TEST_F(SchedulerTest, SendBeginFramesToChildren) { EXPECT_FALSE(client_->begin_frame_is_sent_to_children()); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); scheduler_->SetChildrenNeedBeginFrames(true); @@ -466,17 +464,17 @@ TEST_F(SchedulerTest, SendBeginFramesToChildren) { EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); } TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); scheduler_->SetChildrenNeedBeginFrames(true); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -496,10 +494,10 @@ TEST_F(SchedulerTest, SendBeginFramesToChildrenDeadlineNotAdjusted) { fake_compositor_timing_history_->SetDrawDurationEstimate( base::TimeDelta::FromMilliseconds(1)); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); scheduler_->SetChildrenNeedBeginFrames(true); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -517,8 +515,8 @@ TEST_F(SchedulerTest, VideoNeedsBeginFrames) { SetUpScheduler(true); scheduler_->SetVideoNeedsBeginFrames(true); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -538,9 +536,9 @@ TEST_F(SchedulerTest, VideoNeedsBeginFrames) { client_->Reset(); task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); } TEST_F(SchedulerTest, RequestCommit) { @@ -549,48 +547,48 @@ TEST_F(SchedulerTest, RequestCommit) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // If we don't swap on the deadline, we wait for the next BeginFrame. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // NotifyReadyToCommit should trigger the commit. scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // NotifyReadyToActivate should trigger the activation. scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // BeginImplFrame should prepare the draw. EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // BeginImplFrame deadline should draw. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) @@ -601,7 +599,7 @@ TEST_F(SchedulerTest, RequestCommit) { client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); client_->Reset(); } @@ -619,11 +617,11 @@ TEST_F(SchedulerTest, RequestCommitAfterSetDeferCommit) { task_runner().RunPendingTasks(); // There are no pending tasks or actions. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); client_->Reset(); scheduler_->SetDeferCommits(false); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); // Start new BeginMainFrame after defer commit is off. client_->Reset(); @@ -646,7 +644,7 @@ TEST_F(SchedulerTest, DeferCommitWithRedraw) { // begin frame to be needed. client_->Reset(); scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); AdvanceFrame(); @@ -657,7 +655,7 @@ TEST_F(SchedulerTest, DeferCommitWithRedraw) { task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); AdvanceFrame(); @@ -670,7 +668,7 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -678,7 +676,7 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // Now SetNeedsBeginMainFrame again. Calling here means we need a second @@ -706,7 +704,7 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { // Because we just swapped, the Scheduler should also request the next // BeginImplFrame from the OutputSurface. - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // Since another commit is needed, the next BeginImplFrame should initiate // the second commit. @@ -730,14 +728,14 @@ TEST_F(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // On the next BeginImplFrame, verify we go back to a quiescent state and // no longer request BeginImplFrames. EXPECT_SCOPED(AdvanceFrame()); task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); client_->Reset(); } @@ -1077,7 +1075,7 @@ TEST_F(SchedulerTest, PrepareTiles) { EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); client->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); EXPECT_EQ(0, client->num_draws()); @@ -1236,7 +1234,7 @@ TEST_F(SchedulerTest, PrepareTilesFunnelResetOnVisibilityChange) { client_->Reset(); scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); AdvanceFrame(); @@ -1273,7 +1271,7 @@ TEST_F(SchedulerTest, WaitForReadyToDrawDoNotPostDeadline) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Begin new frame. @@ -1313,7 +1311,7 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Begin new frame. @@ -1342,7 +1340,7 @@ TEST_F(SchedulerTest, WaitForReadyToDrawCancelledWhenLostOutputSurface) { EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } @@ -1358,7 +1356,7 @@ void SchedulerTest::CheckMainFrameSkippedAfterLateCommit( scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); + EXPECT_ACTION("AddObserver(this)", client_, 0, 5); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); @@ -1494,7 +1492,7 @@ void SchedulerTest::ImplFrameSkippedAfterLateSwapAck( scheduler_->SetNeedsRedraw(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); SendNextBeginFrame(); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); + EXPECT_ACTION("AddObserver(this)", client_, 0, 3); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); @@ -1626,7 +1624,7 @@ TEST_F(SchedulerTest, scheduler_->SetNeedsRedraw(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); SendNextBeginFrame(); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 2); + EXPECT_ACTION("AddObserver(this)", client_, 0, 2); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2); client_->Reset(); @@ -1679,7 +1677,7 @@ void SchedulerTest::ImplFrameNotSkippedAfterLateSwapAck() { scheduler_->SetNeedsBeginMainFrame(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); SendNextBeginFrame(); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); + EXPECT_ACTION("AddObserver(this)", client_, 0, 3); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); @@ -1798,7 +1796,7 @@ TEST_F(SchedulerTest, scheduler_->NotifyReadyToActivate(); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); + EXPECT_ACTION("AddObserver(this)", client_, 0, 5); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); EXPECT_ACTION("ScheduledActionCommit", client_, 3, 5); @@ -1922,7 +1920,7 @@ TEST_F( scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); EXPECT_FALSE(scheduler_->CommitPending()); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 6); + EXPECT_ACTION("AddObserver(this)", client_, 0, 6); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 6); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 6); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 6); @@ -1988,7 +1986,7 @@ TEST_F(SchedulerTest, scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_FALSE(scheduler_->CommitPending()); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); + EXPECT_ACTION("AddObserver(this)", client_, 0, 5); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 5); @@ -2065,7 +2063,7 @@ TEST_F( scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_FALSE(scheduler_->CommitPending()); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 5); + EXPECT_ACTION("AddObserver(this)", client_, 0, 5); EXPECT_ACTION("WillBeginImplFrame", client_, 1, 5); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 5); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 3, 5); @@ -2106,7 +2104,7 @@ TEST_F(SchedulerTest, BeginRetroFrame) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Create a BeginFrame with a long deadline to avoid race conditions. @@ -2118,7 +2116,7 @@ TEST_F(SchedulerTest, BeginRetroFrame) { EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // Queue BeginFrames while we are still handling the previous BeginFrame. @@ -2131,34 +2129,34 @@ TEST_F(SchedulerTest, BeginRetroFrame) { task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // NotifyReadyToCommit should trigger the commit. scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // NotifyReadyToActivate should trigger the activation. scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // BeginImplFrame should prepare the draw. task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // BeginImplFrame deadline should draw. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) @@ -2169,7 +2167,7 @@ TEST_F(SchedulerTest, BeginRetroFrame) { client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); client_->Reset(); } @@ -2179,8 +2177,8 @@ TEST_F(SchedulerTest, RetroFrameDoesNotExpireTooEarly) { SetUpScheduler(true); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_TRUE(client_->needs_begin_frames()); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2238,8 +2236,8 @@ TEST_F(SchedulerTest, RetroFrameExpiresOnTime) { SetUpScheduler(true); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_TRUE(client_->needs_begin_frames()); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2290,8 +2288,8 @@ TEST_F(SchedulerTest, MissedFrameDoesNotExpireTooEarly) { SetUpScheduler(true); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_TRUE(client_->needs_begin_frames()); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); BeginFrameArgs missed_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); @@ -2315,8 +2313,8 @@ TEST_F(SchedulerTest, MissedFrameExpiresOnTime) { SetUpScheduler(true); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_TRUE(client_->needs_begin_frames()); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_TRUE(scheduler_->begin_frames_expected()); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); BeginFrameArgs missed_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now_src()); @@ -2560,7 +2558,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2570,7 +2568,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { client_->Reset(); scheduler_->DidLoseOutputSurface(); - // SetNeedsBeginFrames(false) is not called until the end of the frame. + // RemoveObserver(this) is not called until the end of the frame. EXPECT_NO_ACTION(client_); client_->Reset(); @@ -2582,7 +2580,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginFrameStarted) { client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } @@ -2593,7 +2591,7 @@ TEST_F(SchedulerTest, // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2612,7 +2610,7 @@ TEST_F(SchedulerTest, task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); // OnBeginImplFrameDeadline didn't schedule output surface creation because // main frame is not yet completed. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); @@ -2637,7 +2635,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) { // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2655,11 +2653,11 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterReadyToCommit) { // Sync tree should be forced to activate. EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - // SetNeedsBeginFrames(false) is not called until the end of the frame. + // RemoveObserver(this) is not called until the end of the frame. client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } @@ -2669,7 +2667,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) { scheduler_->SetNeedsPrepareTiles(); scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2678,14 +2676,14 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterSetNeedsPrepareTiles) { client_->Reset(); scheduler_->DidLoseOutputSurface(); - // SetNeedsBeginFrames(false) is not called until the end of the frame. + // RemoveObserver(this) is not called until the end of the frame. EXPECT_NO_ACTION(client_); client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 2, 4); + EXPECT_ACTION("RemoveObserver(this)", client_, 2, 4); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 3, 4); } @@ -2695,7 +2693,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); // Create a BeginFrame with a long deadline to avoid race conditions. // This is the first BeginFrame, which will be handled immediately. @@ -2707,7 +2705,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // Queue BeginFrames while we are still handling the previous BeginFrame. args.frame_time += base::TimeDelta::FromSeconds(1); @@ -2720,26 +2718,26 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceAfterBeginRetroFramePosted) { task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToCommit should trigger the commit. client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToActivate should trigger the activation. client_->Reset(); scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty()); scheduler_->DidLoseOutputSurface(); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_TRUE(scheduler_->IsBeginRetroFrameArgsEmpty()); @@ -2755,7 +2753,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); // Create a BeginFrame with a long deadline to avoid race conditions. // This is the first BeginFrame, which will be handled immediately. @@ -2767,7 +2765,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // Queue BeginFrames while we are still handling the previous BeginFrame. args.frame_time += base::TimeDelta::FromSeconds(1); @@ -2780,27 +2778,27 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToCommit should trigger the commit. client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToActivate should trigger the activation. client_->Reset(); scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // BeginImplFrame should prepare the draw. client_->Reset(); task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); EXPECT_FALSE(scheduler_->IsBeginRetroFrameArgsEmpty()); @@ -2812,10 +2810,10 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceDuringBeginRetroFrameRunning) { client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); // No more BeginRetroFrame because BeginRetroFrame queue is cleared. client_->Reset(); @@ -2827,41 +2825,41 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWithSyntheticBeginFrameSource) { SetUpScheduler(true); // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. - EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToCommit should trigger the commit. client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToActivate should trigger the activation. client_->Reset(); scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); scheduler_->DidLoseOutputSurface(); - // SetNeedsBeginFrames(false) is not called until the end of the frame. + // RemoveObserver(this) is not called until the end of the frame. EXPECT_NO_ACTION(client_); - EXPECT_TRUE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); - EXPECT_FALSE(scheduler_->frame_source().NeedsBeginFrames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); } TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) { @@ -2870,7 +2868,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) { // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2895,7 +2893,7 @@ TEST_F(SchedulerTest, DidLoseOutputSurfaceWhenIdle) { client_->Reset(); scheduler_->DidLoseOutputSurface(); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } @@ -2905,7 +2903,7 @@ TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) { // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2925,7 +2923,7 @@ TEST_F(SchedulerTest, ScheduledActionActivateAfterBecomingInvisible) { // Sync tree should be forced to activate. EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); } @@ -2935,7 +2933,7 @@ TEST_F(SchedulerTest, ScheduledActionActivateAfterBeginFrameSourcePaused) { // SetNeedsBeginMainFrame should begin the frame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); @@ -2964,13 +2962,13 @@ TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottled) { // SetNeedsRedraw should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); @@ -3001,29 +2999,32 @@ TEST_F(SchedulerTest, SwitchFrameSourceToUnthrottledBeforeDeadline) { // SetNeedsRedraw should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); - EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); + EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); // Switch to an unthrottled frame source before the frame deadline is hit. scheduler_->SetThrottleFrameProduction(false); client_->Reset(); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); + client_->Reset(); + + task_runner().RunPendingTasks(); // Run posted deadline. + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); client_->Reset(); - task_runner().RunPendingTasks(); // Run posted deadline and BeginFrame. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2); // Unthrottled frame source will immediately begin a new frame. - EXPECT_ACTION("WillBeginImplFrame", client_, 1, 2); + task_runner().RunPendingTasks(); // Run BeginFrame. + EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); scheduler_->SetNeedsRedraw(); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); + EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); } @@ -3062,7 +3063,7 @@ TEST_F(SchedulerTest, SwitchFrameSourceToThrottled) { EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - EXPECT_TRUE(client_->needs_begin_frames()); + EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); @@ -3075,7 +3076,7 @@ TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) { // SetNeedsBeginMainFrame should begin the frame on the next BeginImplFrame. scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Trigger a frame draw. @@ -3099,7 +3100,7 @@ TEST_F(SchedulerTest, SendBeginMainFrameNotExpectedSoon) { client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); client_->Reset(); } @@ -3110,7 +3111,7 @@ TEST_F(SchedulerTest, SynchronousCompositorAnimation) { SetUpScheduler(true); scheduler_->SetNeedsOneBeginImplFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Testing the case where animation ticks a fling scroll. @@ -3154,7 +3155,7 @@ TEST_F(SchedulerTest, SynchronousCompositorAnimation) { // Idle on next vsync, as the animation has completed. AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); @@ -3168,7 +3169,7 @@ TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) { scheduler_->SetNeedsRedraw(); bool resourceless_software_draw = false; scheduler_->OnDrawForOutputSurface(resourceless_software_draw); - EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 2); + EXPECT_ACTION("AddObserver(this)", client_, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); @@ -3176,7 +3177,7 @@ TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) { // Idle on next vsync. AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); @@ -3186,11 +3187,11 @@ TEST_F(SchedulerTest, SetNeedsOneBeginImplFrame) { scheduler_settings_.use_external_begin_frame_source = true; SetUpScheduler(true); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); // Request a frame, should kick the source. scheduler_->SetNeedsOneBeginImplFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // The incoming WillBeginImplFrame will request another one. @@ -3216,7 +3217,7 @@ TEST_F(SchedulerTest, SetNeedsOneBeginImplFrame) { EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); // Scheduler shuts down the source now that no begin frame is requested. - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2); + EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); } @@ -3226,7 +3227,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommit) { SetUpScheduler(true); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Next vsync. @@ -3271,7 +3272,7 @@ TEST_F(SchedulerTest, SynchronousCompositorCommit) { // Idle on next vsync. AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); @@ -3283,7 +3284,7 @@ TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) { SetUpScheduler(true); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Next vsync. @@ -3343,7 +3344,7 @@ TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) { SetUpScheduler(std::move(client), true); scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Next vsync. @@ -3375,9 +3376,9 @@ TEST_F(SchedulerTest, SynchronousCompositorPrepareTilesOnDraw) { EXPECT_SCOPED(AdvanceFrame()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); - EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 1, 3); + EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); - EXPECT_FALSE(client_->needs_begin_frames()); + EXPECT_FALSE(scheduler_->begin_frames_expected()); client_->Reset(); } @@ -3388,7 +3389,7 @@ TEST_F(SchedulerTest, SynchronousCompositorSendBeginMainFrameWhileIdle) { SetUpScheduler(true); scheduler_->SetNeedsRedraw(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + EXPECT_SINGLE_ACTION("AddObserver(this)", client_); client_->Reset(); // Next vsync. diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc index 58a1b72..28f7808 100644 --- a/cc/surfaces/display_scheduler.cc +++ b/cc/surfaces/display_scheduler.cc @@ -27,10 +27,10 @@ DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client, all_active_child_surfaces_ready_to_draw_(false), pending_swaps_(0), max_pending_swaps_(max_pending_swaps), + observing_begin_frame_source_(false), root_surface_damaged_(false), expect_damage_from_root_surface_(false), weak_ptr_factory_(this) { - begin_frame_source_->AddObserver(this); begin_frame_deadline_closure_ = base::Bind( &DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr()); @@ -40,7 +40,8 @@ DisplayScheduler::DisplayScheduler(DisplaySchedulerClient* client, } DisplayScheduler::~DisplayScheduler() { - begin_frame_source_->RemoveObserver(this); + if (observing_begin_frame_source_) + begin_frame_source_->RemoveObserver(this); } // If we try to draw when the root surface resources are locked, the @@ -96,14 +97,17 @@ void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) { child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); } - begin_frame_source_->SetNeedsBeginFrames(!output_surface_lost_); + if (!output_surface_lost_ && !observing_begin_frame_source_) { + observing_begin_frame_source_ = true; + begin_frame_source_->AddObserver(this); + } + ScheduleBeginFrameDeadline(); } void DisplayScheduler::OutputSurfaceLost() { TRACE_EVENT0("cc", "DisplayScheduler::OutputSurfaceLost"); output_surface_lost_ = true; - begin_frame_source_->SetNeedsBeginFrames(false); ScheduleBeginFrameDeadline(); } @@ -278,7 +282,10 @@ void DisplayScheduler::AttemptDrawAndSwap() { all_active_child_surfaces_ready_to_draw_ = true; expect_damage_from_root_surface_ = false; - begin_frame_source_->SetNeedsBeginFrames(false); + if (observing_begin_frame_source_) { + observing_begin_frame_source_ = false; + begin_frame_source_->RemoveObserver(this); + } } } diff --git a/cc/surfaces/display_scheduler.h b/cc/surfaces/display_scheduler.h index 69e39fd..90e99f4 100644 --- a/cc/surfaces/display_scheduler.h +++ b/cc/surfaces/display_scheduler.h @@ -83,6 +83,8 @@ class CC_SURFACES_EXPORT DisplayScheduler : public BeginFrameObserverBase { int pending_swaps_; int max_pending_swaps_; + bool observing_begin_frame_source_; + SurfaceId root_surface_id_; bool root_surface_damaged_; bool expect_damage_from_root_surface_; diff --git a/cc/surfaces/display_scheduler_unittest.cc b/cc/surfaces/display_scheduler_unittest.cc index 0f2725d..18e6303 100644 --- a/cc/surfaces/display_scheduler_unittest.cc +++ b/cc/surfaces/display_scheduler_unittest.cc @@ -241,8 +241,12 @@ TEST_F(DisplaySchedulerTest, SurfaceDamaged) { } TEST_F(DisplaySchedulerTest, OutputSurfaceLost) { + SurfaceId root_surface_id(0); SurfaceId sid1(1); + // Set the root surface + scheduler_->SetNewRootSurface(root_surface_id); + // DrawAndSwap normally. BeginFrameForTest(); EXPECT_LT(now_src().NowTicks(), @@ -268,8 +272,12 @@ TEST_F(DisplaySchedulerTest, OutputSurfaceLost) { } TEST_F(DisplaySchedulerTest, ResizeCausesSwap) { + SurfaceId root_surface_id(0); SurfaceId sid1(1); + // Set the root surface + scheduler_->SetNewRootSurface(root_surface_id); + // DrawAndSwap normally. BeginFrameForTest(); EXPECT_LT(now_src().NowTicks(), @@ -287,9 +295,13 @@ TEST_F(DisplaySchedulerTest, ResizeCausesSwap) { } TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) { + SurfaceId root_surface_id(0); SurfaceId sid1(1); base::TimeTicks late_deadline; + // Set the root surface + scheduler_->SetNewRootSurface(root_surface_id); + // DrawAndSwap normally. BeginFrameForTest(); EXPECT_LT(now_src().NowTicks(), @@ -319,6 +331,7 @@ TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) { scheduler_->SurfaceDamaged(sid1); EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); scheduler_->SetRootSurfaceResourcesLocked(false); + scheduler_->SurfaceDamaged(root_surface_id); EXPECT_EQ(base::TimeTicks(), scheduler_->DesiredBeginFrameDeadlineTimeForTest()); @@ -328,9 +341,13 @@ TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) { } TEST_F(DisplaySchedulerTest, DidSwapBuffers) { + SurfaceId root_surface_id(0); SurfaceId sid1(1); SurfaceId sid2(2); + // Set the root surface + scheduler_->SetNewRootSurface(root_surface_id); + // Get scheduler to detect surface 1 and 2 as active. BeginFrameForTest(); scheduler_->SurfaceDamaged(sid1); @@ -369,7 +386,7 @@ TEST_F(DisplaySchedulerTest, DidSwapBuffers) { // Deadline triggers normally once not swap throttled. // Damage from previous BeginFrame should cary over, so don't damage again. base::TimeTicks expected_deadline = - fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline - + scheduler_->LastUsedBeginFrameArgs().deadline - BeginFrameArgs::DefaultEstimatedParentDrawTime(); scheduler_->DidSwapBuffersComplete(); BeginFrameForTest(); @@ -394,6 +411,10 @@ TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) { int count = 1; EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + // Set the root surface + scheduler_->SetNewRootSurface(root_surface_id); + EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); + BeginFrameForTest(); EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); diff --git a/cc/test/begin_frame_source_test.h b/cc/test/begin_frame_source_test.h index 351e090..cde725b 100644 --- a/cc/test/begin_frame_source_test.h +++ b/cc/test/begin_frame_source_test.h @@ -26,6 +26,13 @@ .InSequence((obs).sequence) \ .WillOnce(::testing::SaveArg<0>(&((obs).last_begin_frame_args))) +#define EXPECT_BEGIN_FRAME_USED_MISSED(obs, frame_time, deadline, interval) \ + EXPECT_CALL((obs), OnBeginFrame(CreateBeginFrameArgsForTesting( \ + BEGINFRAME_FROM_HERE, frame_time, deadline, interval, \ + BeginFrameArgs::MISSED))) \ + .InSequence((obs).sequence) \ + .WillOnce(::testing::SaveArg<0>(&((obs).last_begin_frame_args))) + #define EXPECT_BEGIN_FRAME_SOURCE_PAUSED(obs, paused) \ EXPECT_CALL((obs), OnBeginFrameSourcePausedChanged(paused)) \ .Times(1) \ @@ -57,7 +64,7 @@ namespace cc { class MockBeginFrameObserver : public BeginFrameObserver { public: MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&)); - MOCK_CONST_METHOD0(LastUsedBeginFrameArgs, const BeginFrameArgs()); + MOCK_CONST_METHOD0(LastUsedBeginFrameArgs, const BeginFrameArgs&()); MOCK_METHOD1(OnBeginFrameSourcePausedChanged, void(bool)); virtual void AsValueInto(base::trace_event::TracedValue* dict) const; diff --git a/cc/test/fake_external_begin_frame_source.cc b/cc/test/fake_external_begin_frame_source.cc index 3c35536..1875bdb 100644 --- a/cc/test/fake_external_begin_frame_source.cc +++ b/cc/test/fake_external_begin_frame_source.cc @@ -28,27 +28,28 @@ void FakeExternalBeginFrameSource::SetClientReady() { is_ready_ = true; } -void FakeExternalBeginFrameSource::OnNeedsBeginFramesChange( +void FakeExternalBeginFrameSource::OnNeedsBeginFramesChanged( bool needs_begin_frames) { DCHECK(CalledOnValidThread()); if (needs_begin_frames) { PostTestOnBeginFrame(); + } else { + begin_frame_task_.Cancel(); } } void FakeExternalBeginFrameSource::TestOnBeginFrame() { DCHECK(CalledOnValidThread()); CallOnBeginFrame(CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE)); - - if (NeedsBeginFrames()) { - PostTestOnBeginFrame(); - } + PostTestOnBeginFrame(); } void FakeExternalBeginFrameSource::PostTestOnBeginFrame() { + begin_frame_task_.Reset( + base::Bind(&FakeExternalBeginFrameSource::TestOnBeginFrame, + weak_ptr_factory_.GetWeakPtr())); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&FakeExternalBeginFrameSource::TestOnBeginFrame, - weak_ptr_factory_.GetWeakPtr()), + FROM_HERE, begin_frame_task_.callback(), base::TimeDelta::FromMilliseconds(milliseconds_per_frame_)); } diff --git a/cc/test/fake_external_begin_frame_source.h b/cc/test/fake_external_begin_frame_source.h index 31e1f45..99dbf56 100644 --- a/cc/test/fake_external_begin_frame_source.h +++ b/cc/test/fake_external_begin_frame_source.h @@ -23,7 +23,7 @@ class FakeExternalBeginFrameSource void SetClientReady() override; // BeginFrameSourceBase overrides. - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override; void TestOnBeginFrame(); void PostTestOnBeginFrame(); @@ -31,6 +31,7 @@ class FakeExternalBeginFrameSource private: double milliseconds_per_frame_; bool is_ready_; + base::CancelableClosure begin_frame_task_; base::WeakPtrFactory<FakeExternalBeginFrameSource> weak_ptr_factory_; }; diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc index 4d7f06d..b6b1b2b 100644 --- a/cc/test/scheduler_test_common.cc +++ b/cc/test/scheduler_test_common.cc @@ -37,9 +37,9 @@ std::string TestDelayBasedTimeSource::TypeString() const { TestDelayBasedTimeSource::~TestDelayBasedTimeSource() { } -void FakeBeginFrameSource::DidFinishFrame(size_t remaining_frames) { - remaining_frames_ = remaining_frames; -} +FakeBeginFrameSource::FakeBeginFrameSource() {} + +FakeBeginFrameSource::~FakeBeginFrameSource() {} void FakeBeginFrameSource::AsValueInto( base::trace_event::TracedValue* dict) const { diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h index cf73a25..3993c9f 100644 --- a/cc/test/scheduler_test_common.h +++ b/cc/test/scheduler_test_common.h @@ -91,31 +91,28 @@ class TestDelayBasedTimeSource : public DelayBasedTimeSource { class FakeBeginFrameSource : public BeginFrameSourceBase { public: - FakeBeginFrameSource() : remaining_frames_(false) {} - ~FakeBeginFrameSource() override {} + FakeBeginFrameSource(); + ~FakeBeginFrameSource() override; - BeginFrameObserver* GetObserver() { return observer_; } + // TODO(sunnyps): Use using BeginFrameSourceBase::CallOnBeginFrame instead. + void TestOnBeginFrame(const BeginFrameArgs& args) { + return CallOnBeginFrame(args); + } BeginFrameArgs TestLastUsedBeginFrameArgs() { - if (observer_) { - return observer_->LastUsedBeginFrameArgs(); - } + if (!observers_.empty()) + return (*observers_.begin())->LastUsedBeginFrameArgs(); return BeginFrameArgs(); } - void TestOnBeginFrame(const BeginFrameArgs& args) { - return CallOnBeginFrame(args); - } + bool has_observers() const { return !observers_.empty(); } // BeginFrameSource - void DidFinishFrame(size_t remaining_frames) override; void AsValueInto(base::trace_event::TracedValue* dict) const override; using BeginFrameSourceBase::SetBeginFrameSourcePaused; private: - bool remaining_frames_; - DISALLOW_COPY_AND_ASSIGN(FakeBeginFrameSource); }; @@ -241,6 +238,8 @@ class TestScheduler : public Scheduler { return state_machine_.main_thread_missed_last_deadline(); } + bool begin_frames_expected() const { return observing_frame_source_; } + ~TestScheduler() override; base::TimeDelta BeginImplFrameInterval() { diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index ff46051..a8cbb59 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -168,8 +168,7 @@ class ExternalBeginFrameSource : public cc::BeginFrameSourceBase, } // cc::BeginFrameSourceBase implementation: - void OnNeedsBeginFramesChange( - bool needs_begin_frames) override { + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override { compositor_->OnNeedsBeginFramesChange(needs_begin_frames); } diff --git a/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc b/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc index c5337d0..1ff765a 100644 --- a/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc +++ b/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc @@ -48,13 +48,13 @@ void SynchronousCompositorExternalBeginFrameSource::SetClient( client_ = client; if (client_) - client_->OnNeedsBeginFramesChange(needs_begin_frames_); + client_->OnNeedsBeginFramesChange(needs_begin_frames()); // State without client is paused, and default client state is not paused. SetBeginFrameSourcePaused(!client_); } -void SynchronousCompositorExternalBeginFrameSource::OnNeedsBeginFramesChange( +void SynchronousCompositorExternalBeginFrameSource::OnNeedsBeginFramesChanged( bool needs_begin_frames) { DCHECK(CalledOnValidThread()); if (client_) diff --git a/content/renderer/android/synchronous_compositor_external_begin_frame_source.h b/content/renderer/android/synchronous_compositor_external_begin_frame_source.h index 83fed03..1b7f913 100644 --- a/content/renderer/android/synchronous_compositor_external_begin_frame_source.h +++ b/content/renderer/android/synchronous_compositor_external_begin_frame_source.h @@ -37,7 +37,7 @@ class SynchronousCompositorExternalBeginFrameSource using cc::BeginFrameSourceBase::SetBeginFrameSourcePaused; // cc::BeginFrameSourceBase implementation. - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override; void SetClientReady() override; private: diff --git a/content/renderer/gpu/compositor_external_begin_frame_source.cc b/content/renderer/gpu/compositor_external_begin_frame_source.cc index 7987031..ecc36f8 100644 --- a/content/renderer/gpu/compositor_external_begin_frame_source.cc +++ b/content/renderer/gpu/compositor_external_begin_frame_source.cc @@ -32,12 +32,28 @@ CompositorExternalBeginFrameSource::~CompositorExternalBeginFrameSource() { } } -void CompositorExternalBeginFrameSource::OnNeedsBeginFramesChange( +void CompositorExternalBeginFrameSource::OnNeedsBeginFramesChanged( bool needs_begin_frames) { DCHECK(CalledOnValidThread()); + if (!needs_begin_frames) + missed_begin_frame_args_ = cc::BeginFrameArgs(); Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, needs_begin_frames)); } +void CompositorExternalBeginFrameSource::AddObserver( + cc::BeginFrameObserver* obs) { + DCHECK(CalledOnValidThread()); + BeginFrameSourceBase::AddObserver(obs); + // Send a MISSED begin frame if necessary. + if (missed_begin_frame_args_.IsValid()) { + cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); + if (!last_args.IsValid() || + (missed_begin_frame_args_.frame_time > last_args.frame_time)) { + obs->OnBeginFrame(missed_begin_frame_args_); + } + } +} + void CompositorExternalBeginFrameSource::SetClientReady() { DCHECK(CalledOnValidThread()); DCHECK(!begin_frame_source_proxy_.get()); @@ -63,6 +79,8 @@ void CompositorExternalBeginFrameSource::OnMessageReceived( void CompositorExternalBeginFrameSource::OnBeginFrame( const cc::BeginFrameArgs& args) { DCHECK(CalledOnValidThread()); + missed_begin_frame_args_ = args; + missed_begin_frame_args_.type = cc::BeginFrameArgs::MISSED; CallOnBeginFrame(args); } diff --git a/content/renderer/gpu/compositor_external_begin_frame_source.h b/content/renderer/gpu/compositor_external_begin_frame_source.h index d555832..ac2ebe1 100644 --- a/content/renderer/gpu/compositor_external_begin_frame_source.h +++ b/content/renderer/gpu/compositor_external_begin_frame_source.h @@ -31,7 +31,8 @@ class CompositorExternalBeginFrameSource ~CompositorExternalBeginFrameSource() override; // cc::BeginFrameSourceBase implementation. - void OnNeedsBeginFramesChange(bool needs_begin_frames) override; + void AddObserver(cc::BeginFrameObserver* obs) override; + void OnNeedsBeginFramesChanged(bool needs_begin_frames) override; void SetClientReady() override; private: @@ -69,6 +70,7 @@ class CompositorExternalBeginFrameSource scoped_refptr<IPC::SyncMessageFilter> message_sender_; int routing_id_; CompositorForwardingMessageFilter::Handler begin_frame_source_filter_handler_; + cc::BeginFrameArgs missed_begin_frame_args_; DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSource); }; |