+2012-02-22 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Plumb from GraphicsLayer to the cc thread animation code
+ https://bugs.webkit.org/show_bug.cgi?id=75874
+
+ Reviewed by James Robinson.
+
+ * WebCore.gypi:
+ * page/Settings.cpp:
+ (WebCore::Settings::Settings):
+ * page/Settings.h:
+ (WebCore::Settings::setThreadedAnimationEnabled):
+ (WebCore::Settings::threadedAnimationEnabled):
+ (Settings):
+ * platform/graphics/chromium/GraphicsLayerChromium.cpp:
+ (std):
+ (WebCore::GraphicsLayerChromium::addChild):
+ (WebCore::GraphicsLayerChromium::addAnimation):
+ (WebCore):
+ (WebCore::GraphicsLayerChromium::pauseAnimation):
+ (WebCore::GraphicsLayerChromium::removeAnimation):
+ (WebCore::GraphicsLayerChromium::suspendAnimations):
+ (WebCore::GraphicsLayerChromium::resumeAnimations):
+ (WebCore::GraphicsLayerChromium::setContentsToMedia):
+ (WebCore::GraphicsLayerChromium::updateLayerPreserves3D):
+ (WebCore::GraphicsLayerChromium::mapAnimationNameToId):
+ * platform/graphics/chromium/GraphicsLayerChromium.h:
+ (GraphicsLayerChromium):
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::LayerChromium):
+ (WebCore::LayerChromium::addAnimation):
+ (WebCore):
+ (WebCore::LayerChromium::pauseAnimation):
+ (WebCore::LayerChromium::removeAnimation):
+ (WebCore::LayerChromium::suspendAnimations):
+ (WebCore::LayerChromium::resumeAnimations):
+ (WebCore::LayerChromium::setLayerAnimationController):
+ (WebCore::LayerChromium::pushPropertiesTo):
+ * platform/graphics/chromium/LayerChromium.h:
+ (WebCore):
+ (LayerChromium):
+ (WebCore::LayerChromium::layerAnimationController):
+ (WebCore::LayerChromium::numChildren):
+ * platform/graphics/chromium/cc/CCActiveAnimation.cpp:
+ (WebCore::CCActiveAnimation::create):
+ (WebCore):
+ (WebCore::CCActiveAnimation::CCActiveAnimation):
+ (WebCore::CCActiveAnimation::~CCActiveAnimation):
+ (WebCore::CCActiveAnimation::isWaiting):
+ (WebCore::CCActiveAnimation::isRunningOrHasRun):
+ (WebCore::CCActiveAnimation::cloneForImplThread):
+ (WebCore::CCActiveAnimation::synchronizeProperties):
+ * platform/graphics/chromium/cc/CCActiveAnimation.h:
+ (CCActiveAnimation):
+ (WebCore::CCActiveAnimation::AnimationSignature::AnimationSignature):
+ (AnimationSignature):
+ (WebCore::CCActiveAnimation::id):
+ (WebCore::CCActiveAnimation::group):
+ (WebCore::CCActiveAnimation::signature):
+ * platform/graphics/chromium/cc/CCAnimationCurve.h:
+ (CCAnimationCurve):
+ (CCTransformAnimationCurve):
+ * platform/graphics/chromium/cc/CCAnimationEvents.h: Copied from Source/WebCore/platform/graphics/chromium/cc/CCAnimationCurve.h.
+ (WebCore):
+ (WebCore::CCAnimationStartedEvent::CCAnimationStartedEvent):
+ (CCAnimationStartedEvent):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.cpp: Added.
+ (WebCore):
+ (WebCore::CCLayerAnimationController::CCLayerAnimationController):
+ (WebCore::CCLayerAnimationController::~CCLayerAnimationController):
+ (WebCore::CCLayerAnimationController::create):
+ (WebCore::CCLayerAnimationController::addAnimation):
+ (WebCore::CCLayerAnimationController::pauseAnimation):
+ (WebCore::CCLayerAnimationController::removeAnimation):
+ (WebCore::CCLayerAnimationController::suspendAnimations):
+ (WebCore::CCLayerAnimationController::resumeAnimations):
+ (WebCore::CCLayerAnimationController::synchronizeAnimations):
+ (WebCore::CCLayerAnimationController::removeCompletedAnimations):
+ (WebCore::CCLayerAnimationController::pushNewAnimationsToImplThread):
+ (WebCore::CCLayerAnimationController::removeAnimationsCompletedOnMainThread):
+ (WebCore::CCLayerAnimationController::pushAnimationProperties):
+ (WebCore::CCLayerAnimationController::getActiveAnimation):
+ (WebCore::CCLayerAnimationController::remove):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.h: Added.
+ (WebCore):
+ (CCLayerAnimationController):
+ (WebCore::CCLayerAnimationController::activeAnimations):
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp:
+ (WebCore::CCLayerAnimationControllerImpl::~CCLayerAnimationControllerImpl):
+ (WebCore):
+ (WebCore::CCLayerAnimationControllerImpl::animate):
+ (WebCore::CCLayerAnimationControllerImpl::add):
+ (WebCore::CCLayerAnimationControllerImpl::getActiveAnimation):
+ (WebCore::CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick):
+ (WebCore::CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime):
+ (WebCore::CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability):
+ (WebCore::CCLayerAnimationControllerImpl::purgeFinishedAnimations):
+ (WebCore::CCLayerAnimationControllerImpl::tickAnimations):
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h:
+ (CCLayerAnimationControllerImplClient):
+ (CCLayerAnimationControllerImpl):
+ * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+ (WebCore::CCLayerImpl::CCLayerImpl):
+ * platform/graphics/chromium/cc/CCLayerImpl.h:
+ (CCLayerImpl):
+ (WebCore::CCLayerImpl::id):
+ (WebCore::CCLayerImpl::opacity):
+ (WebCore::CCLayerImpl::transform):
+ (WebCore::CCLayerImpl::bounds):
+ (WebCore::CCLayerImpl::layerAnimationController):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::CCLayerTreeHost::finishCommitOnImplThread):
+ (WebCore::CCLayerTreeHost::setAnimationEvents):
+ (WebCore):
+ (WebCore::CCLayerTreeHost::didBecomeInvisibleOnImplThread):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+ (WebCore::CCSettings::CCSettings):
+ (CCSettings):
+ (CCLayerTreeHost):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+ (WebCore::CCLayerTreeHostImpl::CCLayerTreeHostImpl):
+ (WebCore::CCLayerTreeHostImpl::animate):
+ (WebCore::CCLayerTreeHostImpl::animateLayersRecursive):
+ (WebCore):
+ (WebCore::CCLayerTreeHostImpl::animatePageScale):
+ (WebCore::CCLayerTreeHostImpl::animateLayers):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+ (CCLayerTreeHostImplClient):
+ (CCLayerTreeHostImpl):
+ (WebCore::CCLayerTreeHostImpl::needsAnimateLayers):
+ (WebCore::CCLayerTreeHostImpl::setNeedsAnimateLayers):
+ * platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
+ (WebCore::CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread):
+ (WebCore):
+ * platform/graphics/chromium/cc/CCSingleThreadProxy.h:
+ (CCSingleThreadProxy):
+ (WebCore):
+ (DebugScopedSetMainThread):
+ (WebCore::DebugScopedSetMainThread::DebugScopedSetMainThread):
+ (WebCore::DebugScopedSetMainThread::~DebugScopedSetMainThread):
+ * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+ (WebCore::CCThreadProxy::postAnimationEventsToMainThreadOnImplThread):
+ (WebCore):
+ (WebCore::CCThreadProxy::setAnimationEvents):
+ * platform/graphics/chromium/cc/CCThreadProxy.h:
+ (CCThreadProxy):
+
2012-02-22 Anders Carlsson <andersca@apple.com>
Subframes with scrollable areas must be added to the non-fast scrollable region
'platform/graphics/chromium/cc/CCActiveAnimation.h',
'platform/graphics/chromium/cc/CCAnimationCurve.cpp',
'platform/graphics/chromium/cc/CCAnimationCurve.h',
+ 'platform/graphics/chromium/cc/CCAnimationResults.h',
'platform/graphics/chromium/cc/CCCanvasDrawQuad.cpp',
'platform/graphics/chromium/cc/CCCanvasDrawQuad.h',
'platform/graphics/chromium/cc/CCCanvasLayerImpl.cpp',
'platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp',
'platform/graphics/chromium/cc/CCHeadsUpDisplay.h',
'platform/graphics/chromium/cc/CCInputHandler.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/CCLayerImpl.cpp',
#if ENABLE(TOUCH_EVENTS)
, m_touchEventEmulationEnabled(false)
#endif
+ , m_threadedAnimationEnabled(false)
, m_loadsImagesAutomaticallyTimer(this, &Settings::loadsImagesAutomaticallyTimerFired)
{
// A Frame may not have been created yet, so we initialize the AtomicString
bool isTouchEventEmulationEnabled() const { return m_touchEventEmulationEnabled; }
#endif
+ void setThreadedAnimationEnabled(bool enabled) { m_threadedAnimationEnabled = enabled; }
+ bool threadedAnimationEnabled() const { return m_threadedAnimationEnabled; }
+
private:
Settings(Page*);
#if ENABLE(TOUCH_EVENTS)
bool m_touchEventEmulationEnabled : 1;
#endif
+ bool m_threadedAnimationEnabled : 1;
Timer<Settings> m_loadsImagesAutomaticallyTimer;
void loadsImagesAutomaticallyTimerFired(Timer<Settings>*);
using namespace std;
+namespace {
+static int s_nextGroupId = 0;
+}
+
namespace WebCore {
PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
{
GraphicsLayer::addChild(childLayer);
- if (!m_inSetChildren)
+ if (!m_inSetChildren)
updateChildList();
}
updateChildList();
}
+bool GraphicsLayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
+{
+ return m_layer->addAnimation(values, boxSize, animation, mapAnimationNameToId(animationName), s_nextGroupId++, timeOffset);
+}
+
+void GraphicsLayerChromium::pauseAnimation(const String& animationName, double timeOffset)
+{
+ m_layer->pauseAnimation(mapAnimationNameToId(animationName), timeOffset);
+}
+
+void GraphicsLayerChromium::removeAnimation(const String& animationName)
+{
+ m_layer->removeAnimation(mapAnimationNameToId(animationName));
+}
+
+void GraphicsLayerChromium::suspendAnimations(double time)
+{
+ m_layer->suspendAnimations(time);
+}
+
+void GraphicsLayerChromium::resumeAnimations()
+{
+ m_layer->resumeAnimations();
+}
+
void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
{
bool childrenChanged = false;
} else {
if (m_contentsLayer) {
childrenChanged = true;
-
+
// The old contents layer will be removed via updateChildList.
m_contentsLayer = 0;
}
}
-
+
if (childrenChanged)
updateChildList();
}
m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
TransformationMatrix identity;
m_layer->setTransform(identity);
-
+
// Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
m_layer->setOpacity(1);
paintGraphicsLayerContents(context, clip);
}
+int GraphicsLayerChromium::mapAnimationNameToId(const String& animationName)
+{
+ // FIXME: need to maintain a name to id mapping in this class.
+ return 0;
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
virtual void setContentsToMedia(PlatformLayer*);
virtual void setContentsToCanvas(PlatformLayer*);
+ virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String&, double timeOffset);
+ virtual void pauseAnimation(const String& animationName, double timeOffset);
+ virtual void removeAnimation(const String& animationName);
+ virtual void suspendAnimations(double time);
+ virtual void resumeAnimations();
+
virtual PlatformLayer* platformLayer() const;
virtual void setDebugBackgroundColor(const Color&);
void setupContentsLayer(LayerChromium*);
float contentsScale() const;
+ int mapAnimationNameToId(const String& animationName);
+
String m_nameBase;
RefPtr<ContentLayerChromium> m_layer;
#if USE(ACCELERATED_COMPOSITING)
#include "LayerChromium.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHost.h"
#if USE(SKIA)
: m_needsDisplay(false)
, m_layerId(s_nextLayerId++)
, m_parent(0)
+ , m_layerAnimationController(CCLayerAnimationController::create())
, m_scrollable(false)
, m_anchorPoint(0.5, 0.5)
, m_backgroundColor(0, 0, 0, 0)
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();
+}
+
void LayerChromium::setIsNonCompositedContent(bool isNonCompositedContent)
{
m_isNonCompositedContent = isNonCompositedContent;
if (replicaLayer())
replicaLayer()->pushPropertiesTo(layer->replicaLayer());
+ m_layerAnimationController->synchronizeAnimations(layer->layerAnimationController());
+
// Reset any state that should be cleared for the next update.
m_updateRect = FloatRect();
}
namespace WebCore {
+class CCLayerAnimationController;
class CCLayerImpl;
class CCLayerTreeHost;
class CCTextureUpdater;
// Base class for composited layers. Special layer types are derived from
// this class.
class LayerChromium : public RefCounted<LayerChromium> {
- friend class LayerTilerChromium;
public:
static PassRefPtr<LayerChromium> create();
void setAlwaysReserveTextures(bool alwaysReserveTextures) { m_alwaysReserveTextures = alwaysReserveTextures; }
bool alwaysReserveTextures() const { return m_alwaysReserveTextures; }
+ bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, int animationId, int groupId, double timeOffset);
+ void pauseAnimation(int animationId, double timeOffset);
+ void removeAnimation(int animationId);
+
+ void suspendAnimations(double time);
+ void resumeAnimations();
+
+ CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); }
+ void setLayerAnimationController(PassOwnPtr<CCLayerAnimationController>);
+
protected:
+ friend class CCLayerImpl;
+ friend class LayerTilerChromium;
+ friend class TreeSynchronizer;
+
LayerChromium();
bool isPaintedAxisAlignedInScreen() const;
RefPtr<LayerChromium> m_maskLayer;
- friend class TreeSynchronizer;
- friend class CCLayerImpl;
// Constructs a CCLayerImpl of the correct runtime type for this LayerChromium type.
virtual PassRefPtr<CCLayerImpl> createCCLayerImpl();
int m_layerId;
void setParent(LayerChromium*);
bool hasAncestor(LayerChromium*) const;
- size_t numChildren() const
- {
- return m_children.size();
- }
+ size_t numChildren() const { return m_children.size(); }
// Returns the index of the child or -1 if not found.
int indexOfChild(const LayerChromium*);
RefPtr<CCLayerTreeHost> m_layerTreeHost;
+ OwnPtr<CCLayerAnimationController> m_layerAnimationController;
+
// Layer properties.
IntSize m_bounds;
IntRect m_visibleLayerRect;
namespace WebCore {
-CCActiveAnimation::CCActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, GroupID group, TargetProperty targetProperty)
+PassOwnPtr<CCActiveAnimation> CCActiveAnimation::create(PassOwnPtr<CCAnimationCurve> curve, int animationId, int groupId, TargetProperty targetProperty)
+{
+ return adoptPtr(new CCActiveAnimation(curve, animationId, groupId, targetProperty));
+}
+
+CCActiveAnimation::CCActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int animationId, int groupId, TargetProperty targetProperty)
: m_animationCurve(curve)
- , m_group(group)
+ , m_id(animationId)
+ , m_group(groupId)
, m_targetProperty(targetProperty)
, m_runState(WaitingForTargetAvailability)
, m_iterations(1)
{
}
+CCActiveAnimation::~CCActiveAnimation()
+{
+}
+
void CCActiveAnimation::setRunState(RunState runState, double now)
{
if (runState == Running && m_runState == Paused)
&& m_iterations * m_animationCurve->duration() <= time - startTime() - m_totalPausedTime;
}
+bool CCActiveAnimation::isWaiting() const
+{
+ return m_runState == WaitingForNextTick
+ || m_runState == WaitingForTargetAvailability
+ || m_runState == WaitingForStartTime;
+}
+
+bool CCActiveAnimation::isRunningOrHasRun() const
+{
+ return m_runState == Running
+ || m_runState == Finished
+ || m_runState == Aborted
+ || m_runState == Paused;
+}
+
double CCActiveAnimation::trimTimeToCurrentIteration(double now) const
{
double trimmed = now;
return fmod(trimmed, m_animationCurve->duration());
}
+PassOwnPtr<CCActiveAnimation> CCActiveAnimation::cloneForImplThread() const
+{
+ OwnPtr<CCActiveAnimation> toReturn(adoptPtr(new CCActiveAnimation(m_animationCurve->clone(), m_id, m_group, m_targetProperty)));
+ toReturn->m_runState = m_runState;
+ toReturn->m_iterations = m_iterations;
+ toReturn->m_startTime = m_startTime;
+ toReturn->m_pauseTime = m_pauseTime;
+ toReturn->m_totalPausedTime = m_totalPausedTime;
+ return toReturn.release();
+}
+
+void CCActiveAnimation::synchronizeProperties(CCActiveAnimation* other)
+{
+ // It is possible for the impl thread to initiate a run state change.
+ // This happens when the animation was waiting for a future event to take
+ // place, and the event has happened. In that case, we want 'this' to
+ // assume the impl thread's run state and start time.
+ if (isWaiting() && other->isRunningOrHasRun()) {
+ m_runState = other->m_runState;
+ m_startTime = other->m_startTime;
+ } else {
+ other->m_runState = m_runState;
+ other->m_startTime = m_startTime;
+ }
+
+ // Change in state related to iterations and pause is always initiated from
+ // the main thread, so it is safe to push properties in that direction.
+ other->m_iterations = m_iterations;
+ other->m_pauseTime = m_pauseTime;
+ other->m_totalPausedTime = m_totalPausedTime;
+}
+
} // namespace WebCore
#ifndef CCActiveAnimation_h
#define CCActiveAnimation_h
+#include "cc/CCAnimationCurve.h"
+
+#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
namespace WebCore {
-class CCAnimationCurve;
-
// A CCActiveAnimation, contains all the state required to play a CCAnimationCurve.
// Specifically, the affected property, the run state (paused, finished, etc.),
// loop count, last pause time, and the total time spent paused.
class CCActiveAnimation {
+ WTF_MAKE_NONCOPYABLE(CCActiveAnimation);
public:
- // Animations that must be run together are called 'grouped' and have the same GroupID
- // Grouped animations are guaranteed to start at the same time and no other animations
- // may animate any of the group's target properties until all animations in the
- // group have finished animating. Note: an active animation's group id and target
- // property uniquely identify that animation.
- typedef int GroupID;
-
// Animations begin in one of the 'waiting' states. Animations waiting for the next tick
// will start the next time the controller animates. Animations waiting for target
// availibility will run as soon as their target property is free (and all the animations
Opacity
};
- static PassOwnPtr<CCActiveAnimation> create(PassOwnPtr<CCAnimationCurve> curve, GroupID group, TargetProperty targetProperty)
- {
- return adoptPtr(new CCActiveAnimation(curve, group, targetProperty));
- }
+ struct AnimationSignature {
+ AnimationSignature(int groupId, TargetProperty targetProperty)
+ : groupId(groupId)
+ , targetProperty(targetProperty) { }
+ int groupId;
+ TargetProperty targetProperty;
+ };
- virtual ~CCActiveAnimation() { }
+ static PassOwnPtr<CCActiveAnimation> create(PassOwnPtr<CCAnimationCurve>, int animationId, int groupId, TargetProperty);
- GroupID group() const { return m_group; }
+ virtual ~CCActiveAnimation();
+
+ int id() const { return m_id; }
+ int group() const { return m_group; }
TargetProperty targetProperty() const { return m_targetProperty; }
RunState runState() const { return m_runState; }
bool isFinishedAt(double time) const;
bool isFinished() const { return m_runState == Finished || m_runState == Aborted; }
+ bool isWaiting() const;
+ bool isRunningOrHasRun() const;
+
CCAnimationCurve* animationCurve() { return m_animationCurve.get(); }
const CCAnimationCurve* animationCurve() const { return m_animationCurve.get(); }
// 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*);
+
private:
- CCActiveAnimation(PassOwnPtr<CCAnimationCurve>, GroupID, TargetProperty);
+ CCActiveAnimation(PassOwnPtr<CCAnimationCurve>, int animationId, int groupId, TargetProperty);
OwnPtr<CCAnimationCurve> m_animationCurve;
- GroupID m_group;
+
+ // IDs are not necessarily unique.
+ int m_id;
+
+ // Animations that must be run together are called 'grouped' and have the same group id
+ // Grouped animations are guaranteed to start at the same time and no other animations
+ // may animate any of the group's target properties until all animations in the
+ // group have finished animating. Note: an active animation's group id and target
+ // property uniquely identify that animation.
+ int m_group;
+
TargetProperty m_targetProperty;
RunState m_runState;
int m_iterations;
#ifndef CCAnimationCurve_h
#define CCAnimationCurve_h
+#include "TransformationMatrix.h"
+
+#include <wtf/PassOwnPtr.h>
+
namespace WebCore {
class CCFloatAnimationCurve;
virtual double duration() const = 0;
virtual Type type() const = 0;
+ virtual PassOwnPtr<CCAnimationCurve> clone() const = 0;
const CCFloatAnimationCurve* toFloatAnimationCurve() const;
const CCTransformAnimationCurve* toTransformAnimationCurve() const;
public:
virtual ~CCTransformAnimationCurve() { }
- virtual TransformOperations getValue(double t) const = 0;
+ virtual TransformationMatrix getValue(double t, const IntSize& layerSize) const = 0;
// Partial CCAnimation implementation.
virtual Type type() const { return Transform; }
--- /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 CCAnimationEvents_h
+#define CCAnimationEvents_h
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+// Indicates that an animation has started on a particular layer.
+struct CCAnimationStartedEvent {
+ CCAnimationStartedEvent(int layerID, double time)
+ : layerID(layerID)
+ , time(time) { }
+ int layerID;
+ double time;
+};
+
+typedef Vector<CCAnimationStartedEvent> CCAnimationEventsVector;
+
+} // namespace WebCore
+
+#endif // CCAnimationEvents_h
--- /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/CCLayerAnimationController.h"
+
+#include "GraphicsLayer.h" // for KeyframeValueList
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCLayerAnimationControllerImpl.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+CCLayerAnimationController::CCLayerAnimationController()
+{
+}
+
+CCLayerAnimationController::~CCLayerAnimationController()
+{
+}
+
+PassOwnPtr<CCLayerAnimationController> CCLayerAnimationController::create()
+{
+ return adoptPtr(new CCLayerAnimationController);
+}
+
+bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList,
+ const IntSize&,
+ const Animation* animation,
+ int animationId,
+ int groupId,
+ double timeOffset)
+{
+ return false;
+}
+
+void CCLayerAnimationController::pauseAnimation(int animationId, double timeOffset)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->id() == animationId)
+ m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, timeOffset);
+ }
+}
+
+void CCLayerAnimationController::removeAnimation(int animationId)
+{
+ for (size_t i = 0; i < m_activeAnimations.size();) {
+ if (m_activeAnimations[i]->id() == animationId)
+ m_activeAnimations.remove(i);
+ else
+ i++;
+ }
+}
+
+// According to render layer backing, these are for testing only.
+void CCLayerAnimationController::suspendAnimations(double time)
+{
+}
+
+// Looking at GraphicsLayerCA, this appears to be the analog to suspendAnimations, which is for testing.
+void CCLayerAnimationController::resumeAnimations()
+{
+}
+
+// Ensures that the list of active animations on the main thread and the impl thread
+// are kept in sync.
+void CCLayerAnimationController::synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+{
+ removeCompletedAnimations(controllerImpl);
+ pushNewAnimationsToImplThread(controllerImpl);
+ removeAnimationsCompletedOnMainThread(controllerImpl);
+ pushAnimationProperties(controllerImpl);
+}
+
+void CCLayerAnimationController::removeCompletedAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+{
+ // 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();
+}
+
+void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationControllerImpl* 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());
+ }
+}
+
+void CCLayerAnimationController::removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl* 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
+ // guaranteeing progress towards loop termination.
+ for (size_t i = 0; i < controllerImpl->m_activeAnimations.size();) {
+ CCActiveAnimation* current = getActiveAnimation(controllerImpl->m_activeAnimations[i]->group(), controllerImpl->m_activeAnimations[i]->targetProperty());
+ if (!current)
+ controllerImpl->m_activeAnimations.remove(i);
+ else
+ i++;
+ }
+}
+
+void CCLayerAnimationController::pushAnimationProperties(CCLayerAnimationControllerImpl* 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
+ // 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);
+ }
+}
+
+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;
+}
+
+void CCLayerAnimationController::remove(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) {
+ m_activeAnimations.remove(i);
+ return;
+ }
+ }
+}
+
+} // 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 CCLayerAnimationController_h
+#define CCLayerAnimationController_h
+
+#include "cc/CCActiveAnimation.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Animation;
+class CCLayerAnimationControllerImpl;
+struct IntSize;
+class KeyframeValueList;
+
+class CCLayerAnimationController {
+ WTF_MAKE_NONCOPYABLE(CCLayerAnimationController);
+public:
+ static PassOwnPtr<CCLayerAnimationController> create();
+
+ virtual ~CCLayerAnimationController();
+
+ // These 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);
+ virtual void suspendAnimations(double time);
+ virtual void resumeAnimations();
+
+ // 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*);
+
+ // This is for testing purposes only.
+ Vector<OwnPtr<CCActiveAnimation> >& activeAnimations() { return m_activeAnimations; }
+
+protected:
+ CCLayerAnimationController();
+
+private:
+ void removeCompletedAnimations(CCLayerAnimationControllerImpl*);
+ void pushNewAnimationsToImplThread(CCLayerAnimationControllerImpl*);
+ void removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl*);
+ void pushAnimationProperties(CCLayerAnimationControllerImpl*);
+
+ CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
+ void remove(int groupId, CCActiveAnimation::TargetProperty);
+
+ Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
+};
+
+} // namespace WebCore
+
+#endif // CCLayerAnimationController_h
#include "cc/CCLayerAnimationControllerImpl.h"
+#include "TransformationMatrix.h"
#include "TransformOperations.h"
namespace WebCore {
{
}
-void CCLayerAnimationControllerImpl::animate(double frameBeginTimeSecs)
+CCLayerAnimationControllerImpl::~CCLayerAnimationControllerImpl()
{
- startAnimationsWaitingForNextTick(frameBeginTimeSecs);
- startAnimationsWaitingForStartTime(frameBeginTimeSecs);
- startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs);
+}
+
+void CCLayerAnimationControllerImpl::animate(double frameBeginTimeSecs, CCAnimationEventsVector& events)
+{
+ startAnimationsWaitingForNextTick(frameBeginTimeSecs, events);
+ startAnimationsWaitingForStartTime(frameBeginTimeSecs, events);
+ startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs, events);
resolveConflicts(frameBeginTimeSecs);
tickAnimations(frameBeginTimeSecs);
purgeFinishedAnimations();
- startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs);
+ startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs, events);
}
void CCLayerAnimationControllerImpl::add(PassOwnPtr<CCActiveAnimation> anim)
{
m_activeAnimations.append(anim);
- if (m_client)
- m_client->animationControllerImplDidActivate(this);
}
-CCActiveAnimation* CCLayerAnimationControllerImpl::getActiveAnimation(CCActiveAnimation::GroupID group, CCActiveAnimation::TargetProperty property)
+CCActiveAnimation* CCLayerAnimationControllerImpl::getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty property)
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->group() == group && m_activeAnimations[i]->targetProperty() == property)
+ if (m_activeAnimations[i]->group() == groupId && m_activeAnimations[i]->targetProperty() == property)
return m_activeAnimations[i].get();
}
return 0;
return false;
}
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double now)
+void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double now, 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, now);
m_activeAnimations[i]->setStartTime(now);
+ events.append(CCAnimationStartedEvent(m_client->id(), now));
}
}
}
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double now)
+void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double now, CCAnimationEventsVector& events)
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
- if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= now)
+ if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= now) {
m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now);
+ events.append(CCAnimationStartedEvent(m_client->id(), now));
+ }
}
}
-void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double now)
+void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double now, CCAnimationEventsVector& events)
{
// First collect running properties.
TargetProperties blockedProperties;
if (nullIntersection) {
m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now);
m_activeAnimations[i]->setStartTime(now);
+ events.append(CCAnimationStartedEvent(m_client->id(), now));
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, now);
}
}
}
- if (allAnimsWithSameIdAreFinished)
+ if (allAnimsWithSameIdAreFinished) {
+ m_finishedAnimations.append(m_activeAnimations[i]->signature());
m_activeAnimations.remove(i);
- else
+ } else
i++;
}
}
case CCActiveAnimation::Transform: {
const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->animationCurve()->toTransformAnimationCurve();
- const TransformOperations operations = transformAnimationCurve->getValue(trimmed);
+ const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds());
if (m_activeAnimations[i]->isFinishedAt(now))
m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now);
- // Decide here if absolute or relative. Absolute for now.
- TransformationMatrix toApply;
- operations.apply(FloatSize(), toApply);
- m_client->setTransform(toApply);
+ m_client->setTransform(matrix);
break;
}
#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>
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 void animationControllerImplDidActivate(CCLayerAnimationControllerImpl*) = 0;
+ virtual const IntSize& bounds() const = 0;
};
class CCLayerAnimationControllerImpl {
+ WTF_MAKE_NONCOPYABLE(CCLayerAnimationControllerImpl);
public:
static PassOwnPtr<CCLayerAnimationControllerImpl> create(CCLayerAnimationControllerImplClient*);
- void animate(double frameBeginTimeSecs);
+ virtual ~CCLayerAnimationControllerImpl();
+
+ void animate(double frameBeginTimeSecs, CCAnimationEventsVector&);
void add(PassOwnPtr<CCActiveAnimation>);
// Returns the active animation in the given group, animating the given property if such an
// animation exists.
- CCActiveAnimation* getActiveAnimation(CCActiveAnimation::GroupID, CCActiveAnimation::TargetProperty);
+ CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
// Returns true if there are any animations that are neither finished nor aborted.
bool hasActiveAnimation() const;
private:
+ friend class CCLayerAnimationController;
+
// The animator is owned by the layer.
explicit CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient*);
- void startAnimationsWaitingForNextTick(double now);
- void startAnimationsWaitingForStartTime(double now);
- void startAnimationsWaitingForTargetAvailability(double now);
+ void startAnimationsWaitingForNextTick(double now, CCAnimationEventsVector&);
+ void startAnimationsWaitingForStartTime(double now, CCAnimationEventsVector&);
+ void startAnimationsWaitingForTargetAvailability(double now, CCAnimationEventsVector&);
void resolveConflicts(double now);
void purgeFinishedAnimations();
CCLayerAnimationControllerImplClient* m_client;
Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
+ Vector<CCActiveAnimation::AnimationSignature> m_finishedAnimations;
};
} // namespace WebCore
#include "LayerChromium.h"
#include "LayerRendererChromium.h"
#include "cc/CCDebugBorderDrawQuad.h"
+#include "cc/CCLayerAnimationControllerImpl.h"
#include "cc/CCLayerSorter.h"
#include "cc/CCSolidColorDrawQuad.h"
#include <wtf/text/WTFString.h>
, m_drawOpacity(0)
, m_debugBorderColor(0, 0, 0, 0)
, m_debugBorderWidth(0)
+ , m_layerAnimationController(CCLayerAnimationControllerImpl::create(this))
{
ASSERT(CCProxy::isImplThread());
}
#include "IntRect.h"
#include "TextStream.h"
#include "TransformationMatrix.h"
+#include "cc/CCLayerAnimationControllerImpl.h"
#include "cc/CCRenderPass.h"
#include "cc/CCRenderSurface.h"
#include <wtf/OwnPtr.h>
class LayerChromium;
class LayerRendererChromium;
-class CCLayerImpl : public RefCounted<CCLayerImpl> {
+class CCLayerImpl : public RefCounted<CCLayerImpl>, public CCLayerAnimationControllerImplClient {
public:
static PassRefPtr<CCLayerImpl> create(int id)
{
return adoptRef(new CCLayerImpl(id));
}
+
+ // CCLayerAnimationControllerImplClient implementation.
+ virtual int id() const { return m_layerId; }
+ virtual void setOpacity(float);
+ virtual float opacity() const { return m_opacity; }
+ virtual void setTransform(const TransformationMatrix&);
+ virtual const TransformationMatrix& transform() const { return m_transform; }
+ virtual const IntSize& bounds() const { return m_bounds; }
+
virtual ~CCLayerImpl();
// Tree structure.
void setReplicaLayer(PassRefPtr<CCLayerImpl>);
CCLayerImpl* replicaLayer() const { return m_replicaLayer.get(); }
- int id() const { return m_layerId; }
-
#ifndef NDEBUG
int debugID() const { return m_debugID; }
#endif
void setOpaque(bool);
bool opaque() const { return m_opaque; }
- void setOpacity(float);
- float opacity() const { return m_opacity; }
-
void setPosition(const FloatPoint&);
const FloatPoint& position() const { return m_position; }
void setSublayerTransform(const TransformationMatrix&);
const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
- void setTransform(const TransformationMatrix&);
- const TransformationMatrix& transform() const { return m_transform; }
-
void setName(const String& name) { m_name = name; }
const String& name() const { return m_name; }
CCRenderSurface* targetRenderSurface() const { return m_targetRenderSurface; }
void setTargetRenderSurface(CCRenderSurface* surface) { m_targetRenderSurface = surface; }
- const IntSize& bounds() const { return m_bounds; }
void setBounds(const IntSize&);
const IntSize& contentBounds() const { return m_contentBounds; }
bool layerPropertyChanged() const { return m_layerPropertyChanged; }
void resetAllChangeTrackingForSubtree();
+ CCLayerAnimationControllerImpl* layerAnimationController() { return m_layerAnimationController.get(); }
+
protected:
explicit CCLayerImpl(int);
// Rect indicating what was repainted/updated during update.
// Note that plugin layers bypass this and leave it empty.
FloatRect m_updateRect;
+
+ // Manages animations for this layer.
+ OwnPtr<CCLayerAnimationControllerImpl> m_layerAnimationController;
};
void sortLayers(Vector<RefPtr<CCLayerImpl> >::iterator first, Vector<RefPtr<CCLayerImpl> >::iterator end, CCLayerSorter*);
ASSERT(CCProxy::isImplThread());
// Synchronize trees, if one exists at all...
- if (rootLayer())
+ if (rootLayer()) {
hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer()));
- else
+ // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers.
+ hostImpl->setNeedsAnimateLayers();
+ } else
hostImpl->setRootLayer(0);
hostImpl->setSourceFrameNumber(frameNumber());
m_client->scheduleComposite();
}
+void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events)
+{
+ ASSERT(CCThreadProxy::isMainThread());
+ // FIXME: need to walk the tree.
+}
+
void CCLayerTreeHost::setRootLayer(PassRefPtr<LayerChromium> rootLayer)
{
if (m_rootLayer == rootLayer)
hostImpl->setRootLayer(0);
return;
}
- if (rootLayer())
+
+ if (rootLayer()) {
hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer()));
- else
+ // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers.
+ hostImpl->setNeedsAnimateLayers();
+ } else
hostImpl->setRootLayer(0);
}
#include "LayerChromium.h"
#include "RateLimiter.h"
#include "TransformationMatrix.h"
+#include "cc/CCAnimationEvents.h"
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCProxy.h"
, refreshRate(0)
, perTilePainting(false)
, partialSwapEnabled(false)
+ , threadedAnimationEnabled(false)
, maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) { }
bool acceleratePainting;
double refreshRate;
bool perTilePainting;
bool partialSwapEnabled;
+ bool threadedAnimationEnabled;
size_t maxPartialTextureUpdates;
};
virtual void setNeedsCommit();
void setNeedsRedraw();
+ void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>);
+
LayerChromium* rootLayer() { return m_rootLayer.get(); }
const LayerChromium* rootLayer() const { return m_rootLayer.get(); }
void setRootLayer(PassRefPtr<LayerChromium>);
, m_sentPageScaleDelta(1)
, m_minPageScale(0)
, m_maxPageScale(0)
+ , m_needsAnimateLayers(false)
, m_pinchGestureActive(false)
{
ASSERT(CCProxy::isImplThread());
void CCLayerTreeHostImpl::animate(double frameBeginTimeMs)
{
- if (!m_pageScaleAnimation)
- return;
-
- IntSize scrollTotal = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
-
- setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(frameBeginTimeMs) / m_pageScale);
- IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(frameBeginTimeMs);
- nextScroll.scale(1 / m_pageScaleDelta);
- m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal);
- m_client->setNeedsRedrawOnImplThread();
-
- if (m_pageScaleAnimation->isAnimationCompleteAtTime(frameBeginTimeMs)) {
- m_pageScaleAnimation.clear();
- m_client->setNeedsCommitOnImplThread();
- }
+ animatePageScale(frameBeginTimeMs);
+ animateLayers(frameBeginTimeMs);
}
void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTimeMs, double durationMs)
}
}
+void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double frameBeginTimeSecs, CCAnimationEventsVector& events, bool& didAnimate, bool& needsAnimateLayers)
+{
+ bool subtreeNeedsAnimateLayers = false;
+
+ CCLayerAnimationControllerImpl* currentController = current->layerAnimationController();
+
+ bool hadActiveAnimation = currentController->hasActiveAnimation();
+ currentController->animate(frameBeginTimeSecs, events);
+ bool startedAnimation = events.size() > 0;
+
+ // We animated if we either ticked a running animation, or started a new animation.
+ if (hadActiveAnimation || startedAnimation)
+ didAnimate = true;
+
+ // If the current controller still has an active animation, we must continue animating layers.
+ if (currentController->hasActiveAnimation())
+ subtreeNeedsAnimateLayers = true;
+
+ for (size_t i = 0; i < current->children().size(); ++i) {
+ bool childNeedsAnimateLayers = false;
+ animateLayersRecursive(current->children()[i].get(), frameBeginTimeSecs, events, didAnimate, childNeedsAnimateLayers);
+ if (childNeedsAnimateLayers)
+ subtreeNeedsAnimateLayers = true;
+ }
+
+ needsAnimateLayers = subtreeNeedsAnimateLayers;
+}
+
IntSize CCLayerTreeHostImpl::contentSize() const
{
// TODO(aelias): Hardcoding the first child here is weird. Think of
}
}
+void CCLayerTreeHostImpl::animatePageScale(double frameBeginTimeMs)
+{
+ if (!m_pageScaleAnimation)
+ return;
+
+ IntSize scrollTotal = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
+
+ setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(frameBeginTimeMs) / m_pageScale);
+ IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(frameBeginTimeMs);
+ nextScroll.scale(1 / m_pageScaleDelta);
+ m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal);
+ m_client->setNeedsRedrawOnImplThread();
+
+ if (m_pageScaleAnimation->isAnimationCompleteAtTime(frameBeginTimeMs)) {
+ m_pageScaleAnimation.clear();
+ m_client->setNeedsCommitOnImplThread();
+ }
+}
+
+void CCLayerTreeHostImpl::animateLayers(double frameBeginTimeMs)
+{
+ if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayerImpl)
+ return;
+
+ TRACE_EVENT("CCLayerTreeHostImpl::animateLayers", this, 0);
+
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+
+ bool didAnimate = false;
+ animateLayersRecursive(m_rootLayerImpl.get(), frameBeginTimeMs / 1000, *events, didAnimate, m_needsAnimateLayers);
+
+ if (!events->isEmpty())
+ m_client->postAnimationEventsToMainThreadOnImplThread(events.release());
+
+ if (didAnimate)
+ m_client->setNeedsRedrawOnImplThread();
}
+
+} // namespace WebCore
#ifndef CCLayerTreeHostImpl_h
#define CCLayerTreeHostImpl_h
+#include "cc/CCAnimationEvents.h"
#include "cc/CCInputHandler.h"
#include "cc/CCLayerSorter.h"
#include "cc/CCLayerTreeHost.h"
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCRenderPass.h"
+#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
namespace WebCore {
virtual void onSwapBuffersCompleteOnImplThread() = 0;
virtual void setNeedsRedrawOnImplThread() = 0;
virtual void setNeedsCommitOnImplThread() = 0;
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>) = 0;
};
// CCLayerTreeHostImpl owns the CCLayerImpl tree as well as associated rendering state
virtual void pinchGestureEnd();
virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTimeMs, double durationMs);
- // Virtual for testing
+ // Virtual for testing.
virtual void beginCommit();
virtual void commitComplete();
virtual void animate(double frameDisplayTimeMs);
void startPageScaleAnimation(const IntSize& tragetPosition, bool useAnchor, float scale, double durationSec);
+ bool needsAnimateLayers() const { return m_needsAnimateLayers; }
+ void setNeedsAnimateLayers() { m_needsAnimateLayers = true; }
+
protected:
CCLayerTreeHostImpl(const CCSettings&, CCLayerTreeHostImplClient*);
+
+ void animatePageScale(double frameBeginTimeMs);
+
+ // Virtual for testing.
+ virtual void animateLayers(double frameBeginTimeMs);
+
CCLayerTreeHostImplClient* m_client;
int m_sourceFrameNumber;
int m_frameNumber;
void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList);
void calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
void optimizeRenderPasses(CCRenderPassList&);
+ void animateLayersRecursive(CCLayerImpl*, double frameBeginTimeSecs, CCAnimationEventsVector&, bool& didAnimate, bool& needsAnimateLayers);
IntSize contentSize() const;
OwnPtr<LayerRendererChromium> m_layerRenderer;
float m_sentPageScaleDelta;
float m_minPageScale, m_maxPageScale;
+ // If this is true, it is necessary to traverse the layer tree ticking the animators.
+ bool m_needsAnimateLayers;
bool m_pinchGestureActive;
IntPoint m_previousPinchAnchor;
m_layerTreeHost = 0;
}
+void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events)
+{
+ ASSERT(CCProxy::isImplThread());
+ DebugScopedSetMainThread main;
+ m_layerTreeHost->setAnimationEvents(events);
+}
+
// Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
void CCSingleThreadProxy::compositeImmediately()
{
#ifndef CCSingleThreadProxy_h
#define CCSingleThreadProxy_h
+#include "cc/CCAnimationEvents.h"
#include "cc/CCCompletionEvent.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCProxy.h"
virtual void onSwapBuffersCompleteOnImplThread() { ASSERT_NOT_REACHED(); }
virtual void setNeedsRedrawOnImplThread() { m_layerTreeHost->setNeedsCommit(); }
virtual void setNeedsCommitOnImplThread() { m_layerTreeHost->setNeedsCommit(); }
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>);
// Called by the legacy path where RenderWidget does the scheduling.
void compositeImmediately();
}
};
+// For use in the single-threaded case. In debug builds, it pretends that the
+// code is running on the main thread to satisfy assertion checks.
+class DebugScopedSetMainThread {
+public:
+ DebugScopedSetMainThread()
+ {
+#if !ASSERT_DISABLED
+ CCProxy::setCurrentThreadIsImplThread(false);
+#endif
+ }
+ ~DebugScopedSetMainThread()
+ {
+#if !ASSERT_DISABLED
+ CCProxy::setCurrentThreadIsImplThread(true);
+#endif
+ }
+};
+
} // namespace WebCore
#endif
m_schedulerOnImplThread->setNeedsCommit();
}
+void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events)
+{
+ ASSERT(isImplThread());
+ TRACE_EVENT("CCThreadProxy::postAnimationEventsToMainThreadOnImplThread", this, 0);
+ m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events));
+}
+
void CCThreadProxy::setNeedsRedraw()
{
ASSERT(isMainThread());
m_layerTreeHost->didCompleteSwapBuffers();
}
+void CCThreadProxy::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events)
+{
+ ASSERT(isMainThread());
+ if (!m_layerTreeHost)
+ return;
+ m_layerTreeHost->setAnimationEvents(events);
+}
+
void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion)
{
TRACE_EVENT("CCThreadProxy::initializeImplOnImplThread", this, 0);
#ifndef CCThreadProxy_h
#define CCThreadProxy_h
+#include "cc/CCAnimationEvents.h"
#include "cc/CCCompletionEvent.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCProxy.h"
virtual void onSwapBuffersCompleteOnImplThread();
virtual void setNeedsRedrawOnImplThread();
virtual void setNeedsCommitOnImplThread();
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>);
// CCSchedulerClient implementation
virtual bool canDraw();
void beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollAndScaleSet>);
void didCommitAndDrawFrame();
void didCompleteSwapBuffers();
+ void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>);
// Called on impl thread
struct ReadbackRequest {
+2012-02-22 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Plumb from GraphicsLayer to the cc thread animation code
+ https://bugs.webkit.org/show_bug.cgi?id=75874
+
+ Reviewed by James Robinson.
+
+ * WebKit.gypi:
+ * public/WebSettings.h:
+ * public/platform/WebLayerTreeView.h:
+ (WebKit::WebLayerTreeView::Settings::Settings):
+ (Settings):
+ * src/WebLayerTreeView.cpp:
+ (WebKit::WebLayerTreeView::Settings::operator CCSettings):
+ * src/WebSettingsImpl.cpp:
+ (WebKit::WebSettingsImpl::setThreadedAnimationEnabled):
+ (WebKit):
+ * src/WebSettingsImpl.h:
+ (WebSettingsImpl):
+ * src/WebViewImpl.cpp:
+ (WebKit::WebViewImpl::setIsAcceleratedCompositingActive):
+ * tests/CCActiveAnimationTest.cpp:
+ (WebCore::createActiveAnimation):
+ * tests/CCAnimationTestCommon.cpp: Added.
+ (WebKitTests):
+ (WebKitTests::FakeFloatAnimationCurve::FakeFloatAnimationCurve):
+ (WebKitTests::FakeFloatAnimationCurve::~FakeFloatAnimationCurve):
+ (WebKitTests::FakeFloatAnimationCurve::clone):
+ (WebKitTests::FakeTransformTransition::FakeTransformTransition):
+ (WebKitTests::FakeTransformTransition::~FakeTransformTransition):
+ (WebKitTests::FakeTransformTransition::getValue):
+ (WebKitTests::FakeTransformTransition::clone):
+ (WebKitTests::FakeFloatTransition::FakeFloatTransition):
+ (WebKitTests::FakeFloatTransition::~FakeFloatTransition):
+ (WebKitTests::FakeFloatTransition::getValue):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient):
+ (WebKitTests::FakeFloatTransition::clone):
+ (WebKitTests::addOpacityTransition):
+ * tests/CCAnimationTestCommon.h: Added.
+ (WebCore):
+ (WebKitTests):
+ (FakeFloatAnimationCurve):
+ (WebKitTests::FakeFloatAnimationCurve::duration):
+ (WebKitTests::FakeFloatAnimationCurve::getValue):
+ (FakeTransformTransition):
+ (WebKitTests::FakeTransformTransition::duration):
+ (FakeFloatTransition):
+ (WebKitTests::FakeFloatTransition::duration):
+ (FakeLayerAnimationControllerImplClient):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::id):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::opacity):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::setOpacity):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::transform):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::setTransform):
+ (WebKitTests::FakeLayerAnimationControllerImplClient::bounds):
+ * tests/CCLayerAnimationControllerImplTest.cpp:
+ (WebKitTests::createActiveAnimation):
+ (WebKitTests::TEST):
+ * tests/CCLayerAnimationControllerTest.cpp: Added.
+ (WebKitTests):
+ (WebKitTests::createActiveAnimation):
+ (WebKitTests::TEST):
+ * tests/CCLayerTreeHostImplTest.cpp:
+ (WebKit::CCLayerTreeHostImplTest::postAnimationEventsToMainThreadOnImplThread):
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF::TestHooks::animateLayers):
+ (MockLayerTreeHostImpl):
+ (WTF::MockLayerTreeHostImpl::animateLayers):
+ (WTF::MockLayerTreeHost::create):
+ (WTF::MockLayerTreeHost::createLayerTreeHostImpl):
+ (WTF):
+ (MockLayerAnimationController):
+ (WTF::MockLayerAnimationController::create):
+ (WTF::MockLayerAnimationController::addAnimation):
+ (WTF::MockLayerTreeHostClient::scheduleComposite):
+ (WTF::CCLayerTreeHostTest::postAddAnimationToMainThread):
+ (CCLayerTreeHostTest):
+ (WTF::CCLayerTreeHostTest::dispatchAddAnimation):
+ (WTF::CCLayerTreeHostTest::doBeginTest):
+ (CCLayerTreeHostTestAddAnimation):
+ (WTF::CCLayerTreeHostTestAddAnimation::CCLayerTreeHostTestAddAnimation):
+ (WTF::CCLayerTreeHostTestAddAnimation::beginTest):
+ (WTF::CCLayerTreeHostTestAddAnimation::animateLayers):
+ (WTF::CCLayerTreeHostTestAddAnimation::afterTest):
+ (WTF::TEST_F):
+ * tests/TreeSynchronizerTest.cpp:
+ (FakeLayerAnimationController):
+ (WebKitTests::FakeLayerAnimationController::create):
+ (WebKitTests::FakeLayerAnimationController::synchronizedAnimations):
+ (WebKitTests::FakeLayerAnimationController::FakeLayerAnimationController):
+ (WebKitTests::FakeLayerAnimationController::synchronizeAnimations):
+ (WebKitTests):
+ (WebKitTests::TEST):
+
2012-02-21 Ryosuke Niwa <rniwa@webkit.org>
Remove the remaining uses of CSSStyleDeclaration in Editor
'tests/AssociatedURLLoaderTest.cpp',
'tests/Canvas2DLayerChromiumTest.cpp',
'tests/CCActiveAnimationTest.cpp',
+ 'tests/CCAnimationTestCommon.cpp',
+ 'tests/CCAnimationTestCommon.h',
'tests/CCDamageTrackerTest.cpp',
'tests/CCDelayBasedTimeSourceTest.cpp',
'tests/CCFrameRateControllerTest.cpp',
'tests/CCLayerAnimationControllerImplTest.cpp',
+ 'tests/CCLayerAnimationControllerTest.cpp',
'tests/CCLayerImplTest.cpp',
'tests/CCLayerIteratorTest.cpp',
'tests/CCLayerQuadTest.cpp',
virtual void setAcceleratedPaintingEnabled(bool) = 0;
virtual void setPerTilePaintingEnabled(bool) = 0;
virtual void setPartialSwapEnabled(bool) = 0;
+ virtual void setThreadedAnimationEnabled(bool) = 0;
protected:
~WebSettings() { }
, showPlatformLayerTree(false)
, refreshRate(0)
, perTilePainting(false)
- , partialSwapEnabled(false) { }
+ , partialSwapEnabled(false)
+ , threadedAnimationEnabled(false) { }
bool acceleratePainting;
bool compositeOffscreen;
double refreshRate;
bool perTilePainting;
bool partialSwapEnabled;
+ bool threadedAnimationEnabled;
#if WEBKIT_IMPLEMENTATION
operator WebCore::CCSettings() const;
#endif
settings.refreshRate = refreshRate;
settings.perTilePainting = perTilePainting;
settings.partialSwapEnabled = partialSwapEnabled;
+ settings.threadedAnimationEnabled = threadedAnimationEnabled;
// FIXME: showFPSCounter / showPlatformLayerTree / maxPartialTextureUpdates aren't supported currently.
return settings;
m_settings->setPartialSwapEnabled(enabled);
}
+void WebSettingsImpl::setThreadedAnimationEnabled(bool enabled)
+{
+ m_settings->setThreadedAnimationEnabled(enabled);
+}
+
} // namespace WebKit
virtual void setAcceleratedPaintingEnabled(bool);
virtual void setPerTilePaintingEnabled(bool);
virtual void setPartialSwapEnabled(bool);
+ virtual void setThreadedAnimationEnabled(bool);
private:
WebCore::Settings* m_settings;
ccSettings.perTilePainting = page()->settings()->perTileDrawingEnabled();
ccSettings.partialSwapEnabled = page()->settings()->partialSwapEnabled();
+ ccSettings.threadedAnimationEnabled = page()->settings()->threadedAnimationEnabled();
m_nonCompositedContentHost = NonCompositedContentHost::create(WebViewImplContentPainter::create(this));
m_nonCompositedContentHost->setShowDebugBorders(page()->settings()->showDebugBorders());
#include "config.h"
#include "cc/CCActiveAnimation.h"
-
-#include "cc/CCAnimationCurve.h"
+#include "CCAnimationTestCommon.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <wtf/Vector.h>
-namespace WebCore {
+using namespace WebKitTests;
+using namespace WebCore;
-class FakeFloatAnimation : public CCFloatAnimationCurve {
-public:
- virtual double duration() const { return 1; }
- virtual float getValue(double now) const { return 0; }
-};
+namespace {
PassOwnPtr<CCActiveAnimation> createActiveAnimation(int iterations)
{
- OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimation), 1, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toReturn(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve), 0, 1, CCActiveAnimation::Opacity));
toReturn->setIterations(iterations);
return toReturn.release();
}
EXPECT_TRUE(anim->isFinished());
}
-} // namespace WebCore
+} // namespace
--- /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 "GraphicsLayer.h"
+#include "LayerChromium.h"
+
+using namespace WebCore;
+
+namespace WebKitTests {
+
+FakeFloatAnimationCurve::FakeFloatAnimationCurve()
+{
+}
+
+FakeFloatAnimationCurve::~FakeFloatAnimationCurve()
+{
+}
+
+PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatAnimationCurve::clone() const
+{
+ return adoptPtr(new FakeFloatAnimationCurve);
+}
+
+FakeTransformTransition::FakeTransformTransition(double duration)
+ : m_duration(duration)
+{
+}
+
+FakeTransformTransition::~FakeTransformTransition()
+{
+}
+
+WebCore::TransformationMatrix FakeTransformTransition::getValue(double time, const WebCore::IntSize& size) const
+{
+ return WebCore::TransformationMatrix();
+}
+
+PassOwnPtr<WebCore::CCAnimationCurve> FakeTransformTransition::clone() const
+{
+ return adoptPtr(new FakeTransformTransition(*this));
+}
+
+
+FakeFloatTransition::FakeFloatTransition(double duration, float from, float to)
+ : m_duration(duration)
+ , m_from(from)
+ , m_to(to)
+{
+}
+
+FakeFloatTransition::~FakeFloatTransition()
+{
+}
+
+float FakeFloatTransition::getValue(double time) const
+{
+ time /= m_duration;
+ if (time >= 1)
+ time = 1;
+ return (1 - time) * m_from + time * m_to;
+}
+
+FakeLayerAnimationControllerImplClient::FakeLayerAnimationControllerImplClient()
+ : m_opacity(0)
+{
+}
+
+FakeLayerAnimationControllerImplClient::~FakeLayerAnimationControllerImplClient()
+{
+}
+
+PassOwnPtr<WebCore::CCAnimationCurve> FakeFloatTransition::clone() const
+{
+ return adoptPtr(new FakeFloatTransition(*this));
+}
+
+void addOpacityTransition(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity)
+{
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ if (duration > 0)
+ values.insert(new FloatAnimationValue(0, startOpacity));
+ values.insert(new FloatAnimationValue(duration, endOpacity));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(1);
+
+ IntSize boxSize;
+
+ layer.addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+}
+
+} // namespace WebKitTests
--- /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 CCAnimationTestCommon_h
+#define CCAnimationTestCommon_h
+
+#include "cc/CCAnimationCurve.h"
+#include "cc/CCLayerAnimationControllerImpl.h"
+
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+class LayerChromium;
+}
+
+namespace WebKitTests {
+
+class FakeFloatAnimationCurve : public WebCore::CCFloatAnimationCurve {
+public:
+ FakeFloatAnimationCurve();
+ virtual ~FakeFloatAnimationCurve();
+
+ virtual double duration() const { return 1; }
+ virtual float getValue(double now) const { return 0; }
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+};
+
+class FakeTransformTransition : public WebCore::CCTransformAnimationCurve {
+public:
+ FakeTransformTransition(double duration);
+ virtual ~FakeTransformTransition();
+
+ virtual double duration() const { return m_duration; }
+ virtual WebCore::TransformationMatrix getValue(double time, const WebCore::IntSize&) const;
+
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+
+private:
+ double m_duration;
+};
+
+class FakeFloatTransition : public WebCore::CCFloatAnimationCurve {
+public:
+ FakeFloatTransition(double duration, float from, float to);
+ virtual ~FakeFloatTransition();
+
+ virtual double duration() const { return m_duration; }
+ virtual float getValue(double time) const;
+
+ virtual PassOwnPtr<WebCore::CCAnimationCurve> clone() const;
+
+private:
+ double m_duration;
+ float m_from;
+ float m_to;
+};
+
+class FakeLayerAnimationControllerImplClient : public WebCore::CCLayerAnimationControllerImplClient {
+public:
+ FakeLayerAnimationControllerImplClient();
+ virtual ~FakeLayerAnimationControllerImplClient();
+
+ virtual int id() const { return 0; }
+ virtual float opacity() const { return m_opacity; }
+ virtual void setOpacity(float opacity) { m_opacity = opacity; }
+ 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:
+ float m_opacity;
+ WebCore::TransformationMatrix m_transform;
+ WebCore::IntSize m_bounds;
+};
+
+void addOpacityTransition(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity);
+
+} // namespace WebKitTests
+
+#endif // CCAnimationTesctCommon_h
#include "config.h"
+#include "CCAnimationTestCommon.h"
#include "cc/CCLayerAnimationControllerImpl.h"
-
-#include "TransformOperations.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 {
-class FakeControllerClient : public CCLayerAnimationControllerImplClient {
-public:
- FakeControllerClient() : m_opacity(0) { }
- virtual ~FakeControllerClient() { }
-
- virtual float opacity() const { return m_opacity; }
- virtual void setOpacity(float opacity) { m_opacity = opacity; }
- virtual const TransformationMatrix& transform() const { return m_transform; }
- virtual void setTransform(const TransformationMatrix& transform) { m_transform = transform; }
- virtual void animationControllerImplDidActivate(CCLayerAnimationControllerImpl* controller)
- {
- m_activeControllers.append(controller);
- }
-
- Vector<CCLayerAnimationControllerImpl*>& activeControllers() { return m_activeControllers; }
-
-private:
- float m_opacity;
- TransformationMatrix m_transform;
- Vector<CCLayerAnimationControllerImpl*> m_activeControllers;
-};
-
-class FakeTransformTransition : public CCTransformAnimationCurve {
-public:
- FakeTransformTransition(double duration) : m_duration(duration) { }
- virtual double duration() const { return m_duration; }
- virtual TransformOperations getValue(double time) const
- {
- return TransformOperations();
- }
-
-private:
- double m_duration;
-};
-
-class FakeFloatTransition : public CCFloatAnimationCurve {
-public:
- FakeFloatTransition(double duration, float from, float to)
- : m_duration(duration)
- , m_from(from)
- , m_to(to)
- {
- }
-
- virtual double duration() const { return m_duration; }
- virtual float getValue(double time) const
- {
- time /= m_duration;
- if (time >= 1)
- time = 1;
- return (1 - time) * m_from + time * m_to;
- }
-
-private:
- double m_duration;
- float m_from;
- float m_to;
-};
+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)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
controller->add(toAdd.release());
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ 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)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
+ 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);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_EQ(0.5f, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
// Tests interrupting a transition with another transition.
TEST(CCLayerAnimationControllerImplTest, Interrupt)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->animate(0);
+ 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(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::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); // second anim starts NOW.
+ controller->animate(0.5, *events); // second anim starts NOW.
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
- controller->animate(1.5);
+ 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)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), 1, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), 2, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 2, 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));
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_EQ(0, dummy.opacity());
EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1);
+ 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);
+ controller->animate(2, *events);
EXPECT_EQ(1, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
// for both to finish).
TEST(CCLayerAnimationControllerImplTest, ScheduleTogetherWithAnAnimWaiting)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(2)), 1, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.5f)), 2, CCActiveAnimation::Opacity));
+ 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);
+ 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);
+ 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);
+ 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)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, 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);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(2);
+ 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)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0.5f, 0)), 2, 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);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5);
+ controller->animate(0.5, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_EQ(0, dummy.opacity());
EXPECT_FALSE(controller->hasActiveAnimation());
}
// and there is yet another animation queued to start later.
TEST(CCLayerAnimationControllerImplTest, ScheduledAnimationInterruptsRunningAnimationWithAnimInQueue)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(2, 0, 1)), 1, CCActiveAnimation::Opacity));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0.5f, 0)), 2, 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(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 0.75f)), 3, CCActiveAnimation::Opacity));
// First 2s opacity transition should start immediately.
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5);
+ controller->animate(0.5, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
EXPECT_TRUE(controller->hasActiveAnimation());
- controller->animate(1);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.5f, dummy.opacity());
- controller->animate(3);
+ controller->animate(3, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(4);
+ 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)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, 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);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25);
+ controller->animate(1.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75);
+ controller->animate(1.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(2.25);
+ controller->animate(2.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(2.75);
+ controller->animate(2.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(3);
+ controller->animate(3, *events);
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
// Just be extra sure.
- controller->animate(4);
+ controller->animate(4, *events);
EXPECT_EQ(1, dummy.opacity());
}
// Test that an infinitely looping animation does indeed go until aborted.
TEST(CCLayerAnimationControllerImplTest, InfiniteLooping)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
const int id = 1;
- OwnPtr<CCActiveAnimation> toAdd(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ OwnPtr<CCActiveAnimation> toAdd(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
toAdd->setIterations(-1);
controller->add(toAdd.release());
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1.25);
+ controller->animate(1.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1.75);
+ controller->animate(1.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(1073741824.25);
+ controller->animate(1073741824.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.25f, dummy.opacity());
- controller->animate(1073741824.75);
+ controller->animate(1073741824.75, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
// Test that pausing and resuming work as expected.
TEST(CCLayerAnimationControllerImplTest, PauseResume)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
const int id = 1;
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
+ controller->add(createActiveAnimation(adoptPtr(new FakeFloatTransition(1, 0, 1)), id, CCActiveAnimation::Opacity));
- controller->animate(0);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(0.5);
+ 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);
+ 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);
+ controller->animate(1024.25, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
- controller->animate(1024.5);
+ controller->animate(1024.5, *events);
EXPECT_FALSE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
}
TEST(CCLayerAnimationControllerImplTest, AbortAGroupedAnimation)
{
- FakeControllerClient dummy;
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ FakeLayerAnimationControllerImplClient dummy;
OwnPtr<CCLayerAnimationControllerImpl> controller(
CCLayerAnimationControllerImpl::create(&dummy));
const int id = 1;
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeTransformTransition(1)), id, CCActiveAnimation::Transform));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(2, 0, 1)), id, CCActiveAnimation::Opacity));
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 1, 0.75f)), 2, CCActiveAnimation::Opacity));
+ 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);
+ controller->animate(0, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(0, dummy.opacity());
- controller->animate(1);
+ 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);
+ controller->animate(1, *events);
EXPECT_TRUE(controller->hasActiveAnimation());
EXPECT_EQ(1, dummy.opacity());
- controller->animate(2);
+ controller->animate(2, *events);
EXPECT_TRUE(!controller->hasActiveAnimation());
EXPECT_EQ(0.75f, dummy.opacity());
}
-// Tests that adding an animation to the controller calls the appropriate callback on the controller client
-// (in this case, adding the controller to the list of active controller).
-TEST(CCLayerAnimationControllerImplTest, DidActivate)
-{
- FakeControllerClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controller(
- CCLayerAnimationControllerImpl::create(&dummy));
-
- EXPECT_EQ(size_t(0), dummy.activeControllers().size());
-
- controller->add(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(1, 0, 1)), 1, CCActiveAnimation::Opacity));
-
- EXPECT_EQ(size_t(1), dummy.activeControllers().size());
- EXPECT_EQ(controller.get(), dummy.activeControllers()[0]);
-}
-
} // namespace
--- /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/CCLayerAnimationController.h"
+
+#include "CCAnimationTestCommon.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);
+}
+
+TEST(CCLayerAnimationControllerTest, syncNewAnimation)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
+ CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+}
+
+TEST(CCLayerAnimationControllerTest, syncAnimationProperties)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
+ CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // 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());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::Paused, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+}
+
+TEST(CCLayerAnimationControllerTest, syncAbortedAnimation)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
+ CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ controller->removeAnimation(0);
+
+ // Abort an animation from the main thread.
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+}
+
+TEST(CCLayerAnimationControllerTest, syncCompletedAnimation)
+{
+ FakeLayerAnimationControllerImplClient dummy;
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
+ CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(
+ CCLayerAnimationController::create());
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+
+ controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_TRUE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(CCActiveAnimation::WaitingForTargetAvailability, controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity)->runState());
+
+ // Step through the animation until it is finished. At the next sync, the main thread's animation should be cleared.
+ OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
+ controllerImpl->animate(0, *events);
+ controllerImpl->animate(2, *events);
+
+ EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
+ EXPECT_EQ(size_t(1), controller->activeAnimations().size());
+
+ controller->synchronizeAnimations(controllerImpl.get());
+
+ EXPECT_EQ(size_t(0), controller->activeAnimations().size());
+}
+
+} // namespace
virtual void onSwapBuffersCompleteOnImplThread() { }
virtual void setNeedsRedrawOnImplThread() { m_didRequestRedraw = true; }
virtual void setNeedsCommitOnImplThread() { m_didRequestCommit = true; }
+ virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>) { }
static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
{
#include "cc/CCLayerTreeHost.h"
+#include "CCAnimationTestCommon.h"
#include "CompositorFakeWebGraphicsContext3D.h"
#include "ContentLayerChromium.h"
#include "FilterOperations.h"
#include "TextureManager.h"
#include "WebCompositor.h"
#include "WebKit.h"
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCScopedThreadProxy.h"
using namespace WebCore;
using namespace WebKit;
+using namespace WebKitTests;
using namespace WTF;
namespace {
virtual void beginCommitOnCCThread(CCLayerTreeHostImpl*) { }
virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*) { }
virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*) { }
+ virtual void animateLayers(CCLayerTreeHostImpl*) { }
virtual void applyScrollAndScale(const IntSize&, float) { }
virtual void updateAnimations(double frameBeginTime) { }
virtual void layout() { }
m_testHooks->drawLayersOnCCThread(this);
}
+protected:
+ virtual void animateLayers(double frameBeginTimeMs)
+ {
+ CCLayerTreeHostImpl::animateLayers(frameBeginTimeMs);
+ m_testHooks->animateLayers(this);
+ }
+
private:
MockLayerTreeHostImpl(TestHooks* testHooks, const CCSettings& settings, CCLayerTreeHostImplClient* client)
: CCLayerTreeHostImpl(settings, client)
public:
static PassRefPtr<MockLayerTreeHost> create(TestHooks* testHooks, CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
{
- RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settings));
+ // For these tests, we will enable threaded animations.
+ CCSettings settingsCopy = settings;
+ settingsCopy.threadedAnimationEnabled = true;
+
+ RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settingsCopy));
bool success = layerTreeHost->initialize();
EXPECT_TRUE(success);
layerTreeHost->setRootLayer(rootLayer);
virtual PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
{
- return MockLayerTreeHostImpl::create(m_testHooks, settings(), client);
+ // For these tests, we will enable threaded animations.
+ CCSettings settings;
+ settings.threadedAnimationEnabled = true;
+ return MockLayerTreeHostImpl::create(m_testHooks, settings, client);
}
private:
TestHooks* m_testHooks;
};
+// Adapts CCLayerAnimationController for test. Adds a dummy implementation of addAnimation that inserts a float animation.
+// FIXME: once CCLayerAnimationController::addAnimation is implemented, that function should be called directly and this
+// class can be removed.
+class MockLayerAnimationController : public CCLayerAnimationController {
+public:
+ static PassOwnPtr<MockLayerAnimationController> create()
+ {
+ return adoptPtr(new MockLayerAnimationController);
+ }
+
+private:
+ virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, int animationId, int groupId, double timeOffset)
+ {
+ double duration = 0;
+ activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(duration, 1, 0)), animationId, groupId, CCActiveAnimation::Opacity));
+ return true;
+ }
+};
+
class CompositorFakeWebGraphicsContext3DWithTextureTracking : public CompositorFakeWebGraphicsContext3D {
public:
static PassOwnPtr<CompositorFakeWebGraphicsContext3DWithTextureTracking> create(Attributes attrs)
{
}
- virtual void scheduleComposite() { }
+ virtual void scheduleComposite()
+ {
+ }
private:
explicit MockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHooks) { }
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimate, this);
}
+ void postAddAnimationToMainThread()
+ {
+ callOnMainThread(CCLayerTreeHostTest::dispatchAddAnimation, this);
+ }
+
void postSetNeedsCommitToMainThread()
{
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsCommit, this);
callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimateAndCommit, this);
}
-
void postSetVisibleToMainThread(bool visible)
{
callOnMainThread(visible ? CCLayerTreeHostTest::dispatchSetVisible : CCLayerTreeHostTest::dispatchSetInvisible, this);
test->m_layerTreeHost->setNeedsAnimate();
}
+ static void dispatchAddAnimation(void* self)
+ {
+ ASSERT(isMainThread());
+ CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
+ ASSERT(test);
+ if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
+ test->m_layerTreeHost->rootLayer()->addAnimation(KeyframeValueList(AnimatedPropertyOpacity), IntSize(), 0, 0, 0, 0.0);
+ }
+
static void dispatchSetNeedsAnimateAndCommit(void* self)
{
ASSERT(isMainThread());
m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
ASSERT_TRUE(m_layerTreeHost);
rootLayer->setLayerTreeHost(m_layerTreeHost.get());
+ rootLayer->setLayerAnimationController(MockLayerAnimationController::create());
m_beginning = true;
beginTest();
runTestThreaded();
}
+// Add a layer animation and confirm that CCLayerTreeHostImpl::animateLayers does get
+// called and continues to get called.
+class CCLayerTreeHostTestAddAnimation : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestAddAnimation()
+ : m_numAnimates(0)
+ , m_layerTreeHostImpl(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddAnimationToMainThread();
+ }
+
+ virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl)
+ {
+ if (!m_numAnimates) {
+ // The animation had zero duration so layerTreeHostImpl should no
+ // longer need to animate its layers.
+ EXPECT_FALSE(layerTreeHostImpl->needsAnimateLayers());
+ m_numAnimates++;
+ return;
+ }
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ int m_numAnimates;
+ CCLayerTreeHostImpl* m_layerTreeHostImpl;
+};
+
+TEST_F(CCLayerTreeHostTestAddAnimation, runMultiThread)
+{
+ runTestThreaded();
+}
+
class CCLayerTreeHostTestScrollSimple : public CCLayerTreeHostTestThreadOnly {
public:
CCLayerTreeHostTestScrollSimple()
#include "TreeSynchronizer.h"
+#include "CCAnimationTestCommon.h"
#include "LayerChromium.h"
+#include "cc/CCLayerAnimationController.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCProxy.h"
#include "cc/CCSingleThreadProxy.h"
#include <gtest/gtest.h>
using namespace WebCore;
+using namespace WebKitTests;
namespace {
Vector<int>* m_ccLayerDestructionList;
};
+class FakeLayerAnimationController : public CCLayerAnimationController {
+public:
+ static PassOwnPtr<FakeLayerAnimationController> create()
+ {
+ return adoptPtr(new FakeLayerAnimationController);
+ }
+
+ bool synchronizedAnimations() const { return m_synchronizedAnimations; }
+
+private:
+ FakeLayerAnimationController()
+ : m_synchronizedAnimations(false)
+ {
+ }
+
+ virtual void synchronizeAnimations(CCLayerAnimationControllerImpl* controllerImpl)
+ {
+ CCLayerAnimationController::synchronizeAnimations(controllerImpl);
+ m_synchronizedAnimations = true;
+ }
+
+ bool m_synchronizedAnimations;
+};
+
void expectTreesAreIdentical(LayerChromium* layer, CCLayerImpl* ccLayer)
{
ASSERT_TRUE(layer);
expectTreesAreIdentical(layerTreeRoot.get(), ccLayerTreeRoot.get());
}
+TEST(TreeSynchronizerTest, synchronizeAnimations)
+{
+ DebugScopedSetImplThread impl;
+ RefPtr<LayerChromium> layerTreeRoot = LayerChromium::create();
+
+ layerTreeRoot->setLayerAnimationController(FakeLayerAnimationController::create());
+
+ EXPECT_FALSE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
+
+ RefPtr<CCLayerImpl> ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), 0);
+ ccLayerTreeRoot = TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), ccLayerTreeRoot.get());
+
+ EXPECT_TRUE(static_cast<FakeLayerAnimationController*>(layerTreeRoot->layerAnimationController())->synchronizedAnimations());
+}
} // namespace