Index: cc/scheduler/scheduler_state_machine.cc |
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc |
index 7577fb4b3d6ece5c13528dde1eb6afd8e500ac6f..2bbf2563264bb1365654663e8d13435346357137 100644 |
--- a/cc/scheduler/scheduler_state_machine.cc |
+++ b/cc/scheduler/scheduler_state_machine.cc |
@@ -90,6 +90,8 @@ const char* SchedulerStateMachine::CommitStateToString(CommitState state) { |
return "COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED"; |
case COMMIT_STATE_READY_TO_COMMIT: |
return "COMMIT_STATE_READY_TO_COMMIT"; |
+ case COMMIT_STATE_WAITING_FOR_ACTIVATION: |
+ return "COMMIT_STATE_WAITING_FOR_ACTIVATION"; |
case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: |
return "COMMIT_STATE_WAITING_FOR_FIRST_DRAW"; |
} |
@@ -374,10 +376,8 @@ bool SchedulerStateMachine::ShouldDraw() const { |
return false; |
// Draw immediately for readbacks to unblock the main thread quickly. |
- if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) { |
- DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); |
+ if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) |
return true; |
- } |
// If we need to abort draws, we should do so ASAP since the draw could |
// be blocking other important actions (like output surface initialization), |
@@ -397,10 +397,8 @@ bool SchedulerStateMachine::ShouldDraw() const { |
return false; |
// Only handle forced redraws due to timeouts on the regular deadline. |
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) { |
- DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); |
+ if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) |
return true; |
- } |
return needs_redraw_; |
} |
@@ -465,9 +463,12 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { |
if (commit_state_ != COMMIT_STATE_IDLE) |
return false; |
- // We can't accept a commit if we have a pending tree. |
- if (has_pending_tree_) |
+ // Don't send BeginMainFrame early if we are prioritizing the active tree |
+ // because of smoothness_takes_priority. |
+ if (smoothness_takes_priority_ && |
+ (has_pending_tree_ || active_tree_needs_first_draw_)) { |
return false; |
+ } |
// We want to handle readback commits immediately to unblock the main thread. |
// Note: This BeginMainFrame will correspond to the replacement commit that |
@@ -514,7 +515,20 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { |
} |
bool SchedulerStateMachine::ShouldCommit() const { |
- return commit_state_ == COMMIT_STATE_READY_TO_COMMIT; |
+ if (commit_state_ != COMMIT_STATE_READY_TO_COMMIT) |
+ return false; |
+ |
+ // We must not finish the commit until the pending tree is free. |
+ if (has_pending_tree_) { |
+ DCHECK(settings_.main_frame_before_activation_enabled); |
+ return false; |
+ } |
+ |
+ // Prioritize drawing the previous commit before finishing the next commit. |
+ if (active_tree_needs_first_draw_) |
+ return false; |
+ |
+ return true; |
} |
bool SchedulerStateMachine::ShouldManageTiles() const { |
@@ -588,7 +602,10 @@ void SchedulerStateMachine::UpdateState(Action action) { |
return; |
case ACTION_SEND_BEGIN_MAIN_FRAME: |
- DCHECK(!has_pending_tree_); |
+ DCHECK(!has_pending_tree_ || |
+ settings_.main_frame_before_activation_enabled); |
+ DCHECK(!active_tree_needs_first_draw_ || |
+ settings_.main_frame_before_draw_enabled); |
DCHECK(visible_ || |
readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME); |
commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; |
@@ -645,6 +662,16 @@ void SchedulerStateMachine::UpdateState(Action action) { |
void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) { |
commit_count_++; |
+ if (commit_was_aborted || settings_.main_frame_before_activation_enabled) { |
+ commit_state_ = COMMIT_STATE_IDLE; |
+ } else if (settings_.main_frame_before_draw_enabled) { |
+ commit_state_ = settings_.impl_side_painting |
+ ? COMMIT_STATE_WAITING_FOR_ACTIVATION |
+ : COMMIT_STATE_IDLE; |
+ } else { |
+ commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; |
+ } |
+ |
// If we are impl-side-painting but the commit was aborted, then we behave |
// mostly as if we are not impl-side-painting since there is no pending tree. |
has_pending_tree_ = settings_.impl_side_painting && !commit_was_aborted; |
@@ -690,18 +717,6 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) { |
} |
} |
- // Update the commit state. We expect and wait for a draw if the commit |
- // was not aborted or if we are in a readback or forced draw. |
- if (!commit_was_aborted) { |
- DCHECK(commit_state_ == COMMIT_STATE_READY_TO_COMMIT); |
- commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; |
- } else if (readback_state_ != READBACK_STATE_IDLE || |
- forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE) { |
- commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; |
- } else { |
- commit_state_ = COMMIT_STATE_IDLE; |
- } |
- |
// Update state if we have a new active tree to draw, or if the active tree |
// was unchanged but we need to do a readback or forced draw. |
if (!has_pending_tree_ && |
@@ -727,6 +742,9 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) { |
} |
void SchedulerStateMachine::UpdateStateOnActivation() { |
+ if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION) |
+ commit_state_ = COMMIT_STATE_IDLE; |
+ |
if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION) |
output_surface_state_ = OUTPUT_SURFACE_ACTIVE; |
@@ -750,8 +768,7 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) { |
<< *AsValue(); |
if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) { |
- // The draw correspons to a readback commit. |
- DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); |
+ // The draw corresponds to a readback commit. |
// We are blocking commits from the main thread until after this draw, so |
// we should not have a pending tree. |
DCHECK(!has_pending_tree_); |
@@ -760,14 +777,12 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) { |
commit_state_ = COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; |
readback_state_ = READBACK_STATE_WAITING_FOR_REPLACEMENT_COMMIT; |
} else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW) { |
- DCHECK_EQ(commit_state_, COMMIT_STATE_WAITING_FOR_FIRST_DRAW); |
- commit_state_ = COMMIT_STATE_IDLE; |
forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE; |
- } else if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW && |
- !has_pending_tree_) { |
- commit_state_ = COMMIT_STATE_IDLE; |
} |
+ if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_DRAW) |
+ commit_state_ = COMMIT_STATE_IDLE; |
+ |
if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD) |
texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; |
@@ -962,6 +977,11 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineEarly() const { |
} |
bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const { |
+ // If a commit is pending before the previous commit has been drawn, we |
+ // are definitely in a high latency mode. |
+ if (CommitPending() && (active_tree_needs_first_draw_ || has_pending_tree_)) |
+ return true; |
+ |
// If we just sent a BeginMainFrame and haven't hit the deadline yet, the main |
// thread is in a low latency mode. |
if (last_frame_number_begin_main_frame_sent_ == current_frame_number_ && |