summaryrefslogtreecommitdiffstats
path: root/cc/scheduler/begin_frame_source.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cc/scheduler/begin_frame_source.cc')
-rw-r--r--cc/scheduler/begin_frame_source.cc300
1 files changed, 145 insertions, 155 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