Chromium Code Reviews| Index: cc/scheduler/begin_frame_source.cc |
| diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc |
| index 3421ce978d4811b225c053f93039a8c9cd6b3d5e..dabf485d6491dd356483278a0e103eea1ff845e7 100644 |
| --- a/cc/scheduler/begin_frame_source.cc |
| +++ b/cc/scheduler/begin_frame_source.cc |
| @@ -14,7 +14,6 @@ |
| #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" |
| #include "cc/scheduler/scheduler.h" |
| namespace cc { |
| @@ -27,8 +26,7 @@ static const double kDoubleTickDivisor = 2.0; |
| // BeginFrameObserverBase ----------------------------------------------- |
| BeginFrameObserverBase::BeginFrameObserverBase() |
| - : last_begin_frame_args_(), dropped_begin_frame_args_(0) { |
| -} |
| + : last_begin_frame_args_(), dropped_begin_frame_args_(0) {} |
| const BeginFrameArgs& BeginFrameObserverBase::LastUsedBeginFrameArgs() const { |
| return last_begin_frame_args_; |
| @@ -49,13 +47,13 @@ SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default; |
| // BackToBackBeginFrameSource -------------------------------------------- |
| BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
| - std::unique_ptr<DelayBasedTimeSource> time_source) |
| - : time_source_(std::move(time_source)), weak_factory_(this) { |
| - time_source_->SetClient(this); |
| - // The time_source_ ticks immediately, so we SetActive(true) for a single |
| - // tick when we need it, and keep it as SetActive(false) otherwise. |
| - time_source_->SetTimebaseAndInterval(base::TimeTicks(), base::TimeDelta()); |
| -} |
| + base::SingleThreadTaskRunner* task_runner) |
| + : BackToBackBeginFrameSource(task_runner, nullptr) {} |
| + |
| +BackToBackBeginFrameSource::BackToBackBeginFrameSource( |
| + base::SingleThreadTaskRunner* task_runner, |
| + base::TickClock* clock) |
| + : task_runner_(task_runner), clock_(clock), weak_factory_(this) {} |
| BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default; |
| @@ -63,48 +61,68 @@ void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| DCHECK(obs); |
| DCHECK(observers_.find(obs) == observers_.end()); |
| observers_.insert(obs); |
| - pending_begin_frame_observers_.insert(obs); |
| + if (pending_observers_.empty()) { |
| + DCHECK(begin_frame_callback_.IsCancelled()); |
| + begin_frame_callback_.Reset( |
| + base::Bind(&BackToBackBeginFrameSource::SendBeginFrame, |
| + weak_factory_.GetWeakPtr())); |
| + task_runner_->PostTask(FROM_HERE, begin_frame_callback_.callback()); |
| + } |
| + pending_observers_.insert(obs); |
| obs->OnBeginFrameSourcePausedChanged(false); |
| - time_source_->SetActive(true); |
| } |
| void BackToBackBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
| DCHECK(obs); |
| DCHECK(observers_.find(obs) != observers_.end()); |
| observers_.erase(obs); |
| - pending_begin_frame_observers_.erase(obs); |
| - if (observers_.empty()) |
| - time_source_->SetActive(false); |
| + pending_observers_.erase(obs); |
| + if (pending_observers_.empty()) |
| + begin_frame_callback_.Cancel(); |
| } |
| void BackToBackBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs, |
| size_t remaining_frames) { |
| if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) { |
| - pending_begin_frame_observers_.insert(obs); |
| - time_source_->SetActive(true); |
| + if (pending_observers_.empty()) { |
| + DCHECK(begin_frame_callback_.IsCancelled()); |
| + begin_frame_callback_.Reset( |
| + base::Bind(&BackToBackBeginFrameSource::SendBeginFrame, |
| + weak_factory_.GetWeakPtr())); |
| + task_runner_->PostTask(FROM_HERE, begin_frame_callback_.callback()); |
| + } |
| + pending_observers_.insert(obs); |
| } |
| } |
| -void BackToBackBeginFrameSource::OnTimerTick() { |
| - base::TimeTicks frame_time = time_source_->LastTickTime(); |
| +void BackToBackBeginFrameSource::SendBeginFrame() { |
| + DCHECK(!pending_observers_.empty()); |
| + begin_frame_callback_.Cancel(); |
| + std::unordered_set<BeginFrameObserver*> pending_observers; |
| + pending_observers.swap(pending_observers_); |
| + |
| + base::TimeTicks frame_time = |
| + clock_ ? clock_->NowTicks() : base::TimeTicks::Now(); |
|
brianderson
2016/07/13 21:14:49
Maybe use a base::DefaultTickClock instead of chec
sunnyps
2016/07/13 21:24:53
I tried that but then DelayBasedTimeSource ended u
|
| base::TimeDelta default_interval = BeginFrameArgs::DefaultInterval(); |
| BeginFrameArgs args = BeginFrameArgs::Create( |
| BEGINFRAME_FROM_HERE, frame_time, frame_time + default_interval, |
| default_interval, BeginFrameArgs::NORMAL); |
| - // This must happen after getting the LastTickTime() from the time source. |
| - time_source_->SetActive(false); |
| - |
| - std::unordered_set<BeginFrameObserver*> pending_observers; |
| - pending_observers.swap(pending_begin_frame_observers_); |
| for (BeginFrameObserver* obs : pending_observers) |
| obs->OnBeginFrame(args); |
| } |
| // DelayBasedBeginFrameSource --------------------------------------------- |
| DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( |
| - std::unique_ptr<DelayBasedTimeSource> time_source) |
| - : time_source_(std::move(time_source)) { |
| + base::SingleThreadTaskRunner* task_runner) |
| + : DelayBasedBeginFrameSource(task_runner, nullptr) {} |
| + |
| +DelayBasedBeginFrameSource::DelayBasedBeginFrameSource( |
| + base::SingleThreadTaskRunner* task_runner, |
| + base::TickClock* clock) |
| + : time_source_(new DelayBasedTimeSource(task_runner, clock)), |
| + task_runner_(task_runner), |
| + weak_factory_(this) { |
| time_source_->SetClient(this); |
| } |
| @@ -145,27 +163,31 @@ void DelayBasedBeginFrameSource::AddObserver(BeginFrameObserver* obs) { |
| observers_.insert(obs); |
| obs->OnBeginFrameSourcePausedChanged(false); |
| time_source_->SetActive(true); |
| - 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); |
| + |
| + if (missed_frame_observers_.empty()) { |
| + DCHECK(missed_frame_callback_.IsCancelled()); |
| + missed_frame_callback_.Reset( |
| + base::Bind(&DelayBasedBeginFrameSource::SendMissedBeginFrame, |
| + weak_factory_.GetWeakPtr())); |
| + task_runner_->PostTask(FROM_HERE, missed_frame_callback_.callback()); |
| } |
| + missed_frame_observers_.insert(obs); |
| } |
| void DelayBasedBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) { |
| DCHECK(obs); |
| DCHECK(observers_.find(obs) != observers_.end()); |
| - |
| + missed_frame_observers_.erase(obs); |
| + if (missed_frame_observers_.empty()) |
| + missed_frame_callback_.Cancel(); |
| observers_.erase(obs); |
| if (observers_.empty()) |
| time_source_->SetActive(false); |
| } |
| void DelayBasedBeginFrameSource::OnTimerTick() { |
| + missed_frame_callback_.Cancel(); |
| + missed_frame_observers_.clear(); |
| BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(), |
| BeginFrameArgs::NORMAL); |
| std::unordered_set<BeginFrameObserver*> observers(observers_); |
| @@ -178,4 +200,24 @@ void DelayBasedBeginFrameSource::OnTimerTick() { |
| } |
| } |
| +void DelayBasedBeginFrameSource::SendMissedBeginFrame() { |
| + DCHECK(!missed_frame_observers_.empty()); |
| + missed_frame_callback_.Cancel(); |
| + std::unordered_set<BeginFrameObserver*> missed_frame_observers; |
| + missed_frame_observers.swap(missed_frame_observers_); |
| + |
| + BeginFrameArgs args = CreateBeginFrameArgs( |
| + time_source_->NextTickTime() - time_source_->Interval(), |
| + BeginFrameArgs::MISSED); |
| + |
| + for (BeginFrameObserver* obs : missed_frame_observers) { |
| + BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs(); |
| + if (!last_args.IsValid() || |
| + (args.frame_time > |
| + last_args.frame_time + args.interval / kDoubleTickDivisor)) { |
| + obs->OnBeginFrame(args); |
| + } |
| + } |
| +} |
| + |
| } // namespace cc |