diff options
author | brianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-24 03:16:05 +0000 |
---|---|---|
committer | brianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-24 03:16:05 +0000 |
commit | 4093a6adf9c1dfbd0b157b0e2aec6daa4cbccb80 (patch) | |
tree | 354dc1cd7ade4a73cc3c00dd83687ad8bb5b737b | |
parent | 9557e919576c6e2229bbd0b015e618e1ce9c8fbe (diff) | |
download | chromium_src-4093a6adf9c1dfbd0b157b0e2aec6daa4cbccb80.zip chromium_src-4093a6adf9c1dfbd0b157b0e2aec6daa4cbccb80.tar.gz chromium_src-4093a6adf9c1dfbd0b157b0e2aec6daa4cbccb80.tar.bz2 |
cc: Add additional OutputSurfaceStates
This prevents us from drawing until after the activation
of the first commit after output surface initialization.
Some cleanup regarding ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD
is included in this patch since that logic is being touched
anyway.
BUG=276079
Review URL: https://chromiumcodereview.appspot.com/22831017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219407 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/scheduler/scheduler_state_machine.cc | 172 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine.h | 23 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine_unittest.cc | 93 | ||||
-rw-r--r-- | cc/scheduler/scheduler_unittest.cc | 86 |
4 files changed, 240 insertions, 134 deletions
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index 5108a11..4bba045 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc @@ -13,6 +13,7 @@ namespace cc { SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) : settings_(settings), + output_surface_state_(OUTPUT_SURFACE_LOST), commit_state_(COMMIT_STATE_IDLE), commit_count_(0), current_frame_number_(0), @@ -26,7 +27,6 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) swap_used_incomplete_tile_(false), needs_forced_redraw_(false), needs_forced_redraw_after_next_commit_(false), - needs_redraw_after_next_commit_(false), needs_commit_(false), needs_forced_commit_(false), expect_immediate_begin_frame_for_main_thread_(false), @@ -38,9 +38,26 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) has_pending_tree_(false), draw_if_possible_failed_(false), texture_state_(LAYER_TEXTURE_STATE_UNLOCKED), - output_surface_state_(OUTPUT_SURFACE_LOST), did_create_and_initialize_first_output_surface_(false) {} +const char* SchedulerStateMachine::OutputSurfaceStateToString( + OutputSurfaceState state) { + switch (state) { + case OUTPUT_SURFACE_ACTIVE: + return "OUTPUT_SURFACE_ACTIVE"; + case OUTPUT_SURFACE_LOST: + return "OUTPUT_SURFACE_LOST"; + case OUTPUT_SURFACE_CREATING: + return "OUTPUT_SURFACE_CREATING"; + case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: + return "OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT"; + case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: + return "OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION"; + } + NOTREACHED(); + return "???"; +} + const char* SchedulerStateMachine::CommitStateToString(CommitState state) { switch (state) { case COMMIT_STATE_IDLE: @@ -71,20 +88,6 @@ const char* SchedulerStateMachine::TextureStateToString(TextureState state) { return "???"; } -const char* SchedulerStateMachine::OutputSurfaceStateToString( - OutputSurfaceState state) { - switch (state) { - case OUTPUT_SURFACE_ACTIVE: - return "OUTPUT_SURFACE_ACTIVE"; - case OUTPUT_SURFACE_LOST: - return "OUTPUT_SURFACE_LOST"; - case OUTPUT_SURFACE_CREATING: - return "OUTPUT_SURFACE_CREATING"; - } - NOTREACHED(); - return "???"; -} - const char* SchedulerStateMachine::ActionToString(Action action) { switch (action) { case ACTION_NONE: @@ -175,8 +178,6 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { minor_state->SetBoolean("needs_forced_redraw", needs_forced_redraw_); minor_state->SetBoolean("needs_forced_redraw_after_next_commit", needs_forced_redraw_after_next_commit_); - minor_state->SetBoolean("needs_redraw_after_next_commit", - needs_redraw_after_next_commit_); minor_state->SetBoolean("needs_commit", needs_commit_); minor_state->SetBoolean("needs_forced_commit", needs_forced_commit_); minor_state->SetBoolean("expect_immediate_begin_frame_for_main_thread", @@ -210,19 +211,46 @@ bool SchedulerStateMachine::HasUpdatedVisibleTilesThisFrame() const { last_frame_number_where_update_visible_tiles_was_called_; } +bool SchedulerStateMachine::HasSentBeginFrameToMainThreadThisFrame() const { + return current_frame_number_ == + last_frame_number_where_begin_frame_sent_to_main_thread_; +} + void SchedulerStateMachine::HandleCommitInternal(bool commit_was_aborted) { commit_count_++; - if (commit_was_aborted) { - commit_state_ = COMMIT_STATE_IDLE; - } else if (expect_immediate_begin_frame_for_main_thread_) { + // 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. + bool commit_results_in_pending_tree = + settings_.impl_side_painting && !commit_was_aborted; + + // Update the commit state. + if (expect_immediate_begin_frame_for_main_thread_) commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_FORCED_DRAW; - } else { + else if (!commit_was_aborted) commit_state_ = COMMIT_STATE_WAITING_FOR_FIRST_DRAW; + else + commit_state_ = COMMIT_STATE_IDLE; + + // 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) { + if (commit_results_in_pending_tree) { + output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION; + } else { + output_surface_state_ = OUTPUT_SURFACE_ACTIVE; + needs_redraw_ = true; + } } - if (!settings_.impl_side_painting && !commit_was_aborted) - needs_redraw_ = true; + // if we don't have to wait for activation, update needs_redraw now. + if (!commit_results_in_pending_tree) { + if (!commit_was_aborted) + needs_redraw_ = true; + if (expect_immediate_begin_frame_for_main_thread_) + needs_redraw_ = true; + } // This post-commit work is common to both completed and aborted commits. if (draw_if_possible_failed_) @@ -232,14 +260,10 @@ void SchedulerStateMachine::HandleCommitInternal(bool commit_was_aborted) { needs_forced_redraw_after_next_commit_ = false; needs_forced_redraw_ = true; } - if (needs_redraw_after_next_commit_) { - needs_redraw_after_next_commit_ = false; - needs_redraw_ = true; - } // If we are planing to draw with the new commit, lock the layer textures for // use on the impl thread. Otherwise, leave them unlocked. - if (!commit_was_aborted || needs_redraw_ || needs_forced_redraw_) + if (commit_results_in_pending_tree || needs_redraw_ || needs_forced_redraw_) texture_state_ = LAYER_TEXTURE_STATE_ACQUIRED_BY_IMPL_THREAD; else texture_state_ = LAYER_TEXTURE_STATE_UNLOCKED; @@ -299,6 +323,42 @@ bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { swap_used_incomplete_tile_; } +bool SchedulerStateMachine::ShouldSendBeginFrameToMainThread() const { + if (!needs_commit_) + return false; + + // Only send BeginFrame to the main thread when idle. + if (commit_state_ != COMMIT_STATE_IDLE) + return false; + + // We can't accept a commit if we have a pending tree. + if (has_pending_tree_) + return false; + + // We want to start the first commit after we get a new output surface ASAP. + if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) + return true; + + // We want to start forced commits ASAP. + if (needs_forced_commit_) + return true; + + // After this point, we only start a commit once per frame. + if (HasSentBeginFrameToMainThreadThisFrame()) + return false; + + // We do not need commits if we are not visible, unless there's a + // request for a forced commit. + if (!visible_) + return false; + + // We shouldn't normally accept commits if there isn't an OutputSurface. + if (!HasInitializedOutputSurface()) + return false; + + return true; +} + bool SchedulerStateMachine::ShouldAcquireLayerTexturesForMainThread() const { if (!main_thread_needs_layer_textures_) return false; @@ -334,16 +394,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { return needs_forced_redraw_ ? ACTION_DRAW_FORCED : ACTION_DRAW_IF_POSSIBLE; } - bool can_commit_this_frame = - visible_ && - current_frame_number_ > - last_frame_number_where_begin_frame_sent_to_main_thread_; - if (needs_commit_ && ((can_commit_this_frame && - output_surface_state_ == OUTPUT_SURFACE_ACTIVE) || - needs_forced_commit_)) - // TODO(enne): Should probably drop the active tree on force commit. - 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; } case COMMIT_STATE_FRAME_IN_PROGRESS: @@ -406,7 +458,8 @@ void SchedulerStateMachine::UpdateState(Action action) { case ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD: DCHECK(!has_pending_tree_); - if (!needs_forced_commit_) { + if (!needs_forced_commit_ && + output_surface_state_ != OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT) { DCHECK(visible_); DCHECK_GT(current_frame_number_, last_frame_number_where_begin_frame_sent_to_main_thread_); @@ -478,6 +531,14 @@ void SchedulerStateMachine::SetMainThreadNeedsLayerTextures() { } bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { + // TODO(brianderson): Remove this hack once the Scheduler controls activation, + // otherwise we can get stuck in OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION. + // It lies that we actually need to draw, but we won't actually draw + // if we can't. This will cause WebView to potentially have corruption + // in the first few frames, but this workaround is being removed soon. + if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION) + return true; + // If we can't draw, don't tick until we are notified that we can draw again. if (!can_draw_) return false; @@ -488,8 +549,7 @@ bool SchedulerStateMachine::BeginFrameNeededToDrawByImplThread() const { if (visible_ && swap_used_incomplete_tile_) return true; - return needs_redraw_ && visible_ && - output_surface_state_ == OUTPUT_SURFACE_ACTIVE; + return needs_redraw_ && visible_ && HasInitializedOutputSurface(); } bool SchedulerStateMachine::ProactiveBeginFrameWantedByImplThread() const { @@ -577,9 +637,17 @@ void SchedulerStateMachine::DidLoseOutputSurface() { output_surface_state_ == OUTPUT_SURFACE_CREATING) return; output_surface_state_ = OUTPUT_SURFACE_LOST; + needs_redraw_ = false; } void SchedulerStateMachine::SetHasPendingTree(bool has_pending_tree) { + if (has_pending_tree_ && !has_pending_tree) { + // There is a new active tree. + if (output_surface_state_ == OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION) + output_surface_state_ = OUTPUT_SURFACE_ACTIVE; + + needs_redraw_ = true; + } has_pending_tree_ = has_pending_tree; } @@ -587,23 +655,29 @@ void SchedulerStateMachine::SetCanDraw(bool can) { can_draw_ = can; } void SchedulerStateMachine::DidCreateAndInitializeOutputSurface() { DCHECK_EQ(output_surface_state_, OUTPUT_SURFACE_CREATING); - output_surface_state_ = OUTPUT_SURFACE_ACTIVE; + output_surface_state_ = OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT; if (did_create_and_initialize_first_output_surface_) { // TODO(boliu): See if we can remove this when impl-side painting is always // on. Does anything on the main thread need to update after recreate? needs_commit_ = true; - // If anything has requested a redraw, we don't want to actually draw - // when the output surface is restored until things have a chance to - // sort themselves out with a commit. - needs_redraw_ = false; } - needs_redraw_after_next_commit_ = true; did_create_and_initialize_first_output_surface_ = true; } bool SchedulerStateMachine::HasInitializedOutputSurface() const { - return output_surface_state_ == OUTPUT_SURFACE_ACTIVE; + switch (output_surface_state_) { + case OUTPUT_SURFACE_LOST: + case OUTPUT_SURFACE_CREATING: + return false; + + case OUTPUT_SURFACE_ACTIVE: + case OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT: + case OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION: + return true; + } + NOTREACHED(); + return false; } void SchedulerStateMachine::SetMaximumNumberOfFailedDrawsBeforeDrawIsForced( diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h index eeae995..101b36d 100644 --- a/cc/scheduler/scheduler_state_machine.h +++ b/cc/scheduler/scheduler_state_machine.h @@ -36,6 +36,15 @@ class CC_EXPORT SchedulerStateMachine { // settings must be valid for the lifetime of this class. explicit SchedulerStateMachine(const SchedulerSettings& settings); + enum OutputSurfaceState { + OUTPUT_SURFACE_ACTIVE, + OUTPUT_SURFACE_LOST, + OUTPUT_SURFACE_CREATING, + OUTPUT_SURFACE_WAITING_FOR_FIRST_COMMIT, + OUTPUT_SURFACE_WAITING_FOR_FIRST_ACTIVATION, + }; + static const char* OutputSurfaceStateToString(OutputSurfaceState state); + enum CommitState { COMMIT_STATE_IDLE, COMMIT_STATE_FRAME_IN_PROGRESS, @@ -52,13 +61,6 @@ class CC_EXPORT SchedulerStateMachine { }; static const char* TextureStateToString(TextureState state); - enum OutputSurfaceState { - OUTPUT_SURFACE_ACTIVE, - OUTPUT_SURFACE_LOST, - OUTPUT_SURFACE_CREATING, - }; - static const char* OutputSurfaceStateToString(OutputSurfaceState state); - bool CommitPending() const { return commit_state_ == COMMIT_STATE_FRAME_IN_PROGRESS || commit_state_ == COMMIT_STATE_READY_TO_COMMIT; @@ -175,19 +177,22 @@ class CC_EXPORT SchedulerStateMachine { bool ShouldAttemptTreeActivation() const; bool ShouldAcquireLayerTexturesForMainThread() const; bool ShouldUpdateVisibleTiles() const; + bool ShouldSendBeginFrameToMainThread() const; bool HasDrawnThisFrame() const; bool HasAttemptedTreeActivationThisFrame() const; bool HasUpdatedVisibleTilesThisFrame() const; + bool HasSentBeginFrameToMainThreadThisFrame() const; void HandleCommitInternal(bool commit_was_aborted); void UpdateStateOnDraw(bool did_swap); const SchedulerSettings settings_; + OutputSurfaceState output_surface_state_; CommitState commit_state_; - int commit_count_; + int commit_count_; int current_frame_number_; int last_frame_number_where_begin_frame_sent_to_main_thread_; int last_frame_number_where_draw_was_called_; @@ -199,7 +204,6 @@ class CC_EXPORT SchedulerStateMachine { bool swap_used_incomplete_tile_; bool needs_forced_redraw_; bool needs_forced_redraw_after_next_commit_; - bool needs_redraw_after_next_commit_; bool needs_commit_; bool needs_forced_commit_; bool expect_immediate_begin_frame_for_main_thread_; @@ -212,7 +216,6 @@ class CC_EXPORT SchedulerStateMachine { bool has_pending_tree_; bool draw_if_possible_failed_; TextureState texture_state_; - OutputSurfaceState output_surface_state_; bool did_create_and_initialize_first_output_surface_; private: diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index c9454ce..32fdd08 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc @@ -23,6 +23,12 @@ class StateMachine : public SchedulerStateMachine { public: explicit StateMachine(const SchedulerSettings& scheduler_settings) : SchedulerStateMachine(scheduler_settings) {} + + void CreateAndInitializeOutputSurfaceWithActivatedCommit() { + DidCreateAndInitializeOutputSurface(); + output_surface_state_ = OUTPUT_SURFACE_ACTIVE; + } + void SetCommitState(CommitState cs) { commit_state_ = cs; } CommitState CommitState() const { return commit_state_; } @@ -46,7 +52,7 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE); state.SetNeedsRedraw(false); state.SetVisible(true); @@ -91,7 +97,7 @@ TEST(SchedulerStateMachineTest, TestNextActionBeginsMainFrameIfNeeded) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.UpdateState( SchedulerStateMachine::ACTION_SEND_BEGIN_FRAME_TO_MAIN_THREAD); @@ -114,13 +120,13 @@ TEST(SchedulerStateMachineTest, TestSetForcedRedrawDoesNotSetsNormalRedraw) { TEST(SchedulerStateMachineTest, TestFailedDrawSetsNeedsCommitAndDoesNotDrawAgain) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); @@ -145,14 +151,14 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); @@ -166,7 +172,7 @@ TEST(SchedulerStateMachineTest, // While still in the same begin frame callback on the main thread, // set needs redraw again. This should not redraw. - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); // Failing the draw makes us require a commit. @@ -179,10 +185,10 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestCommitAfterFailedDrawAllowsDrawInSameFrame) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -195,7 +201,7 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.CommitPending()); // Then initiate a draw. - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()); @@ -222,10 +228,10 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestCommitAfterFailedAndSuccessfulDrawDoesNotAllowDrawInSameFrame) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -238,7 +244,7 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.CommitPending()); // Then initiate a draw. - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()); @@ -253,7 +259,7 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.CommitPending()); // Force a draw. - state.SetNeedsForcedRedraw(); + state.SetNeedsForcedRedraw(true); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_FORCED, state.NextAction()); // Do the forced draw. @@ -276,10 +282,10 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestFailedDrawsWillEventuallyForceADrawAfterTheNextCommit) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); state.SetMaximumNumberOfFailedDrawsBeforeDrawIsForced(1); @@ -293,7 +299,7 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.CommitPending()); // Then initiate a draw. - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()); @@ -321,15 +327,15 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginFrameForImplThread) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); // Start a draw. - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()); @@ -355,13 +361,13 @@ TEST(SchedulerStateMachineTest, TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_TRUE(state.BeginFrameNeededToDrawByImplThread()); state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()); @@ -369,7 +375,7 @@ TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) { // While still in the same begin frame for the impl thread, set needs redraw // again. This should not redraw. - state.SetNeedsRedraw(); + state.SetNeedsRedraw(true); EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); // Move to another frame. This should now draw. @@ -396,7 +402,7 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCommitState(all_commit_states[i]); bool visible = j; if (!visible) { @@ -425,7 +431,7 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginFrame) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCanDraw(true); state.SetCommitState(all_commit_states[i]); bool forced_draw = j; @@ -470,7 +476,7 @@ TEST(SchedulerStateMachineTest, TestNoCommitStatesRedrawWhenInvisible) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCommitState(all_commit_states[i]); state.SetVisible(false); state.SetNeedsRedraw(true); @@ -501,7 +507,7 @@ TEST(SchedulerStateMachineTest, TestCanRedraw_StopsDraw) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCommitState(all_commit_states[i]); state.SetVisible(false); state.SetNeedsRedraw(true); @@ -522,7 +528,7 @@ TEST(SchedulerStateMachineTest, StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCommitState( SchedulerStateMachine::COMMIT_STATE_WAITING_FOR_FIRST_DRAW); state.SetNeedsCommit(); @@ -541,7 +547,7 @@ TEST(SchedulerStateMachineTest, TestsetNeedsCommitIsNotLost) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetNeedsCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -587,7 +593,7 @@ TEST(SchedulerStateMachineTest, TestFullCycle) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -637,7 +643,7 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -692,7 +698,7 @@ TEST(SchedulerStateMachineTest, TestRequestCommitInvisible) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetNeedsCommit(); EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction()); } @@ -702,7 +708,7 @@ TEST(SchedulerStateMachineTest, TestGoesInvisibleBeforeFinishCommit) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -781,7 +787,8 @@ TEST(SchedulerStateMachineTest, AbortBeginFrameAndCancelCommit) { // Start a new frame; draw because this is the first frame since output // surface init'd. state.DidEnterBeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()); + EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE, state.NextAction()) + << *state.AsValue(); state.DidLeaveBeginFrame(); // Verify another commit doesn't start on another frame either. @@ -902,7 +909,7 @@ TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) { StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -955,7 +962,7 @@ TEST(SchedulerStateMachineTest, StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetVisible(true); state.SetCanDraw(true); @@ -1306,10 +1313,10 @@ TEST(SchedulerStateMachineTest, ImmediateFinishCommitWhileCantDraw) { TEST(SchedulerStateMachineTest, ReportIfNotDrawing) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCanDraw(true); state.SetVisible(true); @@ -1334,10 +1341,10 @@ TEST(SchedulerStateMachineTest, ReportIfNotDrawing) { TEST(SchedulerStateMachineTest, ReportIfNotDrawingFromAcquiredTextures) { SchedulerSettings default_scheduler_settings; - SchedulerStateMachine state(default_scheduler_settings); + StateMachine state(default_scheduler_settings); state.SetCanStart(); state.UpdateState(state.NextAction()); - state.DidCreateAndInitializeOutputSurface(); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); state.SetCanDraw(true); state.SetVisible(true); EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 0c60131..b419fa7 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc @@ -29,6 +29,17 @@ namespace cc { namespace { +void InitializeOutputSurfaceAndFirstCommit(Scheduler* scheduler) { + scheduler->DidCreateAndInitializeOutputSurface(); + scheduler->SetNeedsCommit(); + scheduler->FinishCommit(); + // Go through the motions to draw the commit. + scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); + // We need another BeginFrame so scheduler calls SetNeedsBeginFrame(false). + scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); + scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); +} + class FakeSchedulerClient : public SchedulerClient { public: FakeSchedulerClient() @@ -159,10 +170,10 @@ TEST(SchedulerTest, RequestCommit) { scheduler->SetCanDraw(true); EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); - client.Reset(); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); // SetNeedsCommit should begin the frame. + client.Reset(); scheduler->SetNeedsCommit(); EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 2); EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2); @@ -171,8 +182,7 @@ TEST(SchedulerTest, RequestCommit) { // FinishCommit should commit scheduler->FinishCommit(); - EXPECT_ACTION("ScheduledActionCommit", client, 0, 2); - EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2); + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); EXPECT_TRUE(client.needs_begin_frame()); client.Reset(); @@ -193,8 +203,8 @@ TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) { scheduler->SetCanDraw(true); EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); + InitializeOutputSurfaceAndFirstCommit(scheduler); client.Reset(); - scheduler->DidCreateAndInitializeOutputSurface(); // SetNedsCommit should begin the frame. scheduler->SetNeedsCommit(); @@ -204,24 +214,21 @@ TEST(SchedulerTest, RequestCommitAfterBeginFrameSentToMainThread) { // Now SetNeedsCommit again. Calling here means we need a second frame. scheduler->SetNeedsCommit(); - EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 0, 1); - client.Reset(); - // Since another commit is needed, FinishCommit should commit, - // then begin another frame. + // Finish the commit for the first frame. scheduler->FinishCommit(); - EXPECT_ACTION("ScheduledActionCommit", client, 0, 2); - EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 2); + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client); client.Reset(); - // Tick should draw but then begin another frame. + // Tick should draw but then begin another frame for the second commit. scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_TRUE(client.needs_begin_frame()); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 1, 2); client.Reset(); - // Go back to quiescent state and verify we no longer request BeginFrames. + // Finish the second commit to go back to quiescent state and verify we no + // longer request BeginFrames. scheduler->FinishCommit(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_FALSE(client.needs_begin_frame()); @@ -236,8 +243,8 @@ TEST(SchedulerTest, TextureAcquisitionCausesCommitInsteadOfDraw) { scheduler->SetCanDraw(true); EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); + InitializeOutputSurfaceAndFirstCommit(scheduler); client.Reset(); - scheduler->DidCreateAndInitializeOutputSurface(); scheduler->SetNeedsRedraw(); EXPECT_TRUE(scheduler->RedrawPending()); EXPECT_SINGLE_ACTION("SetNeedsBeginFrameOnImplThread", client); @@ -300,18 +307,15 @@ TEST(SchedulerTest, TextureAcquisitionCollision) { scheduler->SetCanDraw(true); EXPECT_SINGLE_ACTION("ScheduledActionBeginOutputSurfaceCreation", client); - client.Reset(); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); + client.Reset(); scheduler->SetNeedsCommit(); scheduler->SetMainThreadNeedsLayerTextures(); - EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 4); - EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 4); - EXPECT_ACTION("ScheduledActionAcquireLayerTexturesForMainThread", - client, - 2, - 4); - EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 3, 4); + EXPECT_ACTION("ScheduledActionSendBeginFrameToMainThread", client, 0, 3); + EXPECT_ACTION("SetNeedsBeginFrameOnImplThread", client, 1, 3); + EXPECT_ACTION( + "ScheduledActionAcquireLayerTexturesForMainThread", client, 2, 3); client.Reset(); // Although the compositor cannot draw because textures are locked by main @@ -425,7 +429,8 @@ TEST(SchedulerTest, RequestRedrawInsideDraw) { scheduler->SetCanStart(); scheduler->SetVisible(true); scheduler->SetCanDraw(true); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); + client.Reset(); scheduler->SetNeedsRedraw(); EXPECT_TRUE(scheduler->RedrawPending()); @@ -451,7 +456,8 @@ TEST(SchedulerTest, RequestRedrawInsideFailedDraw) { scheduler->SetCanStart(); scheduler->SetVisible(true); scheduler->SetCanDraw(true); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); + client.Reset(); client.SetDrawWillHappen(false); @@ -486,14 +492,19 @@ TEST(SchedulerTest, RequestRedrawInsideFailedDraw) { EXPECT_TRUE(client.needs_begin_frame()); } -class SchedulerClientThatsetNeedsCommitInsideDraw : public FakeSchedulerClient { +class SchedulerClientThatSetNeedsCommitInsideDraw : public FakeSchedulerClient { public: + SchedulerClientThatSetNeedsCommitInsideDraw() + : set_needs_commit_on_next_draw_(false) {} + virtual void ScheduledActionSendBeginFrameToMainThread() OVERRIDE {} virtual ScheduledActionDrawAndSwapResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE { // Only SetNeedsCommit the first time this is called - if (!num_draws_) + if (set_needs_commit_on_next_draw_) { scheduler_->SetNeedsCommit(); + set_needs_commit_on_next_draw_ = false; + } return FakeSchedulerClient::ScheduledActionDrawAndSwapIfPossible(); } @@ -506,24 +517,31 @@ class SchedulerClientThatsetNeedsCommitInsideDraw : public FakeSchedulerClient { virtual void ScheduledActionCommit() OVERRIDE {} virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {} virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {} + + void SetNeedsCommitOnNextDraw() { set_needs_commit_on_next_draw_ = true; } + + private: + bool set_needs_commit_on_next_draw_; }; // Tests for the scheduler infinite-looping on SetNeedsCommit requests that // happen inside a ScheduledActionDrawAndSwap TEST(SchedulerTest, RequestCommitInsideDraw) { - SchedulerClientThatsetNeedsCommitInsideDraw client; + SchedulerClientThatSetNeedsCommitInsideDraw client; SchedulerSettings default_scheduler_settings; Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings); scheduler->SetCanStart(); scheduler->SetVisible(true); scheduler->SetCanDraw(true); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); + client.Reset(); scheduler->SetNeedsRedraw(); EXPECT_TRUE(scheduler->RedrawPending()); EXPECT_EQ(0, client.num_draws()); EXPECT_TRUE(client.needs_begin_frame()); + client.SetNeedsCommitOnNextDraw(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(1, client.num_draws()); EXPECT_TRUE(scheduler->CommitPending()); @@ -545,7 +563,8 @@ TEST(SchedulerTest, RequestCommitInsideFailedDraw) { scheduler->SetCanStart(); scheduler->SetVisible(true); scheduler->SetCanDraw(true); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); + client.Reset(); client.SetDrawWillHappen(false); @@ -581,13 +600,14 @@ TEST(SchedulerTest, RequestCommitInsideFailedDraw) { } TEST(SchedulerTest, NoSwapWhenDrawFails) { - SchedulerClientThatsetNeedsCommitInsideDraw client; + SchedulerClientThatSetNeedsCommitInsideDraw client; SchedulerSettings default_scheduler_settings; Scheduler* scheduler = client.CreateScheduler(default_scheduler_settings); scheduler->SetCanStart(); scheduler->SetVisible(true); scheduler->SetCanDraw(true); - scheduler->DidCreateAndInitializeOutputSurface(); + InitializeOutputSurfaceAndFirstCommit(scheduler); + client.Reset(); scheduler->SetNeedsRedraw(); EXPECT_TRUE(scheduler->RedrawPending()); @@ -595,6 +615,7 @@ TEST(SchedulerTest, NoSwapWhenDrawFails) { EXPECT_EQ(0, client.num_draws()); // Draw successfully, this starts a new frame. + client.SetNeedsCommitOnNextDraw(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(1, client.num_draws()); @@ -604,6 +625,7 @@ TEST(SchedulerTest, NoSwapWhenDrawFails) { // Fail to draw, this should not start a frame. client.SetDrawWillHappen(false); + client.SetNeedsCommitOnNextDraw(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); EXPECT_EQ(2, client.num_draws()); } |