https://bugs.webkit.org/show_bug.cgi?id=81484
Patch by Ian Vollick <vollick@chromium.org> on 2012-03-21
Reviewed by Adrienne Walker.
Source/WebCore:
Tested in CCLayerTreeHostTestSynchronizeAnimationStartTimes
Eliminated animation finished events. Animations will finish naturally on the
main thread and the final values will be set.
Animation started events are now also used to synchronize the main thread
animations' start times with their impl thread equivalents, preventing skew.
Until main thread animations receive their synchronized start times, they will
apply their initial values (i.e., they will be paused at time zero). This
guarantees that we will not jump to the animation's final value on the main
thread while we wait for the synchronized start time.
* WebCore.gypi:
* platform/graphics/chromium/LayerChromium.cpp:
(WebCore::LayerChromium::notifyAnimationStarted):
* platform/graphics/chromium/LayerChromium.h:
(WebCore):
(LayerChromium):
* platform/graphics/chromium/cc/CCActiveAnimation.cpp:
(WebCore::CCActiveAnimation::CCActiveAnimation):
* platform/graphics/chromium/cc/CCActiveAnimation.h:
(CCActiveAnimation):
(WebCore::CCActiveAnimation::needsSynchronizedStartTime):
(WebCore::CCActiveAnimation::setNeedsSynchronizedStartTime):
* platform/graphics/chromium/cc/CCAnimationEvents.cpp: Removed.
* platform/graphics/chromium/cc/CCAnimationEvents.h:
(WebCore::CCAnimationStartedEvent::CCAnimationStartedEvent):
(CCAnimationStartedEvent):
(WebCore):
* platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
(WebCore::CCLayerAnimationController::animate):
(WebCore::CCLayerAnimationController::notifyAnimationStarted):
(WebCore):
(WebCore::CCLayerAnimationController::pushNewAnimationsToImplThread):
(WebCore::CCLayerAnimationController::startAnimationsWaitingForNextTick):
(WebCore::CCLayerAnimationController::startAnimationsWaitingForStartTime):
(WebCore::CCLayerAnimationController::startAnimationsWaitingForTargetAvailability):
(WebCore::CCLayerAnimationController::purgeFinishedAnimations):
(WebCore::CCLayerAnimationController::tickAnimations):
* platform/graphics/chromium/cc/CCLayerAnimationController.h:
(CCLayerAnimationController):
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::updateAnimations):
(WebCore::CCLayerTreeHost::setAnimationEventsRecursive):
* platform/graphics/chromium/cc/CCLayerTreeHost.h:
(CCLayerTreeHost):
Source/WebKit/chromium:
* tests/CCLayerTreeHostTest.cpp:
(WTF):
(CCLayerTreeHostTestSynchronizeAnimationStartTimes):
(WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::CCLayerTreeHostTestSynchronizeAnimationStartTimes):
(WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::beginTest):
(WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::animateLayers):
(WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::afterTest):
(WTF::TEST_F):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@111525
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-03-21 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Animation events should only be used for synchronizing animation start times
+ https://bugs.webkit.org/show_bug.cgi?id=81484
+
+ Reviewed by Adrienne Walker.
+
+ Tested in CCLayerTreeHostTestSynchronizeAnimationStartTimes
+
+ Eliminated animation finished events. Animations will finish naturally on the
+ main thread and the final values will be set.
+
+ Animation started events are now also used to synchronize the main thread
+ animations' start times with their impl thread equivalents, preventing skew.
+ Until main thread animations receive their synchronized start times, they will
+ apply their initial values (i.e., they will be paused at time zero). This
+ guarantees that we will not jump to the animation's final value on the main
+ thread while we wait for the synchronized start time.
+
+ * WebCore.gypi:
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::notifyAnimationStarted):
+ * platform/graphics/chromium/LayerChromium.h:
+ (WebCore):
+ (LayerChromium):
+ * platform/graphics/chromium/cc/CCActiveAnimation.cpp:
+ (WebCore::CCActiveAnimation::CCActiveAnimation):
+ * platform/graphics/chromium/cc/CCActiveAnimation.h:
+ (CCActiveAnimation):
+ (WebCore::CCActiveAnimation::needsSynchronizedStartTime):
+ (WebCore::CCActiveAnimation::setNeedsSynchronizedStartTime):
+ * platform/graphics/chromium/cc/CCAnimationEvents.cpp: Removed.
+ * platform/graphics/chromium/cc/CCAnimationEvents.h:
+ (WebCore::CCAnimationStartedEvent::CCAnimationStartedEvent):
+ (CCAnimationStartedEvent):
+ (WebCore):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
+ (WebCore::CCLayerAnimationController::animate):
+ (WebCore::CCLayerAnimationController::notifyAnimationStarted):
+ (WebCore):
+ (WebCore::CCLayerAnimationController::pushNewAnimationsToImplThread):
+ (WebCore::CCLayerAnimationController::startAnimationsWaitingForNextTick):
+ (WebCore::CCLayerAnimationController::startAnimationsWaitingForStartTime):
+ (WebCore::CCLayerAnimationController::startAnimationsWaitingForTargetAvailability):
+ (WebCore::CCLayerAnimationController::purgeFinishedAnimations):
+ (WebCore::CCLayerAnimationController::tickAnimations):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.h:
+ (CCLayerAnimationController):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::CCLayerTreeHost::updateAnimations):
+ (WebCore::CCLayerTreeHost::setAnimationEventsRecursive):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+ (CCLayerTreeHost):
+
2012-03-21 Zeno Albisser <zeno@webkit.org>
[Qt][WK2][Mac] MiniBrowser asserts at HashTable.h:480
'platform/graphics/chromium/cc/CCActiveGestureAnimation.h',
'platform/graphics/chromium/cc/CCAnimationCurve.cpp',
'platform/graphics/chromium/cc/CCAnimationCurve.h',
- 'platform/graphics/chromium/cc/CCAnimationEvents.cpp',
'platform/graphics/chromium/cc/CCAnimationEvents.h',
'platform/graphics/chromium/cc/CCDamageTracker.cpp',
'platform/graphics/chromium/cc/CCDamageTracker.h',
return m_layerAnimationController->hasActiveAnimation();
}
-void LayerChromium::setAnimationEvent(const CCAnimationEvent& event, double wallClockTime)
-{
- switch (event.type()) {
- case CCAnimationEvent::Started:
- m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
- break;
-
- case CCAnimationEvent::FinishedFloatAnimation: {
- const CCFloatAnimationFinishedEvent* finishedEvent = event.toFloatAnimationFinishedEvent();
- ASSERT(finishedEvent->targetProperty() == CCActiveAnimation::Opacity);
- setOpacity(finishedEvent->finalValue());
- break;
- }
-
- case CCAnimationEvent::FinishedTransformAnimation: {
- const CCTransformAnimationFinishedEvent* finishedEvent = event.toTransformAnimationFinishedEvent();
- ASSERT(finishedEvent->targetProperty() == CCActiveAnimation::Transform);
- setTransform(finishedEvent->finalValue());
- break;
- }
-
- }
+void LayerChromium::notifyAnimationStarted(const CCAnimationStartedEvent& event, double wallClockTime)
+{
+ m_layerAnimationController->notifyAnimationStarted(event);
+ m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
}
void sortLayers(Vector<RefPtr<LayerChromium> >::iterator, Vector<RefPtr<LayerChromium> >::iterator, void*)
namespace WebCore {
-class CCAnimationEvent;
+struct CCAnimationStartedEvent;
class CCLayerAnimationDelegate;
class CCLayerImpl;
class CCLayerTreeHost;
bool hasActiveAnimation() const;
- void setAnimationEvent(const CCAnimationEvent&, double wallClockTime);
+ void notifyAnimationStarted(const CCAnimationStartedEvent&, double wallClockTime);
virtual Region opaqueContentsRegion() const { return Region(); };
, m_runState(WaitingForTargetAvailability)
, m_iterations(1)
, m_startTime(0)
+ , m_needsSynchronizedStartTime(false)
, m_pauseTime(0)
, m_totalPausedTime(0)
{
CCAnimationCurve* curve() { return m_curve.get(); }
const CCAnimationCurve* curve() const { return m_curve.get(); }
+ // If this is true, even if the animation is running, it will not be tickable until
+ // it is given a start time. This is true for animations running on the main thread.
+ bool needsSynchronizedStartTime() const { return m_needsSynchronizedStartTime; }
+ void setNeedsSynchronizedStartTime(bool needsSynchronizedStartTime) { m_needsSynchronizedStartTime = needsSynchronizedStartTime; }
+
// Takes the given absolute time, and using the start time and the number
// of iterations, returns the relative time in the current iteration.
double trimTimeToCurrentIteration(double now) const;
int m_iterations;
double m_startTime;
+ bool m_needsSynchronizedStartTime;
+
// These are used in trimTimeToCurrentIteration to account for time
// spent while paused. This is not included in AnimationState since it
// there is absolutely no need for clients of this controller to know
+++ /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/CCAnimationEvents.h"
-
-#include <wtf/OwnPtr.h>
-
-namespace WebCore {
-
-CCAnimationEvent::CCAnimationEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty)
- : m_layerId(layerId)
- , m_targetProperty(targetProperty)
-{
-}
-
-CCAnimationEvent::~CCAnimationEvent()
-{
-}
-
-const CCAnimationStartedEvent* CCAnimationEvent::toAnimationStartedEvent() const
-{
- ASSERT(type() == Started);
- return static_cast<const CCAnimationStartedEvent*>(this);
-}
-
-const CCFloatAnimationFinishedEvent* CCAnimationEvent::toFloatAnimationFinishedEvent() const
-{
- ASSERT(type() == FinishedFloatAnimation);
- return static_cast<const CCFloatAnimationFinishedEvent*>(this);
-}
-
-const CCTransformAnimationFinishedEvent* CCAnimationEvent::toTransformAnimationFinishedEvent() const
-{
- ASSERT(type() == FinishedTransformAnimation);
- return static_cast<const CCTransformAnimationFinishedEvent*>(this);
-}
-
-PassOwnPtr<CCAnimationStartedEvent> CCAnimationStartedEvent::create(int layerId, CCActiveAnimation::TargetProperty targetProperty)
-{
- return adoptPtr(new CCAnimationStartedEvent(layerId, targetProperty));
-}
-
-CCAnimationStartedEvent::CCAnimationStartedEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty)
- : CCAnimationEvent(layerId, targetProperty)
-{
-}
-
-CCAnimationStartedEvent::~CCAnimationStartedEvent()
-{
-}
-
-CCAnimationEvent::Type CCAnimationStartedEvent::type() const
-{
- return Started;
-}
-
-PassOwnPtr<CCFloatAnimationFinishedEvent> CCFloatAnimationFinishedEvent::create(int layerId, CCActiveAnimation::TargetProperty targetProperty, float finalValue)
-{
- return adoptPtr(new CCFloatAnimationFinishedEvent(layerId, targetProperty, finalValue));
-}
-
-CCFloatAnimationFinishedEvent::CCFloatAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty, float finalValue)
- : CCAnimationEvent(layerId, targetProperty)
- , m_finalValue(finalValue)
-{
-}
-
-CCFloatAnimationFinishedEvent::~CCFloatAnimationFinishedEvent()
-{
-}
-
-CCAnimationEvent::Type CCFloatAnimationFinishedEvent::type() const
-{
- return FinishedFloatAnimation;
-}
-
-PassOwnPtr<CCTransformAnimationFinishedEvent> CCTransformAnimationFinishedEvent::create(int layerId, CCActiveAnimation::TargetProperty targetProperty, const TransformationMatrix& finalValue)
-{
- return adoptPtr(new CCTransformAnimationFinishedEvent(layerId, targetProperty, finalValue));
-}
-
-CCTransformAnimationFinishedEvent::CCTransformAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty targetProperty, const TransformationMatrix& finalValue)
- : CCAnimationEvent(layerId, targetProperty)
- , m_finalValue(finalValue)
-{
-}
-
-CCTransformAnimationFinishedEvent::~CCTransformAnimationFinishedEvent()
-{
-}
-
-CCAnimationEvent::Type CCTransformAnimationFinishedEvent::type() const
-{
- return FinishedTransformAnimation;
-}
-
-} // namespace WebCore
#include "cc/CCActiveAnimation.h"
-#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
namespace WebCore {
-class CCAnimationStartedEvent;
-class CCFloatAnimationFinishedEvent;
-class CCTransformAnimationFinishedEvent;
-
-class CCAnimationEvent {
-public:
- enum Type { Started, FinishedFloatAnimation, FinishedTransformAnimation };
-
- virtual ~CCAnimationEvent();
-
- virtual Type type() const = 0;
-
- int layerId() const { return m_layerId; }
-
- CCActiveAnimation::TargetProperty targetProperty() const { return m_targetProperty; }
-
- const CCAnimationStartedEvent* toAnimationStartedEvent() const;
- const CCFloatAnimationFinishedEvent* toFloatAnimationFinishedEvent() const;
- const CCTransformAnimationFinishedEvent* toTransformAnimationFinishedEvent() const;
-
-protected:
- CCAnimationEvent(int layerId, CCActiveAnimation::TargetProperty);
-
-private:
- int m_layerId;
- CCActiveAnimation::TargetProperty m_targetProperty;
-};
-
-// Indicates that an animation has started on a particular layer.
-class CCAnimationStartedEvent : public CCAnimationEvent {
-public:
- static PassOwnPtr<CCAnimationStartedEvent> create(int layerId, CCActiveAnimation::TargetProperty);
-
- virtual ~CCAnimationStartedEvent();
-
- virtual Type type() const;
-
-private:
- CCAnimationStartedEvent(int layerId, CCActiveAnimation::TargetProperty);
-};
-
-// Indicates that a float animation has completed.
-class CCFloatAnimationFinishedEvent : public CCAnimationEvent {
-public:
- static PassOwnPtr<CCFloatAnimationFinishedEvent> create(int layerId, CCActiveAnimation::TargetProperty, float finalValue);
-
- virtual ~CCFloatAnimationFinishedEvent();
-
- virtual Type type() const;
-
- float finalValue() const { return m_finalValue; }
-
-private:
- CCFloatAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty, float finalValue);
-
- float m_finalValue;
-};
-
-// Indicates that a transform animation has completed.
-class CCTransformAnimationFinishedEvent : public CCAnimationEvent {
-public:
- static PassOwnPtr<CCTransformAnimationFinishedEvent> create(int layerId, CCActiveAnimation::TargetProperty, const TransformationMatrix& finalValue);
-
- virtual ~CCTransformAnimationFinishedEvent();
-
- virtual Type type() const;
-
- const TransformationMatrix& finalValue() const { return m_finalValue; }
-
-private:
- CCTransformAnimationFinishedEvent(int layerId, CCActiveAnimation::TargetProperty, const TransformationMatrix& finalValue);
-
- TransformationMatrix m_finalValue;
+struct CCAnimationStartedEvent {
+ CCAnimationStartedEvent(int layerId, int groupId, CCActiveAnimation::TargetProperty targetProperty, double monotonicTime)
+ : layerId(layerId)
+ , groupId(groupId)
+ , targetProperty(targetProperty)
+ , monotonicTime(monotonicTime)
+ {
+ }
+
+ int layerId;
+ int groupId;
+ CCActiveAnimation::TargetProperty targetProperty;
+ double monotonicTime;
};
-typedef Vector<OwnPtr<CCAnimationEvent> > CCAnimationEventsVector;
+typedef Vector<CCAnimationStartedEvent> CCAnimationEventsVector;
} // namespace WebCore
anim->setIterations(iterations);
}
+ // In order to avoid skew, the main thread animation cannot tick until it has received the start time of
+ // the corresponding impl thread animation.
+ anim->setNeedsSynchronizedStartTime(true);
+
return anim.release();
}
startAnimationsWaitingForTargetAvailability(monotonicTime, events);
resolveConflicts(monotonicTime);
tickAnimations(monotonicTime);
- purgeFinishedAnimations(events);
+ purgeFinishedAnimations();
startAnimationsWaitingForTargetAvailability(monotonicTime, events);
}
return false;
}
+void CCLayerAnimationController::notifyAnimationStarted(const CCAnimationStartedEvent& event)
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->group() == event.groupId && m_activeAnimations[i]->targetProperty() == event.targetProperty) {
+ ASSERT(m_activeAnimations[i]->needsSynchronizedStartTime());
+ m_activeAnimations[i]->setNeedsSynchronizedStartTime(false);
+ m_activeAnimations[i]->setStartTime(event.monotonicTime);
+ return;
+ }
+ }
+}
+
void CCLayerAnimationController::pushNewAnimationsToImplThread(CCLayerAnimationController* controllerImpl)
{
// Any new animations owned by the main thread's controller are cloned and adde to the impl thread's controller.
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
if (!controllerImpl->getActiveAnimation(m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty())) {
OwnPtr<CCActiveAnimation> toAdd(m_activeAnimations[i]->cloneForImplThread());
- // If the animation is already in progress -- set it to be waiting until the target is available.
- // That way, it will have a chance to start on the impl thread. Otherwise, we will never tick at the
- // very beginning of the animation.
- if (toAdd->runState() == CCActiveAnimation::Running || toAdd->runState() == CCActiveAnimation::Paused)
- toAdd->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 0);
+ ASSERT(m_activeAnimations[i]->needsSynchronizedStartTime());
+ ASSERT(!toAdd->needsSynchronizedStartTime());
+ // The new animation should be set to run as soon as possible.
+ toAdd->setRunState(CCActiveAnimation::WaitingForTargetAvailability, 0);
controllerImpl->add(toAdd.release());
}
}
m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
m_activeAnimations[i]->setStartTime(monotonicTime);
if (events)
- events->append(CCAnimationStartedEvent::create(m_client->id(), m_activeAnimations[i]->targetProperty()));
+ events->append(CCAnimationStartedEvent(m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
}
}
}
if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) {
m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
if (events)
- events->append(CCAnimationStartedEvent::create(m_client->id(), m_activeAnimations[i]->targetProperty()));
+ events->append(CCAnimationStartedEvent(m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
}
}
}
m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime);
m_activeAnimations[i]->setStartTime(monotonicTime);
if (events)
- events->append(CCAnimationStartedEvent::create(m_client->id(), m_activeAnimations[i]->targetProperty()));
+ events->append(CCAnimationStartedEvent(m_client->id(), m_activeAnimations[i]->group(), m_activeAnimations[i]->targetProperty(), monotonicTime));
for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) {
if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) {
m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime);
}
}
-void CCLayerAnimationController::purgeFinishedAnimations(CCAnimationEventsVector* events)
+void CCLayerAnimationController::purgeFinishedAnimations()
{
// Each iteration, m_activeAnimations.size() decreases or i increments,
// guaranteeing progress towards loop termination.
}
}
if (allAnimsWithSameIdAreFinished) {
- // We now need to remove all animations with the same group id as groupId
- // (and send along animation finished notifications, if necessary).
+ // We now need to remove all animations with the same group id as groupId.
// Each iteration, m_activeAnimations.size() decreases or j increments,
// guaranteeing progress towards loop termination. Also, we are guaranteed
// to remove at least one active animation.
for (size_t j = i; j < m_activeAnimations.size();) {
if (groupId != m_activeAnimations[j]->group())
j++;
- else {
- if (events) {
- switch (m_activeAnimations[j]->targetProperty()) {
- case CCActiveAnimation::Opacity:
- events->append(CCFloatAnimationFinishedEvent::create(m_client->id(), CCActiveAnimation::Opacity, m_client->opacity()));
- break;
- case CCActiveAnimation::Transform:
- events->append(CCTransformAnimationFinishedEvent::create(m_client->id(), CCActiveAnimation::Transform, m_client->transform()));
- break;
- }
- }
+ else
m_activeAnimations.remove(j);
- }
}
} else
i++;
if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) {
double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime);
+ // Animation assumes its initial value until it gets the synchronized start time
+ // from the impl thread and can start ticking.
+ if (m_activeAnimations[i]->needsSynchronizedStartTime())
+ trimmed = 0;
+
switch (m_activeAnimations[i]->targetProperty()) {
case CCActiveAnimation::Transform: {
// if there is an animation scheduled to animate this property in the future.
bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const;
+ // This is called in response to an animation being started on the impl thread. This
+ // function updates the corresponding main thread animation's start time.
+ void notifyAnimationStarted(const CCAnimationStartedEvent&);
+
protected:
explicit CCLayerAnimationController(CCLayerAnimationControllerClient*);
void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*);
void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*);
void resolveConflicts(double monotonicTime);
- void purgeFinishedAnimations(CCAnimationEventsVector*);
+ void purgeFinishedAnimations();
void tickAnimations(double monotonicTime);
m_contentsTextureManager->evictAndDeleteAllTextures(allocator);
}
-void CCLayerTreeHost::updateAnimations(double frameBeginTime)
+void CCLayerTreeHost::updateAnimations(double wallClockTime)
{
m_animating = true;
- m_client->updateAnimations(frameBeginTime);
+ m_client->updateAnimations(wallClockTime);
animateLayers(monotonicallyIncreasingTime());
m_animating = false;
}
void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime)
{
for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) {
- if (layer->id() == events[eventIndex]->layerId())
- layer->setAnimationEvent(*events[eventIndex], wallClockTime);
+ if (layer->id() == events[eventIndex].layerId)
+ layer->notifyAnimationStarted(events[eventIndex], wallClockTime);
}
for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex)
static bool anyLayerTreeHostInstanceExists();
// CCLayerTreeHost interface to CCProxy.
- void updateAnimations(double frameBeginTime);
+ void updateAnimations(double wallClockTime);
void layout();
void beginCommitOnImplThread(CCLayerTreeHostImpl*);
void finishCommitOnImplThread(CCLayerTreeHostImpl*);
+2012-03-21 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Animation events should only be used for synchronizing animation start times
+ https://bugs.webkit.org/show_bug.cgi?id=81484
+
+ Reviewed by Adrienne Walker.
+
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF):
+ (CCLayerTreeHostTestSynchronizeAnimationStartTimes):
+ (WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::CCLayerTreeHostTestSynchronizeAnimationStartTimes):
+ (WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::beginTest):
+ (WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::animateLayers):
+ (WTF::CCLayerTreeHostTestSynchronizeAnimationStartTimes::afterTest):
+ (WTF::TEST_F):
+
2012-03-21 Peter Beverloo <peter@chromium.org>
[Chromium] Remove Android build-fix when the proper fix rolled into WebKit
}
};
+// Ensures that main thread animations have their start times synchronized with impl thread animations.
+class CCLayerTreeHostTestSynchronizeAnimationStartTimes : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestSynchronizeAnimationStartTimes()
+ : m_numAnimates(0)
+ {
+ }
+
+ virtual void beginTest()
+ {
+ postAddAnimationToMainThread();
+ }
+
+ virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl, double monotonicTime)
+ {
+ if (!m_numAnimates) {
+ m_numAnimates++;
+ return;
+ }
+
+ CCLayerAnimationController* controllerImpl = layerTreeHostImpl->rootLayer()->layerAnimationController();
+ CCLayerAnimationController* controller = m_layerTreeHost->rootLayer()->layerAnimationController();
+ CCActiveAnimation* animationImpl = controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity);
+ CCActiveAnimation* animation = controller->getActiveAnimation(0, CCActiveAnimation::Opacity);
+
+ EXPECT_EQ(animationImpl->startTime(), animation->startTime());
+
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ int m_numAnimates;
+};
+
+TEST_F(CCLayerTreeHostTestSynchronizeAnimationStartTimes, runMultiThread)
+{
+ runTestThreaded();
+}
+
TEST_F(CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity, runMultiThread)
{
runTestThreaded();