summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-24 03:16:05 +0000
committerbrianderson@chromium.org <brianderson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-24 03:16:05 +0000
commit4093a6adf9c1dfbd0b157b0e2aec6daa4cbccb80 (patch)
tree354dc1cd7ade4a73cc3c00dd83687ad8bb5b737b
parent9557e919576c6e2229bbd0b015e618e1ce9c8fbe (diff)
downloadchromium_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.cc172
-rw-r--r--cc/scheduler/scheduler_state_machine.h23
-rw-r--r--cc/scheduler/scheduler_state_machine_unittest.cc93
-rw-r--r--cc/scheduler/scheduler_unittest.cc86
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());
}