diff options
author | skyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-28 19:16:42 +0000 |
---|---|---|
committer | skyostil@chromium.org <skyostil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-28 19:16:42 +0000 |
commit | c23219664465d1fa295132ab4eede472b38ef6e9 (patch) | |
tree | 5b269f4ed61c1393773cfc8ff67aa8e5b6077773 | |
parent | fda9e0f2b7efdf5bcff04df08570852e88ff60d4 (diff) | |
download | chromium_src-c23219664465d1fa295132ab4eede472b38ef6e9.zip chromium_src-c23219664465d1fa295132ab4eede472b38ef6e9.tar.gz chromium_src-c23219664465d1fa295132ab4eede472b38ef6e9.tar.bz2 |
cc: Split animating and drawing into separate actions
Split impl-side animating and drawing into separate actions. This is
needed to allow for the possibility of a commit between animating and
drawing so that the main thread gets a chance to consume the new
animation state. In particular this allows the main thread to
synchronize with a fling animation using an onscroll handler.
BUG=347366
Review URL: https://codereview.chromium.org/206793003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266624 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/animation/layer_animation_controller.cc | 1 | ||||
-rw-r--r-- | cc/input/input_handler.h | 2 | ||||
-rw-r--r-- | cc/scheduler/scheduler.cc | 8 | ||||
-rw-r--r-- | cc/scheduler/scheduler.h | 3 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine.cc | 51 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine.h | 9 | ||||
-rw-r--r-- | cc/scheduler/scheduler_state_machine_unittest.cc | 111 | ||||
-rw-r--r-- | cc/scheduler/scheduler_unittest.cc | 52 | ||||
-rw-r--r-- | cc/test/fake_layer_tree_host_impl_client.h | 1 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 37 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.h | 8 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 46 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_animation.cc | 64 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.cc | 4 | ||||
-rw-r--r-- | cc/trees/single_thread_proxy.h | 1 | ||||
-rw-r--r-- | cc/trees/thread_proxy.cc | 41 | ||||
-rw-r--r-- | cc/trees/thread_proxy.h | 13 | ||||
-rw-r--r-- | content/renderer/input/input_handler_proxy.cc | 6 | ||||
-rw-r--r-- | content/renderer/input/input_handler_proxy_unittest.cc | 78 |
19 files changed, 427 insertions, 109 deletions
diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index 464801c..5a9337c 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc @@ -205,6 +205,7 @@ void LayerAnimationController::UpdateState(bool start_ready_animations, if (!HasActiveValueObserver()) return; + DCHECK(last_tick_time_); if (start_ready_animations) PromoteStartedAnimations(last_tick_time_, events); diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index 774e011..e78a8d1 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h @@ -125,7 +125,7 @@ class CC_EXPORT InputHandler { base::TimeDelta duration) = 0; // Request another callback to InputHandlerClient::Animate(). - virtual void ScheduleAnimation() = 0; + virtual void SetNeedsAnimate() = 0; virtual bool HaveTouchEventHandlersAt(const gfx::Point& viewport_point) = 0; diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index df7f166..2417455 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc @@ -174,6 +174,11 @@ void Scheduler::SetNeedsRedraw() { ProcessScheduledActions(); } +void Scheduler::SetNeedsAnimate() { + state_machine_.SetNeedsAnimate(); + ProcessScheduledActions(); +} + void Scheduler::SetNeedsManageTiles() { DCHECK(!IsInsideAction(SchedulerStateMachine::ACTION_MANAGE_TILES)); state_machine_.SetNeedsManageTiles(); @@ -630,6 +635,9 @@ void Scheduler::ProcessScheduledActions() { switch (action) { case SchedulerStateMachine::ACTION_NONE: break; + case SchedulerStateMachine::ACTION_ANIMATE: + client_->ScheduledActionAnimate(); + break; case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: client_->ScheduledActionSendBeginMainFrame(); break; diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 0d34f03..1e59192 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h @@ -33,6 +33,7 @@ class SchedulerClient { virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible() = 0; virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() = 0; virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() = 0; + virtual void ScheduledActionAnimate() = 0; virtual void ScheduledActionCommit() = 0; virtual void ScheduledActionUpdateVisibleTiles() = 0; virtual void ScheduledActionActivatePendingTree() = 0; @@ -81,6 +82,8 @@ class CC_EXPORT Scheduler { void SetNeedsRedraw(); + void SetNeedsAnimate(); + void SetNeedsManageTiles(); void SetMaxSwapsPending(int max); diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index 647af71..0ddaa30 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc @@ -22,6 +22,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) readback_state_(READBACK_STATE_IDLE), commit_count_(0), current_frame_number_(0), + last_frame_number_animate_performed_(-1), last_frame_number_swap_performed_(-1), last_frame_number_begin_main_frame_sent_(-1), last_frame_number_update_visible_tiles_was_called_(-1), @@ -30,6 +31,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) max_pending_swaps_(1), pending_swaps_(0), needs_redraw_(false), + needs_animate_(false), needs_manage_tiles_(false), swap_used_incomplete_tile_(false), needs_commit_(false), @@ -46,7 +48,8 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings) skip_next_begin_main_frame_to_reduce_latency_(false), skip_begin_main_frame_to_reduce_latency_(false), continuous_painting_(false), - needs_back_to_back_readback_(false) {} + needs_back_to_back_readback_(false) { +} const char* SchedulerStateMachine::OutputSurfaceStateToString( OutputSurfaceState state) { @@ -143,6 +146,8 @@ const char* SchedulerStateMachine::ActionToString(Action action) { switch (action) { case ACTION_NONE: return "ACTION_NONE"; + case ACTION_ANIMATE: + return "ACTION_ANIMATE"; case ACTION_SEND_BEGIN_MAIN_FRAME: return "ACTION_SEND_BEGIN_MAIN_FRAME"; case ACTION_COMMIT: @@ -216,6 +221,8 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { minor_state->SetInteger("commit_count", commit_count_); minor_state->SetInteger("current_frame_number", current_frame_number_); + minor_state->SetInteger("last_frame_number_animate_performed", + last_frame_number_animate_performed_); minor_state->SetInteger("last_frame_number_swap_performed", last_frame_number_swap_performed_); minor_state->SetInteger( @@ -231,6 +238,7 @@ scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const { minor_state->SetInteger("max_pending_swaps_", max_pending_swaps_); minor_state->SetInteger("pending_swaps_", pending_swaps_); minor_state->SetBoolean("needs_redraw", needs_redraw_); + minor_state->SetBoolean("needs_animate_", needs_animate_); minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_); minor_state->SetBoolean("swap_used_incomplete_tile", swap_used_incomplete_tile_); @@ -427,6 +435,20 @@ bool SchedulerStateMachine::ShouldUpdateVisibleTiles() const { return false; } +bool SchedulerStateMachine::ShouldAnimate() const { + if (!can_draw_) + return false; + + if (last_frame_number_animate_performed_ == current_frame_number_) + return false; + + if (begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING && + begin_impl_frame_state_ != BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) + return false; + + return needs_redraw_ || needs_animate_; +} + bool SchedulerStateMachine::ShouldSendBeginMainFrame() const { if (!needs_commit_) return false; @@ -531,6 +553,8 @@ SchedulerStateMachine::Action SchedulerStateMachine::NextAction() const { return ACTION_ACTIVATE_PENDING_TREE; if (ShouldCommit()) return ACTION_COMMIT; + if (ShouldAnimate()) + return ACTION_ANIMATE; if (ShouldDraw()) { if (readback_state_ == READBACK_STATE_WAITING_FOR_DRAW_AND_READBACK) return ACTION_DRAW_AND_READBACK; @@ -571,6 +595,14 @@ void SchedulerStateMachine::UpdateState(Action action) { UpdateStateOnActivation(); return; + case ACTION_ANIMATE: + last_frame_number_animate_performed_ = current_frame_number_; + needs_animate_ = false; + // TODO(skyostil): Instead of assuming this, require the client to tell + // us. + SetNeedsRedraw(); + return; + case ACTION_SEND_BEGIN_MAIN_FRAME: DCHECK(!has_pending_tree_ || settings_.main_frame_before_activation_enabled); @@ -783,9 +815,9 @@ bool SchedulerStateMachine::BeginFrameNeeded() const { // To poll for state with the synchronous compositor without having to draw, // we rely on ShouldPollForAnticipatedDrawTriggers instead. if (!SupportsProactiveBeginFrame()) - return BeginFrameNeededToDraw(); + return BeginFrameNeededToAnimateOrDraw(); - return BeginFrameNeededToDraw() || ProactiveBeginFrameWanted(); + return BeginFrameNeededToAnimateOrDraw() || ProactiveBeginFrameWanted(); } bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { @@ -793,7 +825,7 @@ bool SchedulerStateMachine::ShouldPollForAnticipatedDrawTriggers() const { // ProactiveBeginFrameWanted when we are using the synchronous // compositor. if (!SupportsProactiveBeginFrame()) { - return !BeginFrameNeededToDraw() && ProactiveBeginFrameWanted(); + return !BeginFrameNeededToAnimateOrDraw() && ProactiveBeginFrameWanted(); } // Non synchronous compositors should rely on @@ -812,8 +844,8 @@ bool SchedulerStateMachine::SupportsProactiveBeginFrame() const { } // These are the cases where we definitely (or almost definitely) have a -// new frame to draw and can draw. -bool SchedulerStateMachine::BeginFrameNeededToDraw() const { +// new frame to animate and/or draw and can draw. +bool SchedulerStateMachine::BeginFrameNeededToAnimateOrDraw() const { // The output surface is the provider of BeginImplFrames, so we are not going // to get them even if we ask for them. if (!HasInitializedOutputSurface()) @@ -838,6 +870,9 @@ bool SchedulerStateMachine::BeginFrameNeededToDraw() const { if (swap_used_incomplete_tile_) return true; + if (needs_animate_) + return true; + return needs_redraw_; } @@ -1007,6 +1042,10 @@ void SchedulerStateMachine::SetCanDraw(bool can_draw) { can_draw_ = can_draw; } void SchedulerStateMachine::SetNeedsRedraw() { needs_redraw_ = true; } +void SchedulerStateMachine::SetNeedsAnimate() { + needs_animate_ = true; +} + void SchedulerStateMachine::SetNeedsManageTiles() { if (!needs_manage_tiles_) { TRACE_EVENT0("cc", diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h index 2779264..e7d05e6 100644 --- a/cc/scheduler/scheduler_state_machine.h +++ b/cc/scheduler/scheduler_state_machine.h @@ -101,6 +101,7 @@ class CC_EXPORT SchedulerStateMachine { enum Action { ACTION_NONE, + ACTION_ANIMATE, ACTION_SEND_BEGIN_MAIN_FRAME, ACTION_COMMIT, ACTION_UPDATE_VISIBLE_TILES, @@ -164,6 +165,9 @@ class CC_EXPORT SchedulerStateMachine { void SetNeedsRedraw(); bool needs_redraw() const { return needs_redraw_; } + void SetNeedsAnimate(); + bool needs_animate() const { return needs_animate_; } + // Indicates that manage-tiles is required. This guarantees another // ManageTiles will occur shortly (even if no redraw is required). void SetNeedsManageTiles(); @@ -248,12 +252,13 @@ class CC_EXPORT SchedulerStateMachine { } protected: - bool BeginFrameNeededToDraw() const; + bool BeginFrameNeededToAnimateOrDraw() const; bool ProactiveBeginFrameWanted() const; // True if we need to force activations to make forward progress. bool PendingActivationsShouldBeForced() const; + bool ShouldAnimate() const; bool ShouldBeginOutputSurfaceCreation() const; bool ShouldDrawForced() const; bool ShouldDraw() const; @@ -286,6 +291,7 @@ class CC_EXPORT SchedulerStateMachine { int commit_count_; int current_frame_number_; + int last_frame_number_animate_performed_; int last_frame_number_swap_performed_; int last_frame_number_begin_main_frame_sent_; int last_frame_number_update_visible_tiles_was_called_; @@ -299,6 +305,7 @@ class CC_EXPORT SchedulerStateMachine { int max_pending_swaps_; int pending_swaps_; bool needs_redraw_; + bool needs_animate_; bool needs_manage_tiles_; bool swap_used_incomplete_tile_; bool needs_commit_; diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index 060269d..3dfe934 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc @@ -237,6 +237,7 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeDrawDisabled) { EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); EXPECT_EQ(state.CommitState(), SchedulerStateMachine::COMMIT_STATE_IDLE); @@ -308,6 +309,7 @@ TEST(SchedulerStateMachineTest, MainFrameBeforeActivationEnabled) { EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); @@ -328,6 +330,7 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); @@ -343,6 +346,7 @@ TEST(SchedulerStateMachineTest, state.DidDrawIfPossibleCompleted( DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_TRUE(state.RedrawPending()); @@ -362,6 +366,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawForMissingHighResNeedsCommit) { EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE( @@ -394,6 +399,7 @@ TEST(SchedulerStateMachineTest, EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); @@ -413,6 +419,7 @@ TEST(SchedulerStateMachineTest, state.DidDrawIfPossibleCompleted( DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_TRUE(state.RedrawPending()); @@ -443,6 +450,7 @@ void TestFailedDrawsEventuallyForceDrawAfterNextCommit( // Then initiate a draw. state.SetNeedsRedraw(true); state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); @@ -465,6 +473,7 @@ void TestFailedDrawsEventuallyForceDrawAfterNextCommit( // The redraw should be forced at the end of the next BeginImplFrame. state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); if (main_frame_before_draw_enabled) { EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); @@ -514,6 +523,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawsDoNotRestartForcedDraw) { // Then initiate a draw. state.SetNeedsRedraw(true); state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); @@ -566,6 +576,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) { state.SetNeedsRedraw(true); EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_TRUE(state.RedrawPending()); @@ -583,6 +594,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) { // We should not be trying to draw again now, but we have a commit pending. EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // We should try to draw again at the end of the next BeginImplFrame on @@ -606,6 +618,7 @@ TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) { // Draw the first frame. EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); @@ -623,6 +636,7 @@ TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) { EXPECT_TRUE(state.BeginFrameNeeded()); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); @@ -686,6 +700,7 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) { state.SetCommitState(all_commit_states[i]); state.SetBeginImplFrameState( SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); + if (request_readback) { state.SetNeedsForcedRedrawForReadback(); } else { @@ -702,6 +717,9 @@ TEST(SchedulerStateMachineTest, TestNextActionDrawsOnBeginImplFrame) { } else { expected_action = SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE; + EXPECT_EQ(state.NextAction(), SchedulerStateMachine::ACTION_ANIMATE) + << *state.AsValue(); + state.UpdateState(state.NextAction()); } // Case 1: needs_commit=false. @@ -859,6 +877,7 @@ void TestSetNeedsCommitIsNotLost(bool main_frame_before_draw_enabled) { // Finish the commit, then make sure we start the next commit immediately // and draw on the next BeginImplFrame. EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); if (main_frame_before_draw_enabled) { EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); @@ -925,6 +944,7 @@ TEST(SchedulerStateMachineTest, TestFullCycle) { // At BeginImplFrame deadline, draw. state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS); @@ -976,6 +996,7 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) { // At BeginImplFrame deadline, draw. state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); state.DidDrawIfPossibleCompleted(DrawSwapReadbackResult::DRAW_SUCCESS); @@ -1084,6 +1105,7 @@ TEST(SchedulerStateMachineTest, AbortBeginMainFrameAndCancelCommit) { // Start a new frame; draw because this is the first frame since output // surface init'd. state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE( @@ -1209,6 +1231,7 @@ TEST(SchedulerStateMachineTest, // Once the context is recreated, whether we draw should be based on // SetCanDraw. state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_EQ(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE, @@ -1236,6 +1259,7 @@ TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) { // Set damage and expect a draw. state.SetNeedsRedraw(true); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -1300,6 +1324,7 @@ TEST(SchedulerStateMachineTest, // Set damage and expect a draw. state.SetNeedsRedraw(true); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -1361,6 +1386,7 @@ TEST(SchedulerStateMachineTest, EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -1524,6 +1550,7 @@ TEST(SchedulerStateMachineTest, DontMakeNewCommitAfterDrawingReplaceCommit) { EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_COMMIT); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE( @@ -1628,6 +1655,7 @@ void TestForceCommitWhenReplacementActivationInProgress( EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // Perform the draw & swap of replacement commit. state.OnBeginImplFrameDeadline(); @@ -1667,6 +1695,7 @@ void TestForceCommitWhenReplacementActivationInProgress( EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrameDeadline(); EXPECT_ACTION_UPDATE_STATE( @@ -1737,6 +1766,7 @@ TEST(SchedulerStateMachineTest, EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); // Perform the draw & swap of replacement commit. state.OnBeginImplFrameDeadline(); @@ -1974,6 +2004,7 @@ TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyAfterAbortedCommit) { state.SetNeedsCommit(); // We should start the commit normally. + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -2002,6 +2033,7 @@ TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) { state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); state.SetNeedsRedraw(true); state.SetNeedsCommit(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); EXPECT_ACTION_UPDATE_STATE( SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); @@ -2012,5 +2044,84 @@ TEST(SchedulerStateMachineTest, TestTriggerDeadlineEarlyForSmoothness) { EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineEarly()); } +TEST(SchedulerStateMachineTest, TestSetNeedsAnimate) { + SchedulerSettings settings; + settings.impl_side_painting = true; + StateMachine state(settings); + state.SetCanStart(); + state.UpdateState(state.NextAction()); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + state.SetVisible(true); + state.SetCanDraw(true); + + // Test requesting an animation that, when run, causes us to draw. + state.SetNeedsAnimate(); + EXPECT_TRUE(state.BeginFrameNeeded()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); + + state.OnBeginImplFrameDeadlinePending(); + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); +} + +TEST(SchedulerStateMachineTest, TestAnimateBeforeCommit) { + SchedulerSettings settings; + settings.impl_side_painting = true; + StateMachine state(settings); + state.SetCanStart(); + state.UpdateState(state.NextAction()); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + state.SetVisible(true); + state.SetCanDraw(true); + + // Check that animations are updated before we start a commit. + state.SetNeedsAnimate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + state.SetNeedsCommit(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + EXPECT_TRUE(state.BeginFrameNeeded()); + + state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME); + + state.OnBeginImplFrameDeadlinePending(); + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); +} + +TEST(SchedulerStateMachineTest, TestSetNeedsAnimateAfterAnimate) { + SchedulerSettings settings; + settings.impl_side_painting = true; + StateMachine state(settings); + state.SetCanStart(); + state.UpdateState(state.NextAction()); + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + state.SetVisible(true); + state.SetCanDraw(true); + + // Test requesting an animation after we have already animated during this + // frame. + state.SetNeedsRedraw(true); + EXPECT_TRUE(state.BeginFrameNeeded()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + state.OnBeginImplFrame(BeginFrameArgs::CreateForTesting()); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_ANIMATE); + + state.SetNeedsAnimate(); + EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::ACTION_NONE); + + state.OnBeginImplFrameDeadline(); + EXPECT_ACTION_UPDATE_STATE( + SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE); +} + } // namespace } // namespace cc diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index a5d279b..921b94a 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc @@ -109,6 +109,10 @@ class FakeSchedulerClient : public SchedulerClient { actions_.push_back("ScheduledActionSendBeginMainFrame"); states_.push_back(scheduler_->StateAsValue().release()); } + virtual void ScheduledActionAnimate() OVERRIDE { + actions_.push_back("ScheduledActionAnimate"); + states_.push_back(scheduler_->StateAsValue().release()); + } virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE { actions_.push_back("ScheduledActionDrawAndSwapIfPossible"); @@ -286,7 +290,8 @@ TEST(SchedulerTest, RequestCommit) { // BeginImplFrame should prepare the draw. scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client.needs_begin_frame()); client.Reset(); @@ -348,7 +353,8 @@ TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client.Reset(); client.task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); // Because we just swapped, the Scheduler should also request the next @@ -371,7 +377,8 @@ TEST(SchedulerTest, RequestCommitAfterBeginMainFrameSent) { EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client.Reset(); client.task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client.needs_begin_frame()); client.Reset(); @@ -738,7 +745,8 @@ TEST(SchedulerTest, ManageTiles) { // the deadline task. client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); // On the deadline, he actions should have occured in the right order. @@ -765,7 +773,8 @@ TEST(SchedulerTest, ManageTiles) { // the deadline task. client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); // Draw. The draw will trigger SetNeedsManageTiles, and @@ -832,7 +841,8 @@ TEST(SchedulerTest, ManageTilesOncePerFrame) { scheduler->SetNeedsRedraw(); client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(scheduler->ManageTilesPending()); @@ -853,7 +863,8 @@ TEST(SchedulerTest, ManageTilesOncePerFrame) { scheduler->SetNeedsRedraw(); client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client.Reset(); @@ -875,7 +886,8 @@ TEST(SchedulerTest, ManageTilesOncePerFrame) { scheduler->SetNeedsRedraw(); client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(scheduler->ManageTilesPending()); @@ -897,7 +909,8 @@ TEST(SchedulerTest, ManageTilesOncePerFrame) { scheduler->SetNeedsRedraw(); client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(scheduler->ManageTilesPending()); @@ -915,7 +928,8 @@ TEST(SchedulerTest, ManageTilesOncePerFrame) { scheduler->SetNeedsRedraw(); client.Reset(); scheduler->BeginFrame(BeginFrameArgs::CreateForTesting()); - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); client.Reset(); @@ -1171,7 +1185,8 @@ TEST(SchedulerTest, BeginRetroFrame) { // BeginImplFrame should prepare the draw. client.task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client.needs_begin_frame()); client.Reset(); @@ -1244,7 +1259,8 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) { // Swapping will put us into a swap throttled state. client.task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client.needs_begin_frame()); client.Reset(); @@ -1276,7 +1292,8 @@ TEST(SchedulerTest, BeginRetroFrame_SwapThrottled) { // BeginImplFrame deadline should draw. scheduler->SetNeedsRedraw(); client.task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_TRUE(client.needs_begin_frame()); client.Reset(); @@ -1328,7 +1345,8 @@ void BeginFramesNotFromClient(bool begin_frame_scheduling_enabled, // BeginImplFrame should prepare the draw. client.task_runner().RunPendingTasks(); // Run posted BeginFrame. - EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); + EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); + EXPECT_ACTION("ScheduledActionAnimate", client, 1, 2); EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_FALSE(client.needs_begin_frame()); client.Reset(); @@ -1417,7 +1435,8 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, // Swapping will put us into a swap throttled state. client.task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_FALSE(client.needs_begin_frame()); client.Reset(); @@ -1441,7 +1460,8 @@ void BeginFramesNotFromClient_SwapThrottled(bool begin_frame_scheduling_enabled, // BeginImplFrame deadline should draw. scheduler->SetNeedsRedraw(); client.task_runner().RunPendingTasks(); // Run posted deadline. - EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); + EXPECT_ACTION("ScheduledActionAnimate", client, 0, 2); + EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 1, 2); EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); EXPECT_FALSE(client.needs_begin_frame()); client.Reset(); diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index 57350bf..3944bf7 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h @@ -27,6 +27,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient { virtual void SetNeedsRedrawOnImplThread() OVERRIDE {} virtual void SetNeedsRedrawRectOnImplThread( const gfx::Rect& damage_rect) OVERRIDE {} + virtual void SetNeedsAnimateOnImplThread() OVERRIDE {} virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {} virtual void SetNeedsCommitOnImplThread() OVERRIDE {} virtual void SetNeedsManageTilesOnImplThread() OVERRIDE {} diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 108969d..e764517 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -470,15 +470,11 @@ void LayerTreeHostImpl::StartPageScaleAnimation( duration.InSecondsF()); } - SetNeedsRedraw(); + SetNeedsAnimate(); client_->SetNeedsCommitOnImplThread(); client_->RenewTreePriority(); } -void LayerTreeHostImpl::ScheduleAnimation() { - SetNeedsRedraw(); -} - bool LayerTreeHostImpl::HaveTouchEventHandlersAt( const gfx::Point& viewport_point) { if (!settings_.touch_hit_testing) @@ -1719,6 +1715,11 @@ void LayerTreeHostImpl::SetVisible(bool visible) { renderer_->SetVisible(visible); } +void LayerTreeHostImpl::SetNeedsAnimate() { + NotifySwapPromiseMonitorsOfSetNeedsRedraw(); + client_->SetNeedsAnimateOnImplThread(); +} + void LayerTreeHostImpl::SetNeedsRedraw() { NotifySwapPromiseMonitorsOfSetNeedsRedraw(); client_->SetNeedsRedrawOnImplThread(); @@ -2714,6 +2715,8 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) { page_scale_animation_.reset(); client_->SetNeedsCommitOnImplThread(); client_->RenewTreePriority(); + } else { + SetNeedsAnimate(); } } @@ -2723,14 +2726,12 @@ void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) { gfx::Vector2dF scroll = top_controls_manager_->Animate(time); if (active_tree_->TotalScrollOffset().y() == 0.f) return; - if (scroll.IsZero()) { - // This may happen on the first animation step. Force redraw otherwise - // the animation would stop because of no new frames. - SetNeedsRedraw(); - } else { + if (!scroll.IsZero()) { ScrollViewportBy(gfx::ScaleVector2d( scroll, 1.f / active_tree_->total_page_scale_factor())); + SetNeedsRedraw(); } + SetNeedsAnimate(); } void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) { @@ -2752,7 +2753,7 @@ void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) { ++iter) (*iter).second->Animate(monotonic_time_for_cc_animations); - SetNeedsRedraw(); + SetNeedsAnimate(); } void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) { @@ -2774,6 +2775,8 @@ void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) { if (!events->empty()) { client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass()); } + + SetNeedsAnimate(); } base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const { @@ -2847,9 +2850,10 @@ void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer, layer->scrollbar_animation_controller(); if (scrollbar_controller && scrollbar_controller->Animate(time)) { TRACE_EVENT_INSTANT0( - "cc", "LayerTreeHostImpl::SetNeedsRedraw due to AnimateScrollbars", + "cc", + "LayerTreeHostImpl::SetNeedsAnimate due to AnimateScrollbars", TRACE_EVENT_SCOPE_THREAD); - SetNeedsRedraw(); + SetNeedsAnimate(); } for (size_t i = 0; i < layer->children().size(); ++i) @@ -2870,10 +2874,11 @@ void LayerTreeHostImpl::StartScrollbarAnimationRecursive(LayerImpl* layer, layer->scrollbar_animation_controller(); if (scrollbar_controller && scrollbar_controller->IsAnimating()) { base::TimeDelta delay = scrollbar_controller->DelayBeforeStart(time); - if (delay > base::TimeDelta()) + if (delay > base::TimeDelta()) { client_->RequestScrollbarAnimationOnImplThread(delay); - else if (scrollbar_controller->Animate(time)) - SetNeedsRedraw(); + } else if (scrollbar_controller->Animate(time)) { + SetNeedsAnimate(); + } } for (size_t i = 0; i < layer->children().size(); ++i) diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 84e7ccd..8eb77fe 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -72,10 +72,12 @@ class LayerTreeHostImplClient { virtual void BeginFrame(const BeginFrameArgs& args) = 0; virtual void OnCanDrawStateChanged(bool can_draw) = 0; virtual void NotifyReadyToActivate() = 0; - // Please call these 2 functions through - // LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsRedrawRect(). + // Please call these 3 functions through + // LayerTreeHostImpl's SetNeedsRedraw(), SetNeedsRedrawRect() and + // SetNeedsAnimate(). virtual void SetNeedsRedrawOnImplThread() = 0; virtual void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) = 0; + virtual void SetNeedsAnimateOnImplThread() = 0; virtual void DidInitializeVisibleTileOnImplThread() = 0; virtual void SetNeedsCommitOnImplThread() = 0; virtual void SetNeedsManageTilesOnImplThread() = 0; @@ -138,7 +140,7 @@ class CC_EXPORT LayerTreeHostImpl bool anchor_point, float page_scale, base::TimeDelta duration) OVERRIDE; - virtual void ScheduleAnimation() OVERRIDE; + virtual void SetNeedsAnimate() OVERRIDE; virtual bool HaveTouchEventHandlersAt(const gfx::Point& viewport_port) OVERRIDE; virtual scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 0d23d11..3711ca7 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -85,6 +85,7 @@ class LayerTreeHostImplTest : public testing::Test, did_notify_ready_to_activate_(false), did_request_commit_(false), did_request_redraw_(false), + did_request_animate_(false), did_request_manage_tiles_(false), did_upload_visible_tile_(false), reduce_memory_result_(true), @@ -131,6 +132,9 @@ class LayerTreeHostImplTest : public testing::Test, const gfx::Rect& damage_rect) OVERRIDE { did_request_redraw_ = true; } + virtual void SetNeedsAnimateOnImplThread() OVERRIDE { + did_request_animate_ = true; + } virtual void SetNeedsManageTilesOnImplThread() OVERRIDE { did_request_manage_tiles_ = true; } @@ -396,6 +400,7 @@ class LayerTreeHostImplTest : public testing::Test, bool did_notify_ready_to_activate_; bool did_request_commit_; bool did_request_redraw_; + bool did_request_animate_; bool did_request_manage_tiles_; bool did_upload_visible_tile_; bool reduce_memory_result_; @@ -904,6 +909,7 @@ TEST_F(LayerTreeHostImplTest, ImplPinchZoom) { scroll_layer->FixedContainerSizeDelta()); host_impl_->PinchGestureEnd(); host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); EXPECT_TRUE(did_request_redraw_); EXPECT_TRUE(did_request_commit_); EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds()); @@ -970,6 +976,7 @@ TEST_F(LayerTreeHostImplTest, PinchGesture) { host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50)); host_impl_->PinchGestureEnd(); host_impl_->ScrollEnd(); + EXPECT_FALSE(did_request_animate_); EXPECT_TRUE(did_request_redraw_); EXPECT_TRUE(did_request_commit_); @@ -1111,19 +1118,30 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) { max_page_scale); scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50)); + did_request_redraw_ = false; + did_request_animate_ = false; host_impl_->StartPageScaleAnimation(gfx::Vector2d(), false, 2.f, duration); + EXPECT_FALSE(did_request_redraw_); + EXPECT_TRUE(did_request_animate_); + did_request_redraw_ = false; + did_request_animate_ = false; host_impl_->Animate(start_time); EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(did_request_animate_); did_request_redraw_ = false; + did_request_animate_ = false; host_impl_->Animate(halfway_through_animation); EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(did_request_animate_); did_request_redraw_ = false; + did_request_animate_ = false; did_request_commit_ = false; host_impl_->Animate(end_time); EXPECT_TRUE(did_request_commit_); + EXPECT_FALSE(did_request_animate_); scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas(); @@ -1138,16 +1156,25 @@ TEST_F(LayerTreeHostImplTest, PageScaleAnimation) { max_page_scale); scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50)); + did_request_redraw_ = false; + did_request_animate_ = false; host_impl_->StartPageScaleAnimation( gfx::Vector2d(25, 25), true, min_page_scale, duration); + EXPECT_FALSE(did_request_redraw_); + EXPECT_TRUE(did_request_animate_); + did_request_redraw_ = false; + did_request_animate_ = false; host_impl_->Animate(start_time); EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(did_request_animate_); did_request_redraw_ = false; did_request_commit_ = false; + did_request_animate_ = false; host_impl_->Animate(end_time); EXPECT_TRUE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); EXPECT_TRUE(did_request_commit_); scoped_ptr<ScrollAndScaleSet> scroll_info = @@ -1301,10 +1328,12 @@ TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) { host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0)); host_impl_->ScrollEnd(); did_request_redraw_ = false; + did_request_animate_ = false; host_impl_->StartScrollbarAnimation(); EXPECT_LT(base::TimeDelta::FromMilliseconds(19), requested_scrollbar_animation_delay_); EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); requested_scrollbar_animation_delay_ = base::TimeDelta(); // After the fade begins, we should start getting redraws instead of a @@ -1313,8 +1342,8 @@ TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) { host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now); host_impl_->StartScrollbarAnimation(); EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); - EXPECT_TRUE(did_request_redraw_); - did_request_redraw_ = false; + EXPECT_TRUE(did_request_animate_); + did_request_animate_ = false; // If no scroll happened recently, StartScrollbarAnimation should have no // effect. @@ -1331,6 +1360,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) { EXPECT_LT(base::TimeDelta::FromMilliseconds(19), requested_scrollbar_animation_delay_); EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); requested_scrollbar_animation_delay_ = base::TimeDelta(); // None of the above should have called CurrentFrameTimeTicks, so if we call @@ -1358,7 +1388,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { // effect. host_impl_->StartScrollbarAnimation(); EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); // If no scroll happened during a scroll gesture, StartScrollbarAnimation // should have no effect. @@ -1366,7 +1396,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { host_impl_->ScrollEnd(); host_impl_->StartScrollbarAnimation(); EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); // After a scroll, no fade animation should be scheduled. host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel); @@ -1375,7 +1405,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { did_request_redraw_ = false; host_impl_->StartScrollbarAnimation(); EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); requested_scrollbar_animation_delay_ = base::TimeDelta(); // We should not see any draw requests. @@ -1383,7 +1413,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now); host_impl_->StartScrollbarAnimation(); EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); // Make page scale > min so that subsequent scrolls will trigger fades. host_impl_->active_tree()->SetPageScaleDelta(1.1f); @@ -1396,7 +1426,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { host_impl_->StartScrollbarAnimation(); EXPECT_LT(base::TimeDelta::FromMilliseconds(19), requested_scrollbar_animation_delay_); - EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_animate_); requested_scrollbar_animation_delay_ = base::TimeDelta(); // After the fade begins, we should start getting redraws instead of a @@ -1405,7 +1435,7 @@ TEST_F(LayerTreeHostImplTest, ScrollbarFadePinchZoomScrollbars) { host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now); host_impl_->StartScrollbarAnimation(); EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_); - EXPECT_TRUE(did_request_redraw_); + EXPECT_TRUE(did_request_animate_); } void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale( diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index aeeb4f5..d546e1b 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc @@ -1244,5 +1244,69 @@ class LayerTreeHostAnimationTestFrozenAnimationTickTime // Only the non-impl-paint multi-threaded compositor freezes animations. MULTI_THREAD_NOIMPL_TEST_F(LayerTreeHostAnimationTestFrozenAnimationTickTime); +class LayerTreeHostAnimationTestAddAnimationAfterAnimating + : public LayerTreeHostAnimationTest { + public: + LayerTreeHostAnimationTestAddAnimationAfterAnimating() + : num_swap_buffers_(0) {} + + virtual void SetupTree() OVERRIDE { + LayerTreeHostAnimationTest::SetupTree(); + content_ = Layer::Create(); + content_->SetBounds(gfx::Size(4, 4)); + layer_tree_host()->root_layer()->AddChild(content_); + } + + virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); } + + virtual void DidCommit() OVERRIDE { + switch (layer_tree_host()->source_frame_number()) { + case 1: + // First frame: add an animation to the root layer. + AddAnimatedTransformToLayer(layer_tree_host()->root_layer(), 0.1, 5, 5); + break; + case 2: + // Second frame: add an animation to the content layer. The root layer + // animation has caused us to animate already during this frame. + AddOpacityTransitionToLayer(content_.get(), 0.1, 5, 5, false); + break; + } + } + + virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, + bool result) OVERRIDE { + // The third frame is when both animations have started. Check that both + // have a valid start time. + if (++num_swap_buffers_ == 3) { + EndTest(); + AnimationRegistrar::AnimationControllerMap copy = + host_impl->animation_registrar()->active_animation_controllers(); + EXPECT_EQ(2u, copy.size()); + for (AnimationRegistrar::AnimationControllerMap::iterator iter = + copy.begin(); + iter != copy.end(); + ++iter) { + int id = ((*iter).second->id()); + if (id == host_impl->RootLayer()->id()) { + Animation* anim = (*iter).second->GetAnimation(Animation::Transform); + EXPECT_GT(anim->start_time(), 0); + } else if (id == host_impl->RootLayer()->children()[0]->id()) { + Animation* anim = (*iter).second->GetAnimation(Animation::Opacity); + EXPECT_GT(anim->start_time(), 0); + } + } + } + } + + virtual void AfterTest() OVERRIDE {} + + private: + scoped_refptr<Layer> content_; + int num_swap_buffers_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostAnimationTestAddAnimationAfterAnimating); + } // namespace } // namespace cc diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index a70e08f..a920f5a 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc @@ -267,6 +267,10 @@ void SingleThreadProxy::SetNeedsRedrawOnImplThread() { client_->ScheduleComposite(); } +void SingleThreadProxy::SetNeedsAnimateOnImplThread() { + SetNeedsRedrawOnImplThread(); +} + void SingleThreadProxy::SetNeedsManageTilesOnImplThread() { // Thread-only/Impl-side-painting-only feature. NOTREACHED(); diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index e26e031..8f682be 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h @@ -67,6 +67,7 @@ class SingleThreadProxy : public Proxy, LayerTreeHostImplClient { virtual void SetNeedsRedrawOnImplThread() OVERRIDE; virtual void SetNeedsRedrawRectOnImplThread( const gfx::Rect& dirty_rect) OVERRIDE; + virtual void SetNeedsAnimateOnImplThread() OVERRIDE; virtual void SetNeedsManageTilesOnImplThread() OVERRIDE; virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE; virtual void SetNeedsCommitOnImplThread() OVERRIDE; diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index 97a0c94..9c97ef6 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc @@ -125,8 +125,10 @@ ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(ThreadProxy* proxy, inside_draw(false), input_throttled_until_commit(false), animations_frozen_until_next_draw(false), + did_commit_after_animating(false), renew_tree_priority_pending(false), - weak_factory(proxy) {} + weak_factory(proxy) { +} ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {} @@ -563,6 +565,12 @@ void ThreadProxy::SetNeedsRedrawOnImplThread() { impl().scheduler->SetNeedsRedraw(); } +void ThreadProxy::SetNeedsAnimateOnImplThread() { + TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread"); + DCHECK(IsImplThread()); + impl().scheduler->SetNeedsAnimate(); +} + void ThreadProxy::SetNeedsManageTilesOnImplThread() { DCHECK(IsImplThread()); impl().scheduler->SetNeedsManageTiles(); @@ -1020,6 +1028,18 @@ void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) { impl().scheduler->BeginMainFrameAborted(did_handle); } +void ThreadProxy::ScheduledActionAnimate() { + TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate"); + DCHECK(IsImplThread()); + + if (!impl().animations_frozen_until_next_draw) { + impl().animation_time = + impl().layer_tree_host_impl->CurrentFrameTimeTicks(); + } + impl().layer_tree_host_impl->Animate(impl().animation_time); + impl().did_commit_after_animating = false; +} + void ThreadProxy::ScheduledActionCommit() { TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit"); DCHECK(IsImplThread()); @@ -1032,10 +1052,10 @@ void ThreadProxy::ScheduledActionCommit() { impl().current_resource_update_controller.reset(); if (impl().animations_frozen_until_next_draw) { - impl().animation_freeze_time = - std::max(impl().animation_freeze_time, - blocked_main().last_monotonic_frame_begin_time); + impl().animation_time = std::max( + impl().animation_time, blocked_main().last_monotonic_frame_begin_time); } + impl().did_commit_after_animating = true; blocked_main().main_thread_inside_commit = true; impl().layer_tree_host_impl->BeginCommit(); @@ -1109,17 +1129,13 @@ DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal( base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); base::AutoReset<bool> mark_inside(&impl().inside_draw, true); - // Advance our animations. - base::TimeTicks monotonic_time; - if (impl().animations_frozen_until_next_draw) - monotonic_time = impl().animation_freeze_time; - else - monotonic_time = impl().layer_tree_host_impl->CurrentFrameTimeTicks(); + if (impl().did_commit_after_animating) { + impl().layer_tree_host_impl->Animate(impl().animation_time); + impl().did_commit_after_animating = false; + } - // TODO(enne): This should probably happen post-animate. if (impl().layer_tree_host_impl->pending_tree()) impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties(); - impl().layer_tree_host_impl->Animate(monotonic_time); // This method is called on a forced draw, regardless of whether we are able // to produce a frame, as the calling site on main thread is blocked until its @@ -1173,7 +1189,6 @@ DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal( // checkerboarding will be displayed when we force a draw. To avoid this, // we freeze animations until we successfully draw. impl().animations_frozen_until_next_draw = true; - impl().animation_freeze_time = monotonic_time; } else { DCHECK_NE(DrawSwapReadbackResult::DRAW_SUCCESS, result.draw_result); } diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h index aab7a43..381e2be 100644 --- a/cc/trees/thread_proxy.h +++ b/cc/trees/thread_proxy.h @@ -82,11 +82,13 @@ class ThreadProxy : public Proxy, virtual void DidSwapBuffersCompleteOnImplThread() OVERRIDE; virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE; virtual void NotifyReadyToActivate() OVERRIDE; - // Please call these 2 functions through - // LayerTreeHostImpl's SetNeedsRedraw() and SetNeedsRedrawRect(). + // Please call these 3 functions through + // LayerTreeHostImpl's SetNeedsRedraw(), SetNeedsRedrawRect() and + // SetNeedsAnimate(). virtual void SetNeedsRedrawOnImplThread() OVERRIDE; virtual void SetNeedsRedrawRectOnImplThread(const gfx::Rect& dirty_rect) OVERRIDE; + virtual void SetNeedsAnimateOnImplThread() OVERRIDE; virtual void SetNeedsManageTilesOnImplThread() OVERRIDE; virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE; virtual void SetNeedsCommitOnImplThread() OVERRIDE; @@ -111,6 +113,7 @@ class ThreadProxy : public Proxy, OVERRIDE; virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() OVERRIDE; virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() OVERRIDE; + virtual void ScheduledActionAnimate() OVERRIDE; virtual void ScheduledActionCommit() OVERRIDE; virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE; virtual void ScheduledActionActivatePendingTree() OVERRIDE; @@ -283,7 +286,11 @@ class ThreadProxy : public Proxy, // Set when we freeze animations to avoid checkerboarding. bool animations_frozen_until_next_draw; - base::TimeTicks animation_freeze_time; + base::TimeTicks animation_time; + + // Whether a commit has been completed since the last time animations were + // ticked. If this happens, we need to animate again. + bool did_commit_after_animating; base::TimeTicks smoothness_takes_priority_expiration_time; bool renew_tree_priority_pending; diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc index d7b594d..471abda 100644 --- a/content/renderer/input/input_handler_proxy.cc +++ b/content/renderer/input/input_handler_proxy.cc @@ -338,7 +338,7 @@ InputHandlerProxy::HandleGestureFling( WebPoint(gesture_event.globalX, gesture_event.globalY); fling_parameters_.modifiers = gesture_event.modifiers; fling_parameters_.sourceDevice = gesture_event.sourceDevice; - input_handler_->ScheduleAnimation(); + input_handler_->SetNeedsAnimate(); return DID_HANDLE; } case cc::InputHandler::ScrollUnknown: @@ -378,7 +378,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) { if (!fling_parameters_.startTime || monotonic_time_sec <= fling_parameters_.startTime) { fling_parameters_.startTime = monotonic_time_sec; - input_handler_->ScheduleAnimation(); + input_handler_->SetNeedsAnimate(); return; } @@ -390,7 +390,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) { fling_is_active = false; if (fling_is_active) { - input_handler_->ScheduleAnimation(); + input_handler_->SetNeedsAnimate(); } else { TRACE_EVENT_INSTANT0("input", "InputHandlerProxy::animate::flingOver", diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/content/renderer/input/input_handler_proxy_unittest.cc index 48f98fe..5cd8a83 100644 --- a/content/renderer/input/input_handler_proxy_unittest.cc +++ b/content/renderer/input/input_handler_proxy_unittest.cc @@ -43,7 +43,7 @@ class MockInputHandler : public cc::InputHandler { void(float magnify_delta, const gfx::Point& anchor)); MOCK_METHOD0(PinchGestureEnd, void()); - MOCK_METHOD0(ScheduleAnimation, void()); + MOCK_METHOD0(SetNeedsAnimate, void()); MOCK_METHOD2(ScrollBegin, ScrollStatus(const gfx::Point& viewport_point, @@ -405,7 +405,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) { EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); gesture_.type = WebInputEvent::GestureFlingStart; gesture_.data.flingStart.velocityX = 10; @@ -488,7 +488,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); @@ -500,7 +500,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { // fling start will typically include the last scroll from the gesture that // lead to the scroll (either wheel or gesture scroll), so there should be no // visible hitch. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); @@ -509,7 +509,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, @@ -562,7 +562,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { // Since we've aborted the fling, the next animation should be a no-op and // should not result in another // frame being requested. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()).Times(0); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); time += base::TimeDelta::FromMilliseconds(100); @@ -597,7 +597,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); @@ -607,7 +607,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { // Start the fling animation at time 10. This shouldn't actually scroll, just // establish a start time. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); @@ -616,7 +616,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, @@ -670,7 +670,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { // Since we've aborted the fling, the next animation should be a no-op and // should not result in another // frame being requested. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()).Times(0); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); time += base::TimeDelta::FromMilliseconds(100); @@ -702,7 +702,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); @@ -712,7 +712,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // Start the second fling animation at time 30. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); time = base::TimeTicks() + base::TimeDelta::FromSeconds(30); @@ -721,7 +721,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // Tick the second fling once normally. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, @@ -776,7 +776,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); gesture_.type = WebInputEvent::GestureFlingStart; gesture_.data.flingStart.velocityX = 10; @@ -881,7 +881,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -892,14 +892,14 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { // fling start will typically include the last scroll from the gesture that // lead to the scroll (either wheel or gesture scroll), so there should be no // visible hitch. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) @@ -945,7 +945,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -956,7 +956,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { // the likelihood of a hitch between the scroll preceding the fling and // the first scroll generated by the fling. // Scrolling should start in the -X direction. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) @@ -1005,7 +1005,7 @@ TEST_F(InputHandlerProxyTest, gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -1020,14 +1020,14 @@ TEST_F(InputHandlerProxyTest, // fling start will typically include the last scroll from the gesture that // lead to the scroll (either wheel or gesture scroll), so there should be no // visible hitch. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) @@ -1057,7 +1057,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { WebFloatPoint fling_delta = WebFloatPoint(1000, 1000); gesture_.data.flingStart.velocityX = fling_delta.x; gesture_.data.flingStart.velocityY = fling_delta.y; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); @@ -1065,13 +1065,13 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The first animate doesn't cause any scrolling. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second animate starts scrolling in the positive X and Y directions. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, @@ -1099,7 +1099,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { latest_overscroll_delta); // The next call to animate will no longer scroll vertically. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, @@ -1144,7 +1144,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -1152,7 +1152,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // With an animation timestamp equivalent to the starting timestamp, the // animation will simply be rescheduled. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); @@ -1160,7 +1160,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { // A small time delta should not stop the fling, even if the client // reports no scrolling. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) @@ -1173,7 +1173,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { // A time delta of zero should not stop the fling, and neither should it // trigger scrolling on the client. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); @@ -1213,18 +1213,18 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { gesture_.data.flingStart.velocityY = fling_delta.y; EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The first animate doesn't cause any scrolling. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second animate starts scrolling in the positive X and Y directions. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) @@ -1249,7 +1249,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { latest_overscroll_delta); // The next call to animate will no longer scroll vertically. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Eq(0)))) @@ -1274,7 +1274,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { latest_overscroll_delta); // The next call to animate will no longer scroll horizontally or vertically, // and the fling should be cancelled. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()).Times(0); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(10); @@ -1363,7 +1363,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { gesture_.data.flingStart.velocityY = fling_delta.y; EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); @@ -1418,7 +1418,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -1428,7 +1428,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { // If we get a negative time delta, that is, the Animation tick time happens // before the fling's start time then we should *not* try scrolling and // instead reset the fling start time. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); @@ -1440,7 +1440,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { // The first call should have reset the start time so subsequent calls should // generate scroll events. - EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) |