Title: [120326] trunk/Source/WebCore
Revision
120326
Author
commit-qu...@webkit.org
Date
2012-06-14 07:57:10 -0700 (Thu, 14 Jun 2012)

Log Message

[chromium] Fix race condition where animations start, finish and are deleted on the composite thread, all before the start even arrives on the main thread.
https://bugs.webkit.org/show_bug.cgi?id=88439

Patch by Eric Penner <epen...@google.com> on 2012-06-14
Reviewed by James Robinson.

Scheduling behavior covered by existing tests.

* platform/graphics/chromium/cc/CCActiveAnimation.cpp:
(WebCore::CCActiveAnimation::isFinishedAt):
* platform/graphics/chromium/cc/CCActiveAnimation.h:
(WebCore::CCActiveAnimation::isFinished):
* platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
(WebCore::CCLayerAnimationController::suspendAnimations):
(WebCore::CCLayerAnimationController::pushAnimationUpdatesTo):
(WebCore::CCLayerAnimationController::animate):
(WebCore::CCLayerAnimationController::hasActiveAnimation):
(WebCore):
(WebCore::CCLayerAnimationController::markAnimationsForDeletion):
(WebCore::CCLayerAnimationController::purgeAnimationsMarkedForDeletion):
* platform/graphics/chromium/cc/CCLayerAnimationController.h:
(CCLayerAnimationController):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (120325 => 120326)


--- trunk/Source/WebCore/ChangeLog	2012-06-14 14:44:37 UTC (rev 120325)
+++ trunk/Source/WebCore/ChangeLog	2012-06-14 14:57:10 UTC (rev 120326)
@@ -1,3 +1,27 @@
+2012-06-14  Eric Penner  <epen...@google.com>
+
+        [chromium] Fix race condition where animations start, finish and are deleted on the composite thread, all before the start even arrives on the main thread.
+        https://bugs.webkit.org/show_bug.cgi?id=88439
+
+        Reviewed by James Robinson.
+
+        Scheduling behavior covered by existing tests.
+
+        * platform/graphics/chromium/cc/CCActiveAnimation.cpp:
+        (WebCore::CCActiveAnimation::isFinishedAt):
+        * platform/graphics/chromium/cc/CCActiveAnimation.h:
+        (WebCore::CCActiveAnimation::isFinished):
+        * platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
+        (WebCore::CCLayerAnimationController::suspendAnimations):
+        (WebCore::CCLayerAnimationController::pushAnimationUpdatesTo):
+        (WebCore::CCLayerAnimationController::animate):
+        (WebCore::CCLayerAnimationController::hasActiveAnimation):
+        (WebCore):
+        (WebCore::CCLayerAnimationController::markAnimationsForDeletion):
+        (WebCore::CCLayerAnimationController::purgeAnimationsMarkedForDeletion):
+        * platform/graphics/chromium/cc/CCLayerAnimationController.h:
+        (CCLayerAnimationController):
+
 2012-06-14  Vsevolod Vlasov  <vse...@chromium.org>
 
         Web Inspector: ConsoleView.evaluateUsingTextPrompt should evaluate without command line API.

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp (120325 => 120326)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp	2012-06-14 14:44:37 UTC (rev 120325)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp	2012-06-14 14:57:10 UTC (rev 120326)
@@ -84,7 +84,7 @@
 
 bool CCActiveAnimation::isFinishedAt(double monotonicTime) const
 {
-    if (m_runState == Finished || m_runState == Aborted)
+    if (isFinished())
         return true;
 
     if (m_needsSynchronizedStartTime)

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h (120325 => 120326)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h	2012-06-14 14:44:37 UTC (rev 120325)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.h	2012-06-14 14:57:10 UTC (rev 120326)
@@ -52,6 +52,7 @@
         WaitingForNextTick = 1,
         WaitingForTargetAvailability,
         WaitingForStartTime,
+        WaitingForDeletion,
         Running,
         Paused,
         Finished,
@@ -95,7 +96,9 @@
     void setAlternatesDirection(bool alternates) { m_alternatesDirection = alternates; }
 
     bool isFinishedAt(double monotonicTime) const;
-    bool isFinished() const { return m_runState == Finished || m_runState == Aborted; }
+    bool isFinished() const { return m_runState == Finished
+                                  || m_runState == Aborted
+                                  || m_runState == WaitingForDeletion; }
 
     CCAnimationCurve* curve() { return m_curve.get(); }
     const CCAnimationCurve* curve() const { return m_curve.get(); }

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp (120325 => 120326)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp	2012-06-14 14:44:37 UTC (rev 120325)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp	2012-06-14 14:57:10 UTC (rev 120326)
@@ -84,7 +84,7 @@
 void CCLayerAnimationController::suspendAnimations(double monotonicTime)
 {
     for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
-        if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
+        if (!m_activeAnimations[i]->isFinished())
             m_activeAnimations[i]->setRunState(CCActiveAnimation::Paused, monotonicTime);
     }
 }
@@ -106,8 +106,14 @@
         replaceImplThreadAnimations(controllerImpl);
         m_forceSync = false;
     } else {
+        purgeAnimationsMarkedForDeletion();
         pushNewAnimationsToImplThread(controllerImpl);
+
+        // Remove finished impl side animations only after pushing,
+        // and only after the animations are deleted on the main thread
+        // this insures we will never push an animation twice.
         removeAnimationsCompletedOnMainThread(controllerImpl);
+
         pushPropertiesToImplThread(controllerImpl);
     }
 }
@@ -119,7 +125,7 @@
     startAnimationsWaitingForTargetAvailability(monotonicTime, events);
     resolveConflicts(monotonicTime);
     tickAnimations(monotonicTime);
-    purgeFinishedAnimations(monotonicTime, events);
+    markAnimationsForDeletion(monotonicTime, events);
     startAnimationsWaitingForTargetAvailability(monotonicTime, events);
 }
 
@@ -149,7 +155,7 @@
 bool CCLayerAnimationController::hasActiveAnimation() const
 {
     for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
-        if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted)
+        if (!m_activeAnimations[i]->isFinished())
             return true;
     }
     return false;
@@ -319,14 +325,14 @@
     }
 }
 
-void CCLayerAnimationController::purgeFinishedAnimations(double monotonicTime, CCAnimationEventsVector* events)
+
+void CCLayerAnimationController::markAnimationsForDeletion(double monotonicTime, CCAnimationEventsVector* events)
 {
-    // Each iteration, m_activeAnimations.size() decreases or i increments,
-    // guaranteeing progress towards loop termination.
-    size_t i = 0;
-    while (i < m_activeAnimations.size()) {
+    for (size_t i = 0; i < m_activeAnimations.size(); i++) {
         int groupId = m_activeAnimations[i]->group();
         bool allAnimsWithSameIdAreFinished = false;
+        // If an animation is finished, and not already marked for deletion,
+        // Find out if all other animations in the same group are also finished.
         if (m_activeAnimations[i]->isFinished()) {
             allAnimsWithSameIdAreFinished = true;
             for (size_t j = 0; j < m_activeAnimations.size(); ++j) {
@@ -339,19 +345,23 @@
         if (allAnimsWithSameIdAreFinished) {
             // We now need to remove all animations with the same group id as groupId
             // (and send along animation finished notifications, if necessary).
-            // Each iteration, m_activeAnimations.size() decreases or j increments,
-            // guaranteeing progress towards loop termination. Also, we are guaranteed
-            // to remove at least one active animation.
-            for (size_t j = i; j < m_activeAnimations.size();) {
-                if (groupId != m_activeAnimations[j]->group())
-                    j++;
-                else {
+            for (size_t j = i; j < m_activeAnimations.size(); j++) {
+                if (groupId == m_activeAnimations[j]->group()) {
                     if (events)
                         events->append(CCAnimationEvent(CCAnimationEvent::Finished, m_client->id(), m_activeAnimations[j]->group(), m_activeAnimations[j]->targetProperty(), monotonicTime));
-                    m_activeAnimations.remove(j);
+                    m_activeAnimations[j]->setRunState(CCActiveAnimation::WaitingForDeletion, monotonicTime);
                 }
             }
-        } else
+        }
+    }
+}
+
+void CCLayerAnimationController::purgeAnimationsMarkedForDeletion()
+{
+    for (size_t i = 0; i < m_activeAnimations.size();) {
+        if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForDeletion)
+            m_activeAnimations.remove(i);
+        else
             i++;
     }
 }

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h (120325 => 120326)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h	2012-06-14 14:44:37 UTC (rev 120325)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.h	2012-06-14 14:57:10 UTC (rev 120326)
@@ -117,7 +117,8 @@
     void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector*);
     void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector*);
     void resolveConflicts(double monotonicTime);
-    void purgeFinishedAnimations(double monotonicTime, CCAnimationEventsVector*);
+    void markAnimationsForDeletion(double monotonicTime, CCAnimationEventsVector*);
+    void purgeAnimationsMarkedForDeletion();
 
     void tickAnimations(double monotonicTime);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to