[chromium] Animation events should only be used for synchronizing animation start...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Mar 2012 12:13:36 +0000 (12:13 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Mar 2012 12:13:36 +0000 (12:13 +0000)
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

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.gypi
Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
Source/WebCore/platform/graphics/chromium/LayerChromium.h
Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp
Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h
Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp [deleted file]
Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp

index 6ae6ec580aa8936930bdd1a19fb62e1f6d2e16cd..2a99395f491bc94fa278204162283021798200df 100644 (file)
@@ -1,3 +1,57 @@
+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
index 0de16202b9591a1c1c63acc085ca5b2c3d5a2177..38f8a0aead22701840943670d60f1f7d1af50360 100644 (file)
             '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',
index ba5ad0408a8d0c29cf0f04ac68a68f149646db9e..dcfb6e31fb08d6d1d693de4f4103da5670b83bf1 100644 (file)
@@ -606,28 +606,10 @@ bool LayerChromium::hasActiveAnimation() const
     return m_layerAnimationController->hasActiveAnimation();
 }
 
-void LayerChromium::setAnimationEvent(const CCAnimationEvent& event, double wallClockTime)
-{
-    switch (event.type()) {
-    case CCAnimationEvent::Started:
-        m_layerAnimationDelegate->notifyAnimationStarted(wallClockTime);
-        break;
-
-    case CCAnimationEvent::FinishedFloatAnimation: {
-        const CCFloatAnimationFinishedEvent* finishedEvent = event.toFloatAnimationFinishedEvent();
-        ASSERT(finishedEvent->targetProperty() == CCActiveAnimation::Opacity);
-        setOpacity(finishedEvent->finalValue());
-        break;
-    }
-
-    case CCAnimationEvent::FinishedTransformAnimation: {
-        const CCTransformAnimationFinishedEvent* finishedEvent = event.toTransformAnimationFinishedEvent();
-        ASSERT(finishedEvent->targetProperty() == CCActiveAnimation::Transform);
-        setTransform(finishedEvent->finalValue());
-        break;
-    }
-
-    }
+void 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*)
index 16607ca30ffdc64ebdc90ee05d3237eeae2abb69..4ff128270a153592096f9c6501b80ce33a413b39 100644 (file)
@@ -56,7 +56,7 @@
 
 namespace WebCore {
 
-class CCAnimationEvent;
+struct CCAnimationStartedEvent;
 class CCLayerAnimationDelegate;
 class CCLayerImpl;
 class CCLayerTreeHost;
@@ -242,7 +242,7 @@ public:
 
     bool hasActiveAnimation() const;
 
-    void setAnimationEvent(const CCAnimationEvent&, double wallClockTime);
+    void notifyAnimationStarted(const CCAnimationStartedEvent&, double wallClockTime);
 
     virtual Region opaqueContentsRegion() const { return Region(); };
 
index 8c0303ed6210c7f49be1d2ea5ea30f98b05192cb..260d7d47e3b31b62f59b1da8060acd5b787372ac 100644 (file)
@@ -45,6 +45,7 @@ CCActiveAnimation::CCActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int ani
     , m_runState(WaitingForTargetAvailability)
     , m_iterations(1)
     , m_startTime(0)
+    , m_needsSynchronizedStartTime(false)
     , m_pauseTime(0)
     , m_totalPausedTime(0)
 {
index 9c6633c3e4c6f9d6c4e6bbe3fd3765cb7dbe4ec2..5db83af95621f650f3dfc3eec314d48ddc94e4f5 100644 (file)
@@ -92,6 +92,11 @@ public:
     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;
@@ -120,6 +125,8 @@ private:
     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
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp
deleted file mode 100644 (file)
index b77d02b..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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
index e24f75dc7c1b3ec5285018cde1af97b83aa4d696..f4628de9ec56d13ceaefd8764bdd02d682a71c3b 100644 (file)
 
 #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
 
index a0e600b242bd1f468fc4f56025b31619eb4fc11c..39f9b1699619a60b4d97c2549ab532ceee24af14 100644 (file)
@@ -96,6 +96,10 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val
         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();
 }
 
@@ -177,7 +181,7 @@ void CCLayerAnimationController::animate(double monotonicTime, CCAnimationEvents
     startAnimationsWaitingForTargetAvailability(monotonicTime, events);
     resolveConflicts(monotonicTime);
     tickAnimations(monotonicTime);
-    purgeFinishedAnimations(events);
+    purgeFinishedAnimations();
     startAnimationsWaitingForTargetAvailability(monotonicTime, events);
 }
 
@@ -212,17 +216,28 @@ bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetPr
     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());
         }
     }
@@ -249,7 +264,7 @@ void CCLayerAnimationController::startAnimationsWaitingForNextTick(double monoto
             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));
         }
     }
 }
@@ -260,7 +275,7 @@ void CCLayerAnimationController::startAnimationsWaitingForStartTime(double monot
         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));
         }
     }
 }
@@ -298,7 +313,7 @@ void CCLayerAnimationController::startAnimationsWaitingForTargetAvailability(dou
                 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);
@@ -331,7 +346,7 @@ void CCLayerAnimationController::resolveConflicts(double monotonicTime)
     }
 }
 
-void CCLayerAnimationController::purgeFinishedAnimations(CCAnimationEventsVector* events)
+void CCLayerAnimationController::purgeFinishedAnimations()
 {
     // Each iteration, m_activeAnimations.size() decreases or i increments,
     // guaranteeing progress towards loop termination.
@@ -349,27 +364,15 @@ void CCLayerAnimationController::purgeFinishedAnimations(CCAnimationEventsVector
             }
         }
         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++;
@@ -382,6 +385,11 @@ void CCLayerAnimationController::tickAnimations(double monotonicTime)
         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: {
index 57b5babeb567332096d15d9d219df0f05ff1683d..b9652d089171c8ab2c71a65f1a036c49d6c847c4 100644 (file)
@@ -86,6 +86,10 @@ public:
     // 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*);
 
@@ -99,7 +103,7 @@ private:
     void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*);
     void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*);
     void resolveConflicts(double monotonicTime);
-    void purgeFinishedAnimations(CCAnimationEventsVector*);
+    void purgeFinishedAnimations();
 
     void tickAnimations(double monotonicTime);
 
index ad400e979bece2fcf807ec9c7eabc444759c727d..8e375de1626cd077e702b0fcf0e7908d0780569d 100644 (file)
@@ -179,10 +179,10 @@ void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* alloc
         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;
 }
@@ -682,8 +682,8 @@ bool CCLayerTreeHost::animateLayersRecursive(LayerChromium* current, double mono
 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)
index f749a6b03d17f44ed61984fe9802aa010d8e61bf..9f780a7ae77aa1e8e15137a1db8f9f0f90bf8cab 100644 (file)
@@ -125,7 +125,7 @@ public:
     static bool anyLayerTreeHostInstanceExists();
 
     // CCLayerTreeHost interface to CCProxy.
-    void updateAnimations(double frameBeginTime);
+    void updateAnimations(double wallClockTime);
     void layout();
     void beginCommitOnImplThread(CCLayerTreeHostImpl*);
     void finishCommitOnImplThread(CCLayerTreeHostImpl*);
index 75ba8298258516a51e1697c60f800f96673956f9..6c3b8453e6e4163fe87cc81b52f41b489c650522 100644 (file)
@@ -1,3 +1,19 @@
+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
index 1c342dbe9f9fe49edd8c6ee33f1fadd14166fdd1..533ad545facafa47a300703f931c0c696b7eb36e 100644 (file)
@@ -1006,6 +1006,49 @@ public:
     }
 };
 
+// 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();