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

Unified Diff: cc/scheduler/scheduler.cc

Issue 267783004: Refactoring the way begin frame sources inside scheduler work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Major rewrite based on Brian's comments. Created 6 years, 3 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/scheduler.cc
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 1c66f01ab320d34187eca2bf73b1cad3687e22da..7cf3c47469e7423bacb670e0259fa831bf8bdfd1 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -17,57 +17,6 @@
namespace cc {
-Scheduler::SyntheticBeginFrameSource::SyntheticBeginFrameSource(
- Scheduler* scheduler,
- scoped_refptr<DelayBasedTimeSource> time_source)
- : scheduler_(scheduler), time_source_(time_source) {
- time_source_->SetClient(this);
-}
-
-Scheduler::SyntheticBeginFrameSource::~SyntheticBeginFrameSource() {
-}
-
-void Scheduler::SyntheticBeginFrameSource::CommitVSyncParameters(
- base::TimeTicks timebase,
- base::TimeDelta interval) {
- time_source_->SetTimebaseAndInterval(timebase, interval);
-}
-
-void Scheduler::SyntheticBeginFrameSource::SetNeedsBeginFrame(
- bool needs_begin_frame,
- std::deque<BeginFrameArgs>* begin_retro_frame_args) {
- DCHECK(begin_retro_frame_args);
- base::TimeTicks missed_tick_time =
- time_source_->SetActive(needs_begin_frame);
- if (!missed_tick_time.is_null()) {
- begin_retro_frame_args->push_back(
- CreateSyntheticBeginFrameArgs(missed_tick_time));
- }
-}
-
-bool Scheduler::SyntheticBeginFrameSource::IsActive() const {
- return time_source_->Active();
-}
-
-void Scheduler::SyntheticBeginFrameSource::OnTimerTick() {
- BeginFrameArgs begin_frame_args(
- CreateSyntheticBeginFrameArgs(time_source_->LastTickTime()));
- scheduler_->BeginFrame(begin_frame_args);
-}
-
-void Scheduler::SyntheticBeginFrameSource::AsValueInto(
- base::debug::TracedValue* state) const {
- time_source_->AsValueInto(state);
-}
-
-BeginFrameArgs
-Scheduler::SyntheticBeginFrameSource::CreateSyntheticBeginFrameArgs(
- base::TimeTicks frame_time) {
- base::TimeTicks deadline = time_source_->NextTickTime();
- return BeginFrameArgs::Create(
- frame_time, deadline, scheduler_->VSyncInterval());
-}
-
Scheduler::Scheduler(
SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
@@ -77,9 +26,6 @@ Scheduler::Scheduler(
client_(client),
layer_tree_host_id_(layer_tree_host_id),
task_runner_(task_runner),
- vsync_interval_(BeginFrameArgs::DefaultInterval()),
- last_set_needs_begin_frame_(false),
- begin_unthrottled_frame_posted_(false),
begin_retro_frame_posted_(false),
state_machine_(scheduler_settings),
inside_process_scheduled_actions_(false),
@@ -97,8 +43,6 @@ Scheduler::Scheduler(
begin_retro_frame_closure_ =
base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr());
- begin_unthrottled_frame_closure_ =
- base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr());
begin_impl_frame_deadline_closure_ = base::Bind(
&Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr());
poll_for_draw_triggers_closure_ = base::Bind(
@@ -106,30 +50,46 @@ Scheduler::Scheduler(
advance_commit_state_closure_ = base::Bind(
&Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr());
- if (!settings_.begin_frame_scheduling_enabled) {
- SetupSyntheticBeginFrames();
- }
+ frame_source_ = BeginFrameSourceMultiplexer::Create();
+ frame_source_->AddObserver(this);
+
+ // Background ticking frame source
+ SetUpBackgroundFrameSource();
+ frame_source_->AddSource(background_frame_source_store_.get());
+
+ // Primary frame source
+ SetUpPrimaryFrameSource();
+ frame_source_->AddSource(primary_frame_source_);
}
-Scheduler::~Scheduler() {
- if (synthetic_begin_frame_source_) {
- synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
- &begin_retro_frame_args_);
- }
+void Scheduler::SetUpBackgroundFrameSource() {
+ background_frame_source_store_ = SyntheticBeginFrameSource::Create(
+ task_runner_.get(), base::TimeDelta::FromSeconds(1));
}
-void Scheduler::SetupSyntheticBeginFrames() {
- scoped_refptr<DelayBasedTimeSource> time_source;
- if (gfx::FrameTime::TimestampsAreHighRes()) {
- time_source = DelayBasedTimeSourceHighRes::Create(VSyncInterval(),
- task_runner_.get());
+void Scheduler::SetUpPrimaryFrameSource() {
+ if (!settings_.throttle_frame_production) {
+ TRACE_EVENT0("cc", "Scheduler::Scheduler() BackToBackBeginFrameSource");
+ primary_frame_source_store_ =
+ BackToBackBeginFrameSource::Create(task_runner_.get());
+ primary_frame_source_ = primary_frame_source_store_.get();
+ } else if (settings_.begin_frame_scheduling_enabled) {
+ TRACE_EVENT0("cc",
+ "Scheduler::Scheduler() SchedulerClient BeginFrameSource");
+ primary_frame_source_ = client_->GetBeginFrameSource();
} else {
- time_source =
- DelayBasedTimeSource::Create(VSyncInterval(), task_runner_.get());
+ TRACE_EVENT0("cc", "Scheduler::Scheduler() SyntheticBeginFrameSource");
+ scoped_ptr<SyntheticBeginFrameSource> synthetic_source =
+ SyntheticBeginFrameSource::Create(task_runner_.get(),
+ BeginFrameArgs::DefaultInterval());
+ vsync_observer_ = synthetic_source.get();
+ primary_frame_source_store_ = synthetic_source.Pass();
+ primary_frame_source_ = primary_frame_source_store_.get();
}
- DCHECK(!synthetic_begin_frame_source_);
- synthetic_begin_frame_source_.reset(
- new SyntheticBeginFrameSource(this, time_source));
+}
+
+Scheduler::~Scheduler() {
+ frame_source_->SetNeedsBeginFrames(false);
}
base::TimeTicks Scheduler::Now() const {
@@ -141,9 +101,9 @@ void Scheduler::CommitVSyncParameters(base::TimeTicks timebase,
// TODO(brianderson): We should not be receiving 0 intervals.
if (interval == base::TimeDelta())
interval = BeginFrameArgs::DefaultInterval();
- vsync_interval_ = interval;
- if (!settings_.begin_frame_scheduling_enabled)
- synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval);
+
+ if (vsync_observer_)
+ vsync_observer_->OnUpdateVSyncParameters(timebase, interval);
brianderson 2014/09/13 01:38:13 How does this additional indirection help?
}
void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
@@ -158,6 +118,11 @@ void Scheduler::SetCanStart() {
void Scheduler::SetVisible(bool visible) {
state_machine_.SetVisible(visible);
+ if (visible) {
+ frame_source_->SetActiveSource(primary_frame_source_);
+ } else {
+ frame_source_->SetActiveSource(background_frame_source_store_.get());
+ }
ProcessScheduledActions();
}
@@ -240,18 +205,14 @@ void Scheduler::DidManageTiles() {
void Scheduler::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
state_machine_.DidLoseOutputSurface();
- last_set_needs_begin_frame_ = false;
- if (!settings_.begin_frame_scheduling_enabled) {
- synthetic_begin_frame_source_->SetNeedsBeginFrame(false,
- &begin_retro_frame_args_);
- }
+ frame_source_->SetNeedsBeginFrames(false);
begin_retro_frame_args_.clear();
ProcessScheduledActions();
}
void Scheduler::DidCreateAndInitializeOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
- DCHECK(!last_set_needs_begin_frame_);
+ DCHECK(!frame_source_->NeedsBeginFrames());
DCHECK(begin_impl_frame_deadline_task_.IsCancelled());
state_machine_.DidCreateAndInitializeOutputSurface();
ProcessScheduledActions();
@@ -263,7 +224,7 @@ void Scheduler::NotifyBeginMainFrameStarted() {
}
base::TimeTicks Scheduler::AnticipatedDrawTime() const {
- if (!last_set_needs_begin_frame_ ||
+ if (!frame_source_->NeedsBeginFrames() ||
begin_impl_frame_args_.interval <= base::TimeDelta())
return base::TimeTicks();
@@ -274,6 +235,10 @@ base::TimeTicks Scheduler::AnticipatedDrawTime() const {
return timebase + (begin_impl_frame_args_.interval * intervals);
}
+const BeginFrameArgs& Scheduler::LastBeginFrameArgs() const {
+ return last_begin_frame_args_;
+}
+
base::TimeTicks Scheduler::LastBeginImplFrameTime() {
return begin_impl_frame_args_.frame_time;
}
@@ -284,75 +249,28 @@ void Scheduler::SetupNextBeginFrameIfNeeded() {
bool needs_begin_frame = state_machine_.BeginFrameNeeded();
- if (settings_.throttle_frame_production) {
- SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame);
- } else {
- SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame);
- }
- SetupPollingMechanisms(needs_begin_frame);
-}
-
-// When we are throttling frame production, we request BeginFrames
-// from the OutputSurface.
-void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled(
- bool needs_begin_frame) {
bool at_end_of_deadline =
- state_machine_.begin_impl_frame_state() ==
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
+ (state_machine_.begin_impl_frame_state() ==
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) ||
+ (state_machine_.begin_impl_frame_state() ==
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
brianderson 2014/09/13 01:38:13 I remember intentionally not including the idle st
bool should_call_set_needs_begin_frame =
// Always request the BeginFrame immediately if it wasn't needed before.
- (needs_begin_frame && !last_set_needs_begin_frame_) ||
+ needs_begin_frame ||
// Only stop requesting BeginFrames after a deadline.
- (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline);
+ (!needs_begin_frame && at_end_of_deadline);
if (should_call_set_needs_begin_frame) {
- if (settings_.begin_frame_scheduling_enabled) {
- client_->SetNeedsBeginFrame(needs_begin_frame);
- } else {
- synthetic_begin_frame_source_->SetNeedsBeginFrame(
- needs_begin_frame, &begin_retro_frame_args_);
- }
- last_set_needs_begin_frame_ = needs_begin_frame;
- }
-
- PostBeginRetroFrameIfNeeded();
-}
-
-// When we aren't throttling frame production, we initiate a BeginFrame
-// as soon as one is needed.
-void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled(
- bool needs_begin_frame) {
- last_set_needs_begin_frame_ = needs_begin_frame;
-
- if (!needs_begin_frame || begin_unthrottled_frame_posted_)
- return;
-
- if (state_machine_.begin_impl_frame_state() !=
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE &&
- state_machine_.begin_impl_frame_state() !=
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) {
- return;
+ frame_source_->SetNeedsBeginFrames(needs_begin_frame);
}
- begin_unthrottled_frame_posted_ = true;
- task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_);
-}
-
-// BeginUnthrottledFrame is used when we aren't throttling frame production.
-// This will usually be because VSync is disabled.
-void Scheduler::BeginUnthrottledFrame() {
- DCHECK(!settings_.throttle_frame_production);
- DCHECK(begin_retro_frame_args_.empty());
+ // TODO(mithro): Use pending frames properly.
+ if (at_end_of_deadline)
+ frame_source_->FinishedFrame(0);
- base::TimeTicks now = Now();
- base::TimeTicks deadline = now + vsync_interval_;
-
- BeginFrameArgs begin_frame_args =
- BeginFrameArgs::Create(now, deadline, vsync_interval_);
- BeginImplFrame(begin_frame_args);
-
- begin_unthrottled_frame_posted_ = false;
+ PostBeginRetroFrameIfNeeded();
+ SetupPollingMechanisms(needs_begin_frame);
}
// We may need to poll when we can't rely on BeginFrame to advance certain
@@ -408,7 +326,7 @@ void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) {
// making a frame. Usually this means that user input for the frame is complete.
// If the scheduler is busy, we queue the BeginFrame to be handled later as
// a BeginRetroFrame.
-void Scheduler::BeginFrame(const BeginFrameArgs& args) {
+void Scheduler::OnBeginFrame(const BeginFrameArgs& args) {
TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
DCHECK(settings_.throttle_frame_production);
@@ -421,7 +339,7 @@ void Scheduler::BeginFrame(const BeginFrameArgs& args) {
} else {
should_defer_begin_frame =
!begin_retro_frame_args_.empty() || begin_retro_frame_posted_ ||
- !last_set_needs_begin_frame_ ||
+ !frame_source_->NeedsBeginFrames() ||
(state_machine_.begin_impl_frame_state() !=
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
}
@@ -488,7 +406,7 @@ void Scheduler::PostBeginRetroFrameIfNeeded() {
"Scheduler::PostBeginRetroFrameIfNeeded",
"state",
AsValue());
- if (!last_set_needs_begin_frame_)
+ if (!frame_source_->NeedsBeginFrames())
return;
if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_)
@@ -698,24 +616,25 @@ scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue()
const {
scoped_refptr<base::debug::TracedValue> state =
new base::debug::TracedValue();
+ AsValueInto(state.get());
+ return state;
+}
+
+void Scheduler::AsValueInto(base::debug::TracedValue* state) const {
state->BeginDictionary("state_machine");
- state_machine_.AsValueInto(state.get());
+ state_machine_.AsValueInto(state);
+ state->EndDictionary();
+ state->BeginDictionary("frame_source_");
+ frame_source_->AsValueInto(state);
state->EndDictionary();
- if (synthetic_begin_frame_source_) {
- state->BeginDictionary("synthetic_begin_frame_source_");
- synthetic_begin_frame_source_->AsValueInto(state.get());
- state->EndDictionary();
- }
state->BeginDictionary("scheduler_state");
state->SetDouble("time_until_anticipated_draw_time_ms",
(AnticipatedDrawTime() - Now()).InMillisecondsF());
- state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
state->SetDouble("estimated_parent_draw_time_ms",
estimated_parent_draw_time_.InMillisecondsF());
- state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_);
- state->SetBoolean("begin_unthrottled_frame_posted_",
- begin_unthrottled_frame_posted_);
+ state->SetBoolean("last_set_needs_begin_frame_",
+ frame_source_->NeedsBeginFrames());
state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
state->SetBoolean("begin_impl_frame_deadline_task_",
@@ -725,7 +644,7 @@ scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue()
state->SetBoolean("advance_commit_state_task_",
!advance_commit_state_task_.IsCancelled());
state->BeginDictionary("begin_impl_frame_args");
- begin_impl_frame_args_.AsValueInto(state.get());
+ begin_impl_frame_args_.AsValueInto(state);
state->EndDictionary();
state->EndDictionary();
@@ -740,7 +659,6 @@ scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue()
"commit_to_activate_duration_estimate_ms",
client_->CommitToActivateDurationEstimate().InMillisecondsF());
state->EndDictionary();
- return state;
}
bool Scheduler::CanCommitAndActivateBeforeDeadline() const {

Powered by Google App Engine
This is Rietveld 408576698