+2012-03-20 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Infrastructure to allow animating layers to be only partially updated
+ https://bugs.webkit.org/show_bug.cgi?id=81106
+
+ Reviewed by James Robinson
+
+ Merged the controller tests in CCLayerAnimationControllerTest
+
+ * WebCore.gypi:
+ * platform/graphics/chromium/GraphicsLayerChromium.cpp:
+ * platform/graphics/chromium/GraphicsLayerChromium.h:
+ (GraphicsLayerChromium):
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::LayerChromium):
+ (WebCore::LayerChromium::pushPropertiesTo):
+ (WebCore::LayerChromium::setOpacityFromAnimation):
+ (WebCore):
+ (WebCore::LayerChromium::setTransformFromAnimation):
+ (WebCore::LayerChromium::addAnimation):
+ (WebCore::LayerChromium::pauseAnimation):
+ (WebCore::LayerChromium::removeAnimation):
+ (WebCore::LayerChromium::suspendAnimations):
+ (WebCore::LayerChromium::resumeAnimations):
+ (WebCore::LayerChromium::setLayerAnimationController):
+ (WebCore::LayerChromium::hasActiveAnimation):
+ (WebCore::LayerChromium::setAnimationEvent):
+ * platform/graphics/chromium/LayerChromium.h:
+ (WebCore):
+ (LayerChromium):
+ (WebCore::LayerChromium::id):
+ (WebCore::LayerChromium::opacity):
+ (WebCore::LayerChromium::transform):
+ (WebCore::LayerChromium::bounds):
+ * platform/graphics/chromium/cc/CCActiveAnimation.h:
+ (CCActiveAnimation):
+ * platform/graphics/chromium/cc/CCAnimationEvents.cpp:
+ (WebCore::CCAnimationEvent::CCAnimationEvent):
+ (WebCore::CCAnimationEvent::toFloatAnimationFinishedEvent):
+ (WebCore::CCAnimationEvent::toTransformAnimationFinishedEvent):
+ (WebCore::CCAnimationStartedEvent::create):
+ (WebCore):
+ (WebCore::CCAnimationStartedEvent::CCAnimationStartedEvent):
+ (WebCore::CCFloatAnimationFinishedEvent::create):
+ (WebCore::CCFloatAnimationFinishedEvent::CCFloatAnimationFinishedEvent):
+ (WebCore::CCFloatAnimationFinishedEvent::~CCFloatAnimationFinishedEvent):
+ (WebCore::CCFloatAnimationFinishedEvent::type):
+ (WebCore::CCTransformAnimationFinishedEvent::create):
+ (WebCore::CCTransformAnimationFinishedEvent::CCTransformAnimationFinishedEvent):
+ (WebCore::CCTransformAnimationFinishedEvent::~CCTransformAnimationFinishedEvent):
+ (WebCore::CCTransformAnimationFinishedEvent::type):
+ * platform/graphics/chromium/cc/CCAnimationEvents.h:
+ (WebCore):
+ (WebCore::CCAnimationEvent::targetProperty):
+ (CCAnimationEvent):
+ (CCAnimationStartedEvent):
+ (CCFloatAnimationFinishedEvent):
+ (WebCore::CCFloatAnimationFinishedEvent::finalValue):
+ (CCTransformAnimationFinishedEvent):
+ (WebCore::CCTransformAnimationFinishedEvent::finalValue):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
+ (WebCore::CCLayerAnimationController::CCLayerAnimationController):
+ (WebCore::CCLayerAnimationController::create):
+ (WebCore::CCLayerAnimationController::pushAnimationUpdatesTo):
+ (WebCore::CCLayerAnimationController::animate):
+ (WebCore):
+ (WebCore::CCLayerAnimationController::add):
+ (WebCore::CCLayerAnimationController::getActiveAnimation):
+ (WebCore::CCLayerAnimationController::hasActiveAnimation):
+ (WebCore::CCLayerAnimationController::isAnimatingProperty):
+ (WebCore::CCLayerAnimationController::pushNewAnimationsToImplThread):
+ (WebCore::CCLayerAnimationController::removeAnimationsCompletedOnMainThread):
+ (WebCore::CCLayerAnimationController::startAnimationsWaitingForNextTick):
+ (WebCore::CCLayerAnimationController::startAnimationsWaitingForStartTime):
+ (WebCore::CCLayerAnimationController::startAnimationsWaitingForTargetAvailability):
+ (WebCore::CCLayerAnimationController::resolveConflicts):
+ (WebCore::CCLayerAnimationController::purgeFinishedAnimations):
+ (WebCore::CCLayerAnimationController::tickAnimations):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.h:
+ (WebCore):
+ (CCLayerAnimationControllerClient):
+ (WebCore::CCLayerAnimationControllerClient::~CCLayerAnimationControllerClient):
+ (CCLayerAnimationController):
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp: Removed.
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h: Removed.
+ * platform/graphics/chromium/cc/CCLayerAnimationDelegate.h:
+ (CCLayerAnimationDelegate):
+ * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+ (WebCore::CCLayerImpl::CCLayerImpl):
+ (WebCore::CCLayerImpl::setOpacityFromAnimation):
+ (WebCore):
+ (WebCore::CCLayerImpl::setTransformFromAnimation):
+ * platform/graphics/chromium/cc/CCLayerImpl.h:
+ (CCLayerImpl):
+ (WebCore::CCLayerImpl::id):
+ (WebCore::CCLayerImpl::layerAnimationController):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::CCLayerTreeHost::CCLayerTreeHost):
+ (WebCore::CCLayerTreeHost::updateAnimations):
+ (WebCore::CCLayerTreeHost::finishCommitOnImplThread):
+ (WebCore::CCLayerTreeHost::didBecomeInvisibleOnImplThread):
+ (WebCore::CCLayerTreeHost::animateLayers):
+ (WebCore):
+ (WebCore::CCLayerTreeHost::animateLayersRecursive):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+ * platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+ (WebCore::CCLayerTreeHostImpl::animateLayersRecursive):
+ (WebCore::CCLayerTreeHostImpl::animateLayers):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+ (CCLayerTreeHostImpl):
+ * platform/graphics/chromium/cc/CCThreadProxy.h:
+ (WebCore::CCThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState):
+
2012-03-20 Ilya Tikhonovsky <loislo@chromium.org>
Web Inspector: REGRESSION Detached DOM Nodes are not highlighted
'platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h',
'platform/graphics/chromium/cc/CCLayerAnimationController.h',
'platform/graphics/chromium/cc/CCLayerAnimationController.cpp',
- 'platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h',
- 'platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp',
'platform/graphics/chromium/cc/CCLayerAnimationDelegate.h',
'platform/graphics/chromium/cc/CCLayerImpl.cpp',
'platform/graphics/chromium/cc/CCLayerImpl.h',
m_client->notifyAnimationStarted(this, startTime);
}
-void GraphicsLayerChromium::notifyAnimationFinished(int animationId)
-{
- for (AnimationIdMap::iterator idIter = m_animationIdMap.begin(); idIter != m_animationIdMap.end(); ++idIter) {
- if (idIter->second == animationId) {
- m_animationIdMap.remove(idIter);
- return;
- }
- }
-}
-
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
// CCLayerAnimationDelegate implementation.
virtual void notifyAnimationStarted(double startTime);
- virtual void notifyAnimationFinished(int animationId);
// Exposed for tests.
LayerChromium* contentsLayer() const { return m_contentsLayer.get(); }
: m_needsDisplay(false)
, m_layerId(s_nextLayerId++)
, m_parent(0)
- , m_layerAnimationController(CCLayerAnimationController::create())
+ , m_layerAnimationController(CCLayerAnimationController::create(this))
, m_scrollable(false)
, m_shouldScrollOnMainThread(false)
, m_haveWheelEventHandlers(false)
removeAllChildren();
}
-bool LayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, int animationId, int groupId, double timeOffset)
-{
- if (!m_layerTreeHost || !m_layerTreeHost->settings().threadedAnimationEnabled)
- return false;
-
- bool addedAnimation = m_layerAnimationController->addAnimation(values, boxSize, animation, animationId, groupId, timeOffset);
- if (addedAnimation)
- setNeedsCommit();
- return addedAnimation;
-}
-
-void LayerChromium::pauseAnimation(int animationId, double timeOffset)
-{
- m_layerAnimationController->pauseAnimation(animationId, timeOffset);
- setNeedsCommit();
-}
-
-void LayerChromium::removeAnimation(int animationId)
-{
- m_layerAnimationController->removeAnimation(animationId);
- setNeedsCommit();
-}
-
-void LayerChromium::suspendAnimations(double time)
-{
- m_layerAnimationController->suspendAnimations(time);
- setNeedsCommit();
-}
-
-void LayerChromium::resumeAnimations()
-{
- m_layerAnimationController->resumeAnimations();
- setNeedsCommit();
-}
-
-void LayerChromium::setLayerAnimationController(PassOwnPtr<CCLayerAnimationController> layerAnimationController)
-{
- m_layerAnimationController = layerAnimationController;
- setNeedsCommit();
-}
-
-bool LayerChromium::hasActiveAnimation() const
-{
- return m_layerAnimationController->hasActiveAnimation();
-}
-
-void LayerChromium::setAnimationEvent(const CCAnimationEvent& event, double wallClockTime)
-{
- switch (event.type()) {
-
- case CCAnimationEvent::Started: {
- m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
- break;
- }
-
- case CCAnimationEvent::Finished: {
- const CCAnimationFinishedEvent* finishedEvent = event.toAnimationFinishedEvent();
- m_layerAnimationDelegate->notifyAnimationFinished(finishedEvent->animationId());
- break;
- }
-
- }
-}
-
void LayerChromium::setIsNonCompositedContent(bool isNonCompositedContent)
{
m_isNonCompositedContent = isNonCompositedContent;
m_nonFastScrollableRegionChanged = false;
}
layer->setOpaque(m_opaque);
- layer->setOpacity(m_opacity);
+ if (!opacityIsAnimating())
+ layer->setOpacity(m_opacity);
layer->setPosition(m_position);
layer->setPreserves3D(preserves3D());
layer->setScrollPosition(m_scrollPosition);
layer->setSublayerTransform(m_sublayerTransform);
- layer->setTransform(m_transform);
+ if (!transformIsAnimating())
+ layer->setTransform(m_transform);
layer->setUpdateRect(m_updateRect);
layer->setScrollDelta(layer->scrollDelta() - layer->sentScrollDelta());
if (replicaLayer())
replicaLayer()->pushPropertiesTo(layer->replicaLayer());
- m_layerAnimationController->synchronizeAnimations(layer->layerAnimationController());
+ m_layerAnimationController->pushAnimationUpdatesTo(layer->layerAnimationController());
// Reset any state that should be cleared for the next update.
m_updateRect = FloatRect();
return false;
}
+void LayerChromium::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;
+}
+
+void LayerChromium::setTransformFromAnimation(const TransformationMatrix& 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 LayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, int animationId, int groupId, double timeOffset)
+{
+ if (!m_layerTreeHost || !m_layerTreeHost->settings().threadedAnimationEnabled)
+ return false;
+
+ bool addedAnimation = m_layerAnimationController->addAnimation(values, boxSize, animation, animationId, groupId, timeOffset);
+ if (addedAnimation)
+ setNeedsCommit();
+ return addedAnimation;
+}
+
+void LayerChromium::pauseAnimation(int animationId, double timeOffset)
+{
+ m_layerAnimationController->pauseAnimation(animationId, timeOffset);
+ setNeedsCommit();
+}
+
+void LayerChromium::removeAnimation(int animationId)
+{
+ m_layerAnimationController->removeAnimation(animationId);
+ setNeedsCommit();
+}
+
+void LayerChromium::suspendAnimations(double time)
+{
+ m_layerAnimationController->suspendAnimations(time);
+ setNeedsCommit();
+}
+
+void LayerChromium::resumeAnimations()
+{
+ m_layerAnimationController->resumeAnimations();
+ setNeedsCommit();
+}
+
+void LayerChromium::setLayerAnimationController(PassOwnPtr<CCLayerAnimationController> layerAnimationController)
+{
+ m_layerAnimationController = layerAnimationController;
+ setNeedsCommit();
+}
+
+bool LayerChromium::hasActiveAnimation() const
+{
+ return m_layerAnimationController->hasActiveAnimation();
+}
+
+void LayerChromium::setAnimationEvent(const CCAnimationEvent& event, double wallClockTime)
+{
+ switch (event.type()) {
+ case CCAnimationEvent::Started:
+ m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
+ break;
+
+ case CCAnimationEvent::FinishedFloatAnimation: {
+ const CCFloatAnimationFinishedEvent* finishedEvent = event.toFloatAnimationFinishedEvent();
+ ASSERT(finishedEvent->targetProperty() == CCActiveAnimation::Opacity);
+ setOpacity(finishedEvent->finalValue());
+ break;
+ }
+
+ case CCAnimationEvent::FinishedTransformAnimation: {
+ const CCTransformAnimationFinishedEvent* finishedEvent = event.toTransformAnimationFinishedEvent();
+ ASSERT(finishedEvent->targetProperty() == CCActiveAnimation::Transform);
+ setTransform(finishedEvent->finalValue());
+ break;
+ }
+
+ }
+}
+
void sortLayers(Vector<RefPtr<LayerChromium> >::iterator, Vector<RefPtr<LayerChromium> >::iterator, void*)
{
// Currently we don't use z-order to decide what to paint, so there's no need to actually sort LayerChromiums.
#include "RenderSurfaceChromium.h"
#include "ShaderChromium.h"
#include "TransformationMatrix.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCOcclusionTracker.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
class CCAnimationEvent;
-class CCLayerAnimationController;
class CCLayerAnimationDelegate;
class CCLayerImpl;
class CCLayerTreeHost;
// Base class for composited layers. Special layer types are derived from
// this class.
-class LayerChromium : public RefCounted<LayerChromium> {
+class LayerChromium : public RefCounted<LayerChromium>, public CCLayerAnimationControllerClient {
public:
static PassRefPtr<LayerChromium> create();
virtual ~LayerChromium();
+ // CCLayerAnimationControllerClient implementation
+ virtual int id() const { return m_layerId; }
+ virtual void setOpacityFromAnimation(float);
+ virtual float opacity() const { return m_opacity; }
+ virtual void setTransformFromAnimation(const TransformationMatrix&);
+ virtual const TransformationMatrix& transform() const { return m_transform; }
+ virtual const IntSize& bounds() const { return m_bounds; }
+
const LayerChromium* rootLayer() const;
LayerChromium* parent() const;
void addChild(PassRefPtr<LayerChromium>);
bool backgroundCoversViewport() const { return m_backgroundCoversViewport; }
void setBounds(const IntSize&);
- const IntSize& bounds() const { return m_bounds; }
virtual IntSize contentBounds() const { return bounds(); }
void setMasksToBounds(bool);
virtual bool needsDisplay() const { return m_needsDisplay; }
void setOpacity(float);
- float opacity() const { return m_opacity; }
bool opacityIsAnimating() const;
void setFilters(const FilterOperations&);
const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
void setTransform(const TransformationMatrix&);
- const TransformationMatrix& transform() const { return m_transform; }
bool transformIsAnimating() const;
const IntRect& visibleLayerRect() const { return m_visibleLayerRect; }
typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> BorderProgram;
- int id() const { return m_layerId; }
-
void clearRenderSurface() { m_renderSurface.clear(); }
RenderSurfaceChromium* renderSurface() const { return m_renderSurface.get(); }
void createRenderSurface();
Opacity
};
- struct AnimationSignature {
- AnimationSignature(int groupId, TargetProperty targetProperty)
- : groupId(groupId)
- , targetProperty(targetProperty) { }
- int groupId;
- TargetProperty targetProperty;
- };
-
static PassOwnPtr<CCActiveAnimation> create(PassOwnPtr<CCAnimationCurve>, int animationId, int groupId, TargetProperty);
virtual ~CCActiveAnimation();
// of iterations, returns the relative time in the current iteration.
double trimTimeToCurrentIteration(double now) const;
- AnimationSignature signature() const { return AnimationSignature(m_group, m_targetProperty); }
-
PassOwnPtr<CCActiveAnimation> cloneForImplThread() const;
void synchronizeProperties(CCActiveAnimation*);
namespace WebCore {
-CCAnimationEvent::CCAnimationEvent(int layerId)
+CCAnimationEvent::CCAnimationEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty)
: m_layerId(layerId)
+ , m_targetProperty(targetProperty)
{
}
return static_cast<const CCAnimationStartedEvent*>(this);
}
-const CCAnimationFinishedEvent* CCAnimationEvent::toAnimationFinishedEvent() const
+const CCFloatAnimationFinishedEvent* CCAnimationEvent::toFloatAnimationFinishedEvent() const
{
- ASSERT(type() == Finished);
- return static_cast<const CCAnimationFinishedEvent*>(this);
+ ASSERT(type() == FinishedFloatAnimation);
+ return static_cast<const CCFloatAnimationFinishedEvent*>(this);
}
-PassOwnPtr<CCAnimationStartedEvent> CCAnimationStartedEvent::create(int layerId)
+const CCTransformAnimationFinishedEvent* CCAnimationEvent::toTransformAnimationFinishedEvent() const
{
- return adoptPtr(new CCAnimationStartedEvent(layerId));
+ ASSERT(type() == FinishedTransformAnimation);
+ return static_cast<const CCTransformAnimationFinishedEvent*>(this);
}
-CCAnimationStartedEvent::CCAnimationStartedEvent(int layerId)
- : CCAnimationEvent(layerId)
+PassOwnPtr<CCAnimationStartedEvent> CCAnimationStartedEvent::create(int layerId, CCActiveAnimation::TargetProperty targetProperty)
+{
+ return adoptPtr(new CCAnimationStartedEvent(layerId, targetProperty));
+}
+
+CCAnimationStartedEvent::CCAnimationStartedEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty)
+ : CCAnimationEvent(layerId, targetProperty)
{
}
return Started;
}
-PassOwnPtr<CCAnimationFinishedEvent> CCAnimationFinishedEvent::create(int layerId, int animationId)
+PassOwnPtr<CCFloatAnimationFinishedEvent> CCFloatAnimationFinishedEvent::create(int layerId, CCActiveAnimation::TargetProperty targetProperty, float finalValue)
+{
+ return adoptPtr(new CCFloatAnimationFinishedEvent(layerId, targetProperty, finalValue));
+}
+
+CCFloatAnimationFinishedEvent::CCFloatAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty, float finalValue)
+ : CCAnimationEvent(layerId, targetProperty)
+ , m_finalValue(finalValue)
+{
+}
+
+CCFloatAnimationFinishedEvent::~CCFloatAnimationFinishedEvent()
+{
+}
+
+CCAnimationEvent::Type CCFloatAnimationFinishedEvent::type() const
+{
+ return FinishedFloatAnimation;
+}
+
+PassOwnPtr<CCTransformAnimationFinishedEvent> CCTransformAnimationFinishedEvent::create(int layerId, CCActiveAnimation::TargetProperty targetProperty, const TransformationMatrix& finalValue)
{
- return adoptPtr(new CCAnimationFinishedEvent(layerId, animationId));
+ return adoptPtr(new CCTransformAnimationFinishedEvent(layerId, targetProperty, finalValue));
}
-CCAnimationFinishedEvent::CCAnimationFinishedEvent(int layerId, int animationId)
- : CCAnimationEvent(layerId)
- , m_animationId(animationId)
+CCTransformAnimationFinishedEvent::CCTransformAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty, const TransformationMatrix& finalValue)
+ : CCAnimationEvent(layerId, targetProperty)
+ , m_finalValue(finalValue)
{
}
-CCAnimationFinishedEvent::~CCAnimationFinishedEvent()
+CCTransformAnimationFinishedEvent::~CCTransformAnimationFinishedEvent()
{
}
-CCAnimationEvent::Type CCAnimationFinishedEvent::type() const
+CCAnimationEvent::Type CCTransformAnimationFinishedEvent::type() const
{
- return Finished;
+ return FinishedTransformAnimation;
}
} // namespace WebCore
#ifndef CCAnimationEvents_h
#define CCAnimationEvents_h
+#include "cc/CCActiveAnimation.h"
+
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
class CCAnimationStartedEvent;
-class CCAnimationFinishedEvent;
+class CCFloatAnimationFinishedEvent;
+class CCTransformAnimationFinishedEvent;
class CCAnimationEvent {
public:
- enum Type { Started, Finished };
+ enum Type { Started, FinishedFloatAnimation, FinishedTransformAnimation };
virtual ~CCAnimationEvent();
int layerId() const { return m_layerId; }
+ CCActiveAnimation::TargetProperty targetProperty() const { return m_targetProperty; }
+
const CCAnimationStartedEvent* toAnimationStartedEvent() const;
- const CCAnimationFinishedEvent* toAnimationFinishedEvent() const;
+ const CCFloatAnimationFinishedEvent* toFloatAnimationFinishedEvent() const;
+ const CCTransformAnimationFinishedEvent* toTransformAnimationFinishedEvent() const;
protected:
- CCAnimationEvent(int layerId);
+ CCAnimationEvent(int layerId, CCActiveAnimation::TargetProperty);
private:
int m_layerId;
+ CCActiveAnimation::TargetProperty m_targetProperty;
};
// Indicates that an animation has started on a particular layer.
class CCAnimationStartedEvent : public CCAnimationEvent {
public:
- static PassOwnPtr<CCAnimationStartedEvent> create(int layerId);
+ static PassOwnPtr<CCAnimationStartedEvent> create(int layerId, CCActiveAnimation::TargetProperty);
virtual ~CCAnimationStartedEvent();
virtual Type type() const;
private:
- explicit CCAnimationStartedEvent(int layerId);
+ CCAnimationStartedEvent(int layerId, CCActiveAnimation::TargetProperty);
};
-// Indicates that an animation has started on a particular layer.
-class CCAnimationFinishedEvent : public CCAnimationEvent {
+// Indicates that a float animation has completed.
+class CCFloatAnimationFinishedEvent : public CCAnimationEvent {
+public:
+ static PassOwnPtr<CCFloatAnimationFinishedEvent> create(int layerId, CCActiveAnimation::TargetProperty, float finalValue);
+
+ virtual ~CCFloatAnimationFinishedEvent();
+
+ virtual Type type() const;
+
+ float finalValue() const { return m_finalValue; }
+
+private:
+ CCFloatAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty, float finalValue);
+
+ float m_finalValue;
+};
+
+// Indicates that a transform animation has completed.
+class CCTransformAnimationFinishedEvent : public CCAnimationEvent {
public:
- static PassOwnPtr<CCAnimationFinishedEvent> create(int layerId, int animationId);
+ static PassOwnPtr<CCTransformAnimationFinishedEvent> create(int layerId, CCActiveAnimation::TargetProperty, const TransformationMatrix& finalValue);
- virtual ~CCAnimationFinishedEvent();
+ virtual ~CCTransformAnimationFinishedEvent();
virtual Type type() const;
- int animationId() const { return m_animationId; }
+ const TransformationMatrix& finalValue() const { return m_finalValue; }
private:
- CCAnimationFinishedEvent(int layerId, int animationId);
+ CCTransformAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty, const TransformationMatrix& finalValue);
- int m_animationId;
+ TransformationMatrix m_finalValue;
};
typedef Vector<OwnPtr<CCAnimationEvent> > CCAnimationEventsVector;
#include "cc/CCLayerAnimationController.h"
#include "GraphicsLayer.h" // for KeyframeValueList
+#include "TransformationMatrix.h"
#include "cc/CCActiveAnimation.h"
#include "cc/CCKeyframedAnimationCurve.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
#include <wtf/CurrentTime.h>
#include <wtf/HashMap.h>
if (animation && animation->isDirectionSet() && animation->direction() == Animation::AnimationDirectionAlternate)
return nullptr;
- // FIXME: add support for delay
- if (animation && animation->isDelaySet() && animation->delay() > 0)
- return nullptr;
-
// FIXME: add support for fills forwards and fills backwards
if (animation && animation->isFillModeSet() && (animation->fillsForwards() || animation->fillsBackwards()))
return nullptr;
} // namepace
-CCLayerAnimationController::CCLayerAnimationController()
+CCLayerAnimationController::CCLayerAnimationController(CCLayerAnimationControllerClient* client)
+ : m_client(client)
{
}
{
}
-PassOwnPtr<CCLayerAnimationController> CCLayerAnimationController::create()
+PassOwnPtr<CCLayerAnimationController> CCLayerAnimationController::create(CCLayerAnimationControllerClient* client)
{
- return adoptPtr(new CCLayerAnimationController);
+ return adoptPtr(new CCLayerAnimationController(client));
}
bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList, const IntSize&, const Animation* animation, int animationId, int groupId, double timeOffset)
// Ensures that the list of active animations on the main thread and the impl thread
// are kept in sync.
-void CCLayerAnimationController::synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::pushAnimationUpdatesTo(CCLayerAnimationController* controllerImpl)
{
- removeCompletedAnimations(controllerImpl);
pushNewAnimationsToImplThread(controllerImpl);
removeAnimationsCompletedOnMainThread(controllerImpl);
- pushAnimationProperties(controllerImpl);
}
-void CCLayerAnimationController::removeCompletedAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::animate(double monotonicTime, CCAnimationEventsVector* events)
+{
+ startAnimationsWaitingForNextTick(monotonicTime, events);
+ startAnimationsWaitingForStartTime(monotonicTime, events);
+ startAnimationsWaitingForTargetAvailability(monotonicTime, events);
+ resolveConflicts(monotonicTime);
+ tickAnimations(monotonicTime);
+ purgeFinishedAnimations(events);
+ startAnimationsWaitingForTargetAvailability(monotonicTime, events);
+}
+
+void CCLayerAnimationController::add(PassOwnPtr<CCActiveAnimation> animation)
{
- // Any animations finished on the impl thread are removed from the main thread's collection.
- for (size_t i = 0; i < controllerImpl->m_finishedAnimations.size(); ++i)
- remove(controllerImpl->m_finishedAnimations[i].groupId, controllerImpl->m_finishedAnimations[i].targetProperty);
- controllerImpl->m_finishedAnimations.clear();
+ m_activeAnimations.append(animation);
}
-void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationControllerImpl* controllerImpl)
+CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty targetProperty)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i)
+ if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty)
+ return m_activeAnimations[i].get();
+ return 0;
+}
+
+bool CCLayerAnimationController::hasActiveAnimation() const
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
+ return true;
+ }
+ return false;
+}
+
+bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty)
+ return true;
+ }
+ return false;
+}
+
+void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationController* controllerImpl)
{
// Any new animations owned by the main thread's controller are cloned and adde to the impl thread's controller.
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (!controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty()))
- controllerImpl->add(m_activeAnimations[i]->cloneForImplThread());
+ if (!controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty())) {
+ OwnPtr<CCActiveAnimation> toAdd(m_activeAnimations[i]->cloneForImplThread());
+ // If the animation is already in progress -- set it to be waiting until the target is available.
+ // That way, it will have a chance to start on the impl thread. Otherwise, we will never tick at the
+ // very beginning of the animation.
+ if (toAdd->runState() == CCActiveAnimation::Running || toAdd->runState() == CCActiveAnimation::Paused)
+ toAdd->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 0);
+ controllerImpl->add(toAdd.release());
+ }
}
}
-void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationController* controllerImpl)
{
// Delete all impl thread animations for which there is no corresponding main thread animation.
// Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented
}
}
-void CCLayerAnimationController::pushAnimationProperties(CCLayerAnimationControllerImpl* controllerImpl)
+void CCLayerAnimationController::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector* events)
{
- // Delete all impl thread animations for which there is no corresponding main thread animation.
- // Each iteration, controller->m_activeAnimations.size() is decremented or i is incremented
- // guaranteeing progress towards loop termination.
- for (size_t i = 0; i < controllerImpl->m_activeAnimations.size(); ++i) {
- CCActiveAnimation* currentImpl = controllerImpl->m_activeAnimations[i].get();
- CCActiveAnimation* current = getActiveAnimation(currentImpl->group(), currentImpl->targetProperty());
- ASSERT(current);
- if (current)
- current->synchronizeProperties(currentImpl);
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ m_activeAnimations[i]->setStartTime(monotonicTime);
+ if (events)
+ events->append(CCAnimationStartedEvent::create(m_client->id(), m_activeAnimations[i]->targetProperty()));
+ }
}
}
-CCActiveAnimation* CCLayerAnimationController::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty targetProperty)
+void CCLayerAnimationController::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector* events)
{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i)
- if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty)
- return m_activeAnimations[i].get();
- return 0;
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ if (events)
+ events->append(CCAnimationStartedEvent::create(m_client->id(), m_activeAnimations[i]->targetProperty()));
+ }
+ }
}
-bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const
+void CCLayerAnimationController::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector* events)
{
+ // First collect running properties.
+ TargetProperties blockedProperties;
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty)
- return true;
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Finished)
+ blockedProperties.add(m_activeAnimations[i]->targetProperty());
+ }
+
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForTargetAvailability) {
+ // Collect all properties for animations with the same group id (they should all also be in the list of animations).
+ TargetProperties enqueuedProperties;
+ enqueuedProperties.add(m_activeAnimations[i]->targetProperty());
+ for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
+ if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group())
+ enqueuedProperties.add(m_activeAnimations[j]->targetProperty());
+ }
+
+ // Check to see if intersection of the list of properties affected by the group and the list of currently
+ // blocked properties is null. In any case, the group's target properties need to be added to the list
+ // of blocked properties.
+ bool nullIntersection = true;
+ for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) {
+ if (!blockedProperties.add(*pIter).second)
+ nullIntersection = false;
+ }
+
+ // If the intersection is null, then we are free to start the animations in the group.
+ if (nullIntersection) {
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ m_activeAnimations[i]->setStartTime(monotonicTime);
+ if (events)
+ events->append(CCAnimationStartedEvent::create(m_client->id(), m_activeAnimations[i]->targetProperty()));
+ for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
+ if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) {
+ m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime);
+ m_activeAnimations[j]->setStartTime(monotonicTime);
+ }
+ }
+ }
+ }
}
- return false;
}
-void CCLayerAnimationController::remove(int groupId, CCActiveAnimation::TargetProperty targetProperty)
+void CCLayerAnimationController::resolveConflicts(double monotonicTime)
{
+ // Find any animations that are animating the same property and resolve the
+ // confict. We could eventually blend, but for now we'll just abort the
+ // previous animation (where 'previous' means: (1) has a prior start time or
+ // (2) has an equal start time, but was added to the queue earlier, i.e.,
+ // has a lower index in m_activeAnimations).
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == targetProperty) {
- m_activeAnimations.remove(i);
- return;
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
+ for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
+ if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) {
+ if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime())
+ m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
+ else
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
+ }
+ }
+ }
+ }
+}
+
+void CCLayerAnimationController::purgeFinishedAnimations(CCAnimationEventsVector* events)
+{
+ // Each iteration, m_activeAnimations.size() decreases or i increments,
+ // guaranteeing progress towards loop termination.
+ size_t i = 0;
+ while (i < m_activeAnimations.size()) {
+ int groupId = m_activeAnimations[i]->group();
+ bool allAnimsWithSameIdAreFinished = false;
+ if (m_activeAnimations[i]->isFinished()) {
+ allAnimsWithSameIdAreFinished = true;
+ for (size_t j = 0; j < m_activeAnimations.size(); ++j) {
+ if (groupId == m_activeAnimations[j]->group() && !m_activeAnimations[j]->isFinished()) {
+ allAnimsWithSameIdAreFinished = false;
+ break;
+ }
+ }
+ }
+ if (allAnimsWithSameIdAreFinished) {
+ // We now need to remove all animations with the same group id as groupId
+ // (and send along animation finished notifications, if necessary).
+ // Each iteration, m_activeAnimations.size() decreases or j increments,
+ // guaranteeing progress towards loop termination. Also, we are guaranteed
+ // to remove at least one active animation.
+ for (size_t j = i; j < m_activeAnimations.size();) {
+ if (groupId != m_activeAnimations[j]->group())
+ j++;
+ else {
+ if (events) {
+ switch (m_activeAnimations[j]->targetProperty()) {
+ case CCActiveAnimation::Opacity:
+ events->append(CCFloatAnimationFinishedEvent::create(m_client->id(), CCActiveAnimation::Opacity, m_client->opacity()));
+ break;
+ case CCActiveAnimation::Transform:
+ events->append(CCTransformAnimationFinishedEvent::create(m_client->id(), CCActiveAnimation::Transform, m_client->transform()));
+ break;
+ }
+ }
+ m_activeAnimations.remove(j);
+ }
+ }
+ } else
+ i++;
+ }
+}
+
+void CCLayerAnimationController::tickAnimations(double monotonicTime)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
+ double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime);
+
+ switch (m_activeAnimations[i]->targetProperty()) {
+
+ case CCActiveAnimation::Transform: {
+ const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve();
+ const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds());
+ if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
+
+ m_client->setTransformFromAnimation(matrix);
+ break;
+ }
+
+ case CCActiveAnimation::Opacity: {
+ const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve();
+ const float opacity = floatAnimationCurve->getValue(trimmed);
+ if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
+
+ m_client->setOpacityFromAnimation(opacity);
+ break;
+ }
+
+ }
}
}
}
#define CCLayerAnimationController_h
#include "cc/CCActiveAnimation.h"
+#include "cc/CCAnimationCurve.h"
+#include "cc/CCAnimationEvents.h"
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
-
namespace WebCore {
class Animation;
-class CCLayerAnimationControllerImpl;
class IntSize;
class KeyframeValueList;
+class TransformationMatrix;
+
+class CCLayerAnimationControllerClient {
+public:
+ virtual ~CCLayerAnimationControllerClient() { }
+
+ virtual int id() const = 0;
+ virtual void setOpacityFromAnimation(float) = 0;
+ virtual float opacity() const = 0;
+ virtual void setTransformFromAnimation(const TransformationMatrix&) = 0;
+ virtual const TransformationMatrix& transform() const = 0;
+ virtual const IntSize& bounds() const = 0;
+};
class CCLayerAnimationController {
WTF_MAKE_NONCOPYABLE(CCLayerAnimationController);
public:
- static PassOwnPtr<CCLayerAnimationController> create();
+ static PassOwnPtr<CCLayerAnimationController> create(CCLayerAnimationControllerClient*);
virtual ~CCLayerAnimationController();
- // These are virtual for testing.
+ // These methods are virtual for testing.
virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, int animationId, int groupId, double timeOffset);
virtual void pauseAnimation(int animationId, double timeOffset);
virtual void removeAnimation(int animationId);
// Ensures that the list of active animations on the main thread and the impl thread
// are kept in sync. This function does not take ownership of the impl thread controller.
- virtual void synchronizeAnimations(CCLayerAnimationControllerImpl*);
+ virtual void pushAnimationUpdatesTo(CCLayerAnimationController*);
+
+ void animate(double monotonicTime, CCAnimationEventsVector*);
- bool hasActiveAnimation() const { return m_activeAnimations.size(); }
+ void add(PassOwnPtr<CCActiveAnimation>);
+
+ // Returns the active animation in the given group, animating the given property if such an
+ // animation exists.
CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
+
+ // Returns true if there are any animations that have neither finished nor aborted.
+ bool hasActiveAnimation() const;
+
+ // Returns true if there is an animation currently animating the given property, or
+ // if there is an animation scheduled to animate this property in the future.
bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const;
protected:
- CCLayerAnimationController();
+ explicit CCLayerAnimationController(CCLayerAnimationControllerClient*);
private:
- void removeCompletedAnimations(CCLayerAnimationControllerImpl*);
- void pushNewAnimationsToImplThread(CCLayerAnimationControllerImpl*);
- void removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl*);
- void pushAnimationProperties(CCLayerAnimationControllerImpl*);
+ typedef HashSet<int> TargetProperties;
+
+ void pushNewAnimationsToImplThread(CCLayerAnimationController*);
+ void removeAnimationsCompletedOnMainThread(CCLayerAnimationController*);
+
+ void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector*);
+ void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*);
+ void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*);
+ void resolveConflicts(double monotonicTime);
+ void purgeFinishedAnimations(CCAnimationEventsVector*);
- void remove(int groupId, CCActiveAnimation::TargetProperty);
+ void tickAnimations(double monotonicTime);
+ CCLayerAnimationControllerClient* m_client;
Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
};
+++ /dev/null
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "cc/CCLayerAnimationControllerImpl.h"
-
-#include "TransformationMatrix.h"
-#include "TransformOperations.h"
-
-namespace WebCore {
-
-// A collection of properties. Used when deterimining if animations waiting for target
-// availibility are able to run.
-typedef HashSet<int> TargetProperties;
-
-PassOwnPtr<CCLayerAnimationControllerImpl> CCLayerAnimationControllerImpl::create(CCLayerAnimationControllerImplClient* client)
-{
- return adoptPtr(new CCLayerAnimationControllerImpl(client));
-}
-
-CCLayerAnimationControllerImpl::CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient* client)
- : m_client(client)
-{
-}
-
-CCLayerAnimationControllerImpl::~CCLayerAnimationControllerImpl()
-{
-}
-
-void CCLayerAnimationControllerImpl::animate(double monotonicTime, CCAnimationEventsVector& events)
-{
- startAnimationsWaitingForNextTick(monotonicTime, events);
- startAnimationsWaitingForStartTime(monotonicTime, events);
- startAnimationsWaitingForTargetAvailability(monotonicTime, events);
- resolveConflicts(monotonicTime);
- tickAnimations(monotonicTime);
- purgeFinishedAnimations(events);
- startAnimationsWaitingForTargetAvailability(monotonicTime, events);
-}
-
-void CCLayerAnimationControllerImpl::add(PassOwnPtr<CCActiveAnimation> anim)
-{
- m_activeAnimations.append(anim);
-}
-
-CCActiveAnimation* CCLayerAnimationControllerImpl::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty property)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == property)
- return m_activeAnimations[i].get();
- }
- return 0;
-}
-
-bool CCLayerAnimationControllerImpl::hasActiveAnimation() const
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
- return true;
- }
- return false;
-}
-
-bool CCLayerAnimationControllerImpl::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty)
- return true;
- }
- return false;
-}
-
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector& events)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) {
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
- m_activeAnimations[i]->setStartTime(monotonicTime);
- events.append(CCAnimationStartedEvent::create(m_client->id()));
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector& events)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) {
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
- events.append(CCAnimationStartedEvent::create(m_client->id()));
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector& events)
-{
- // First collect running properties.
- TargetProperties blockedProperties;
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running || m_activeAnimations[i]->runState() == CCActiveAnimation::Finished)
- blockedProperties.add(m_activeAnimations[i]->targetProperty());
- }
-
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForTargetAvailability) {
- // Collect all properties for animations with the same group id (they should all also be in the list of animations).
- TargetProperties enqueuedProperties;
- enqueuedProperties.add(m_activeAnimations[i]->targetProperty());
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group())
- enqueuedProperties.add(m_activeAnimations[j]->targetProperty());
- }
-
- // Check to see if intersection of the list of properties affected by the group and the list of currently
- // blocked properties is null. In any case, the group's target properties need to be added to the list
- // of blocked properties.
- bool nullIntersection = true;
- for (TargetProperties::iterator pIter = enqueuedProperties.begin(); pIter != enqueuedProperties.end(); ++pIter) {
- if (!blockedProperties.add(*pIter).second)
- nullIntersection = false;
- }
-
- // If the intersection is null, then we are free to start the animations in the group.
- if (nullIntersection) {
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
- m_activeAnimations[i]->setStartTime(monotonicTime);
- events.append(CCAnimationStartedEvent::create(m_client->id()));
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) {
- m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime);
- m_activeAnimations[j]->setStartTime(monotonicTime);
- }
- }
- }
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::resolveConflicts(double monotonicTime)
-{
- // Find any animations that are animating the same property and resolve the
- // confict. We could eventually blend, but for now we'll just abort the
- // previous animation (where 'previous' means: (1) has a prior start time or
- // (2) has an equal start time, but was added to the queue earlier, i.e.,
- // has a lower index in m_activeAnimations).
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) {
- if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime())
- m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
- else
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime);
- }
- }
- }
- }
-}
-
-void CCLayerAnimationControllerImpl::purgeFinishedAnimations(CCAnimationEventsVector& events)
-{
- // Each iteration, m_activeAnimations.size() decreases or i increments,
- // guaranteeing progress towards loop termination.
- size_t i = 0;
- while (i < m_activeAnimations.size()) {
- bool allAnimsWithSameIdAreFinished = false;
- if (m_activeAnimations[i]->isFinished()) {
- allAnimsWithSameIdAreFinished = true;
- for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
- if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group() && !m_activeAnimations[j]->isFinished()) {
- allAnimsWithSameIdAreFinished = false;
- break;
- }
- }
- }
- if (allAnimsWithSameIdAreFinished) {
- events.append(CCAnimationFinishedEvent::create(m_client->id(), m_activeAnimations[i]->id()));
- m_finishedAnimations.append(m_activeAnimations[i]->signature());
- m_activeAnimations.remove(i);
- } else
- i++;
- }
-}
-
-void CCLayerAnimationControllerImpl::tickAnimations(double monotonicTime)
-{
- for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
- double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime);
-
- switch (m_activeAnimations[i]->targetProperty()) {
-
- case CCActiveAnimation::Transform: {
- const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve();
- const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds());
- if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
-
- m_client->setTransform(matrix);
- break;
- }
-
- case CCActiveAnimation::Opacity: {
- const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve();
- const float opacity = floatAnimationCurve->getValue(trimmed);
- if (m_activeAnimations[i]->isFinishedAt(monotonicTime))
- m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime);
-
- m_client->setOpacity(opacity);
- break;
- }
-
- } // switch
- } // if running
- } // for each animation
-}
-
-} // namespace WebCore
+++ /dev/null
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CCLayerAnimationControllerImpl_h
-#define CCLayerAnimationControllerImpl_h
-
-#include "cc/CCActiveAnimation.h"
-#include "cc/CCAnimationCurve.h"
-#include "cc/CCAnimationEvents.h"
-
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class CCLayerAnimationControllerImpl;
-class IntSize;
-class TransformationMatrix;
-class TransformOperations;
-
-class CCLayerAnimationControllerImplClient {
-public:
- virtual ~CCLayerAnimationControllerImplClient() { }
-
- virtual int id() const = 0;
- virtual float opacity() const = 0;
- virtual void setOpacity(float) = 0;
- virtual const TransformationMatrix& transform() const = 0;
- virtual void setTransform(const TransformationMatrix&) = 0;
- virtual const IntSize& bounds() const = 0;
-};
-
-class CCLayerAnimationControllerImpl {
- WTF_MAKE_NONCOPYABLE(CCLayerAnimationControllerImpl);
-public:
- static PassOwnPtr<CCLayerAnimationControllerImpl> create(CCLayerAnimationControllerImplClient*);
-
- virtual ~CCLayerAnimationControllerImpl();
-
- void animate(double monotonicTime, CCAnimationEventsVector&);
-
- void add(PassOwnPtr<CCActiveAnimation>);
-
- // Returns the active animation in the given group, animating the given property if such an
- // animation exists.
- CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
-
- // Returns true if there are any animations that are neither finished nor aborted.
- bool hasActiveAnimation() const;
-
- bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const;
-
-private:
- friend class CCLayerAnimationController;
-
- // The animator is owned by the layer.
- explicit CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient*);
-
- void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector&);
- void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector&);
- void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector&);
- void resolveConflicts(double monotonicTime);
- void purgeFinishedAnimations(CCAnimationEventsVector&);
-
- void tickAnimations(double monotonicTime);
-
- CCLayerAnimationControllerImplClient* m_client;
- Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
- Vector<CCActiveAnimation::AnimationSignature> m_finishedAnimations;
-};
-
-} // namespace WebCore
-
-#endif // CCLayerAnimationControllerImpl_h
-
class CCLayerAnimationDelegate {
public:
virtual void notifyAnimationStarted(double time) = 0;
- virtual void notifyAnimationFinished(int animationId) = 0;
};
} // namespace WebCore
#include "LayerChromium.h"
#include "LayerRendererChromium.h"
#include "cc/CCDebugBorderDrawQuad.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
#include "cc/CCLayerSorter.h"
#include "cc/CCQuadCuller.h"
#include "cc/CCSolidColorDrawQuad.h"
, m_debugBorderWidth(0)
, m_drawTransformIsAnimating(false)
, m_screenSpaceTransformIsAnimating(false)
- , m_layerAnimationController(CCLayerAnimationControllerImpl::create(this))
+ , m_layerAnimationController(CCLayerAnimationController::create(this))
{
ASSERT(CCProxy::isImplThread());
}
m_children[i]->resetAllChangeTrackingForSubtree();
}
+void CCLayerImpl::setOpacityFromAnimation(float opacity)
+{
+ setOpacity(opacity);
+}
+
+void CCLayerImpl::setTransformFromAnimation(const TransformationMatrix& transform)
+{
+ setTransform(transform);
+}
+
void CCLayerImpl::setBounds(const IntSize& bounds)
{
if (m_bounds == bounds)
#include "Region.h"
#include "TextStream.h"
#include "TransformationMatrix.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCRenderSurface.h"
#include "cc/CCSharedQuadState.h"
#include <wtf/OwnPtr.h>
class LayerChromium;
class LayerRendererChromium;
-class CCLayerImpl : public CCLayerAnimationControllerImplClient {
+class CCLayerImpl : public CCLayerAnimationControllerClient {
public:
static PassOwnPtr<CCLayerImpl> create(int id)
{
return adoptPtr(new CCLayerImpl(id));
}
- // CCLayerAnimationControllerImplClient implementation.
- virtual int id() const { return m_layerId; }
+ virtual ~CCLayerImpl();
- virtual void setOpacity(float);
+ // CCLayerAnimationControllerClient implementation.
+ virtual int id() const { return m_layerId; }
+ virtual void setOpacityFromAnimation(float);
virtual float opacity() const { return m_opacity; }
- bool opacityIsAnimating() const;
-
- virtual void setTransform(const TransformationMatrix&);
+ virtual void setTransformFromAnimation(const TransformationMatrix&);
virtual const TransformationMatrix& transform() const { return m_transform; }
- bool transformIsAnimating() const;
-
virtual const IntSize& bounds() const { return m_bounds; }
- virtual ~CCLayerImpl();
-
// Tree structure.
CCLayerImpl* parent() const { return m_parent; }
const Vector<OwnPtr<CCLayerImpl> >& children() const { return m_children; }
void setOpaque(bool);
bool opaque() const { return m_opaque; }
+ void setOpacity(float);
+ bool opacityIsAnimating() const;
+
void setPosition(const FloatPoint&);
const FloatPoint& position() const { return m_position; }
// Returns the rect containtaining this layer in the current view's coordinate system.
const IntRect getDrawRect() const;
+ void setTransform(const TransformationMatrix&);
+ bool transformIsAnimating() const;
+
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
void setDrawTransform(const TransformationMatrix& matrix) { m_drawTransform = matrix; }
const TransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
bool layerPropertyChanged() const { return m_layerPropertyChanged; }
void resetAllChangeTrackingForSubtree();
- CCLayerAnimationControllerImpl* layerAnimationController() { return m_layerAnimationController.get(); }
+ CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); }
virtual Region opaqueContentsRegion() const { return Region(); };
FloatRect m_updateRect;
// Manages animations for this layer.
- OwnPtr<CCLayerAnimationControllerImpl> m_layerAnimationController;
+ OwnPtr<CCLayerAnimationController> m_layerAnimationController;
};
void sortLayers(Vector<CCLayerImpl*>::iterator first, Vector<CCLayerImpl*>::iterator end, CCLayerSorter*);
#include "Region.h"
#include "TraceEvent.h"
#include "TreeSynchronizer.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerIterator.h"
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCLayerTreeHostImpl.h"
CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings& settings)
: m_compositorIdentifier(-1)
, m_animating(false)
+ , m_needsAnimateLayers(false)
, m_client(client)
, m_frameNumber(0)
, m_layerRendererInitialized(false)
{
m_animating = true;
m_client->updateAnimations(frameBeginTime);
+ animateLayers(monotonicallyIncreasingTime());
m_animating = false;
}
hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer()));
- // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers.
- if (rootLayer())
+ // We may have added an animation during the tree sync. This will cause both layer tree hosts
+ // to visit their controllers.
+ if (rootLayer()) {
hostImpl->setNeedsAnimateLayers();
+ m_needsAnimateLayers = true;
+ }
hostImpl->setSourceFrameNumber(frameNumber());
hostImpl->setViewportSize(viewportSize());
hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer()));
- // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers.
- if (rootLayer())
+ // We may have added an animation during the tree sync. This will cause both layer tree hosts
+ // to visit their controllers.
+ if (rootLayer()) {
hostImpl->setNeedsAnimateLayers();
+ m_needsAnimateLayers = true;
+ }
}
void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec)
m_deleteTextureAfterCommitList.append(texture);
}
+void CCLayerTreeHost::animateLayers(double monotonicTime)
+{
+ if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayer)
+ return;
+
+ TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
+ m_needsAnimateLayers = animateLayersRecursive(m_rootLayer.get(), monotonicTime);
+}
+
+bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double monotonicTime)
+{
+ bool subtreeNeedsAnimateLayers = false;
+ CCLayerAnimationController* currentController = current->layerAnimationController();
+ currentController->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(), monotonicTime))
+ subtreeNeedsAnimateLayers = true;
+ }
+
+ return subtreeNeedsAnimateLayers;
+}
+
void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
{
for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
void reserveTextures();
void clearPendingUpdate();
+ void animateLayers(double monotonicTime);
+ bool animateLayersRecursive(LayerChromium* current, double monotonicTime);
void setAnimationEventsRecursive(const CCAnimationEventsVector&, LayerChromium*, double wallClockTime);
int m_compositorIdentifier;
bool m_animating;
+ bool m_needsAnimateLayers;
CCLayerTreeHostClient* m_client;
#include "LayerChromium.h"
#include "RenderSurfaceChromium.h"
#include "TransformationMatrix.h"
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerIterator.h"
#include "cc/CCLayerSorter.h"
occlusionTracker.overdrawMetrics().recordMetrics(this);
}
-void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector& events, bool& didAnimate, bool& needsAnimateLayers)
+void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
{
bool subtreeNeedsAnimateLayers = false;
- CCLayerAnimationControllerImpl* currentController = current->layerAnimationController();
+ CCLayerAnimationController* currentController = current->layerAnimationController();
bool hadActiveAnimation = currentController->hasActiveAnimation();
currentController->animate(monotonicTime, events);
- bool startedAnimation = events.size() > 0;
+ bool startedAnimation = events->size() > 0;
// We animated if we either ticked a running animation, or started a new animation.
if (hadActiveAnimation || startedAnimation)
OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
bool didAnimate = false;
- animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, *events, didAnimate, m_needsAnimateLayers);
+ animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
if (!events->isEmpty())
m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
void updateMaxScrollPosition();
void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
void calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
- void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector&, bool& didAnimate, bool& needsAnimateLayers);
+ void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers);
IntSize contentSize() const;
void sendDidLoseContextRecursive(CCLayerImpl*);
// Set on impl thread, read on main thread.
struct BeginFrameAndCommitState {
- BeginFrameAndCommitState() : frameBeginTime(0) { }
+ BeginFrameAndCommitState() : frameBeginTime() { }
double frameBeginTime;
OwnPtr<CCScrollAndScaleSet> scrollInfo;
};
+2012-03-20 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Infrastructure to allow animating layers to be only partially updated
+ https://bugs.webkit.org/show_bug.cgi?id=81106
+
+ Reviewed by James Robinson
+
+ * WebKit.gypi:
+ * tests/CCAnimationTestCommon.cpp:
+ (WebKitTests::FakeLayerAnimationControllerClient::FakeLayerAnimationControllerClient):
+ (WebKitTests::FakeLayerAnimationControllerClient::~FakeLayerAnimationControllerClient):
+ * tests/CCAnimationTestCommon.h:
+ (FakeLayerAnimationControllerClient):
+ (WebKitTests::FakeLayerAnimationControllerClient::setOpacityFromAnimation):
+ (WebKitTests::FakeLayerAnimationControllerClient::setTransformFromAnimation):
+ * tests/CCLayerAnimationControllerImplTest.cpp: Removed.
+ * tests/CCLayerAnimationControllerTest.cpp:
+ (WebKitTests::TEST):
+ (WebKitTests):
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF::CCLayerTreeHostTestAddAnimation::CCLayerTreeHostTestAddAnimation):
+ (WTF::CCLayerTreeHostTestAddAnimation::animateLayers):
+ (CCLayerTreeHostTestAddAnimation):
+ * tests/TreeSynchronizerTest.cpp:
+ (WebKitTests::FakeLayerAnimationController::create):
+ (WebKitTests::FakeLayerAnimationController::FakeLayerAnimationController):
+ (WebKitTests::FakeLayerAnimationController::pushAnimationUpdatesTo):
+ (WebKitTests::TEST):
+
2012-03-20 Keishi Hattori <keishi@webkit.org>
[chromium] Marking WebFrameTest.DivAutoZoomParamsTest as failing.
'tests/CCDelayBasedTimeSourceTest.cpp',
'tests/CCFrameRateControllerTest.cpp',
'tests/CCKeyframedAnimationCurveTest.cpp',
- 'tests/CCLayerAnimationControllerImplTest.cpp',
'tests/CCLayerAnimationControllerTest.cpp',
'tests/CCLayerImplTest.cpp',
'tests/CCLayerIteratorTest.cpp',
return (1 - time) * m_from + time * m_to;
}
-FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient()
+FakeLayerAnimationControllerClient::FakeLayerAnimationControllerClient()
: m_opacity(0)
{
}
-FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient()
+FakeLayerAnimationControllerClient::~FakeLayerAnimationControllerClient()
{
}
#define CCAnimationTestCommon_h
#include "cc/CCAnimationCurve.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
+#include "cc/CCLayerAnimationController.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
-class CCLayerAnimationController;
class LayerChromium;
}
float m_to;
};
-class FakeLayerAnimationControllerImplClient : public WebCore::CCLayerAnimationControllerImplClient {
+class FakeLayerAnimationControllerClient : public WebCore::CCLayerAnimationControllerClient {
public:
- FakeLayerAnimationControllerImplClient();
- virtual ~FakeLayerAnimationControllerImplClient();
+ FakeLayerAnimationControllerClient();
+ virtual ~FakeLayerAnimationControllerClient();
+ // CCLayerAnimationControllerClient implementation
virtual int id() const { return 0; }
+ virtual void setOpacityFromAnimation(float opacity) { m_opacity = opacity; }
virtual float opacity() const { return m_opacity; }
- virtual void setOpacity(float opacity) { m_opacity = opacity; }
+ virtual void setTransformFromAnimation(const WebCore::TransformationMatrix& transform) { m_transform = transform; }
virtual const WebCore::TransformationMatrix& transform() const { return m_transform; }
- virtual void setTransform(const WebCore::TransformationMatrix& transform) { m_transform = transform; }
virtual const WebCore::IntSize& bounds() const { return m_bounds; }
private:
+++ /dev/null
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "CCAnimationTestCommon.h"
-#include "cc/CCLayerAnimationControllerImpl.h"
-#include "cc/CCAnimationCurve.h"
-#include "cc/CCAnimationEvents.h"
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <wtf/Vector.h>
-
-using namespace WebCore;
-using namespace WebKitTests;
-
-namespace {
-
-PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property)
-{
- return CCActiveAnimation::create(curve, 0, id, property);
-}
-
-// Tests that transitioning opacity from 0 to 1 works as expected.
-TEST(CCLayerAnimationControllerImplTest, TrivialTransition)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- controller->add(toAdd.release());
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_EQ(1, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests that two queued animations affecting the same property run in sequence.
-TEST(CCLayerAnimationControllerImplTest, TrivialQueuing)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
- controller->animate(2, *events);
- EXPECT_EQ(0.5f, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests interrupting a transition with another transition.
-TEST(CCLayerAnimationControllerImplTest, Interrupt)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
- controller->add(toAdd.release());
-
- controller->animate(0.5, *events); // second anim starts NOW.
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
- controller->animate(1.5, *events);
- EXPECT_EQ(0.5f, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests scheduling two animations to run together when only one property is free.
-TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWhenAPropertyIsBlocked)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_EQ(0, dummy.opacity());
- EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1, *events);
- // Should not have started the float transition yet.
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- // The the float animation should have started at time 1 and should be done.
- controller->animate(2, *events);
- EXPECT_EQ(1, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests scheduling two animations to run together with different lengths and another
-// animation queued to start when the shorter animation finishes (should wait
-// for both to finish).
-TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
-
- // Anims with id 1 should both start now.
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- 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);
- // Should not have started the float transition yet.
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
-
- // The the second opacity animation should start at time 2 and should be
- // done by time 3
- controller->animate(3, *events);
- EXPECT_EQ(0.5f, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future.
-TEST(CCLayerAnimationControllerImplTest, ScheduleAnimation)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
- toAdd->setStartTime(1);
- controller->add(toAdd.release());
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(2, *events);
- EXPECT_EQ(1, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future that's interrupting a running animation.
-TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimation)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
- toAdd->setStartTime(1);
- controller->add(toAdd.release());
-
- // First 2s opacity transition should start immediately.
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(2, *events);
- EXPECT_EQ(0, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Tests scheduling an animation to start in the future that interrupts a running animation
-// and there is yet another animation queued to start later.
-TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, CCActiveAnimation::Opacity));
- toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
- toAdd->setStartTime(1);
- controller->add(toAdd.release());
-
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity));
-
- // First 2s opacity transition should start immediately.
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(3, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(4, *events);
- EXPECT_EQ(0.75f, dummy.opacity());
- EXPECT_FALSE(controller->hasActiveAnimation());
-}
-
-// Test that a looping animation loops and for the correct number of iterations.
-TEST(CCLayerAnimationControllerImplTest, TrivialLooping)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- toAdd->setIterations(3);
- controller->add(toAdd.release());
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(2.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(2.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(3, *events);
- EXPECT_FALSE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
-
- // Just be extra sure.
- controller->animate(4, *events);
- EXPECT_EQ(1, dummy.opacity());
-}
-
-// Test that an infinitely looping animation does indeed go until aborted.
-TEST(CCLayerAnimationControllerImplTest, InfiniteLooping)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- const int id = 1;
- OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
- toAdd->setIterations(-1);
- controller->add(toAdd.release());
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
-
- controller->animate(1073741824.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1073741824.75, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 0.75f);
- EXPECT_FALSE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
-}
-
-// Test that pausing and resuming work as expected.
-TEST(CCLayerAnimationControllerImplTest, PauseResume)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- const int id = 1;
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5f);
-
- controller->animate(1024, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024);
-
- controller->animate(1024.25, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(1024.5, *events);
- EXPECT_FALSE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
-}
-
-TEST(CCLayerAnimationControllerImplTest, AbortAGroupedAnimation)
-{
- OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- const int id = 1;
- controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
- controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity));
-
- controller->animate(0, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0, dummy.opacity());
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(0.5f, dummy.opacity());
-
- EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
- controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1);
- controller->animate(1, *events);
- EXPECT_TRUE(controller->hasActiveAnimation());
- EXPECT_EQ(1, dummy.opacity());
- controller->animate(2, *events);
- EXPECT_TRUE(!controller->hasActiveAnimation());
- EXPECT_EQ(0.75f, dummy.opacity());
-}
-
-} // namespace
TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
{
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
values.insert(new FloatAnimationValue(0, 0));
TEST(CCLayerAnimationControllerTest, createTransformAnimation)
{
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
TEST(CCLayerAnimationControllerTest, syncNewAnimation)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummyImpl;
+ OwnPtr<CCLayerAnimationController> controllerImpl(CCLayerAnimationController::create(&dummyImpl));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
addOpacityTransitionToController(*controller, 1, 0, 1);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->pushAnimationUpdatesTo(controllerImpl.get());
EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
}
-TEST(CCLayerAnimationControllerTest, syncAnimationProperties)
+// Tests that transitioning opacity from 0 to 1 works as expected.
+TEST(CCLayerAnimationControllerTest, TrivialTransition)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ controller->add(toAdd.release());
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
- controller->synchronizeAnimations(controllerImpl.get());
+// Tests that two queued animations affecting the same property run in sequence.
+TEST(CCLayerAnimationControllerTest, TrivialQueuing)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
- // Push an animation property change to the impl thread (should not cause an animation to be added).
- controller->pauseAnimation(0, 0);
- controller->synchronizeAnimations(controllerImpl.get());
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
- EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+// Tests interrupting a transition with another transition.
+TEST(CCLayerAnimationControllerTest, Interrupt)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForNextTick, 0);
+ controller->add(toAdd.release());
+
+ // Since the animation was in the WaitingForNextTick state, it should start right in
+ // this call to animate.
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(1.5, events.get());
+ EXPECT_EQ(0.5, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
}
-TEST(CCLayerAnimationControllerTest, syncAbortedAnimation)
+// Tests scheduling two animations to run together when only one property is free.
+TEST(CCLayerAnimationControllerTest, ScheduleTogetherWhenAPropertyIsBlocked)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ controller->animate(0, events.get());
+ 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, dummy.opacity());
+ // The float animation should have started at time 1 and should be done.
+ controller->animate(2, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
- controller->synchronizeAnimations(controllerImpl.get());
+// Tests scheduling two animations to run together with different lengths and another
+// animation queued to start when the shorter animation finishes (should wait
+// for both to finish).
+TEST(CCLayerAnimationControllerTest, ScheduleTogetherWithAnAnimWaiting)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.5)), 2, CCActiveAnimation::Opacity));
+
+ // Animations with id 1 should both start now.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ 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, dummy.opacity());
- controller->removeAnimation(0);
+ // 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, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
- // Abort an animation from the main thread.
- controller->synchronizeAnimations(controllerImpl.get());
+// Tests scheduling an animation to start in the future.
+TEST(CCLayerAnimationControllerTest, ScheduleAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
}
-TEST(CCLayerAnimationControllerTest, syncCompletedAnimation)
+// Tests scheduling an animation to start in the future that's interrupting a running animation.
+TEST(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimation)
{
- FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
- addOpacityTransitionToController(*controller, 1, 0, 1);
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0.5, 0)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
- controller->synchronizeAnimations(controllerImpl.get());
+ // First 2s opacity transition should start immediately.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_EQ(0, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
- EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+// Tests scheduling an animation to start in the future that interrupts a running animation
+// and there is yet another animation queued to start later.
+TEST(CCLayerAnimationControllerTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared.
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0.5, 0)), 2, CCActiveAnimation::Opacity));
+ toAdd->setRunState(CCActiveAnimation::WaitingForStartTime, 0);
+ toAdd->setStartTime(1);
+ controller->add(toAdd.release());
+
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75)), 3, CCActiveAnimation::Opacity));
+
+ // First 2s opacity transition should start immediately.
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+ controller->animate(3, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(4, events.get());
+ EXPECT_EQ(0.75, dummy.opacity());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+}
+
+// Test that a looping animation loops and for the correct number of iterations.
+TEST(CCLayerAnimationControllerTest, TrivialLooping)
+{
OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
- controllerImpl->animate(0, *events);
- controllerImpl->animate(2, *events);
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
- EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ toAdd->setIterations(3);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(2.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(2.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(3, events.get());
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+
+ // Just be extra sure.
+ controller->animate(4, events.get());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+// Test that an infinitely looping animation does indeed go until aborted.
+TEST(CCLayerAnimationControllerTest, InfiniteLooping)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ toAdd->setIterations(-1);
+ controller->add(toAdd.release());
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1.25, events.get());
EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+
+ controller->animate(1073741824.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.25, dummy.opacity());
+ controller->animate(1073741824.75, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 0.75);
+ EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+}
+
+// Test that pausing and resuming work as expected.
+TEST(CCLayerAnimationControllerTest, PauseResume)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(0.5, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
- controller->synchronizeAnimations(controllerImpl.get());
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Paused, 0.5);
+ controller->animate(1024, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Running, 1024);
+
+ controller->animate(1024.25, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
+ controller->animate(1024.5, events.get());
EXPECT_FALSE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+}
+
+TEST(CCLayerAnimationControllerTest, AbortAGroupedAnimation)
+{
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create(&dummy));
+
+ const int id = 1;
+ controller->add(createActiveAnimation(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 1, 0.75)), 2, CCActiveAnimation::Opacity));
+
+ controller->animate(0, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0, dummy.opacity());
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(0.5, dummy.opacity());
+
+ EXPECT_TRUE(controller->getActiveAnimation(id, CCActiveAnimation::Opacity));
+ controller->getActiveAnimation(id, CCActiveAnimation::Opacity)->setRunState(CCActiveAnimation::Aborted, 1);
+ controller->animate(1, events.get());
+ EXPECT_TRUE(controller->hasActiveAnimation());
+ EXPECT_EQ(1, dummy.opacity());
+ controller->animate(2, events.get());
+ EXPECT_TRUE(!controller->hasActiveAnimation());
+ EXPECT_EQ(0.75, dummy.opacity());
}
} // namespace
// Implementation of CCLayerAnimationDelegate
virtual void notifyAnimationStarted(double time) { }
- virtual void notifyAnimationFinished(int animationId) { }
};
// Adapts CCLayerTreeHostImpl for test. Runs real code, then invokes test hooks.
CCLayerTreeHostTestAddAnimation()
: m_numAnimates(0)
, m_receivedAnimationStartedNotification(false)
- , m_receivedAnimationFinishedNotification(false)
, m_startTime(0)
, m_firstMonotonicTime(0)
{
EXPECT_LT(0, m_firstMonotonicTime);
EXPECT_NE(m_startTime, m_firstMonotonicTime);
EXPECT_TRUE(m_receivedAnimationStartedNotification);
- EXPECT_TRUE(m_receivedAnimationFinishedNotification);
endTest();
}
m_startTime = wallClockTime;
}
- virtual void notifyAnimationFinished(int)
- {
- m_receivedAnimationFinishedNotification = true;
- }
-
virtual void afterTest()
{
}
private:
int m_numAnimates;
bool m_receivedAnimationStartedNotification;
- bool m_receivedAnimationFinishedNotification;
double m_startTime;
double m_firstMonotonicTime;
};
class FakeLayerAnimationController : public CCLayerAnimationController {
public:
- static PassOwnPtr<FakeLayerAnimationController> create()
+ static PassOwnPtr<FakeLayerAnimationController> create(CCLayerAnimationControllerClient* client)
{
- return adoptPtr(new FakeLayerAnimationController);
+ return adoptPtr(new FakeLayerAnimationController(client));
}
bool synchronizedAnimations() const { return m_synchronizedAnimations; }
private:
- FakeLayerAnimationController()
- : m_synchronizedAnimations(false)
+ explicit FakeLayerAnimationController(CCLayerAnimationControllerClient* client)
+ : CCLayerAnimationController(client)
+ , m_synchronizedAnimations(false)
{
}
- virtual void synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+ virtual void pushAnimationUpdatesTo(CCLayerAnimationController* controllerImpl)
{
- CCLayerAnimationController::synchronizeAnimations(controllerImpl);
+ CCLayerAnimationController::pushAnimationUpdatesTo(controllerImpl);
m_synchronizedAnimations = true;
}
DebugScopedSetImplThread impl;
RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
- layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create());
+ FakeLayerAnimationControllerClient dummy;
+ layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create(&dummy));
EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());