diff options
author | danakj <danakj@chromium.org> | 2015-08-28 12:28:59 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-28 19:29:31 +0000 |
commit | b56d7d81c1d3a9f93f819faee2e0de5ccc315edf (patch) | |
tree | 54690d8bebd18c59296a92f8b10d833f37604a5c | |
parent | 35179fe97bd4a26a165b76aa95a82f21e1ba47cb (diff) | |
download | chromium_src-b56d7d81c1d3a9f93f819faee2e0de5ccc315edf.zip chromium_src-b56d7d81c1d3a9f93f819faee2e0de5ccc315edf.tar.gz chromium_src-b56d7d81c1d3a9f93f819faee2e0de5ccc315edf.tar.bz2 |
cc: Do Animate() for the new pending tree on CommitComplete.
This adds an Animate() call in LayerTreeHostImpl::CommitComplete. This
call will move any animations on the new pending tree that are ready
from the WAITING_FOR_TARGET_AVAILABILITY to the STARTING state,
allowing them to notify the layers they are attached to of their new
animated values.
Doing this before UpdateDrawProperties ensures that the draw properties
reflect the animations in order to prepare the correct tiles for
activating.
This adds a new test that verifies we do start animations on the
pending tree, and that the properties propogate to the layers they
are on, both in single thread (commit-to-active) and in threaded mode.
It also adds a test that verifies we request new animation frames when
a layer animation is active from LayerTreeHostImpl, similar to other
tests we have for animating scrollbars or pinch zoom, etc.
R=ajuma, brianderson
BUG=522658
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1319073002
Cr-Commit-Position: refs/heads/master@{#346211}
-rw-r--r-- | cc/test/layer_tree_test.cc | 5 | ||||
-rw-r--r-- | cc/test/layer_tree_test.h | 1 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 16 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 97 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_animation.cc | 77 |
5 files changed, 182 insertions, 14 deletions
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 8bb46c88..c87c36b 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc @@ -338,6 +338,11 @@ class LayerTreeHostImplForTesting : public LayerTreeHostImpl { test_hooks_->CommitCompleteOnThread(this); } + bool PrepareTiles() override { + test_hooks_->WillPrepareTiles(this); + return LayerTreeHostImpl::PrepareTiles(); + } + DrawResult PrepareToDraw(FrameData* frame) override { DrawResult draw_result = LayerTreeHostImpl::PrepareToDraw(frame); return test_hooks_->PrepareToDrawOnThread(this, frame, draw_result); diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h index 9eaa8f4..5a22087 100644 --- a/cc/test/layer_tree_test.h +++ b/cc/test/layer_tree_test.h @@ -61,6 +61,7 @@ class TestHooks : public AnimationDelegate { virtual void DidFinishImplFrameOnThread(LayerTreeHostImpl* host_impl) {} virtual void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl, CommitEarlyOutReason reason) {} + virtual void WillPrepareTiles(LayerTreeHostImpl* host_impl) {} virtual void BeginCommitOnThread(LayerTreeHostImpl* host_impl) {} virtual void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) {} virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) {} diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index f711cd9..fa3ba0e 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -322,6 +322,12 @@ void LayerTreeHostImpl::CommitComplete() { ActivateAnimations(); } + // Start animations before UpdateDrawProperties and PrepareTiles, as they can + // change the results. When doing commit to the active tree, this must happen + // after ActivateAnimations() in order for this ticking to be propogated to + // layers on the active tree. + Animate(); + // LayerTreeHost may have changed the GPU rasterization flags state, which // may require an update of the tree resources. UpdateTreeResourcesForGpuRasterizationIfNeeded(); @@ -3072,13 +3078,19 @@ void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) { if (!settings_.accelerated_animation_enabled) return; + bool animated = false; if (animation_host_) { if (animation_host_->AnimateLayers(monotonic_time)) - SetNeedsAnimate(); + animated = true; } else { if (animation_registrar_->AnimateLayers(monotonic_time)) - SetNeedsAnimate(); + animated = true; } + + // TODO(ajuma): Only do this if the animations are on the active tree, or if + // they are on the pending tree waiting for some future time to start. + if (animated) + SetNeedsAnimate(); } void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) { diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 06c5c83..db51dc9 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -14,6 +14,7 @@ #include "base/location.h" #include "base/thread_task_runner_handle.h" #include "cc/animation/scrollbar_animation_controller_thinning.h" +#include "cc/animation/transform_operations.h" #include "cc/base/math_util.h" #include "cc/input/page_scale_animation.h" #include "cc/input/top_controls_manager.h" @@ -1068,6 +1069,102 @@ TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset()); } +TEST_F(LayerTreeHostImplTest, AnimationSchedulingPendingTree) { + host_impl_->SetViewportSize(gfx::Size(50, 50)); + + host_impl_->CreatePendingTree(); + host_impl_->pending_tree()->SetRootLayer( + LayerImpl::Create(host_impl_->pending_tree(), 1)); + LayerImpl* root = host_impl_->pending_tree()->root_layer(); + root->SetBounds(gfx::Size(50, 50)); + root->SetHasRenderSurface(true); + + root->AddChild(LayerImpl::Create(host_impl_->pending_tree(), 2)); + LayerImpl* child = root->children()[0]; + child->SetBounds(gfx::Size(10, 10)); + child->draw_properties().visible_layer_rect = gfx::Rect(10, 10); + child->SetDrawsContent(true); + AddAnimatedTransformToLayer(child, 10.0, 3, 0); + + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_commit_); + + host_impl_->Animate(); + + // An animation exists on the pending layer. Doing Animate() requests another + // frame. + // In reality, animations without has_set_start_time() == true do not need to + // be continuously ticked on the pending tree, so it should not request + // another animation frame here. But we currently do so blindly if any + // animation exists. + EXPECT_TRUE(did_request_animate_); + // The pending tree with an animation does not need to draw after animating. + EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_commit_); + + did_request_animate_ = false; + did_request_redraw_ = false; + did_request_commit_ = false; + + host_impl_->ActivateSyncTree(); + + // When the animation activates, we should request another animation frame + // to keep the animation moving. + EXPECT_TRUE(did_request_animate_); + // On activation we don't need to request a redraw for the animation, + // activating will draw on its own when it's ready. + EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_commit_); +} + +TEST_F(LayerTreeHostImplTest, AnimationSchedulingActiveTree) { + host_impl_->SetViewportSize(gfx::Size(50, 50)); + + host_impl_->active_tree()->SetRootLayer( + LayerImpl::Create(host_impl_->active_tree(), 1)); + LayerImpl* root = host_impl_->active_tree()->root_layer(); + root->SetBounds(gfx::Size(50, 50)); + root->SetHasRenderSurface(true); + + root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2)); + LayerImpl* child = root->children()[0]; + child->SetBounds(gfx::Size(10, 10)); + child->draw_properties().visible_layer_rect = gfx::Rect(10, 10); + child->SetDrawsContent(true); + + // Add a translate from 6,7 to 8,9. + TransformOperations start; + start.AppendTranslate(6.f, 7.f, 0.f); + TransformOperations end; + end.AppendTranslate(8.f, 9.f, 0.f); + AddAnimatedTransformToLayer(child, 4.0, start, end); + + base::TimeTicks now = base::TimeTicks::Now(); + host_impl_->WillBeginImplFrame( + CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now)); + + EXPECT_FALSE(did_request_animate_); + EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_commit_); + + host_impl_->ActivateAnimations(); + did_request_animate_ = false; + did_request_redraw_ = false; + did_request_commit_ = false; + + host_impl_->Animate(); + + // An animation exists on the active layer. Doing Animate() requests another + // frame after the current one. + EXPECT_TRUE(did_request_animate_); + // TODO(danakj): We also need to draw in the current frame if something + // animated, but this is currently handled by + // SchedulerStateMachine::WillAnimate. + EXPECT_FALSE(did_request_redraw_); + EXPECT_FALSE(did_request_commit_); +} + TEST_F(LayerTreeHostImplTest, ImplPinchZoom) { LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); host_impl_->SetViewportSize(gfx::Size(50, 50)); diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index 5587d6d..b41005a 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc @@ -8,6 +8,7 @@ #include "cc/animation/layer_animation_controller.h" #include "cc/animation/scroll_offset_animation_curve.h" #include "cc/animation/timing_function.h" +#include "cc/animation/transform_operations.h" #include "cc/base/completion_event.h" #include "cc/base/time_util.h" #include "cc/layers/layer.h" @@ -228,8 +229,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostAnimationTestAnimationsGetDeleted); class LayerTreeHostAnimationTestAddAnimationWithTimingFunction : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestAddAnimationWithTimingFunction() {} - void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); @@ -241,6 +240,10 @@ class LayerTreeHostAnimationTestAddAnimationWithTimingFunction void AnimateLayers(LayerTreeHostImpl* host_impl, base::TimeTicks monotonic_time) override { + // TODO(ajuma): This test only checks the active tree. Add checks for + // pending tree too. + if (!host_impl->active_tree()->root_layer()) + return; LayerAnimationController* controller_impl = host_impl->active_tree()->root_layer()->children()[0]-> layer_animation_controller(); @@ -277,8 +280,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F( class LayerTreeHostAnimationTestSynchronizeAnimationStartTimes : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestSynchronizeAnimationStartTimes() {} - void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); picture_ = FakePictureLayer::Create(layer_settings(), &client_); @@ -332,8 +333,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F( class LayerTreeHostAnimationTestAnimationFinishedEvents : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestAnimationFinishedEvents() {} - void BeginTest() override { PostAddInstantAnimationToMainThread(layer_tree_host()->root_layer()); } @@ -405,8 +404,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F( class LayerTreeHostAnimationTestLayerAddedWithAnimation : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestLayerAddedWithAnimation() {} - void BeginTest() override { PostSetNeedsCommitToMainThread(); } void DidCommit() override { @@ -635,8 +632,6 @@ MULTI_THREAD_TEST_F( class LayerTreeHostAnimationTestScrollOffsetChangesArePropagated : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestScrollOffsetChangesArePropagated() {} - void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); @@ -879,13 +874,71 @@ class LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers MULTI_THREAD_BLOCKNOTIFY_TEST_F( LayerTreeHostAnimationTestAnimationsAddedToNewAndExistingLayers); +class LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit + : public LayerTreeHostAnimationTest { + public: + void SetupTree() override { + LayerTreeHostAnimationTest::SetupTree(); + + layer_ = FakePictureLayer::Create(layer_settings(), &client_); + layer_->SetBounds(gfx::Size(2, 2)); + // Transform the layer to 4,4 to start. + gfx::Transform start_transform; + start_transform.Translate(4.0, 4.0); + layer_->SetTransform(start_transform); + + layer_tree_host()->root_layer()->AddChild(layer_); + } + + void BeginTest() override { + // Add a translate from 6,7 to 8,9. + TransformOperations start; + start.AppendTranslate(6.f, 7.f, 0.f); + TransformOperations end; + end.AppendTranslate(8.f, 9.f, 0.f); + AddAnimatedTransformToLayer(layer_.get(), 4.0, start, end); + + PostSetNeedsCommitToMainThread(); + } + + void WillPrepareTiles(LayerTreeHostImpl* host_impl) override { + if (host_impl->sync_tree()->source_frame_number() != 0) + return; + LayerImpl* root = host_impl->sync_tree()->root_layer(); + LayerImpl* child = root->children()[0]; + LayerAnimationController* controller_impl = + child->layer_animation_controller(); + Animation* animation = controller_impl->GetAnimation(Animation::TRANSFORM); + + // The animation should be starting for the first frame. + EXPECT_EQ(Animation::STARTING, animation->run_state()); + + // And the transform should be propogated to the sync tree layer, at its + // starting state which is 6,7. + gfx::Transform expected_transform; + expected_transform.Translate(6.0, 7.0); + EXPECT_EQ(expected_transform, child->draw_transform()); + // And the sync tree layer should know it is animating. + EXPECT_TRUE(child->screen_space_transform_is_animating()); + + controller_impl->AbortAnimations(Animation::TRANSFORM); + EndTest(); + } + + void AfterTest() override {} + + FakeContentLayerClient client_; + scoped_refptr<Layer> layer_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostAnimationTestPendingTreeAnimatesFirstCommit); + // When a layer with an animation is removed from the tree and later re-added, // the animation should resume. class LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded : public LayerTreeHostAnimationTest { public: - LayerTreeHostAnimationTestAnimatedLayerRemovedAndAdded() {} - void SetupTree() override { LayerTreeHostAnimationTest::SetupTree(); layer_ = Layer::Create(layer_settings()); |