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

Unified Diff: cc/scheduler/scheduler_state_machine.cc

Issue 1131633003: cc: Use multiple PrepareTiles approaches Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 7 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
« no previous file with comments | « cc/scheduler/scheduler_state_machine.h ('k') | cc/test/fake_layer_tree_host_impl_client.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/scheduler/scheduler_state_machine.cc
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 5881f2a72340802d180d182fdd7faa4b5a014332..33e33c4544e74076b8d0a963b74d619e4e51c317 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -18,7 +18,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
output_surface_state_(OUTPUT_SURFACE_LOST),
begin_impl_frame_state_(BEGIN_IMPL_FRAME_STATE_IDLE),
commit_state_(COMMIT_STATE_IDLE),
- forced_redraw_state_(FORCED_REDRAW_STATE_IDLE),
+ prepare_tiles_approach_(PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY),
+ prepare_tiles_reason_(PREPARE_TILES_NOT_NEEDED),
commit_count_(0),
current_frame_number_(0),
last_frame_number_animate_performed_(-1),
@@ -31,18 +32,20 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
send_begin_main_frame_funnel_(false),
invalidate_output_surface_funnel_(false),
prepare_tiles_funnel_(0),
- consecutive_checkerboard_animations_(0),
max_pending_swaps_(1),
pending_swaps_(0),
needs_redraw_(false),
+ last_draw_result_(DRAW_SUCCESS),
+ retry_begin_impl_frame_(false),
+ retry_begin_impl_frame_deadline_(false),
needs_animate_(false),
- needs_prepare_tiles_(false),
needs_commit_(false),
visible_(false),
can_start_(false),
can_draw_(false),
has_pending_tree_(false),
pending_tree_is_ready_for_activation_(false),
+ requires_high_res_to_draw_(false),
active_tree_needs_first_draw_(false),
did_create_and_initialize_first_output_surface_(false),
impl_latency_takes_priority_(false),
@@ -103,6 +106,8 @@ const char* SchedulerStateMachine::BeginImplFrameDeadlineModeToString(
return "BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR";
case BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE:
return "BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE";
+ case BEGIN_IMPL_FRAME_DEADLINE_MODE_TRY_TO_AVOID_CHECKERBOARD:
+ return "BEGIN_IMPL_FRAME_DEADLINE_MODE_TRY_TO_AVOID_CHECKERBOARD";
case BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW:
return "BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW";
}
@@ -129,17 +134,31 @@ const char* SchedulerStateMachine::CommitStateToString(CommitState state) {
return "???";
}
-const char* SchedulerStateMachine::ForcedRedrawOnTimeoutStateToString(
- ForcedRedrawOnTimeoutState state) {
- switch (state) {
- case FORCED_REDRAW_STATE_IDLE:
- return "FORCED_REDRAW_STATE_IDLE";
- case FORCED_REDRAW_STATE_WAITING_FOR_COMMIT:
- return "FORCED_REDRAW_STATE_WAITING_FOR_COMMIT";
- case FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION:
- return "FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION";
- case FORCED_REDRAW_STATE_WAITING_FOR_DRAW:
- return "FORCED_REDRAW_STATE_WAITING_FOR_DRAW";
+const char* SchedulerStateMachine::PrepareTilesApproachToString(
+ PrepareTilesApproach approach) {
+ switch (approach) {
+ case PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY:
+ return "PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY";
+ case PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK:
+ return "PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK";
+ }
+ NOTREACHED();
+ return "???";
+}
+
+const char* SchedulerStateMachine::PrepareTilesReasonToString(
+ PrepareTilesReason reason) {
+ switch (reason) {
+ case PREPARE_TILES_NOT_NEEDED:
+ return "PREPARE_TILES_NOT_NEEDED";
+ case PREPARE_TILES_REQUESTED:
+ return "PREPARE_TILES_REQUESTED";
+ case PREPARE_TILES_NEEDED_FOR_COMMIT:
+ return "PREPARE_TILES_NEEDED_FOR_COMMIT";
+ case PREPARE_TILES_NEEDED_FOR_ABORTED_DRAW:
+ return "PREPARE_TILES_NEEDED_FOR_ABORTED_DRAW";
+ case PREPARE_TILES_NEEDED_TO_EVICT_TILES:
+ return "PREPARE_TILES_NEEDED_TO_EVICT_TILES";
}
NOTREACHED();
return "???";
@@ -189,10 +208,12 @@ void SchedulerStateMachine::AsValueInto(
state->SetString("begin_impl_frame_state",
BeginImplFrameStateToString(begin_impl_frame_state_));
state->SetString("commit_state", CommitStateToString(commit_state_));
- state->SetString("output_surface_state_",
+ state->SetString("prepare_tiles_approach",
+ PrepareTilesApproachToString(prepare_tiles_approach_));
+ state->SetString("prepare_tiles_reason",
+ PrepareTilesReasonToString(prepare_tiles_reason_));
+ state->SetString("output_surface_state",
OutputSurfaceStateToString(output_surface_state_));
- state->SetString("forced_redraw_state",
- ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
state->EndDictionary();
state->BeginDictionary("minor_state");
@@ -213,13 +234,10 @@ void SchedulerStateMachine::AsValueInto(
state->SetInteger("funnel: prepare_tiles_funnel", prepare_tiles_funnel_);
state->SetBoolean("funnel: invalidate_output_surface_funnel",
invalidate_output_surface_funnel_);
- state->SetInteger("consecutive_checkerboard_animations",
- consecutive_checkerboard_animations_);
state->SetInteger("max_pending_swaps_", max_pending_swaps_);
state->SetInteger("pending_swaps_", pending_swaps_);
state->SetBoolean("needs_redraw", needs_redraw_);
state->SetBoolean("needs_animate_", needs_animate_);
- state->SetBoolean("needs_prepare_tiles", needs_prepare_tiles_);
state->SetBoolean("needs_commit", needs_commit_);
state->SetBoolean("visible", visible_);
state->SetBoolean("can_start", can_start_);
@@ -344,10 +362,6 @@ bool SchedulerStateMachine::ShouldDraw() const {
if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
return false;
- // Only handle forced redraws due to timeouts on the regular deadline.
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
- return true;
-
return needs_redraw_;
}
@@ -445,14 +459,6 @@ bool SchedulerStateMachine::ShouldSendBeginMainFrame() const {
BeginFrameNeeded())
return false;
- // We need a new commit for the forced redraw. This honors the
- // single commit per interval because the result will be swapped to screen.
- // TODO(brianderson): Remove this or move it below the
- // SendingBeginMainFrameMightCauseDeadlock check since we want to avoid
- // ever returning true from this method if we might cause deadlock.
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT)
- return true;
-
// We shouldn't normally accept commits if there isn't an OutputSurface.
if (!HasInitializedOutputSurface())
return false;
@@ -500,18 +506,36 @@ bool SchedulerStateMachine::ShouldCommit() const {
}
bool SchedulerStateMachine::ShouldPrepareTiles() const {
- // PrepareTiles only really needs to be called immediately after commit
- // and then periodically after that. Use a funnel to make sure we average
- // one PrepareTiles per BeginImplFrame in the long run.
- if (prepare_tiles_funnel_ > 0)
- return false;
+ // Handle the clear cut cases.
+ switch (prepare_tiles_reason_) {
+ case PREPARE_TILES_NOT_NEEDED:
+ return false;
+ case PREPARE_TILES_NEEDED_FOR_COMMIT:
+ case PREPARE_TILES_NEEDED_FOR_ABORTED_DRAW:
+ case PREPARE_TILES_NEEDED_TO_EVICT_TILES:
+ return true;
+ case PREPARE_TILES_REQUESTED:
+ break;
+ }
- // Limiting to once per-frame is not enough, since we only want to
- // prepare tiles _after_ draws.
- if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
- return false;
+ switch (prepare_tiles_approach_) {
+ case PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK:
+ return begin_impl_frame_state_ ==
+ BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
+ case PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY:
+ break;
+ }
+
+ DCHECK_EQ(PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY, prepare_tiles_approach_);
+ DCHECK_EQ(PREPARE_TILES_REQUESTED, prepare_tiles_reason_);
- return needs_prepare_tiles_;
+ // Only PrepareTiles after a draw if we haven't already PreparedTiles this
+ // frame. This takes PrepareTiles out of the critical path, but wil make the
+ // NotifyReadyToDraw and NotifyReadyToActivate signals liars.
+ bool did_not_prepare_tiles_at_end_of_frame =
+ prepare_tiles_funnel_ == 0 &&
+ begin_impl_frame_state_ == BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
+ return did_not_prepare_tiles_at_end_of_frame;
}
bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const {
@@ -527,10 +551,11 @@ bool SchedulerStateMachine::ShouldInvalidateOutputSurface() const {
if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
return false;
+ // TODO(brianderson): Figure out what to do with this.
// TODO(sunnyps): needs_prepare_tiles_ is needed here because PrepareTiles is
// called only inside the deadline / draw phase. We could remove this if we
// allowed PrepareTiles to happen in OnBeginImplFrame.
- return needs_redraw_ || needs_prepare_tiles_;
+ return needs_redraw_ || PrepareTilesPending();
}
SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
@@ -543,10 +568,12 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
if (ShouldDraw()) {
if (PendingDrawsShouldBeAborted())
return ACTION_DRAW_AND_SWAP_ABORT;
- else if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
- return ACTION_DRAW_AND_SWAP_FORCED;
- else
+ else if (requires_high_res_to_draw_ ||
+ prepare_tiles_approach_ ==
+ PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY)
return ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
+ else
+ return ACTION_DRAW_AND_SWAP_FORCED;
}
if (ShouldPrepareTiles())
return ACTION_PREPARE_TILES;
@@ -559,57 +586,91 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const {
return ACTION_NONE;
}
-void SchedulerStateMachine::UpdateState(Action action) {
+void SchedulerStateMachine::WillAction(Action action) {
switch (action) {
case ACTION_NONE:
return;
+ case ACTION_COMMIT:
+ WillCommit();
+ return;
+
case ACTION_ACTIVATE_SYNC_TREE:
- UpdateStateOnActivation();
+ WillActivateSyncTree();
return;
case ACTION_ANIMATE:
- UpdateStateOnAnimate();
+ WillAnimate();
return;
case ACTION_SEND_BEGIN_MAIN_FRAME:
- UpdateStateOnSendBeginMainFrame();
+ WillSendBeginMainFrame();
+ return;
+
+ case ACTION_DRAW_AND_SWAP_FORCED:
+ case ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
+ case ACTION_DRAW_AND_SWAP_ABORT:
+ return;
+
+ case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
+ WillBeginOutputSurfaceCreation();
+ return;
+
+ case ACTION_PREPARE_TILES:
+ return;
+
+ case ACTION_INVALIDATE_OUTPUT_SURFACE:
+ WillInvalidateOutputSurface();
+ return;
+ }
+}
+
+void SchedulerStateMachine::DidAction(Action action) {
+ switch (action) {
+ case ACTION_NONE:
return;
case ACTION_COMMIT: {
bool commit_has_no_updates = false;
- UpdateStateOnCommit(commit_has_no_updates);
+ DidCommit(commit_has_no_updates);
return;
}
+ case ACTION_ACTIVATE_SYNC_TREE:
+ return;
+
+ case ACTION_ANIMATE:
+ return;
+
+ case ACTION_SEND_BEGIN_MAIN_FRAME:
+ return;
+
case ACTION_DRAW_AND_SWAP_FORCED:
case ACTION_DRAW_AND_SWAP_IF_POSSIBLE: {
bool did_request_swap = true;
- UpdateStateOnDraw(did_request_swap);
+ DidDraw(did_request_swap);
return;
}
case ACTION_DRAW_AND_SWAP_ABORT: {
bool did_request_swap = false;
- UpdateStateOnDraw(did_request_swap);
+ DidDraw(did_request_swap);
return;
}
case ACTION_BEGIN_OUTPUT_SURFACE_CREATION:
- UpdateStateOnBeginOutputSurfaceCreation();
return;
case ACTION_PREPARE_TILES:
- UpdateStateOnPrepareTiles();
+ DidPrepareTiles();
return;
case ACTION_INVALIDATE_OUTPUT_SURFACE:
- UpdateStateOnInvalidateOutputSurface();
return;
}
}
-void SchedulerStateMachine::UpdateStateOnAnimate() {
+void SchedulerStateMachine::WillAnimate() {
DCHECK(!animate_funnel_);
last_frame_number_animate_performed_ = current_frame_number_;
animate_funnel_ = true;
@@ -618,7 +679,7 @@ void SchedulerStateMachine::UpdateStateOnAnimate() {
SetNeedsRedraw();
}
-void SchedulerStateMachine::UpdateStateOnSendBeginMainFrame() {
+void SchedulerStateMachine::WillSendBeginMainFrame() {
DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled);
DCHECK(visible_);
DCHECK(!send_begin_main_frame_funnel_);
@@ -628,7 +689,13 @@ void SchedulerStateMachine::UpdateStateOnSendBeginMainFrame() {
last_frame_number_begin_main_frame_sent_ = current_frame_number_;
}
-void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
+void SchedulerStateMachine::WillCommit() {
+ // The commit may set this synchronously if the new pending tree is
+ // ready for activation immediately.
+ pending_tree_is_ready_for_activation_ = false;
+}
+
+void SchedulerStateMachine::DidCommit(bool commit_has_no_updates) {
commit_count_++;
// Animate after commit even if we've already animated.
@@ -649,13 +716,6 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
// mostly as if we are not impl-side-painting since there is no pending tree.
has_pending_tree_ = settings_.impl_side_painting && !commit_has_no_updates;
- // Update state related to forced draws.
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_COMMIT) {
- forced_redraw_state_ = has_pending_tree_
- ? FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION
- : FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
- }
-
// Update the output surface state.
DCHECK_NE(output_surface_state_, OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION);
if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) {
@@ -667,24 +727,19 @@ void SchedulerStateMachine::UpdateStateOnCommit(bool commit_has_no_updates) {
}
}
- // Update state if we have a new active tree to draw, or if the active tree
- // was unchanged but we need to do a forced draw.
- if (!has_pending_tree_ &&
- (!commit_has_no_updates ||
- forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)) {
+ // Update state if we have a new active tree to draw.
+ if (!has_pending_tree_) {
needs_redraw_ = true;
active_tree_needs_first_draw_ = true;
}
// This post-commit work is common to both completed and aborted commits.
- pending_tree_is_ready_for_activation_ = false;
-
if (continuous_painting_)
needs_commit_ = true;
last_commit_had_no_updates_ = commit_has_no_updates;
}
-void SchedulerStateMachine::UpdateStateOnActivation() {
+void SchedulerStateMachine::WillActivateSyncTree() {
if (commit_state_ == COMMIT_STATE_WAITING_FOR_ACTIVATION) {
commit_state_ = settings_.main_thread_should_always_be_low_latency
? COMMIT_STATE_WAITING_FOR_DRAW
@@ -694,19 +749,13 @@ void SchedulerStateMachine::UpdateStateOnActivation() {
if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION)
output_surface_state_ = OUTPUT_SURFACE_ACTIVE;
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_ACTIVATION)
- forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_DRAW;
-
has_pending_tree_ = false;
pending_tree_is_ready_for_activation_ = false;
active_tree_needs_first_draw_ = true;
needs_redraw_ = true;
}
-void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
- forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
-
+void SchedulerStateMachine::DidDraw(bool did_request_swap) {
if (commit_state_ == COMMIT_STATE_WAITING_FOR_DRAW)
commit_state_ = COMMIT_STATE_IDLE;
@@ -719,13 +768,68 @@ void SchedulerStateMachine::UpdateStateOnDraw(bool did_request_swap) {
did_request_swap_in_last_frame_ = true;
last_frame_number_swap_requested_ = current_frame_number_;
}
+
+ switch (last_draw_result_) {
+ case INVALID_RESULT:
+ NOTREACHED() << "Uninitialized DrawResult.";
+ break;
+
+ case DRAW_ABORTED_CANT_DRAW:
+ case DRAW_ABORTED_CONTEXT_LOST:
+ NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
+ << last_draw_result_;
+ break;
+
+ case DRAW_SUCCESS:
+ break;
+
+ case DRAW_ABORTED_MISSING_RASTER_OUTPUT_HIGH_RES:
+ case DRAW_ABORTED_MISSING_RASTER_OUTPUT_ANY_RES:
+ prepare_tiles_reason_ = PREPARE_TILES_NEEDED_FOR_ABORTED_DRAW;
+ if (prepare_tiles_approach_ ==
+ PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY) {
+ prepare_tiles_approach_ = PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK;
+ }
+ retry_begin_impl_frame_deadline_ = true;
+ needs_redraw_ = true;
+ break;
+
+ case DRAW_ABORTED_MISSING_RASTER_SOURCE:
+ prepare_tiles_reason_ = PREPARE_TILES_NEEDED_FOR_ABORTED_DRAW;
+ if (prepare_tiles_approach_ ==
+ PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY) {
+ prepare_tiles_approach_ = PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK;
+ }
+
+ if (CommitPending() || has_pending_tree_) {
+ // The new active tree in flight might have an updated raster source,
+ // so wait and see.
+ retry_begin_impl_frame_deadline_ = true;
+ } else {
+ // We need a new active tree to get an updated raster source.
+ needs_commit_ = true;
+ retry_begin_impl_frame_ = true;
+ }
+
+ // This is one of the few cases where we actively avoid drawing a commit.
+ // Skipping draw of the commit can be better than a flash of checkerboard.
+ active_tree_needs_first_draw_ = false;
+ break;
+ }
}
-void SchedulerStateMachine::UpdateStateOnPrepareTiles() {
- needs_prepare_tiles_ = false;
+void SchedulerStateMachine::DidPrepareTiles() {
+ prepare_tiles_reason_ = PREPARE_TILES_NOT_NEEDED;
+
+ active_tree_ready_to_draw_ = false;
+
+ if (prepare_tiles_approach_ == PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY)
+ prepare_tiles_funnel_++;
+ else
+ prepare_tiles_funnel_ = 0;
}
-void SchedulerStateMachine::UpdateStateOnBeginOutputSurfaceCreation() {
+void SchedulerStateMachine::WillBeginOutputSurfaceCreation() {
DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_LOST);
output_surface_state_ = OUTPUT_SURFACE_CREATING;
@@ -737,7 +841,7 @@ void SchedulerStateMachine::UpdateStateOnBeginOutputSurfaceCreation() {
DCHECK(!active_tree_needs_first_draw_);
}
-void SchedulerStateMachine::UpdateStateOnInvalidateOutputSurface() {
+void SchedulerStateMachine::WillInvalidateOutputSurface() {
DCHECK(!invalidate_output_surface_funnel_);
invalidate_output_surface_funnel_ = true;
last_frame_number_invalidate_output_surface_performed_ =
@@ -787,6 +891,13 @@ void SchedulerStateMachine::SetVideoNeedsBeginFrames(
video_needs_begin_frames_ = video_needs_begin_frames;
}
+void SchedulerStateMachine::NotifyBeginFrameSourceActive(bool active) {
+ // Upon becoming inactive, switch back to prioritizing latency.
+ if (!active &&
+ prepare_tiles_approach_ == PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK)
+ prepare_tiles_approach_ = PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY;
+}
+
void SchedulerStateMachine::SetDeferCommits(bool defer_commits) {
defer_commits_ = defer_commits;
}
@@ -794,11 +905,6 @@ void SchedulerStateMachine::SetDeferCommits(bool defer_commits) {
// These are the cases where we require a BeginFrame message to make progress
// on requested actions.
bool SchedulerStateMachine::BeginFrameRequiredForAction() const {
- // The forced draw respects our normal draw scheduling, so we need to
- // request a BeginImplFrame for it.
- if (forced_redraw_state_ == FORCED_REDRAW_STATE_WAITING_FOR_DRAW)
- return true;
-
return needs_animate_ || needs_redraw_ || (needs_commit_ && !defer_commits_);
}
@@ -828,7 +934,7 @@ bool SchedulerStateMachine::ProactiveBeginFrameWanted() const {
// Changing priorities may allow us to activate (given the new priorities),
// which may result in a new frame.
- if (needs_prepare_tiles_)
+ if (PrepareTilesPending())
return true;
// If we just sent a swap request, it's likely that we are going to produce
@@ -851,6 +957,9 @@ void SchedulerStateMachine::OnBeginImplFrame() {
begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
current_frame_number_++;
+ retry_begin_impl_frame_ = false;
+ retry_begin_impl_frame_deadline_ = false;
+
last_commit_had_no_updates_ = false;
did_request_swap_in_last_frame_ = false;
@@ -863,6 +972,15 @@ void SchedulerStateMachine::OnBeginImplFrame() {
if (prepare_tiles_funnel_ > 0)
prepare_tiles_funnel_--;
+ // PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK doesn't work well in
+ // main thread low-latency mode. Transition back to
+ // PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY if we just recovered
+ // main-thread latency.
+ if (skip_begin_main_frame_to_reduce_latency_ &&
+ prepare_tiles_approach_ == PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK) {
+ prepare_tiles_approach_ = PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY;
+ }
+
skip_begin_main_frame_to_reduce_latency_ =
skip_next_begin_main_frame_to_reduce_latency_;
skip_next_begin_main_frame_to_reduce_latency_ = false;
@@ -896,17 +1014,23 @@ SchedulerStateMachine::CurrentBeginImplFrameDeadlineMode() const {
return BEGIN_IMPL_FRAME_DEADLINE_MODE_BLOCKED_ON_READY_TO_DRAW;
} else if (ShouldTriggerBeginImplFrameDeadlineImmediately()) {
return BEGIN_IMPL_FRAME_DEADLINE_MODE_IMMEDIATE;
- } else if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) {
- // We have an animation or fast input path on the impl thread that wants
- // to draw, so don't wait too long for a new active tree.
- // If we are swap throttled we should wait until we are unblocked.
- return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR;
- } else {
- // The impl thread doesn't have anything it wants to draw and we are just
- // waiting for a new active tree or we are swap throttled. In short we are
- // blocked.
- return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE;
}
+
+ if (prepare_tiles_approach_ == PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY) {
+ if (needs_redraw_ && pending_swaps_ < max_pending_swaps_) {
+ // We have an animation or fast input path on the impl thread that wants
+ // to draw, so don't wait too long for a new active tree.
+ // If we are swap throttled we should wait until we are unblocked.
+ return BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR;
+ } else {
+ // The impl thread doesn't have anything it wants to draw and we are just
+ // waiting for a new active tree or we are swap throttled. In short we are
+ // blocked.
+ return BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE;
+ }
+ }
+
+ return BEGIN_IMPL_FRAME_DEADLINE_MODE_TRY_TO_AVOID_CHECKERBOARD;
}
bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
@@ -923,6 +1047,11 @@ bool SchedulerStateMachine::ShouldTriggerBeginImplFrameDeadlineImmediately()
if (pending_swaps_ >= max_pending_swaps_)
return false;
+ // PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY is the only approach
+ // where we want to trigger the deadline before NotifyReadyToDraw.
+ if (prepare_tiles_approach_ != PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY)
+ return active_tree_ready_to_draw_;
+
if (active_tree_needs_first_draw_)
return true;
@@ -985,7 +1114,11 @@ bool SchedulerStateMachine::MainThreadIsInHighLatencyMode() const {
return active_tree_needs_first_draw_;
}
-void SchedulerStateMachine::SetVisible(bool visible) { visible_ = visible; }
+void SchedulerStateMachine::SetVisible(bool visible) {
+ visible_ = visible;
+ if (!visible)
+ prepare_tiles_reason_ = PREPARE_TILES_NEEDED_TO_EVICT_TILES;
+}
void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; }
@@ -1000,10 +1133,22 @@ void SchedulerStateMachine::SetWaitForReadyToDraw() {
wait_for_active_tree_ready_to_draw_ = true;
}
-void SchedulerStateMachine::SetNeedsPrepareTiles() {
- if (!needs_prepare_tiles_) {
- TRACE_EVENT0("cc", "SchedulerStateMachine::SetNeedsPrepareTiles");
- needs_prepare_tiles_ = true;
+void SchedulerStateMachine::SetNeedsPrepareTiles(bool for_commit) {
+ TRACE_EVENT0("cc", "SchedulerStateMachine::SetNeedsPrepareTiles");
+ switch (prepare_tiles_approach_) {
+ case PREPARE_TILES_APPROACH_PRIORITIZE_LATENCY:
+ if (for_commit)
+ prepare_tiles_reason_ = PREPARE_TILES_NEEDED_FOR_COMMIT;
+ else if (prepare_tiles_reason_ == PREPARE_TILES_NOT_NEEDED)
+ prepare_tiles_reason_ = PREPARE_TILES_REQUESTED;
+ break;
+
+ case PREPARE_TILES_APPROACH_ACCURATE_ACTIVE_WORK:
+ // We don't uncondititionally PrepareTiles immediately after a commit with
+ // this approach.
+ if (prepare_tiles_reason_ == PREPARE_TILES_NOT_NEEDED)
+ prepare_tiles_reason_ = PREPARE_TILES_REQUESTED;
+ break;
}
}
@@ -1029,47 +1174,8 @@ void SchedulerStateMachine::SetImplLatencyTakesPriority(
impl_latency_takes_priority_ = impl_latency_takes_priority;
}
-void SchedulerStateMachine::DidDrawIfPossibleCompleted(DrawResult result) {
- switch (result) {
- case INVALID_RESULT:
- NOTREACHED() << "Uninitialized DrawResult.";
- break;
- case DRAW_ABORTED_CANT_DRAW:
- case DRAW_ABORTED_CONTEXT_LOST:
- NOTREACHED() << "Invalid return value from DrawAndSwapIfPossible:"
- << result;
- break;
- case DRAW_SUCCESS:
- consecutive_checkerboard_animations_ = 0;
- forced_redraw_state_ = FORCED_REDRAW_STATE_IDLE;
- break;
- case DRAW_ABORTED_CHECKERBOARD_ANIMATIONS:
- needs_redraw_ = true;
-
- // If we're already in the middle of a redraw, we don't need to
- // restart it.
- if (forced_redraw_state_ != FORCED_REDRAW_STATE_IDLE)
- return;
-
- needs_commit_ = true;
- consecutive_checkerboard_animations_++;
- if (settings_.timeout_and_draw_when_animation_checkerboards &&
- consecutive_checkerboard_animations_ >=
- settings_.maximum_number_of_failed_draws_before_draw_is_forced_) {
- consecutive_checkerboard_animations_ = 0;
- // We need to force a draw, but it doesn't make sense to do this until
- // we've committed and have new textures.
- forced_redraw_state_ = FORCED_REDRAW_STATE_WAITING_FOR_COMMIT;
- }
- break;
- case DRAW_ABORTED_MISSING_HIGH_RES_CONTENT:
- // It's not clear whether this missing content is because of missing
- // pictures (which requires a commit) or because of memory pressure
- // removing textures (which might not). To be safe, request a commit
- // anyway.
- needs_commit_ = true;
- break;
- }
+void SchedulerStateMachine::SetDrawResult(DrawResult result) {
+ last_draw_result_ = result;
}
void SchedulerStateMachine::SetNeedsCommit() {
@@ -1098,17 +1204,11 @@ void SchedulerStateMachine::BeginMainFrameAborted(CommitEarlyOutReason reason) {
return;
case CommitEarlyOutReason::FINISHED_NO_UPDATES:
bool commit_has_no_updates = true;
- UpdateStateOnCommit(commit_has_no_updates);
+ DidCommit(commit_has_no_updates);
return;
}
}
-void SchedulerStateMachine::DidPrepareTiles() {
- needs_prepare_tiles_ = false;
- // "Fill" the PrepareTiles funnel.
- prepare_tiles_funnel_++;
-}
-
void SchedulerStateMachine::DidLoseOutputSurface() {
if (output_surface_state_ == OUTPUT_SURFACE_LOST ||
output_surface_state_ == OUTPUT_SURFACE_CREATING)
@@ -1119,12 +1219,18 @@ void SchedulerStateMachine::DidLoseOutputSurface() {
}
void SchedulerStateMachine::NotifyReadyToActivate() {
- if (has_pending_tree_)
- pending_tree_is_ready_for_activation_ = true;
+ pending_tree_is_ready_for_activation_ = true;
}
void SchedulerStateMachine::NotifyReadyToDraw() {
wait_for_active_tree_ready_to_draw_ = false;
+ active_tree_ready_to_draw_ = true;
+}
+
+void SchedulerStateMachine::SetRequiresHighResToDraw(bool required) {
+ if (requires_high_res_to_draw_ == required)
+ return;
+ requires_high_res_to_draw_ = required;
}
void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() {
« no previous file with comments | « cc/scheduler/scheduler_state_machine.h ('k') | cc/test/fake_layer_tree_host_impl_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698