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

Unified Diff: cc/scheduler/begin_frame_source.cc

Issue 2061273002: cc: Make BackToBackBeginFrameSource a SyntheticBeginFrameSource. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: syntheticbeginframesource: onemorenit Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: cc/scheduler/begin_frame_source.cc
diff --git a/cc/scheduler/begin_frame_source.cc b/cc/scheduler/begin_frame_source.cc
index 5c20a86caf2c4b11fd1fd54d48b74ca78a893cc7..2f56c890eb6aa7db8a29ee2a60ff9c95bd61ae4b 100644
--- a/cc/scheduler/begin_frame_source.cc
+++ b/cc/scheduler/begin_frame_source.cc
@@ -9,6 +9,7 @@
#include "base/auto_reset.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
@@ -97,92 +98,37 @@ void BeginFrameSourceBase::SetBeginFrameSourcePaused(bool paused) {
// BackToBackBeginFrameSource --------------------------------------------
BackToBackBeginFrameSource::BackToBackBeginFrameSource(
base::SingleThreadTaskRunner* task_runner)
- : BeginFrameSourceBase(), task_runner_(task_runner), weak_factory_(this) {
- DCHECK(task_runner);
+ : SyntheticBeginFrameSource(
+ base::MakeUnique<DelayBasedTimeSource>(task_runner)) {
+ SetUnthrottled(true);
}
-BackToBackBeginFrameSource::~BackToBackBeginFrameSource() {
-}
-
-base::TimeTicks BackToBackBeginFrameSource::Now() {
- return base::TimeTicks::Now();
-}
-
-// BeginFrameSourceBase support
-void BackToBackBeginFrameSource::AddObserver(BeginFrameObserver* obs) {
- BeginFrameSourceBase::AddObserver(obs);
- pending_begin_frame_observers_.insert(obs);
- PostPendingBeginFramesTask();
-}
-
-void BackToBackBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) {
- BeginFrameSourceBase::RemoveObserver(obs);
- pending_begin_frame_observers_.erase(obs);
- if (pending_begin_frame_observers_.empty())
- begin_frame_task_.Cancel();
-}
-
-void BackToBackBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs,
- size_t remaining_frames) {
- BeginFrameSourceBase::DidFinishFrame(obs, remaining_frames);
- if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) {
- pending_begin_frame_observers_.insert(obs);
- PostPendingBeginFramesTask();
- }
-}
-
-void BackToBackBeginFrameSource::PostPendingBeginFramesTask() {
- DCHECK(needs_begin_frames());
- DCHECK(!pending_begin_frame_observers_.empty());
- if (begin_frame_task_.IsCancelled()) {
- begin_frame_task_.Reset(
- base::Bind(&BackToBackBeginFrameSource::SendPendingBeginFrames,
- weak_factory_.GetWeakPtr()));
- task_runner_->PostTask(FROM_HERE, begin_frame_task_.callback());
- }
-}
-
-void BackToBackBeginFrameSource::SendPendingBeginFrames() {
- 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(),
- BeginFrameArgs::DefaultInterval(), BeginFrameArgs::NORMAL);
-
- std::set<BeginFrameObserver*> pending_observers;
- pending_observers.swap(pending_begin_frame_observers_);
- for (BeginFrameObserver* obs : pending_observers)
- obs->OnBeginFrame(args);
-}
+BackToBackBeginFrameSource::~BackToBackBeginFrameSource() = default;
// SyntheticBeginFrameSource ---------------------------------------------
SyntheticBeginFrameSource::SyntheticBeginFrameSource(
- base::SingleThreadTaskRunner* task_runner,
- base::TimeDelta initial_vsync_interval)
- : time_source_(
- DelayBasedTimeSource::Create(initial_vsync_interval, task_runner)) {
- time_source_->SetClient(this);
-}
-
-SyntheticBeginFrameSource::SyntheticBeginFrameSource(
std::unique_ptr<DelayBasedTimeSource> time_source)
- : time_source_(std::move(time_source)) {
+ : time_source_(std::move(time_source)),
+ last_interval_(time_source_->Interval()) {
time_source_->SetClient(this);
}
-SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {}
+SyntheticBeginFrameSource::~SyntheticBeginFrameSource() = default;
void SyntheticBeginFrameSource::OnUpdateVSyncParameters(
base::TimeTicks timebase,
base::TimeDelta interval) {
- if (!authoritative_interval_.is_zero())
+ if (!authoritative_interval_.is_zero()) {
interval = authoritative_interval_;
+ } else if (interval.is_zero()) {
+ // TODO(brianderson): We should not be receiving 0 intervals.
enne (OOO) 2016/06/14 21:25:17 I love how this comment has proliferated.
brianderson 2016/06/14 21:59:48 I have so many fewer TODO's now! =)
+ interval = BeginFrameArgs::DefaultInterval();
+ }
last_timebase_ = timebase;
- time_source_->SetTimebaseAndInterval(timebase, interval);
+ last_interval_ = interval;
+ if (!unthrottled_)
+ time_source_->SetTimebaseAndInterval(timebase, interval);
}
void SyntheticBeginFrameSource::SetAuthoritativeVSyncInterval(
@@ -191,20 +137,44 @@ void SyntheticBeginFrameSource::SetAuthoritativeVSyncInterval(
OnUpdateVSyncParameters(last_timebase_, interval);
}
+void SyntheticBeginFrameSource::SetUnthrottled(bool unthrottled) {
+ if (unthrottled)
+ time_source_->SetTimebaseAndInterval(base::TimeTicks(), base::TimeDelta());
+ else
+ time_source_->SetTimebaseAndInterval(last_timebase_, last_interval_);
+ unthrottled_ = unthrottled;
+}
+
BeginFrameArgs SyntheticBeginFrameSource::CreateBeginFrameArgs(
base::TimeTicks frame_time,
BeginFrameArgs::BeginFrameArgsType type) {
+ if (unthrottled_) {
+ // When unthrottled, the NextTickTime is not meaningful, so just use the
+ // current interval as the deadline.
+ return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time,
+ frame_time + last_interval_, last_interval_,
+ type);
+ }
return BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time,
- time_source_->NextTickTime(),
- time_source_->Interval(), type);
+ time_source_->NextTickTime(), last_interval_,
+ type);
}
// BeginFrameSource support
void SyntheticBeginFrameSource::AddObserver(BeginFrameObserver* obs) {
BeginFrameSourceBase::AddObserver(obs);
+
+ if (unthrottled_) {
+ // When unthrottled, ensure the time source is ticking for the first frame
+ // this observer sees (since it only ticks when an observer is ready), and
+ // don't post a MISSED frame since unthrottled just goes as fast as it can.
+ time_source_->SetActive(true);
+ frame_finished_observers_.insert(obs);
+ return;
+ }
+
BeginFrameArgs args = CreateBeginFrameArgs(
- time_source_->NextTickTime() - time_source_->Interval(),
- BeginFrameArgs::MISSED);
+ time_source_->NextTickTime() - last_interval_, BeginFrameArgs::MISSED);
BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
if (!last_args.IsValid() ||
(args.frame_time >
@@ -213,23 +183,55 @@ void SyntheticBeginFrameSource::AddObserver(BeginFrameObserver* obs) {
}
}
+void SyntheticBeginFrameSource::RemoveObserver(BeginFrameObserver* obs) {
+ BeginFrameSourceBase::RemoveObserver(obs);
+ frame_finished_observers_.erase(obs);
+}
+
void SyntheticBeginFrameSource::OnNeedsBeginFramesChanged(
bool needs_begin_frames) {
time_source_->SetActive(needs_begin_frames);
}
+void SyntheticBeginFrameSource::DidFinishFrame(BeginFrameObserver* obs,
+ size_t remaining_frames) {
+ if (remaining_frames == 0 && observers_.find(obs) != observers_.end()) {
+ frame_finished_observers_.insert(obs);
+ time_source_->SetActive(true);
+ }
+}
+
// DelayBasedTimeSourceClient support
void SyntheticBeginFrameSource::OnTimerTick() {
- BeginFrameArgs args = CreateBeginFrameArgs(time_source_->LastTickTime(),
- BeginFrameArgs::NORMAL);
+ // This must be captured before calling SetActive(false) on the time_source_.
+ base::TimeTicks now = time_source_->LastTickTime();
+
+ if (unthrottled_) {
+ // When unthrottled, we only want to tick when an observer finishes a frame,
+ // so stop and wait for that.
+ time_source_->SetActive(false);
+ }
+
+ BeginFrameArgs args = CreateBeginFrameArgs(now, 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);
+ for (auto& obs : observers) {
+ bool on_begin_frame = false;
+ if (unthrottled_) {
+ // When unthrottled, we only want to generate a new begin frame for each
+ // observer when its previous one finished.
+ on_begin_frame = frame_finished_observers_.count(obs) > 0;
+ } else {
+ // When ticking at a throttled rate we want to generate a new begin frame
+ // regularly, but not too often.
+ BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
+ on_begin_frame =
+ !last_args.IsValid() ||
+ (args.frame_time >
+ last_args.frame_time + args.interval / kDoubleTickDivisor);
}
+ frame_finished_observers_.erase(obs);
+ if (on_begin_frame)
+ obs->OnBeginFrame(args);
}
}

Powered by Google App Engine
This is Rietveld 408576698