| Index: cc/scheduler/scheduler_state_machine.cc
|
| diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
|
| index 1111ba36f13c0030b50d5eb5373e563ce955815f..942655509ee6df6d570eceef4d3d5a772e38dc39 100644
|
| --- a/cc/scheduler/scheduler_state_machine.cc
|
| +++ b/cc/scheduler/scheduler_state_machine.cc
|
| @@ -87,6 +87,8 @@ const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
|
| return "COMMIT_STATE_FRAME_IN_PROGRESS";
|
| 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";
|
| }
|
| @@ -365,10 +367,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),
|
| @@ -388,10 +388,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_;
|
| }
|
| @@ -456,9 +454,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
|
| @@ -505,7 +506,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_.start_commit_before_activate_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::IsCommitStateWaiting() const {
|
| @@ -578,7 +592,10 @@ void SchedulerStateMachine::UpdateState(Action action) {
|
| return;
|
|
|
| case ACTION_SEND_BEGIN_MAIN_FRAME:
|
| - DCHECK(!has_pending_tree_);
|
| + DCHECK(!has_pending_tree_ ||
|
| + settings_.start_commit_before_activate_enabled);
|
| + DCHECK(!active_tree_needs_first_draw_ ||
|
| + settings_.start_commit_before_draw_enabled);
|
| DCHECK(visible_ ||
|
| readback_state_ == READBACK_STATE_NEEDS_BEGIN_MAIN_FRAME);
|
| commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
|
| @@ -635,6 +652,16 @@ void SchedulerStateMachine::UpdateState(Action action) {
|
| void SchedulerStateMachine::UpdateStateOnCommit(bool commit_was_aborted) {
|
| commit_count_++;
|
|
|
| + if (commit_was_aborted || settings_.start_commit_before_activate_enabled) {
|
| + commit_state_ = COMMIT_STATE_IDLE;
|
| + } else if (settings_.start_commit_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;
|
| @@ -680,18 +707,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_ &&
|
| @@ -717,6 +732,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;
|
|
|
| @@ -740,8 +758,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_);
|
| @@ -750,14 +767,12 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_swap) {
|
| commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
|
| 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;
|
|
|
| @@ -952,6 +967,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_ &&
|
| @@ -962,8 +982,7 @@ bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
|
| // If there's a commit in progress it must either be from the previous frame
|
| // or it started after the impl thread's deadline. In either case the main
|
| // thread is in high latency mode.
|
| - if (commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS ||
|
| - commit_state_ == COMMIT_STATE_READY_TO_COMMIT)
|
| + if (CommitPending())
|
| return true;
|
|
|
| // Similarly, if there's a pending tree the main thread is in high latency
|
| @@ -1094,7 +1113,7 @@ void SchedulerStateMachine::SetNeedsForcedCommitForReadback() {
|
| }
|
|
|
| void SchedulerStateMachine::FinishCommit() {
|
| - DCHECK(commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS) << *AsValue();
|
| + DCHECK(commit_state_ != COMMIT_STATE_IDLE) << *AsValue();
|
| commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
|
| }
|
|
|
|
|