| Index: cc/scheduler/scheduler_state_machine.cc
|
| diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
|
| index 6446e8dcbb7a9b181676c62e84605a85ee1d2630..b37de1bc19a068c7f4c2145f7cfaf3221d4ef36c 100644
|
| --- a/cc/scheduler/scheduler_state_machine.cc
|
| +++ b/cc/scheduler/scheduler_state_machine.cc
|
| @@ -14,10 +14,13 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
|
| : settings_(settings),
|
| commit_state_(COMMIT_STATE_IDLE),
|
| commit_count_(0),
|
| - current_frame_number_(0),
|
| - last_frame_number_where_draw_was_called_(-1),
|
| - last_frame_number_where_tree_activation_attempted_(-1),
|
| - last_frame_number_where_check_for_completed_tile_uploads_called_(-1),
|
| + begin_frame_count_(0),
|
| + begin_frame_deadline_count_(0),
|
| + draw_attempt_count_(0),
|
| + last_begin_frame_count_draw_was_called_(-1),
|
| + last_begin_frame_count_begin_frame_sent_to_main_thread_(-1),
|
| + last_draw_attempt_count_tree_activation_attempted_(-1),
|
| + last_draw_attempt_count_completed_tile_uploads_checked_(-1),
|
| consecutive_failed_draws_(0),
|
| maximum_number_of_failed_draws_before_draw_is_forced_(3),
|
| needs_redraw_(false),
|
| @@ -28,7 +31,9 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
|
| needs_forced_commit_(false),
|
| expect_immediate_begin_frame_for_main_thread_(false),
|
| main_thread_needs_layer_textures_(false),
|
| - inside_begin_frame_(false),
|
| + begin_frame_state_(BEGIN_FRAME_STATE_IDLE),
|
| + commit_tree_has_been_drawn_(true),
|
| + active_tree_has_been_drawn_(false),
|
| visible_(false),
|
| can_start_(false),
|
| can_draw_(false),
|
| @@ -45,19 +50,21 @@ std::string SchedulerStateMachine::ToString() {
|
| settings_.impl_side_painting);
|
| base::StringAppendF(&str, "commit_state_ = %d; ", commit_state_);
|
| base::StringAppendF(&str, "commit_count_ = %d; ", commit_count_);
|
| - base::StringAppendF(
|
| - &str, "current_frame_number_ = %d; ", current_frame_number_);
|
| + base::StringAppendF(&str, "begin_frame_count_ = %d; ",
|
| + begin_frame_count_);
|
| + base::StringAppendF(&str, "draw_attempt_count_ = %d; ",
|
| + draw_attempt_count_);
|
| base::StringAppendF(&str,
|
| - "last_frame_number_where_draw_was_called_ = %d; ",
|
| - last_frame_number_where_draw_was_called_);
|
| + "last_begin_frame_count_draw_was_called_ = %d; ",
|
| + last_begin_frame_count_draw_was_called_);
|
| base::StringAppendF(
|
| &str,
|
| - "last_frame_number_where_tree_activation_attempted_ = %d; ",
|
| - last_frame_number_where_tree_activation_attempted_);
|
| + "last_draw_attempt_count_tree_activation_attempted_ = %d; ",
|
| + last_draw_attempt_count_tree_activation_attempted_);
|
| base::StringAppendF(
|
| &str,
|
| - "last_frame_number_where_check_for_completed_tile_uploads_called_ = %d; ",
|
| - last_frame_number_where_check_for_completed_tile_uploads_called_);
|
| + "last_draw_attempt_count_completed_tile_uploads_checked_ = %d; ",
|
| + last_draw_attempt_count_completed_tile_uploads_checked_);
|
| base::StringAppendF(
|
| &str, "consecutive_failed_draws_ = %d; ", consecutive_failed_draws_);
|
| base::StringAppendF(
|
| @@ -81,8 +88,7 @@ std::string SchedulerStateMachine::ToString() {
|
| base::StringAppendF(&str,
|
| "main_thread_needs_layer_textures_ = %d; ",
|
| main_thread_needs_layer_textures_);
|
| - base::StringAppendF(&str, "inside_begin_frame_ = %d; ",
|
| - inside_begin_frame_);
|
| + base::StringAppendF(&str, "begin_frame_state_ = %d; ", begin_frame_state_);
|
| base::StringAppendF(&str, "last_frame_time_ = %"PRId64"; ",
|
| (last_begin_frame_args_.frame_time - base::TimeTicks())
|
| .InMilliseconds());
|
| @@ -96,6 +102,10 @@ std::string SchedulerStateMachine::ToString() {
|
| base::StringAppendF(
|
| &str, "draw_if_possible_failed_ = %d; ", draw_if_possible_failed_);
|
| base::StringAppendF(&str, "has_pending_tree_ = %d; ", has_pending_tree_);
|
| + base::StringAppendF(&str, "commit_tree_has_been_drawn_ = %d; ",
|
| + commit_tree_has_been_drawn_);
|
| + base::StringAppendF(&str, "active_tree_has_been_drawn_ = %d; ",
|
| + active_tree_has_been_drawn_);
|
| base::StringAppendF(&str, "texture_state_ = %d; ", texture_state_);
|
| base::StringAppendF(
|
| &str, "output_surface_state_ = %d; ", output_surface_state_);
|
| @@ -103,17 +113,23 @@ std::string SchedulerStateMachine::ToString() {
|
| }
|
|
|
| bool SchedulerStateMachine::HasDrawnThisFrame() const {
|
| - return current_frame_number_ == last_frame_number_where_draw_was_called_;
|
| + return begin_frame_count_ == last_begin_frame_count_draw_was_called_;
|
| +}
|
| +
|
| +bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const {
|
| + return begin_frame_count_ ==
|
| + last_begin_frame_count_begin_frame_sent_to_main_thread_;
|
| }
|
|
|
| -bool SchedulerStateMachine::HasAttemptedTreeActivationThisFrame() const {
|
| - return current_frame_number_ ==
|
| - last_frame_number_where_tree_activation_attempted_;
|
| +bool SchedulerStateMachine::HasAttemptedTreeActivationThisDrawAttempt() const {
|
| + return draw_attempt_count_ ==
|
| + last_draw_attempt_count_tree_activation_attempted_;
|
| }
|
|
|
| -bool SchedulerStateMachine::HasCheckedForCompletedTileUploadsThisFrame() const {
|
| - return current_frame_number_ ==
|
| - last_frame_number_where_check_for_completed_tile_uploads_called_;
|
| +bool SchedulerStateMachine::
|
| + HasCheckedForCompletedTileUploadsThisDrawAttempt() const {
|
| + return draw_attempt_count_ ==
|
| + last_draw_attempt_count_completed_tile_uploads_checked_;
|
| }
|
|
|
| bool SchedulerStateMachine::DrawSuspendedUntilCommit() const {
|
| @@ -140,7 +156,7 @@ bool SchedulerStateMachine::ShouldDraw() const {
|
|
|
| if (!ScheduledToDraw())
|
| return false;
|
| - if (!inside_begin_frame_)
|
| + if (begin_frame_state_ != BEGIN_FRAME_STATE_INSIDE_DEADLINE)
|
| return false;
|
| if (HasDrawnThisFrame())
|
| return false;
|
| @@ -150,14 +166,17 @@ bool SchedulerStateMachine::ShouldDraw() const {
|
| }
|
|
|
| bool SchedulerStateMachine::ShouldAttemptTreeActivation() const {
|
| - return has_pending_tree_ && inside_begin_frame_ &&
|
| - !HasAttemptedTreeActivationThisFrame();
|
| + return !HasAttemptedTreeActivationThisDrawAttempt() &&
|
| + has_pending_tree_ &&
|
| + (!can_draw_ || !visible_ ||
|
| + (active_tree_has_been_drawn_ &&
|
| + begin_frame_state_ != BEGIN_FRAME_STATE_IDLE));
|
| }
|
|
|
| bool SchedulerStateMachine::ShouldCheckForCompletedTileUploads() const {
|
| if (!settings_.impl_side_painting)
|
| return false;
|
| - if (HasCheckedForCompletedTileUploadsThisFrame())
|
| + if (HasCheckedForCompletedTileUploadsThisDrawAttempt())
|
| return false;
|
|
|
| return ShouldAttemptTreeActivation() || ShouldDraw() ||
|
| @@ -179,6 +198,48 @@ bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const {
|
| return false;
|
| }
|
|
|
| +bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const {
|
| + if (HasSentBeginFrameToMainThreadThisFrame())
|
| + return false;
|
| +
|
| + // TODO(brianderson): Allow sending BeginFrame to main thread while idle when
|
| + // the main thread isn't consuming user input?
|
| + bool can_expect_begin_frame = BeginFrameNeededToDrawByImplThread() ||
|
| + ProactiveBeginFrameWantedByImplThread();
|
| + if (can_expect_begin_frame &&
|
| + begin_frame_state_ == BEGIN_FRAME_STATE_IDLE)
|
| + return false;
|
| +
|
| + // Do not send begin frame to main thread in the deadline until we have drawn.
|
| + if ((can_expect_begin_frame || WillDrawNewTree()) &&
|
| + begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_DEADLINE)
|
| + return false;
|
| +
|
| + // We can't accept a commit if we have a pending tree.
|
| + if (has_pending_tree_)
|
| + return false;
|
| +
|
| + bool can_commit = needs_commit_ && (visible_ || needs_forced_commit_);
|
| + switch (commit_state_) {
|
| + case COMMIT_STATE_IDLE:
|
| + return can_commit && (needs_forced_commit_ ||
|
| + output_surface_state_ == OUTPUT_SURFACE_ACTIVE);
|
| +
|
| + // COMMIT_STATE_WAITING_FOR_ACTIVATION wants to enforce activation and
|
| + // eventually a draw.
|
| + // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw.
|
| + // If can_draw_ is false or textures are not available, proceed to the
|
| + // next step (similar as in COMMIT_STATE_IDLE).
|
| + case COMMIT_STATE_WAITING_FOR_ACTIVATION:
|
| + case COMMIT_STATE_WAITING_FOR_FIRST_DRAW:
|
| + return can_commit && DrawSuspendedUntilCommit();
|
| + default:
|
| + return false;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| if (ShouldAcquireLayerTexturesForMainThread())
|
| return ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD;
|
| @@ -205,12 +266,10 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| return needs_forced_redraw_ ? ACTION_DRAW_FORCED
|
| : ACTION_DRAW_IF_POSSIBLE;
|
| }
|
| - if (needs_commit_ &&
|
| - ((visible_ && output_surface_state_ == OUTPUT_SURFACE_ACTIVE)
|
| - || needs_forced_commit_))
|
| + if (ShouldSendBeginFrameToMainThread()) {
|
| // TODO(enne): Should probably drop the active tree on force commit.
|
| - return has_pending_tree_ ? ACTION_NONE
|
| - : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
|
| + return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
|
| + }
|
| return ACTION_NONE;
|
|
|
| case COMMIT_STATE_FRAME_IN_PROGRESS:
|
| @@ -227,6 +286,7 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| case COMMIT_STATE_READY_TO_COMMIT:
|
| return ACTION_COMMIT;
|
|
|
| + case COMMIT_STATE_WAITING_FOR_ACTIVATION:
|
| case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: {
|
| if (ShouldCheckForCompletedTileUploads())
|
| return ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS;
|
| @@ -236,13 +296,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| return needs_forced_redraw_ ? ACTION_DRAW_FORCED
|
| : ACTION_DRAW_IF_POSSIBLE;
|
| }
|
| - // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If
|
| - // can_draw_ is false or textures are not available, proceed to the next
|
| - // step (similar as in COMMIT_STATE_IDLE).
|
| - bool can_commit = visible_ || needs_forced_commit_;
|
| - if (needs_commit_ && can_commit && DrawSuspendedUntilCommit())
|
| - return has_pending_tree_ ? ACTION_NONE
|
| - : ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
|
| + if (ShouldSendBeginFrameToMainThread())
|
| + return ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD;
|
| return ACTION_NONE;
|
| }
|
|
|
| @@ -262,16 +317,20 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
|
| void SchedulerStateMachine::UpdateState(Action action) {
|
| switch (action) {
|
| case ACTION_NONE:
|
| + if (begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME)
|
| + begin_frame_state_ = BEGIN_FRAME_STATE_DEADLINE_PENDING;
|
| + if (begin_frame_state_ == BEGIN_FRAME_STATE_INSIDE_DEADLINE)
|
| + begin_frame_state_ = BEGIN_FRAME_STATE_IDLE;
|
| return;
|
|
|
| case ACTION_CHECK_FOR_COMPLETED_TILE_UPLOADS:
|
| - last_frame_number_where_check_for_completed_tile_uploads_called_ =
|
| - current_frame_number_;
|
| + last_draw_attempt_count_completed_tile_uploads_checked_ =
|
| + draw_attempt_count_;
|
| return;
|
|
|
| case ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED:
|
| - last_frame_number_where_tree_activation_attempted_ =
|
| - current_frame_number_;
|
| + last_draw_attempt_count_tree_activation_attempted_ =
|
| + draw_attempt_count_;
|
| return;
|
|
|
| case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD:
|
| @@ -280,25 +339,29 @@ void SchedulerStateMachine::UpdateState(Action action) {
|
| commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
|
| needs_commit_ = false;
|
| needs_forced_commit_ = false;
|
| + last_begin_frame_count_begin_frame_sent_to_main_thread_ =
|
| + begin_frame_count_;
|
| return;
|
|
|
| case ACTION_COMMIT:
|
| commit_count_++;
|
| if (expect_immediate_begin_frame_for_main_thread_)
|
| commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW;
|
| + else if (settings_.impl_side_painting)
|
| + commit_state_ = COMMIT_STATE_WAITING_FOR_ACTIVATION;
|
| else
|
| commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW;
|
| // When impl-side painting, we draw on activation instead of on commit.
|
| if (!settings_.impl_side_painting)
|
| needs_redraw_ = true;
|
| if (draw_if_possible_failed_)
|
| - last_frame_number_where_draw_was_called_ = -1;
|
| + last_begin_frame_count_draw_was_called_ = -1;
|
|
|
| if (needs_forced_redraw_after_next_commit_) {
|
| needs_forced_redraw_after_next_commit_ = false;
|
| needs_forced_redraw_ = true;
|
| }
|
| -
|
| + commit_tree_has_been_drawn_ = false;
|
| texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD;
|
| return;
|
|
|
| @@ -308,8 +371,7 @@ void SchedulerStateMachine::UpdateState(Action action) {
|
| needs_forced_redraw_ = false;
|
| draw_if_possible_failed_ = false;
|
| swap_used_incomplete_tile_ = false;
|
| - if (inside_begin_frame_)
|
| - last_frame_number_where_draw_was_called_ = current_frame_number_;
|
| + last_begin_frame_count_draw_was_called_ = begin_frame_count_;
|
| if (commit_state_ == COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW) {
|
| DCHECK(expect_immediate_begin_frame_for_main_thread_);
|
| commit_state_ = COMMIT_STATE_FRAME_IN_PROGRESS;
|
| @@ -319,6 +381,8 @@ void SchedulerStateMachine::UpdateState(Action action) {
|
| }
|
| if (texture_state_ == LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD)
|
| texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED;
|
| + active_tree_has_been_drawn_ = true;
|
| + commit_tree_has_been_drawn_ = true;
|
| return;
|
|
|
| case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
|
| @@ -364,6 +428,13 @@ bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const {
|
| }
|
|
|
| bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
|
| + if (settings_.using_synchronous_renderer_compositor)
|
| + return false;
|
| +
|
| + if ((!visible_ || output_surface_state_ != OUTPUT_SURFACE_ACTIVE) &&
|
| + !(needs_forced_commit_ || needs_forced_redraw_))
|
| + return false;
|
| +
|
| // We should proactively request a BeginFrame if a commit is pending.
|
| if (needs_commit_ || needs_forced_commit_ ||
|
| commit_state_ != COMMIT_STATE_IDLE)
|
| @@ -372,17 +443,40 @@ bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const {
|
| return false;
|
| }
|
|
|
| -void SchedulerStateMachine::DidEnterBeginFrame(const BeginFrameArgs& args) {
|
| - inside_begin_frame_ = true;
|
| +void SchedulerStateMachine::OnBeginFrame(const BeginFrameArgs& args) {
|
| + begin_frame_count_++;
|
| + draw_attempt_count_++;
|
| last_begin_frame_args_ = args;
|
| + begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_BEGIN_FRAME;
|
| +}
|
| +
|
| +bool SchedulerStateMachine::ShouldTriggerBeginFrameDeadlineEarly() const {
|
| + // TODO(brianderson): This should take into account multiple commit sources.
|
| + return begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING &&
|
| + WillDrawNewTree();
|
| +}
|
| +
|
| +bool SchedulerStateMachine::InsideBeginFrame() const {
|
| + return begin_frame_state_ != BEGIN_FRAME_STATE_IDLE;
|
| +}
|
| +
|
| +bool SchedulerStateMachine::WillDrawNewTree() const {
|
| + if (settings_.impl_side_painting)
|
| + return !active_tree_has_been_drawn_;
|
| + else
|
| + return !commit_tree_has_been_drawn_;
|
| }
|
|
|
| -void SchedulerStateMachine::DidLeaveBeginFrame() {
|
| - current_frame_number_++;
|
| - inside_begin_frame_ = false;
|
| +void SchedulerStateMachine::OnBeginFrameDeadline() {
|
| + begin_frame_deadline_count_++;
|
| + draw_attempt_count_++;
|
| + if (begin_frame_state_ == BEGIN_FRAME_STATE_DEADLINE_PENDING)
|
| + begin_frame_state_ = BEGIN_FRAME_STATE_INSIDE_DEADLINE;
|
| }
|
|
|
| -void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
|
| +void SchedulerStateMachine::SetVisible(bool visible) {
|
| + visible_ = visible;
|
| +}
|
|
|
| void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; }
|
|
|
| @@ -445,11 +539,25 @@ void SchedulerStateMachine::DidLoseOutputSurface() {
|
| output_surface_state_ = OUTPUT_SURFACE_LOST;
|
| }
|
|
|
| -void SchedulerStateMachine::SetHasPendingTree(bool has_pending_tree) {
|
| +void SchedulerStateMachine::SetHasTrees(bool has_pending_tree,
|
| + bool active_tree_is_null) {
|
| + if (has_pending_tree_ && !has_pending_tree) {
|
| + // This is a new activation.
|
| + draw_attempt_count_++;
|
| + active_tree_has_been_drawn_ = false;
|
| + if (COMMIT_STATE_WAITING_FOR_ACTIVATION == commit_state_)
|
| + commit_state_ = COMMIT_STATE_IDLE;
|
| + }
|
| +
|
| has_pending_tree_ = has_pending_tree;
|
| +
|
| + if (active_tree_is_null)
|
| + active_tree_has_been_drawn_ = true;
|
| }
|
|
|
| -void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; }
|
| +void SchedulerStateMachine::SetCanDraw(bool can_draw) {
|
| + can_draw_ = can_draw;
|
| +}
|
|
|
| void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
|
| DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING);
|
|
|