summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorloyso <loyso@chromium.org>2016-03-08 19:07:32 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-09 03:09:29 +0000
commit3338dfbd7f61e4ebb5a1e1519e0ef930cd7499d8 (patch)
tree4e9178d21feeb5c2cc791eeb440186b509191174
parente8cb0a5872250fc3845c0fbe7e49c88888301c71 (diff)
downloadchromium_src-3338dfbd7f61e4ebb5a1e1519e0ef930cd7499d8.zip
chromium_src-3338dfbd7f61e4ebb5a1e1519e0ef930cd7499d8.tar.gz
chromium_src-3338dfbd7f61e4ebb5a1e1519e0ef930cd7499d8.tar.bz2
UI Compositor: Fix threaded animation survival if layer removed and added.
This is minimal fix, scoped in ui/compositor. To be merged. In general, we must allow to move AnimationPlayers between timelines inside same Compositor(AnimationHost) without any animation losses. See http://crbug.com/592873 (To be designed separately) BUG=591474 Review URL: https://codereview.chromium.org/1776513002 Cr-Commit-Position: refs/heads/master@{#380047}
-rw-r--r--ui/compositor/layer_animator.cc29
-rw-r--r--ui/compositor/layer_animator.h6
-rw-r--r--ui/compositor/layer_animator_unittest.cc35
3 files changed, 69 insertions, 1 deletions
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc
index 7960200..20d268e 100644
--- a/ui/compositor/layer_animator.cc
+++ b/ui/compositor/layer_animator.cc
@@ -10,10 +10,13 @@
#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
#include "cc/animation/animation_events.h"
+#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/animation/animation_player.h"
+#include "cc/animation/animation_registrar.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/element_animations.h"
+#include "cc/animation/layer_animation_controller.h"
#include "cc/layers/layer_settings.h"
#include "cc/output/begin_frame_args.h"
#include "ui/compositor/compositor.h"
@@ -135,6 +138,9 @@ void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
}
void LayerAnimator::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
+ // Release LAC state for old layer.
+ animation_controller_state_ = nullptr;
+
if (delegate_) {
if (animation_player_)
DetachLayerFromAnimationPlayer();
@@ -154,16 +160,37 @@ void LayerAnimator::SetCompositor(Compositor* compositor) {
if (animation_player_) {
cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
DCHECK(timeline);
- timeline->AttachPlayer(animation_player_);
DCHECK(delegate_->GetCcLayer());
+
+ // Register LAC so ElementAnimations picks it up via
+ // AnimationRegistrar::GetAnimationControllerForId.
+ if (animation_controller_state_) {
+ DCHECK_EQ(animation_controller_state_->id(),
+ delegate_->GetCcLayer()->id());
+ timeline->animation_host()
+ ->animation_registrar()
+ ->RegisterAnimationController(animation_controller_state_.get());
+ }
+
+ timeline->AttachPlayer(animation_player_);
+
AttachLayerToAnimationPlayer(delegate_->GetCcLayer()->id());
+
+ // Release LAC (it is referenced in ElementAnimations).
+ animation_controller_state_ = nullptr;
}
}
void LayerAnimator::ResetCompositor(Compositor* compositor) {
DCHECK(compositor);
if (animation_player_) {
+ // Store a reference to LAC if any so it may be picked up in SetCompositor.
+ if (animation_player_->element_animations()) {
+ animation_controller_state_ =
+ animation_player_->element_animations()->layer_animation_controller();
+ }
+
DetachLayerFromAnimationPlayer();
cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
diff --git a/ui/compositor/layer_animator.h b/ui/compositor/layer_animator.h
index 349fd75..48e8a1e 100644
--- a/ui/compositor/layer_animator.h
+++ b/ui/compositor/layer_animator.h
@@ -26,6 +26,7 @@ class Animation;
class AnimationPlayer;
class AnimationTimeline;
class Layer;
+class LayerAnimationController;
}
namespace gfx {
@@ -391,6 +392,11 @@ class COMPOSITOR_EXPORT LayerAnimator
// aborted.
base::ObserverList<LayerAnimationObserver> observers_;
+ // We store a state of LayerAnimationController here to save it in
+ // ResetCompositor/SetCompositor scope.
+ // TODO(loyso): Remove it. crbug.com/592873.
+ scoped_refptr<cc::LayerAnimationController> animation_controller_state_;
+
DISALLOW_COPY_AND_ASSIGN(LayerAnimator);
};
diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc
index f15bb4a..9c1c5f1 100644
--- a/ui/compositor/layer_animator_unittest.cc
+++ b/ui/compositor/layer_animator_unittest.cc
@@ -2532,15 +2532,50 @@ TEST(LayerAnimatorTest, LayerMovedBetweenCompositorsDuringAnimation) {
LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
EXPECT_TRUE(compositor_1->layer_animator_collection()->HasActiveAnimators());
EXPECT_FALSE(compositor_2->layer_animator_collection()->HasActiveAnimators());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimation());
root_2.Add(&layer);
EXPECT_FALSE(compositor_1->layer_animator_collection()->HasActiveAnimators());
EXPECT_TRUE(compositor_2->layer_animator_collection()->HasActiveAnimators());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimation());
+
host_2.reset();
host_1.reset();
TerminateContextFactoryForTests();
}
+TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) {
+ bool enable_pixel_output = false;
+ ui::ContextFactory* context_factory =
+ InitializeContextFactoryForTests(enable_pixel_output);
+ const gfx::Rect bounds(10, 10, 100, 100);
+ scoped_ptr<TestCompositorHost> host(
+ TestCompositorHost::Create(bounds, context_factory));
+ host->Show();
+
+ Compositor* compositor = host->GetCompositor();
+
+ Layer root;
+ compositor->SetRootLayer(&root);
+
+ Layer layer;
+ root.Add(&layer);
+
+ LayerAnimator* animator = layer.GetAnimator();
+ double target_opacity = 1.0;
+ base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
+ animator->ScheduleAnimation(new LayerAnimationSequence(
+ LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
+
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimation());
+ root.Remove(&layer);
+ root.Add(&layer);
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimation());
+
+ host.reset();
+ TerminateContextFactoryForTests();
+}
+
class LayerOwnerAnimationObserver : public LayerAnimationObserver {
public:
LayerOwnerAnimationObserver(LayerAnimator* animator)