Index: cc/scheduler/scheduler.cc |
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc |
index 15b13d0391c87f6985340305c859ef7b99ef9be8..b24430f2aa6e12e7f7784f7423f2904f7523125d 100644 |
--- a/cc/scheduler/scheduler.cc |
+++ b/cc/scheduler/scheduler.cc |
@@ -20,16 +20,7 @@ namespace cc { |
BeginFrameSource* SchedulerFrameSourcesConstructor::ConstructPrimaryFrameSource( |
Scheduler* scheduler) { |
- if (!scheduler->settings_.throttle_frame_production) { |
- TRACE_EVENT1("cc", |
- "Scheduler::Scheduler()", |
- "PrimaryFrameSource", |
- "BackToBackBeginFrameSource"); |
- DCHECK(!scheduler->primary_frame_source_internal_); |
- scheduler->primary_frame_source_internal_ = |
- BackToBackBeginFrameSource::Create(scheduler->task_runner_.get()); |
- return scheduler->primary_frame_source_internal_.get(); |
- } else if (scheduler->settings_.use_external_begin_frame_source) { |
+ if (scheduler->settings_.use_external_begin_frame_source) { |
TRACE_EVENT1("cc", |
"Scheduler::Scheduler()", |
"PrimaryFrameSource", |
@@ -71,6 +62,17 @@ SchedulerFrameSourcesConstructor::ConstructBackgroundFrameSource( |
return scheduler->background_frame_source_internal_.get(); |
} |
+BeginFrameSource* |
+SchedulerFrameSourcesConstructor::ConstructUnthrottledFrameSource( |
+ Scheduler* scheduler) { |
+ TRACE_EVENT1("cc", "Scheduler::Scheduler()", "UnthrottledFrameSource", |
+ "BackToBackBeginFrameSource"); |
+ DCHECK(!scheduler->unthrottled_frame_source_internal_); |
+ scheduler->unthrottled_frame_source_internal_ = |
+ BackToBackBeginFrameSource::Create(scheduler->task_runner_.get()); |
+ return scheduler->unthrottled_frame_source_internal_.get(); |
+} |
+ |
Scheduler::Scheduler( |
SchedulerClient* client, |
const SchedulerSettings& scheduler_settings, |
@@ -85,12 +87,12 @@ Scheduler::Scheduler( |
primary_frame_source_internal_(external_begin_frame_source.Pass()), |
background_frame_source_internal_(), |
vsync_observer_(NULL), |
+ throttle_frame_production_(scheduler_settings.throttle_frame_production), |
settings_(scheduler_settings), |
client_(client), |
layer_tree_host_id_(layer_tree_host_id), |
task_runner_(task_runner), |
power_monitor_(power_monitor), |
- begin_retro_frame_posted_(false), |
state_machine_(scheduler_settings), |
inside_process_scheduled_actions_(false), |
inside_action_(SchedulerStateMachine::ACTION_NONE), |
@@ -125,6 +127,11 @@ Scheduler::Scheduler( |
frame_sources_constructor->ConstructBackgroundFrameSource(this); |
frame_source_->AddSource(background_frame_source_); |
+ // Unthrottled frame source |
+ unthrottled_frame_source_ = |
+ frame_sources_constructor->ConstructUnthrottledFrameSource(this); |
+ frame_source_->AddSource(unthrottled_frame_source_); |
+ |
SetupPowerMonitoring(); |
} |
@@ -184,16 +191,24 @@ void Scheduler::SetCanStart() { |
ProcessScheduledActions(); |
} |
-void Scheduler::SetVisible(bool visible) { |
- state_machine_.SetVisible(visible); |
- if (visible) { |
- frame_source_->SetActiveSource(primary_frame_source_); |
+void Scheduler::UpdateActiveFrameSource() { |
+ if (state_machine_.visible()) { |
+ if (throttle_frame_production_) { |
+ frame_source_->SetActiveSource(primary_frame_source_); |
+ } else { |
+ frame_source_->SetActiveSource(unthrottled_frame_source_); |
+ } |
} else { |
frame_source_->SetActiveSource(background_frame_source_); |
} |
ProcessScheduledActions(); |
} |
+void Scheduler::SetVisible(bool visible) { |
+ state_machine_.SetVisible(visible); |
+ UpdateActiveFrameSource(); |
+} |
+ |
void Scheduler::SetCanDraw(bool can_draw) { |
state_machine_.SetCanDraw(can_draw); |
ProcessScheduledActions(); |
@@ -209,6 +224,11 @@ void Scheduler::NotifyReadyToDraw() { |
// crbugs 352894, 383157, 421923. |
} |
+void Scheduler::SetThrottleFrameProduction(bool throttle) { |
+ throttle_frame_production_ = throttle; |
+ UpdateActiveFrameSource(); |
+} |
+ |
void Scheduler::SetNeedsCommit() { |
state_machine_.SetNeedsCommit(); |
ProcessScheduledActions(); |
@@ -273,10 +293,9 @@ void Scheduler::DidPrepareTiles() { |
void Scheduler::DidLoseOutputSurface() { |
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
- state_machine_.DidLoseOutputSurface(); |
- if (frame_source_->NeedsBeginFrames()) |
- frame_source_->SetNeedsBeginFrames(false); |
begin_retro_frame_args_.clear(); |
+ begin_retro_frame_task_.Cancel(); |
+ state_machine_.DidLoseOutputSurface(); |
ProcessScheduledActions(); |
} |
@@ -313,41 +332,29 @@ void Scheduler::SetupNextBeginFrameIfNeeded() { |
if (!task_runner_.get()) |
return; |
- bool needs_begin_frame = state_machine_.BeginFrameNeeded(); |
- |
- bool at_end_of_deadline = |
- (state_machine_.begin_impl_frame_state() == |
- SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); |
- |
- bool should_call_set_needs_begin_frame = |
- // Always request the BeginFrame immediately if it wasn't needed before. |
- (needs_begin_frame && !frame_source_->NeedsBeginFrames()) || |
- // Only stop requesting BeginFrames after a deadline. |
- (!needs_begin_frame && frame_source_->NeedsBeginFrames() && |
- at_end_of_deadline); |
- |
- if (should_call_set_needs_begin_frame) { |
- frame_source_->SetNeedsBeginFrames(needs_begin_frame); |
+ if (state_machine_.ShouldSetNeedsBeginFrames( |
+ frame_source_->NeedsBeginFrames())) { |
+ frame_source_->SetNeedsBeginFrames(state_machine_.BeginFrameNeeded()); |
} |
- if (at_end_of_deadline) { |
+ if (state_machine_.begin_impl_frame_state() == |
+ SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { |
frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); |
} |
PostBeginRetroFrameIfNeeded(); |
- SetupPollingMechanisms(needs_begin_frame); |
+ SetupPollingMechanisms(); |
} |
// We may need to poll when we can't rely on BeginFrame to advance certain |
// state or to avoid deadlock. |
-void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { |
+void Scheduler::SetupPollingMechanisms() { |
bool needs_advance_commit_state_timer = false; |
// Setup PollForAnticipatedDrawTriggers if we need to monitor state but |
// aren't expecting any more BeginFrames. This should only be needed by |
// the synchronous compositor when BeginFrameNeeded is false. |
if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { |
DCHECK(!state_machine_.SupportsProactiveBeginFrame()); |
- DCHECK(!needs_begin_frame); |
if (poll_for_draw_triggers_task_.IsCancelled()) { |
poll_for_draw_triggers_task_.Reset(poll_for_draw_triggers_closure_); |
base::TimeDelta delay = begin_impl_frame_args_.IsValid() |
@@ -427,7 +434,8 @@ bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) { |
should_defer_begin_frame = false; |
} else { |
should_defer_begin_frame = |
- !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || |
+ !begin_retro_frame_args_.empty() || |
+ !begin_retro_frame_task_.IsCancelled() || |
!frame_source_->NeedsBeginFrames() || |
(state_machine_.begin_impl_frame_state() != |
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
@@ -455,15 +463,12 @@ void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
void Scheduler::BeginRetroFrame() { |
TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); |
DCHECK(!settings_.using_synchronous_renderer_compositor); |
- DCHECK(begin_retro_frame_posted_); |
+ DCHECK(!begin_retro_frame_args_.empty()); |
+ DCHECK(!begin_retro_frame_task_.IsCancelled()); |
DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
- begin_retro_frame_posted_ = false; |
- // If there aren't any retroactive BeginFrames, then we've lost the |
- // OutputSurface and should abort. |
- if (begin_retro_frame_args_.empty()) |
- return; |
+ begin_retro_frame_task_.Cancel(); |
// Discard expired BeginRetroFrames |
// Today, we should always end up with at most one un-expired BeginRetroFrame |
@@ -510,7 +515,7 @@ void Scheduler::PostBeginRetroFrameIfNeeded() { |
if (!frame_source_->NeedsBeginFrames()) |
return; |
- if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) |
+ if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) |
return; |
// begin_retro_frame_args_ should always be empty for the |
@@ -521,8 +526,9 @@ void Scheduler::PostBeginRetroFrameIfNeeded() { |
SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) |
return; |
- begin_retro_frame_posted_ = true; |
- task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); |
+ begin_retro_frame_task_.Reset(begin_retro_frame_closure_); |
+ |
+ task_runner_->PostTask(FROM_HERE, begin_retro_frame_task_.callback()); |
} |
// BeginImplFrame starts a compositor frame that will wait up until a deadline |
@@ -757,8 +763,9 @@ void Scheduler::AsValueInto(base::debug::TracedValue* state) const { |
estimated_parent_draw_time_.InMillisecondsF()); |
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_retro_frame_task_", |
+ !begin_retro_frame_task_.IsCancelled()); |
state->SetBoolean("begin_impl_frame_deadline_task_", |
!begin_impl_frame_deadline_task_.IsCancelled()); |
state->SetBoolean("poll_for_draw_triggers_task_", |