summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj <danakj@chromium.org>2015-08-28 12:28:59 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-28 19:29:31 +0000
commitb56d7d81c1d3a9f93f819faee2e0de5ccc315edf (patch)
tree54690d8bebd18c59296a92f8b10d833f37604a5c
parent35179fe97bd4a26a165b76aa95a82f21e1ba47cb (diff)
downloadchromium_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.cc5
-rw-r--r--cc/test/layer_tree_test.h1
-rw-r--r--cc/trees/layer_tree_host_impl.cc16
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc97
-rw-r--r--cc/trees/layer_tree_host_unittest_animation.cc77
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());