0

Revert 171714 - Use an auxiliary list of animation controllers.

> With this patch we accomplish the following:
>  1. layer animation controllers are ref counted (so they can be shared by the two impl trees)
>  2. the layer tree hosts now own a list of active animation controllers. This allows for a couple of nice things
>  __a. Ticking the animation controllers no longer requires a tree walk
>  __b. We will be able to support ticking of animation controllers for layers that are not yet added to the layer tree. (Support coming in a future patch).
>  3. animation controllers register and unregister themselves from their respective layer tree host's list when they have an animation to tick.
>
> BUG=162111
> Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=171714

TBR=vollick@chromium.org
BUG=

Review URL: https://codereview.chromium.org/11491003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171981 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
vollick@chromium.org
2012-12-08 17:01:18 +00:00
parent 9b39fe5ba8
commit df1ec1ac79
24 changed files with 434 additions and 414 deletions

@ -1,35 +0,0 @@
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_ANIMATION_REGISTRAR_H_
#define CC_ANIMATION_REGISTRAR_H_
namespace cc {
class LayerAnimationController;
// TODO(vollick): we need to rename:
// AnimationRegistrar -> AnimationController
// LayerAnimationController -> LayerAnimator
class CC_EXPORT AnimationRegistrar {
public:
// Registers the given animation controller as active. An active animation
// controller is one that has a running animation that needs to be ticked.
virtual void DidActivateAnimationController(LayerAnimationController*) = 0;
// Unregisters the given animation controller. When this happens, the
// animation controller will no longer be ticked (since it's not active). It
// is not an error to call this function with a deactivated controller.
virtual void DidDeactivateAnimationController(LayerAnimationController*) = 0;
// Registers the given controller as alive.
virtual void RegisterAnimationController(LayerAnimationController*) = 0;
// Unregisters the given controller as alive.
virtual void UnregisterAnimationController(LayerAnimationController*) = 0;
};
} // namespace cc
#endif // CC_ANIMATION_REGISTRAR_H_

@ -10,7 +10,6 @@
'animation_curve.cc',
'animation_curve.h',
'animation_events.h',
'animation_registrar.h',
'append_quads_data.h',
'bitmap_content_layer_updater.cc',
'bitmap_content_layer_updater.h',

@ -32,7 +32,7 @@ Layer::Layer()
, m_layerId(s_nextLayerId++)
, m_parent(0)
, m_layerTreeHost(0)
, m_layerAnimationController(LayerAnimationController::create())
, m_layerAnimationController(LayerAnimationController::create(this))
, m_scrollable(false)
, m_shouldScrollOnMainThread(false)
, m_haveWheelEventHandlers(false)
@ -40,6 +40,7 @@ Layer::Layer()
, m_touchEventHandlerRegionChanged(false)
, m_anchorPoint(0.5, 0.5)
, m_backgroundColor(0)
, m_opacity(1.0)
, m_anchorPointZ(0)
, m_isContainerForFixedPositionLayers(false)
, m_fixedToContainerLayer(false)
@ -63,7 +64,6 @@ Layer::Layer()
s_nextLayerId = 1;
m_layerId = s_nextLayerId++;
}
m_layerAnimationController->setId(m_layerId);
}
Layer::~Layer()
@ -96,7 +96,9 @@ void Layer::setLayerTreeHost(LayerTreeHost* host)
if (m_replicaLayer)
m_replicaLayer->setLayerTreeHost(host);
m_layerAnimationController->setAnimationRegistrar(host);
// If this layer already has active animations, the host needs to be notified.
if (host && m_layerAnimationController->hasActiveAnimation())
host->didAddAnimation();
}
void Layer::setNeedsCommit()
@ -356,16 +358,12 @@ bool Layer::needsDisplay() const
void Layer::setOpacity(float opacity)
{
if (!m_layerAnimationController->setOpacity(opacity))
if (m_opacity == opacity)
return;
m_opacity = opacity;
setNeedsCommit();
}
float Layer::opacity() const
{
return m_layerAnimationController->opacity();
}
bool Layer::opacityIsAnimating() const
{
return m_layerAnimationController->isAnimatingProperty(ActiveAnimation::Opacity);
@ -397,16 +395,12 @@ void Layer::setSublayerTransform(const gfx::Transform& sublayerTransform)
void Layer::setTransform(const gfx::Transform& transform)
{
if (!m_layerAnimationController->setTransform(transform))
if (m_transform == transform)
return;
m_transform = transform;
setNeedsCommit();
}
const gfx::Transform& Layer::transform() const
{
return m_layerAnimationController->transform();
}
bool Layer::transformIsAnimating() const
{
return m_layerAnimationController->isAnimatingProperty(ActiveAnimation::Transform);
@ -589,6 +583,8 @@ void Layer::pushPropertiesTo(LayerImpl* layer)
m_touchEventHandlerRegionChanged = false;
}
layer->setContentsOpaque(m_contentsOpaque);
if (!opacityIsAnimating())
layer->setOpacity(m_opacity);
layer->setPosition(m_position);
layer->setIsContainerForFixedPositionLayers(m_isContainerForFixedPositionLayers);
layer->setFixedToContainerLayer(m_fixedToContainerLayer);
@ -597,6 +593,8 @@ void Layer::pushPropertiesTo(LayerImpl* layer)
layer->setScrollOffset(m_scrollOffset);
layer->setMaxScrollOffset(m_maxScrollOffset);
layer->setSublayerTransform(m_sublayerTransform);
if (!transformIsAnimating())
layer->setTransform(m_transform);
// If the main thread commits multiple times before the impl thread actually draws, then damage tracking
// will become incorrect if we simply clobber the updateRect here. The LayerImpl's updateRect needs to
@ -720,6 +718,32 @@ int Layer::id() const
return m_layerId;
}
float Layer::opacity() const
{
return m_opacity;
}
void Layer::setOpacityFromAnimation(float opacity)
{
// This is called due to an ongoing accelerated animation. Since this animation is
// also being run on the impl thread, there is no need to request a commit to push
// this value over, so set the value directly rather than calling setOpacity.
m_opacity = opacity;
}
const gfx::Transform& Layer::transform() const
{
return m_transform;
}
void Layer::setTransformFromAnimation(const gfx::Transform& transform)
{
// This is called due to an ongoing accelerated animation. Since this animation is
// also being run on the impl thread, there is no need to request a commit to push
// this value over, so set this value directly rather than calling setTransform.
m_transform = transform;
}
bool Layer::addAnimation(scoped_ptr <ActiveAnimation> animation)
{
// WebCore currently assumes that accelerated animations will start soon
@ -739,7 +763,10 @@ bool Layer::addAnimation(scoped_ptr <ActiveAnimation> animation)
#endif
m_layerAnimationController->addAnimation(animation.Pass());
if (m_layerTreeHost) {
m_layerTreeHost->didAddAnimation();
setNeedsCommit();
}
return true;
}
@ -767,24 +794,21 @@ void Layer::resumeAnimations(double monotonicTime)
setNeedsCommit();
}
void Layer::setLayerAnimationController(scoped_refptr<LayerAnimationController> layerAnimationController)
void Layer::setLayerAnimationController(scoped_ptr<LayerAnimationController> layerAnimationController)
{
m_layerAnimationController = layerAnimationController;
m_layerAnimationController = layerAnimationController.Pass();
if (m_layerAnimationController) {
m_layerAnimationController->setId(id());
m_layerAnimationController->setClient(this);
m_layerAnimationController->setForceSync();
}
setNeedsCommit();
}
scoped_refptr<LayerAnimationController> Layer::releaseLayerAnimationController()
scoped_ptr<LayerAnimationController> Layer::releaseLayerAnimationController()
{
scoped_refptr<LayerAnimationController> toReturn = m_layerAnimationController;
m_layerAnimationController = LayerAnimationController::create();
m_layerAnimationController->setId(id());
m_layerAnimationController->setTransform(toReturn->transform());
m_layerAnimationController->setOpacity(toReturn->opacity());
return toReturn;
scoped_ptr<LayerAnimationController> toReturn = m_layerAnimationController.Pass();
m_layerAnimationController = LayerAnimationController::create(this);
return toReturn.Pass();
}
bool Layer::hasActiveAnimation() const

@ -44,13 +44,21 @@ struct RenderingStats;
// Base class for composited layers. Special layer types are derived from
// this class.
class CC_EXPORT Layer : public base::RefCounted<Layer> {
class CC_EXPORT Layer : public base::RefCounted<Layer>, public LayerAnimationControllerClient {
public:
typedef std::vector<scoped_refptr<Layer> > LayerList;
static scoped_refptr<Layer> create();
int id() const;
// LayerAnimationControllerClient implementation
virtual int id() const OVERRIDE;
virtual void setOpacityFromAnimation(float) OVERRIDE;
virtual float opacity() const OVERRIDE;
virtual void setTransformFromAnimation(const gfx::Transform&) OVERRIDE;
// A layer's transform operates layer space. That is, entirely in logical,
// non-page-scaled pixels (that is, they have page zoom baked in, but not page scale).
// The root layer is a special case -- it operates in physical pixels.
virtual const gfx::Transform& transform() const OVERRIDE;
Layer* rootLayer();
Layer* parent() { return m_parent; }
@ -91,7 +99,6 @@ public:
virtual bool needsDisplay() const;
void setOpacity(float);
float opacity() const;
bool opacityIsAnimating() const;
void setFilters(const WebKit::WebFilterOperations&);
@ -121,7 +128,6 @@ public:
const gfx::Transform& sublayerTransform() const { return m_sublayerTransform; }
void setTransform(const gfx::Transform&);
const gfx::Transform& transform() const;
bool transformIsAnimating() const;
DrawProperties<Layer, RenderSurface>& drawProperties() { return m_drawProperties; }
@ -261,8 +267,8 @@ public:
void resumeAnimations(double monotonicTime);
LayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); }
void setLayerAnimationController(scoped_refptr<LayerAnimationController>);
scoped_refptr<LayerAnimationController> releaseLayerAnimationController();
void setLayerAnimationController(scoped_ptr<LayerAnimationController>);
scoped_ptr<LayerAnimationController> releaseLayerAnimationController();
void setLayerAnimationDelegate(WebKit::WebAnimationDelegate* layerAnimationDelegate) { m_layerAnimationDelegate = layerAnimationDelegate; }
@ -333,7 +339,7 @@ private:
// updated via setLayerTreeHost() if a layer moves between trees.
LayerTreeHost* m_layerTreeHost;
scoped_refptr<LayerAnimationController> m_layerAnimationController;
scoped_ptr<LayerAnimationController> m_layerAnimationController;
// Layer properties.
gfx::Size m_bounds;
@ -351,6 +357,7 @@ private:
gfx::PointF m_anchorPoint;
SkColor m_backgroundColor;
std::string m_debugName;
float m_opacity;
skia::RefPtr<SkImageFilter> m_filter;
WebKit::WebFilterOperations m_filters;
WebKit::WebFilterOperations m_backgroundFilters;
@ -367,6 +374,7 @@ private:
bool m_drawCheckerboardForMissingTiles;
bool m_forceRenderSurface;
gfx::Transform m_transform;
gfx::Transform m_sublayerTransform;
// Replica layer used for reflections.

@ -5,29 +5,24 @@
#include "cc/layer_animation_controller.h"
#include "cc/active_animation.h"
#include "cc/animation_registrar.h"
#include "cc/keyframed_animation_curve.h"
#include "ui/gfx/transform.h"
namespace cc {
LayerAnimationController::LayerAnimationController()
LayerAnimationController::LayerAnimationController(LayerAnimationControllerClient* client)
: m_forceSync(false)
, m_id(-1)
, m_opacity(1.0)
, m_registrar(0)
, m_client(client)
{
}
LayerAnimationController::~LayerAnimationController()
{
if (m_registrar)
m_registrar->DidDeactivateAnimationController(this);
}
scoped_refptr<LayerAnimationController> LayerAnimationController::create()
scoped_ptr<LayerAnimationController> LayerAnimationController::create(LayerAnimationControllerClient* client)
{
return make_scoped_refptr(new LayerAnimationController());
return make_scoped_ptr(new LayerAnimationController(client));
}
void LayerAnimationController::pauseAnimation(int animationId, double timeOffset)
@ -46,7 +41,6 @@ void LayerAnimationController::removeAnimation(int animationId)
else
i++;
}
updateRegistration();
}
void LayerAnimationController::removeAnimation(int animationId, ActiveAnimation::TargetProperty targetProperty)
@ -57,7 +51,6 @@ void LayerAnimationController::removeAnimation(int animationId, ActiveAnimation:
else
i++;
}
updateRegistration();
}
// According to render layer backing, these are for testing only.
@ -82,12 +75,6 @@ void LayerAnimationController::resumeAnimations(double monotonicTime)
// are kept in sync.
void LayerAnimationController::pushAnimationUpdatesTo(LayerAnimationController* controllerImpl)
{
if (!isAnimatingProperty(ActiveAnimation::Opacity))
controllerImpl->m_opacity = m_opacity;
if (!isAnimatingProperty(ActiveAnimation::Transform))
controllerImpl->m_transform = m_transform;
if (m_forceSync) {
replaceImplThreadAnimations(controllerImpl);
m_forceSync = false;
@ -113,14 +100,11 @@ void LayerAnimationController::animate(double monotonicTime, AnimationEventsVect
tickAnimations(monotonicTime);
markAnimationsForDeletion(monotonicTime, events);
startAnimationsWaitingForTargetAvailability(monotonicTime, events);
updateRegistration();
}
void LayerAnimationController::addAnimation(scoped_ptr<ActiveAnimation> animation)
{
m_activeAnimations.append(animation.Pass());
updateRegistration();
}
ActiveAnimation* LayerAnimationController::getActiveAnimation(int groupId, ActiveAnimation::TargetProperty targetProperty) const
@ -170,40 +154,9 @@ void LayerAnimationController::notifyAnimationStarted(const AnimationEvent& even
}
}
void LayerAnimationController::setAnimationRegistrar(AnimationRegistrar* registrar)
void LayerAnimationController::setClient(LayerAnimationControllerClient* client)
{
if (m_registrar == registrar)
return;
if (m_registrar)
m_registrar->UnregisterAnimationController(this);
m_registrar = registrar;
if (m_registrar)
m_registrar->RegisterAnimationController(this);
updateRegistration();
}
void LayerAnimationController::setId(int id)
{
m_id = id;
}
bool LayerAnimationController::setOpacity(float opacity)
{
if (m_opacity == opacity || isAnimatingProperty(ActiveAnimation::Opacity))
return false;
m_opacity = opacity;
return true;
}
bool LayerAnimationController::setTransform(const gfx::Transform& transform)
{
if (m_transform == transform || isAnimatingProperty(ActiveAnimation::Transform))
return false;
m_transform = transform;
return true;
m_client = client;
}
void LayerAnimationController::pushNewAnimationsToImplThread(LayerAnimationController* controllerImpl) const
@ -261,7 +214,7 @@ void LayerAnimationController::startAnimationsWaitingForNextTick(double monotoni
if (!m_activeAnimations[i]->hasSetStartTime())
m_activeAnimations[i]->setStartTime(monotonicTime);
if (events)
events->push_back(AnimationEvent(AnimationEvent::Started, m_id, m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
events->push_back(AnimationEvent(AnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
}
}
}
@ -272,7 +225,7 @@ void LayerAnimationController::startAnimationsWaitingForStartTime(double monoton
if (m_activeAnimations[i]->runState() == ActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) {
m_activeAnimations[i]->setRunState(ActiveAnimation::Running, monotonicTime);
if (events)
events->push_back(AnimationEvent(AnimationEvent::Started, m_id, m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
events->push_back(AnimationEvent(AnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
}
}
}
@ -311,7 +264,7 @@ void LayerAnimationController::startAnimationsWaitingForTargetAvailability(doubl
if (!m_activeAnimations[i]->hasSetStartTime())
m_activeAnimations[i]->setStartTime(monotonicTime);
if (events)
events->push_back(AnimationEvent(AnimationEvent::Started, m_id, m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
events->push_back(AnimationEvent(AnimationEvent::Started, m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) {
m_activeAnimations[j]->setRunState(ActiveAnimation::Running, monotonicTime);
@ -367,7 +320,7 @@ void LayerAnimationController::markAnimationsForDeletion(double monotonicTime, A
for (size_t j = i; j < m_activeAnimations.size(); j++) {
if (groupId == m_activeAnimations[j]->group()) {
if (events)
events->push_back(AnimationEvent(AnimationEvent::Finished, m_id, m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty(), monotonicTime));
events->push_back(AnimationEvent(AnimationEvent::Finished, m_client->id(), m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty(), monotonicTime));
m_activeAnimations[j]->setRunState(ActiveAnimation::WaitingForDeletion, monotonicTime);
}
}
@ -405,7 +358,7 @@ void LayerAnimationController::replaceImplThreadAnimations(LayerAnimationControl
void LayerAnimationController::tickAnimations(double monotonicTime)
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
if (m_activeAnimations[i]->runState() == ActiveAnimation::Running || m_activeAnimations[i]->runState() == ActiveAnimation::Paused) {
double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime);
@ -418,17 +371,21 @@ void LayerAnimationController::tickAnimations(double monotonicTime)
case ActiveAnimation::Transform: {
const TransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve();
m_transform = transformAnimationCurve->getValue(trimmed).toTransform();
const gfx::Transform matrix = transformAnimationCurve->getValue(trimmed).toTransform();
if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
m_activeAnimations[i]->setRunState(ActiveAnimation::Finished, monotonicTime);
m_client->setTransformFromAnimation(matrix);
break;
}
case ActiveAnimation::Opacity: {
const FloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve();
m_opacity = floatAnimationCurve->getValue(trimmed);
const float opacity = floatAnimationCurve->getValue(trimmed);
if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
m_activeAnimations[i]->setRunState(ActiveAnimation::Finished, monotonicTime);
m_client->setOpacityFromAnimation(opacity);
break;
}
@ -440,14 +397,4 @@ void LayerAnimationController::tickAnimations(double monotonicTime)
}
}
void LayerAnimationController::updateRegistration()
{
if (m_registrar) {
if (hasActiveAnimation())
m_registrar->DidActivateAnimationController(this);
else
m_registrar->DidDeactivateAnimationController(this);
}
}
} // namespace cc

@ -7,13 +7,10 @@
#include "base/basictypes.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "cc/animation_events.h"
#include "cc/cc_export.h"
#include "cc/scoped_ptr_vector.h"
#include "ui/gfx/transform.h"
namespace gfx {
class Transform;
@ -22,13 +19,24 @@ class Transform;
namespace cc {
class Animation;
class AnimationRegistrar;
class KeyframeValueList;
class CC_EXPORT LayerAnimationController
: public base::RefCounted<LayerAnimationController> {
class CC_EXPORT LayerAnimationControllerClient {
public:
static scoped_refptr<LayerAnimationController> create();
virtual ~LayerAnimationControllerClient() { }
virtual int id() const = 0;
virtual void setOpacityFromAnimation(float) = 0;
virtual float opacity() const = 0;
virtual void setTransformFromAnimation(const gfx::Transform&) = 0;
virtual const gfx::Transform& transform() const = 0;
};
class CC_EXPORT LayerAnimationController {
public:
static scoped_ptr<LayerAnimationController> create(LayerAnimationControllerClient*);
virtual ~LayerAnimationController();
// These methods are virtual for testing.
virtual void addAnimation(scoped_ptr<ActiveAnimation>);
@ -67,30 +75,10 @@ public:
// thread, all animations will be transferred.
void setForceSync() { m_forceSync = true; }
void setAnimationRegistrar(AnimationRegistrar*);
void setId(int id);
// Gets the last animated opacity value.
float opacity() const { return m_opacity; }
// Sets the opacity. Returns true if this call actually updates the opacity.
// This can return false if either the new opacity matches the old, or if
// the property is currently animating.
bool setOpacity(float opacity);
// Gets the last animate transform value.
const gfx::Transform& transform() const { return m_transform; }
// Sets the transform. Returns true if this call actually updates the
// transform. This can return false if either the new transform matches the
// old or if the property is currently animating.
bool setTransform(const gfx::Transform& transform);
void setClient(LayerAnimationControllerClient*);
protected:
friend class base::RefCounted<LayerAnimationController>;
LayerAnimationController();
virtual ~LayerAnimationController();
explicit LayerAnimationController(LayerAnimationControllerClient*);
private:
typedef base::hash_set<int> TargetProperties;
@ -109,16 +97,10 @@ private:
void tickAnimations(double monotonicTime);
void updateRegistration();
// If this is true, we force a sync to the impl thread.
bool m_forceSync;
float m_opacity;
gfx::Transform m_transform;
AnimationRegistrar* m_registrar;
int m_id;
LayerAnimationControllerClient* m_client;
ScopedPtrVector<ActiveAnimation> m_activeAnimations;
DISALLOW_COPY_AND_ASSIGN(LayerAnimationController);

@ -26,8 +26,10 @@ scoped_ptr<ActiveAnimation> createActiveAnimation(scoped_ptr<AnimationCurve> cur
TEST(LayerAnimationControllerTest, syncNewAnimation)
{
scoped_refptr<LayerAnimationController> controllerImpl(LayerAnimationController::create());
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummyImpl;
scoped_ptr<LayerAnimationController> controllerImpl(LayerAnimationController::create(&dummyImpl));
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(LayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, ActiveAnimation::Opacity));
@ -43,8 +45,10 @@ TEST(LayerAnimationControllerTest, syncNewAnimation)
// thread, we must be sure to respect the synchronized start time.
TEST(LayerAnimationControllerTest, doNotClobberStartTimes)
{
scoped_refptr<LayerAnimationController> controllerImpl(LayerAnimationController::create());
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummyImpl;
scoped_ptr<LayerAnimationController> controllerImpl(LayerAnimationController::create(&dummyImpl));
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(LayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, ActiveAnimation::Opacity));
@ -70,8 +74,10 @@ TEST(LayerAnimationControllerTest, doNotClobberStartTimes)
TEST(LayerAnimationControllerTest, syncPauseAndResume)
{
scoped_refptr<LayerAnimationController> controllerImpl(LayerAnimationController::create());
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummyImpl;
scoped_ptr<LayerAnimationController> controllerImpl(LayerAnimationController::create(&dummyImpl));
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(LayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, ActiveAnimation::Opacity));
@ -108,8 +114,10 @@ TEST(LayerAnimationControllerTest, syncPauseAndResume)
TEST(LayerAnimationControllerTest, doNotSyncFinishedAnimation)
{
scoped_refptr<LayerAnimationController> controllerImpl(LayerAnimationController::create());
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummyImpl;
scoped_ptr<LayerAnimationController> controllerImpl(LayerAnimationController::create(&dummyImpl));
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(LayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, ActiveAnimation::Opacity));
@ -139,16 +147,18 @@ TEST(LayerAnimationControllerTest, doNotSyncFinishedAnimation)
TEST(LayerAnimationControllerTest, TrivialTransition)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
controller->addAnimation(toAdd.Pass());
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1, events.get());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -156,7 +166,9 @@ TEST(LayerAnimationControllerTest, TrivialTransition)
TEST(LayerAnimationControllerTest, AnimationsWaitingForStartTimeDoNotFinishIfTheyWaitLongerToStartThanTheirDuration)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
toAdd->setNeedsSynchronizedStartTime(true);
@ -165,18 +177,18 @@ TEST(LayerAnimationControllerTest, AnimationsWaitingForStartTimeDoNotFinishIfThe
controller->addAnimation(toAdd.Pass());
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(2, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
// Send the synchronized start time.
controller->notifyAnimationStarted(AnimationEvent(AnimationEvent::Started, 0, 1, ActiveAnimation::Opacity, 2));
controller->animate(5, events.get());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -184,19 +196,21 @@ TEST(LayerAnimationControllerTest, AnimationsWaitingForStartTimeDoNotFinishIfThe
TEST(LayerAnimationControllerTest, TrivialQueuing)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 1, 0.5)).PassAs<AnimationCurve>(), 2, ActiveAnimation::Opacity));
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
controller->animate(2, events.get());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -204,12 +218,13 @@ TEST(LayerAnimationControllerTest, TrivialQueuing)
TEST(LayerAnimationControllerTest, Interrupt)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 1, 0.5)).PassAs<AnimationCurve>(), 2, ActiveAnimation::Opacity));
toAdd->setRunState(ActiveAnimation::WaitingForNextTick, 0);
@ -219,9 +234,9 @@ TEST(LayerAnimationControllerTest, Interrupt)
// this call to animate.
controller->animate(0.5, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
controller->animate(1.5, events.get());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -229,23 +244,24 @@ TEST(LayerAnimationControllerTest, Interrupt)
TEST(LayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->setOpacity(0);
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeTransformTransition(1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Transform));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeTransformTransition(1)).PassAs<AnimationCurve>(), 2, ActiveAnimation::Transform));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 2, ActiveAnimation::Opacity));
controller->animate(0, events.get());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
EXPECT_TRUE(controller->hasActiveAnimation());
controller->animate(1, events.get());
// Should not have started the float transition yet.
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
// The float animation should have started at time 1 and should be done.
controller->animate(2, events.get());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -255,7 +271,9 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked)
TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeTransformTransition(2)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Transform));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
@ -264,18 +282,18 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting)
// Animations with id 1 should both start now.
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
// The opacity animation should have finished at time 1, but the group
// of animations with id 1 don't finish until time 2 because of the length
// of the transform animation.
controller->animate(2, events.get());
// Should not have started the float transition yet.
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
// The second opacity animation should start at time 2 and should be done by time 3
controller->animate(3, events.get());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -283,9 +301,10 @@ TEST(LayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting)
TEST(LayerAnimationControllerTest, ScheduleAnimation)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->setOpacity(0);
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
toAdd->setRunState(ActiveAnimation::WaitingForStartTime, 0);
toAdd->setStartTime(1);
@ -293,12 +312,12 @@ TEST(LayerAnimationControllerTest, ScheduleAnimation)
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(2, events.get());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -306,7 +325,9 @@ TEST(LayerAnimationControllerTest, ScheduleAnimation)
TEST(LayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(2, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
@ -318,15 +339,15 @@ TEST(LayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation)
// First 2s opacity transition should start immediately.
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(0.5, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25, controller->opacity());
EXPECT_EQ(0.25, dummy.opacity());
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
controller->animate(2, events.get());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -335,7 +356,9 @@ TEST(LayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation)
TEST(LayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(2, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
@ -349,19 +372,19 @@ TEST(LayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationW
// First 2s opacity transition should start immediately.
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(0.5, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25, controller->opacity());
EXPECT_EQ(0.25, dummy.opacity());
EXPECT_TRUE(controller->hasActiveAnimation());
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
controller->animate(3, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(4, events.get());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
@ -369,7 +392,9 @@ TEST(LayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationW
TEST(LayerAnimationControllerTest, TrivialLooping)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), 1, ActiveAnimation::Opacity));
toAdd->setIterations(3);
@ -377,33 +402,35 @@ TEST(LayerAnimationControllerTest, TrivialLooping)
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1.25, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25, controller->opacity());
EXPECT_EQ(0.25, dummy.opacity());
controller->animate(1.75, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
controller->animate(2.25, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25, controller->opacity());
EXPECT_EQ(0.25, dummy.opacity());
controller->animate(2.75, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
controller->animate(3, events.get());
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
// Just be extra sure.
controller->animate(4, events.get());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
}
// Test that an infinitely looping animation does indeed go until aborted.
TEST(LayerAnimationControllerTest, InfiniteLooping)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
const int id = 1;
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), id, ActiveAnimation::Opacity));
@ -412,65 +439,69 @@ TEST(LayerAnimationControllerTest, InfiniteLooping)
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1.25, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25, controller->opacity());
EXPECT_EQ(0.25, dummy.opacity());
controller->animate(1.75, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
controller->animate(1073741824.25, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25, controller->opacity());
EXPECT_EQ(0.25, dummy.opacity());
controller->animate(1073741824.75, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, ActiveAnimation::Opacity));
controller->getActiveAnimation(id, ActiveAnimation::Opacity)->setRunState(ActiveAnimation::Aborted, 0.75);
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
}
// Test that pausing and resuming work as expected.
TEST(LayerAnimationControllerTest, PauseResume)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
const int id = 1;
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(1, 0, 1)).PassAs<AnimationCurve>(), id, ActiveAnimation::Opacity));
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(0.5, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, ActiveAnimation::Opacity));
controller->getActiveAnimation(id, ActiveAnimation::Opacity)->setRunState(ActiveAnimation::Paused, 0.5);
controller->animate(1024, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, ActiveAnimation::Opacity));
controller->getActiveAnimation(id, ActiveAnimation::Opacity)->setRunState(ActiveAnimation::Running, 1024);
controller->animate(1024.25, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
controller->animate(1024.5, events.get());
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
}
TEST(LayerAnimationControllerTest, AbortAGroupedAnimation)
{
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
const int id = 1;
controller->addAnimation(createActiveAnimation(make_scoped_ptr(new FakeTransformTransition(1)).PassAs<AnimationCurve>(), id, ActiveAnimation::Transform));
@ -479,25 +510,29 @@ TEST(LayerAnimationControllerTest, AbortAGroupedAnimation)
controller->animate(0, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, controller->opacity());
EXPECT_EQ(0, dummy.opacity());
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5, controller->opacity());
EXPECT_EQ(0.5, dummy.opacity());
EXPECT_TRUE(controller->getActiveAnimation(id, ActiveAnimation::Opacity));
controller->getActiveAnimation(id, ActiveAnimation::Opacity)->setRunState(ActiveAnimation::Aborted, 1);
controller->animate(1, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, controller->opacity());
EXPECT_EQ(1, dummy.opacity());
controller->animate(2, events.get());
EXPECT_TRUE(!controller->hasActiveAnimation());
EXPECT_EQ(0.75, controller->opacity());
EXPECT_EQ(0.75, dummy.opacity());
}
TEST(LayerAnimationControllerTest, ForceSyncWhenSynchronizedStartTimeNeeded)
{
scoped_refptr<LayerAnimationController> controllerImpl(LayerAnimationController::create());
scoped_refptr<LayerAnimationController> controller(LayerAnimationController::create());
FakeLayerAnimationControllerClient dummyImpl;
scoped_ptr<LayerAnimationController> controllerImpl(LayerAnimationController::create(&dummyImpl));
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
FakeLayerAnimationControllerClient dummy;
scoped_ptr<LayerAnimationController> controller(
LayerAnimationController::create(&dummy));
scoped_ptr<ActiveAnimation> toAdd(createActiveAnimation(make_scoped_ptr(new FakeFloatTransition(2, 0, 1)).PassAs<AnimationCurve>(), 0, ActiveAnimation::Opacity));
toAdd->setNeedsSynchronizedStartTime(true);

@ -38,6 +38,7 @@ LayerImpl::LayerImpl(LayerTreeHostImpl* hostImpl, int id)
, m_layerSurfacePropertyChanged(false)
, m_masksToBounds(false)
, m_contentsOpaque(false)
, m_opacity(1.0)
, m_preserves3D(false)
, m_useParentBackfaceVisibility(false)
, m_drawCheckerboardForMissingTiles(false)
@ -50,12 +51,10 @@ LayerImpl::LayerImpl(LayerTreeHostImpl* hostImpl, int id)
#ifndef NDEBUG
, m_betweenWillDrawAndDidDraw(false)
#endif
, m_layerAnimationController(LayerAnimationController::create())
, m_layerAnimationController(LayerAnimationController::create(this))
{
DCHECK(m_layerId > 0);
DCHECK(m_layerTreeHostImpl);
m_layerAnimationController->setId(m_layerId);
m_layerAnimationController->setAnimationRegistrar(hostImpl);
}
LayerImpl::~LayerImpl()
@ -452,6 +451,26 @@ int LayerImpl::id() const
return m_layerId;
}
float LayerImpl::opacity() const
{
return m_opacity;
}
void LayerImpl::setOpacityFromAnimation(float opacity)
{
setOpacity(opacity);
}
const gfx::Transform& LayerImpl::transform() const
{
return m_transform;
}
void LayerImpl::setTransformFromAnimation(const gfx::Transform& transform)
{
setTransform(transform);
}
void LayerImpl::setBounds(const gfx::Size& bounds)
{
if (m_bounds == bounds)
@ -578,14 +597,11 @@ void LayerImpl::setContentsOpaque(bool opaque)
void LayerImpl::setOpacity(float opacity)
{
if (!m_layerAnimationController->setOpacity(opacity))
if (m_opacity == opacity)
return;
m_layerSurfacePropertyChanged = true;
}
float LayerImpl::opacity() const
{
return m_layerAnimationController->opacity();
m_opacity = opacity;
m_layerSurfacePropertyChanged = true;
}
bool LayerImpl::opacityIsAnimating() const
@ -623,14 +639,11 @@ void LayerImpl::setSublayerTransform(const gfx::Transform& sublayerTransform)
void LayerImpl::setTransform(const gfx::Transform& transform)
{
if (!m_layerAnimationController->setTransform(transform))
if (m_transform == transform)
return;
m_layerSurfacePropertyChanged = true;
}
const gfx::Transform& LayerImpl::transform() const
{
return m_layerAnimationController->transform();
m_transform = transform;
m_layerSurfacePropertyChanged = true;
}
bool LayerImpl::transformIsAnimating() const

@ -42,7 +42,7 @@ class Layer;
struct AppendQuadsData;
class CC_EXPORT LayerImpl {
class CC_EXPORT LayerImpl : public LayerAnimationControllerClient {
public:
typedef ScopedPtrVector<LayerImpl> LayerList;
@ -53,7 +53,12 @@ public:
virtual ~LayerImpl();
int id() const;
// LayerAnimationControllerClient implementation.
virtual int id() const OVERRIDE;
virtual void setOpacityFromAnimation(float) OVERRIDE;
virtual float opacity() const OVERRIDE;
virtual void setTransformFromAnimation(const gfx::Transform&) OVERRIDE;
virtual const gfx::Transform& transform() const OVERRIDE;
// Tree structure.
LayerImpl* parent() { return m_parent; }
@ -129,7 +134,6 @@ public:
bool contentsOpaque() const { return m_contentsOpaque; }
void setOpacity(float);
float opacity() const;
bool opacityIsAnimating() const;
void setPosition(const gfx::PointF&);
@ -238,7 +242,6 @@ public:
void setDoubleSided(bool);
void setTransform(const gfx::Transform&);
const gfx::Transform& transform() const;
bool transformIsAnimating() const;
const gfx::RectF& updateRect() const { return m_updateRect; }
@ -344,11 +347,13 @@ private:
bool m_masksToBounds;
bool m_contentsOpaque;
float m_opacity;
gfx::PointF m_position;
bool m_preserves3D;
bool m_useParentBackfaceVisibility;
bool m_drawCheckerboardForMissingTiles;
gfx::Transform m_sublayerTransform;
gfx::Transform m_transform;
bool m_useLCDText;
bool m_drawsContent;
@ -385,7 +390,7 @@ private:
gfx::RectF m_updateRect;
// Manages animations for this layer.
scoped_refptr<LayerAnimationController> m_layerAnimationController;
scoped_ptr<LayerAnimationController> m_layerAnimationController;
// Manages scrollbars for this layer
scoped_ptr<ScrollbarAnimationController> m_scrollbarAnimationController;

@ -7,7 +7,6 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
#include "cc/font_atlas.h"
#include "cc/heads_up_display_layer.h"
@ -178,6 +177,7 @@ scoped_ptr<LayerTreeHost> LayerTreeHost::create(LayerTreeHostClient* client, con
LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client, const LayerTreeSettings& settings)
: m_animating(false)
, m_needsAnimateLayers(false)
, m_needsFullTreeSync(true)
, m_client(client)
, m_commitNumber(0)
@ -235,9 +235,6 @@ LayerTreeHost::~LayerTreeHost()
RateLimiterMap::iterator it = m_rateLimiters.begin();
if (it != m_rateLimiters.end())
it->second->stop();
if (m_rootLayer)
m_rootLayer = 0;
}
void LayerTreeHost::setSurfaceReady()
@ -390,6 +387,11 @@ void LayerTreeHost::finishCommitOnImplThread(LayerTreeHostImpl* hostImpl)
else
hostImpl->activeTree()->set_hud_layer(0);
// We may have added an animation during the tree sync. This will cause both layer tree hosts
// to visit their controllers.
if (rootLayer() && m_needsAnimateLayers)
hostImpl->setNeedsAnimateLayers();
hostImpl->activeTree()->set_source_frame_number(commitNumber());
hostImpl->setViewportSize(layoutViewportSize(), deviceViewportSize());
hostImpl->setDeviceScaleFactor(deviceScaleFactor());
@ -523,6 +525,12 @@ void LayerTreeHost::setAnimationEvents(scoped_ptr<AnimationEventsVector> events,
setAnimationEventsRecursive(*events.get(), m_rootLayer.get(), wallClockTime);
}
void LayerTreeHost::didAddAnimation()
{
m_needsAnimateLayers = true;
m_proxy->didAddAnimation();
}
void LayerTreeHost::setRootLayer(scoped_refptr<Layer> rootLayer)
{
if (m_rootLayer == rootLayer)
@ -925,16 +933,33 @@ void LayerTreeHost::setDeviceScaleFactor(float deviceScaleFactor)
void LayerTreeHost::animateLayers(base::TimeTicks time)
{
if (!m_settings.acceleratedAnimationEnabled || m_activeAnimationControllers.empty())
if (!m_settings.acceleratedAnimationEnabled || !m_needsAnimateLayers)
return;
TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), time);
}
bool LayerTreeHost::animateLayersRecursive(Layer* current, base::TimeTicks time)
{
if (!current)
return false;
bool subtreeNeedsAnimateLayers = false;
LayerAnimationController* currentController = current->layerAnimationController();
double monotonicTime = (time - base::TimeTicks()).InSecondsF();
currentController->animate(monotonicTime, 0);
AnimationControllerSet copy = m_activeAnimationControllers;
for (AnimationControllerSet::iterator iter = copy.begin(); iter != copy.end(); ++iter)
(*iter)->animate(monotonicTime, 0);
// If the current controller still has an active animation, we must continue animating layers.
if (currentController->hasActiveAnimation())
subtreeNeedsAnimateLayers = true;
for (size_t i = 0; i < current->children().size(); ++i) {
if (animateLayersRecursive(current->children()[i].get(), time))
subtreeNeedsAnimateLayers = true;
}
return subtreeNeedsAnimateLayers;
}
void LayerTreeHost::setAnimationEventsRecursive(const AnimationEventsVector& events, Layer* layer, base::Time wallClockTime)
@ -955,30 +980,4 @@ void LayerTreeHost::setAnimationEventsRecursive(const AnimationEventsVector& eve
setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime);
}
void LayerTreeHost::DidActivateAnimationController(LayerAnimationController* controller) {
// Controllers register themselves when they have new animations. We need
// to commit in this case.
setNeedsCommit();
m_activeAnimationControllers.insert(controller);
}
void LayerTreeHost::DidDeactivateAnimationController(LayerAnimationController* controller) {
if (ContainsKey(m_activeAnimationControllers, controller))
m_activeAnimationControllers.erase(controller);
}
void LayerTreeHost::RegisterAnimationController(LayerAnimationController* controller) {
#if !defined(NDEBUG)
m_allAnimationControllers.insert(controller);
#endif
}
void LayerTreeHost::UnregisterAnimationController(LayerAnimationController* controller) {
#if !defined(NDEBUG)
if (ContainsKey(m_allAnimationControllers, controller))
m_allAnimationControllers.erase(controller);
#endif
DidDeactivateAnimationController(controller);
}
} // namespace cc

@ -14,7 +14,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "cc/animation_events.h"
#include "cc/animation_registrar.h"
#include "cc/cc_export.h"
#include "cc/layer_tree_host_client.h"
#include "cc/layer_tree_host_common.h"
@ -37,15 +36,6 @@ struct hash<WebKit::WebGraphicsContext3D*> {
}
};
} // namespace BASE_HASH_NAMESPACE
namespace BASE_HASH_NAMESPACE {
template<>
struct hash<cc::LayerAnimationController*> {
size_t operator()(cc::LayerAnimationController* ptr) const {
return hash<size_t>()(reinterpret_cast<size_t>(ptr));
}
};
} // namespace BASE_HASH_NAMESPACE
#endif // COMPILER
namespace cc {
@ -123,8 +113,7 @@ struct CC_EXPORT RendererCapabilities {
int maxTextureSize;
};
class CC_EXPORT LayerTreeHost : public RateLimiterClient,
public AnimationRegistrar {
class CC_EXPORT LayerTreeHost : public RateLimiterClient {
public:
static scoped_ptr<LayerTreeHost> create(LayerTreeHostClient*, const LayerTreeSettings&, scoped_ptr<Thread> implThread);
virtual ~LayerTreeHost();
@ -201,6 +190,7 @@ public:
bool commitRequested() const;
void setAnimationEvents(scoped_ptr<AnimationEventsVector>, base::Time wallClockTime);
virtual void didAddAnimation();
Layer* rootLayer() { return m_rootLayer.get(); }
const Layer* rootLayer() const { return m_rootLayer.get(); }
@ -258,15 +248,8 @@ protected:
bool initialize(scoped_ptr<Thread> implThread);
bool initializeForTesting(scoped_ptr<Proxy> proxyForTesting);
// AnimationRegistar implementation.
virtual void DidActivateAnimationController(LayerAnimationController*) OVERRIDE;
virtual void DidDeactivateAnimationController(LayerAnimationController*) OVERRIDE;
virtual void RegisterAnimationController(LayerAnimationController*) OVERRIDE;
virtual void UnregisterAnimationController(LayerAnimationController*) OVERRIDE;
private:
typedef std::vector<scoped_refptr<Layer> > LayerList;
typedef base::hash_set<LayerAnimationController*> AnimationControllerSet;
bool initializeProxy(scoped_ptr<Proxy> proxy);
void initializeRenderer();
@ -288,6 +271,7 @@ private:
void setAnimationEventsRecursive(const AnimationEventsVector&, Layer*, base::Time wallClockTime);
bool m_animating;
bool m_needsAnimateLayers;
bool m_needsFullTreeSync;
base::CancelableClosure m_prepaintCallback;
@ -334,12 +318,6 @@ private:
static bool s_needsFilterContext;
AnimationControllerSet m_activeAnimationControllers;
#if !defined(NDEBUG)
AnimationControllerSet m_allAnimationControllers;
#endif
DISALLOW_COPY_AND_ASSIGN(LayerTreeHost);
};

@ -1702,11 +1702,24 @@ TEST(LayerTreeHostCommonTest, verifyAnimationsForRenderSurfaceHierarchy)
renderSurface1->setForceRenderSurface(true);
renderSurface2->setForceRenderSurface(true);
// Put an animated opacity on the render surface.
addOpacityTransitionToController(*renderSurface1->layerAnimationController(), 10, 1, 0, false);
// Also put an animated opacity on a layer without descendants.
addOpacityTransitionToController(*grandChildOfRoot->layerAnimationController(), 10, 1, 0, false);
gfx::Transform layerTransform;
layerTransform.Translate(1, 1);
gfx::Transform sublayerTransform;
sublayerTransform.Scale3d(10, 1, 1);
// Put a transform animation on the render surface.
addAnimatedTransformToController(*renderSurface2->layerAnimationController(), 10, 30, 0);
// Also put transform animations on grandChildOfRoot, and grandChildOfRS2
addAnimatedTransformToController(*grandChildOfRoot->layerAnimationController(), 10, 30, 0);
addAnimatedTransformToController(*grandChildOfRS2->layerAnimationController(), 10, 30, 0);
setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(2.5, 0), gfx::Size(10, 10), false);
setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(2.5, 0), gfx::Size(10, 10), false);
setLayerPropertiesForTesting(renderSurface2.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(2.5, 0), gfx::Size(10, 10), false);
@ -1717,19 +1730,6 @@ TEST(LayerTreeHostCommonTest, verifyAnimationsForRenderSurfaceHierarchy)
setLayerPropertiesForTesting(grandChildOfRS1.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(2.5, 0), gfx::Size(10, 10), false);
setLayerPropertiesForTesting(grandChildOfRS2.get(), layerTransform, sublayerTransform, gfx::PointF(0.25, 0), gfx::PointF(2.5, 0), gfx::Size(10, 10), false);
// Put an animated opacity on the render surface.
addOpacityTransitionToController(*renderSurface1->layerAnimationController(), 10, 1, 0, false);
// Also put an animated opacity on a layer without descendants.
addOpacityTransitionToController(*grandChildOfRoot->layerAnimationController(), 10, 1, 0, false);
// Put a transform animation on the render surface.
addAnimatedTransformToController(*renderSurface2->layerAnimationController(), 10, 30, 0);
// Also put transform animations on grandChildOfRoot, and grandChildOfRS2
addAnimatedTransformToController(*grandChildOfRoot->layerAnimationController(), 10, 30, 0);
addAnimatedTransformToController(*grandChildOfRS2->layerAnimationController(), 10, 30, 0);
executeCalculateDrawProperties(parent.get());
// Only layers that are associated with render surfaces should have an actual renderSurface() value.

@ -9,7 +9,6 @@
#include "base/basictypes.h"
#include "base/debug/trace_event.h"
#include "base/json/json_writer.h"
#include "base/stl_util.h"
#include "cc/append_quads_data.h"
#include "cc/damage_tracker.h"
#include "cc/debug_rect_history.h"
@ -219,6 +218,7 @@ LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTre
PriorityCalculator::allowNothingCutoff())
, m_backgroundColor(0)
, m_hasTransparentBackground(false)
, m_needsAnimateLayers(false)
, m_pinchGestureActive(false)
, m_fpsCounter(FrameRateCounter::create(m_proxy->hasImplThread()))
, m_debugRectHistory(DebugRectHistory::create())
@ -243,13 +243,8 @@ LayerTreeHostImpl::~LayerTreeHostImpl()
DCHECK(m_proxy->isImplThread());
TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
if (rootLayer()) {
if (rootLayer())
clearRenderSurfaces();
// The layer trees must be destroyed before the layer tree host. We've
// made a contract with our animation controllers that the registrar
// will outlive them, and we must make good.
m_activeTree.reset();
}
}
void LayerTreeHostImpl::beginCommit()
@ -597,6 +592,35 @@ bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
return drawFrame;
}
void LayerTreeHostImpl::animateLayersRecursive(LayerImpl* current, base::TimeTicks monotonicTime, base::Time wallClockTime, AnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
{
bool subtreeNeedsAnimateLayers = false;
LayerAnimationController* currentController = current->layerAnimationController();
bool hadActiveAnimation = currentController->hasActiveAnimation();
double monotonicTimeSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
currentController->animate(monotonicTimeSeconds, events);
bool startedAnimation = events->size() > 0;
// We animated if we either ticked a running animation, or started a new animation.
if (hadActiveAnimation || startedAnimation)
didAnimate = true;
// If the current controller still has an active animation, we must continue animating layers.
if (currentController->hasActiveAnimation())
subtreeNeedsAnimateLayers = true;
for (size_t i = 0; i < current->children().size(); ++i) {
bool childNeedsAnimateLayers = false;
animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
if (childNeedsAnimateLayers)
subtreeNeedsAnimateLayers = true;
}
needsAnimateLayers = subtreeNeedsAnimateLayers;
}
void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
{
// Lazily create the timeSource adapter so that we can vary the interval for testing.
@ -953,7 +977,7 @@ void LayerTreeHostImpl::setVisible(bool visible)
m_renderer->setVisible(visible);
setBackgroundTickingEnabled(!m_visible && !m_activeAnimationControllers.empty());
setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
}
bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<OutputSurface> outputSurface)
@ -1508,23 +1532,23 @@ void LayerTreeHostImpl::animatePageScale(base::TimeTicks time)
void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime)
{
if (!m_settings.acceleratedAnimationEnabled || m_activeAnimationControllers.empty() || !rootLayer())
if (!m_settings.acceleratedAnimationEnabled || !m_needsAnimateLayers || !rootLayer())
return;
TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
double monotonicSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
AnimationControllerSet copy = m_activeAnimationControllers;
for (AnimationControllerSet::iterator iter = copy.begin(); iter != copy.end(); ++iter)
(*iter)->animate(monotonicSeconds, events.get());
bool didAnimate = false;
animateLayersRecursive(rootLayer(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
if (!events->empty())
m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
m_client->setNeedsRedrawOnImplThread();
setBackgroundTickingEnabled(!m_visible && !m_activeAnimationControllers.empty());
if (didAnimate)
m_client->setNeedsRedrawOnImplThread();
setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
}
base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
@ -1654,27 +1678,4 @@ void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeT
animateScrollbarsRecursive(layer->children()[i], time);
}
void LayerTreeHostImpl::DidActivateAnimationController(LayerAnimationController* controller) {
m_activeAnimationControllers.insert(controller);
}
void LayerTreeHostImpl::DidDeactivateAnimationController(LayerAnimationController* controller) {
if (ContainsKey(m_activeAnimationControllers, controller))
m_activeAnimationControllers.erase(controller);
}
void LayerTreeHostImpl::RegisterAnimationController(LayerAnimationController* controller) {
#if !defined(NDEBUG)
m_allAnimationControllers.insert(controller);
#endif
}
void LayerTreeHostImpl::UnregisterAnimationController(LayerAnimationController* controller) {
#if !defined(NDEBUG)
if (ContainsKey(m_allAnimationControllers, controller))
m_allAnimationControllers.erase(controller);
#endif
DidDeactivateAnimationController(controller);
}
} // namespace cc

@ -9,7 +9,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "cc/animation_events.h"
#include "cc/animation_registrar.h"
#include "cc/cc_export.h"
#include "cc/input_handler.h"
#include "cc/layer_tree_impl.h"
@ -114,10 +113,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandlerClient,
public RendererClient,
public TileManagerClient,
public LayerTreeImplClient,
public AnimationRegistrar,
public OutputSurfaceClient {
typedef std::vector<LayerImpl*> LayerList;
typedef base::hash_set<LayerAnimationController*> AnimationControllerSet;
public:
static scoped_ptr<LayerTreeHostImpl> create(const LayerTreeSettings&, LayerTreeHostImplClient*, Proxy*);
@ -248,7 +245,9 @@ public:
bool hasTransparentBackground() const { return m_hasTransparentBackground; }
void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; }
bool needsAnimateLayers() const { return !m_activeAnimationControllers.empty(); }
bool needsAnimateLayers() const { return m_needsAnimateLayers; }
void setNeedsAnimateLayers() { m_needsAnimateLayers = true; }
void setNeedsRedraw();
@ -343,14 +342,7 @@ private:
void dumpRenderSurfaces(std::string*, int indent, const LayerImpl*) const;
// AnimationRegistar implementation.
virtual void DidActivateAnimationController(LayerAnimationController*) OVERRIDE;
virtual void DidDeactivateAnimationController(LayerAnimationController*) OVERRIDE;
virtual void RegisterAnimationController(LayerAnimationController*) OVERRIDE;
virtual void UnregisterAnimationController(LayerAnimationController*) OVERRIDE;
scoped_ptr<OutputSurface> m_outputSurface;
scoped_ptr<ResourceProvider> m_resourceProvider;
scoped_ptr<Renderer> m_renderer;
scoped_ptr<TileManager> m_tileManager;
@ -371,6 +363,7 @@ private:
bool m_hasTransparentBackground;
// If this is true, it is necessary to traverse the layer tree ticking the animators.
bool m_needsAnimateLayers;
bool m_pinchGestureActive;
gfx::Point m_previousPinchAnchor;
@ -395,12 +388,6 @@ private:
int64 m_cumulativeNumMissingTiles;
AnimationControllerSet m_activeAnimationControllers;
#if !defined(NDEBUG)
AnimationControllerSet m_allAnimationControllers;
#endif
size_t m_lastSentMemoryVisibleBytes;
size_t m_lastSentMemoryVisibleAndNearbyBytes;
size_t m_lastSentMemoryUseBytes;

@ -80,6 +80,8 @@ public:
// like compositeAndReadback while commits are deferred.
virtual void setDeferCommits(bool) = 0;
virtual void didAddAnimation() = 0;
virtual bool commitRequested() const = 0;
virtual void start() = 0; // Must be called before using the proxy.

@ -241,6 +241,10 @@ bool SingleThreadProxy::commitRequested() const
return false;
}
void SingleThreadProxy::didAddAnimation()
{
}
size_t SingleThreadProxy::maxPartialTextureUpdates() const
{
return std::numeric_limits<size_t>::max();

@ -39,6 +39,7 @@ public:
virtual void setNeedsRedraw() OVERRIDE;
virtual void setDeferCommits(bool) OVERRIDE;
virtual bool commitRequested() const OVERRIDE;
virtual void didAddAnimation() OVERRIDE;
virtual void start() OVERRIDE;
virtual void stop() OVERRIDE;
virtual size_t maxPartialTextureUpdates() const OVERRIDE;

@ -150,6 +150,40 @@ float FakeFloatTransition::getValue(double time) const
return (1 - time) * m_from + time * m_to;
}
FakeLayerAnimationControllerClient::FakeLayerAnimationControllerClient()
: m_opacity(0)
{
}
FakeLayerAnimationControllerClient::~FakeLayerAnimationControllerClient()
{
}
int FakeLayerAnimationControllerClient::id() const
{
return 0;
}
void FakeLayerAnimationControllerClient::setOpacityFromAnimation(float opacity)
{
m_opacity = opacity;
}
float FakeLayerAnimationControllerClient::opacity() const
{
return m_opacity;
}
void FakeLayerAnimationControllerClient::setTransformFromAnimation(const gfx::Transform& transform)
{
m_transform = transform;
}
const gfx::Transform& FakeLayerAnimationControllerClient::transform() const
{
return m_transform;
}
scoped_ptr<cc::AnimationCurve> FakeFloatTransition::clone() const
{
return make_scoped_ptr(new FakeFloatTransition(*this)).PassAs<cc::AnimationCurve>();

@ -60,6 +60,23 @@ private:
float m_to;
};
class FakeLayerAnimationControllerClient : public cc::LayerAnimationControllerClient {
public:
FakeLayerAnimationControllerClient();
virtual ~FakeLayerAnimationControllerClient();
// LayerAnimationControllerClient implementation
virtual int id() const OVERRIDE;
virtual void setOpacityFromAnimation(float) OVERRIDE;
virtual float opacity() const OVERRIDE;
virtual void setTransformFromAnimation(const gfx::Transform&) OVERRIDE;
virtual const gfx::Transform& transform() const OVERRIDE;
private:
float m_opacity;
gfx::Transform m_transform;
};
int addOpacityTransitionToController(cc::LayerAnimationController&, double duration, float startOpacity, float endOpacity, bool useTimingFunction);
int addAnimatedTransformToController(cc::LayerAnimationController&, double duration, int deltaX, int deltaY);

@ -30,6 +30,7 @@ public:
virtual void setNeedsCommit() OVERRIDE { }
virtual void setNeedsRedraw() OVERRIDE { }
virtual void setDeferCommits(bool) OVERRIDE { }
virtual void didAddAnimation() OVERRIDE { }
virtual bool commitRequested() const OVERRIDE;
virtual void start() OVERRIDE { }
virtual void stop() OVERRIDE { }

@ -156,6 +156,12 @@ public:
return MockLayerTreeHostImpl::create(m_testHooks, settings(), client, proxy()).PassAs<cc::LayerTreeHostImpl>();
}
virtual void didAddAnimation() OVERRIDE
{
LayerTreeHost::didAddAnimation();
m_testHooks->didAddAnimation();
}
virtual void setNeedsCommit() OVERRIDE
{
if (!m_testStarted)
@ -163,12 +169,6 @@ public:
LayerTreeHost::setNeedsCommit();
}
virtual void DidActivateAnimationController(cc::LayerAnimationController* controller) OVERRIDE
{
LayerTreeHost::DidActivateAnimationController(controller);
m_testHooks->didAddAnimation();
}
void setTestStarted(bool started) { m_testStarted = started; }
virtual void didDeferCommit() OVERRIDE
@ -335,6 +335,11 @@ void ThreadedTest::postSetVisibleToMainThread(bool visible)
m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadedTest::dispatchSetVisible, base::Unretained(this), visible));
}
void ThreadedTest::postDidAddAnimationToMainThread()
{
m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadedTest::dispatchDidAddAnimation, base::Unretained(this)));
}
void ThreadedTest::doBeginTest()
{
m_client = ThreadedMockLayerTreeHostClient::create(this);
@ -464,6 +469,17 @@ void ThreadedTest::dispatchComposite()
m_layerTreeHost->composite();
}
void ThreadedTest::dispatchDidAddAnimation()
{
DCHECK(!proxy() || proxy()->isMainThread());
if (m_finished)
return;
if (m_layerTreeHost.get())
m_layerTreeHost->didAddAnimation();
}
void ThreadedTest::runTest(bool threaded)
{
if (threaded) {

@ -84,6 +84,7 @@ public:
void postAcquireLayerTextures();
void postSetNeedsRedrawToMainThread();
void postSetVisibleToMainThread(bool visible);
void postDidAddAnimationToMainThread();
void doBeginTest();
void timeout();

@ -47,6 +47,7 @@ public:
virtual void setNeedsRedraw() OVERRIDE;
virtual void setDeferCommits(bool) OVERRIDE;
virtual bool commitRequested() const OVERRIDE;
virtual void didAddAnimation() OVERRIDE { }
virtual void start() OVERRIDE;
virtual void stop() OVERRIDE;
virtual size_t maxPartialTextureUpdates() const OVERRIDE;

@ -75,20 +75,19 @@ private:
class FakeLayerAnimationController : public LayerAnimationController {
public:
static scoped_refptr<LayerAnimationController> create()
static scoped_ptr<FakeLayerAnimationController> create(LayerAnimationControllerClient* client)
{
return static_cast<LayerAnimationController*>(new FakeLayerAnimationController);
return make_scoped_ptr(new FakeLayerAnimationController(client));
}
bool synchronizedAnimations() const { return m_synchronizedAnimations; }
private:
FakeLayerAnimationController()
: LayerAnimationController()
explicit FakeLayerAnimationController(LayerAnimationControllerClient* client)
: LayerAnimationController(client)
, m_synchronizedAnimations(false)
{ }
virtual ~FakeLayerAnimationController() { }
{
}
virtual void pushAnimationUpdatesTo(LayerAnimationController* controllerImpl)
{
@ -393,7 +392,8 @@ TEST(TreeSynchronizerTest, synchronizeAnimations)
scoped_refptr<Layer> layerTreeRoot = Layer::create();
layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create());
FakeLayerAnimationControllerClient dummy;
layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create(&dummy).PassAs<LayerAnimationController>());
EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());