summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc')
-rw-r--r--cc/scheduler/begin_frame_source.cc300
-rw-r--r--cc/scheduler/begin_frame_source.h64
-rw-r--r--cc/scheduler/begin_frame_source_unittest.cc375
-rw-r--r--cc/scheduler/delay_based_time_source.cc66
-rw-r--r--cc/scheduler/delay_based_time_source.h5
-rw-r--r--cc/scheduler/delay_based_time_source_unittest.cc61
-rw-r--r--cc/scheduler/scheduler.cc28
-rw-r--r--cc/scheduler/scheduler.h1
-rw-r--r--cc/scheduler/scheduler_unittest.cc281
-rw-r--r--cc/surfaces/display_scheduler.cc17
-rw-r--r--cc/surfaces/display_scheduler.h2
-rw-r--r--cc/surfaces/display_scheduler_unittest.cc23
-rw-r--r--cc/test/begin_frame_source_test.h9
-rw-r--r--cc/test/fake_external_begin_frame_source.cc15
-rw-r--r--cc/test/fake_external_begin_frame_source.h3
-rw-r--r--cc/test/scheduler_test_common.cc6
-rw-r--r--cc/test/scheduler_test_common.h23
17 files changed, 702 insertions, 577 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() {