Title: [255663] trunk
Revision
255663
Author
[email protected]
Date
2020-02-03 21:56:04 -0800 (Mon, 03 Feb 2020)

Log Message

Accelerated animations freeze on render tree rebuild
https://bugs.webkit.org/show_bug.cgi?id=201048
<rdar://problem/54612621>

Reviewed by Antoine Quint.

Source/WebCore:

If there is an accelerated animation in progress for a renderer and the render tree is rebuild the animation
does not continue with the new renderer.

To fix, make sure that the animation leaves the accelerated state when the renderer is removed. The new renderer
will then become accelerated automatically.

Original test case by Tim Guan-tin Chien.

Test: webanimations/accelerated-animation-renderer-change.html

* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::willChangeRendererForElement):
* animation/AnimationTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::willChangeRenderer):
* animation/KeyframeEffect.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::willChangeRenderer):
* animation/WebAnimation.h:
* rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::tearDownRenderers):

LayoutTests:

* webanimations/accelerated-animation-renderer-change-expected.html: Added.
* webanimations/accelerated-animation-renderer-change.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (255662 => 255663)


--- trunk/LayoutTests/ChangeLog	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/LayoutTests/ChangeLog	2020-02-04 05:56:04 UTC (rev 255663)
@@ -1,3 +1,14 @@
+2020-02-03  Antti Koivisto  <[email protected]>
+
+        Accelerated animations freeze on render tree rebuild
+        https://bugs.webkit.org/show_bug.cgi?id=201048
+        <rdar://problem/54612621>
+
+        Reviewed by Antoine Quint.
+
+        * webanimations/accelerated-animation-renderer-change-expected.html: Added.
+        * webanimations/accelerated-animation-renderer-change.html: Added.
+
 2020-02-03  Jacob Uphoff  <[email protected]>
 
         [ macOS wk1 ] inspector/unit-tests/server-timing-entry.html is flaky timeout

Added: trunk/LayoutTests/webanimations/accelerated-animation-renderer-change-expected.html (0 => 255663)


--- trunk/LayoutTests/webanimations/accelerated-animation-renderer-change-expected.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/accelerated-animation-renderer-change-expected.html	2020-02-04 05:56:04 UTC (rev 255663)
@@ -0,0 +1,15 @@
+<style>
+div {
+    background-color: rebeccapurple;
+    width: 100px;
+    height: 100px;
+}
+
+#test{
+    position: absolute;
+    top: 200px;
+    left: 200px;
+}
+
+</style>
+<div id=test></div>

Added: trunk/LayoutTests/webanimations/accelerated-animation-renderer-change.html (0 => 255663)


--- trunk/LayoutTests/webanimations/accelerated-animation-renderer-change.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/accelerated-animation-renderer-change.html	2020-02-04 05:56:04 UTC (rev 255663)
@@ -0,0 +1,67 @@
+<style>
+
+div {
+    background-color: rebeccapurple;
+    width: 100px;
+    height: 100px;
+}
+
+#test{
+    position: absolute;
+    top: 200px;
+    left: 200px;
+}
+
+.animate-class {
+    animation: 1s linear 0s 1 normal scale;
+}
+
+.first-letter::first-letter {
+    color:red;
+}
+
+@keyframes scale {
+    0% {
+        transform: scale(0);
+    }
+
+    10% {
+        transform: scale(1);
+    }
+
+    100% {
+        transform: scale(1);
+    }
+}
+
+</style>
+<script>
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+window._onload_ = async function() {
+    const element = document.body.appendChild(document.createElement("div"));
+    element.className = "animate-class";
+    element.id = "test";
+
+    const animation = element.getAnimations()[0];
+
+    await animation.ready;
+
+    await new Promise(resolve => requestAnimationFrame(resolve));
+    await new Promise(resolve => requestAnimationFrame(resolve));
+
+    // Force render tree rebuild in the middle of the animation.
+    document.body.classList.add("first-letter");
+
+    // See that the accelerated animation still progresses.
+    while (animation.currentTime < 100)
+        await new Promise(resolve => requestAnimationFrame(resolve));
+
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+</script>
+

Modified: trunk/Source/WebCore/ChangeLog (255662 => 255663)


--- trunk/Source/WebCore/ChangeLog	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/ChangeLog	2020-02-04 05:56:04 UTC (rev 255663)
@@ -1,3 +1,33 @@
+2020-02-03  Antti Koivisto  <[email protected]>
+
+        Accelerated animations freeze on render tree rebuild
+        https://bugs.webkit.org/show_bug.cgi?id=201048
+        <rdar://problem/54612621>
+
+        Reviewed by Antoine Quint.
+
+        If there is an accelerated animation in progress for a renderer and the render tree is rebuild the animation
+        does not continue with the new renderer.
+
+        To fix, make sure that the animation leaves the accelerated state when the renderer is removed. The new renderer
+        will then become accelerated automatically.
+
+        Original test case by Tim Guan-tin Chien.
+
+        Test: webanimations/accelerated-animation-renderer-change.html
+
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::willChangeRendererForElement):
+        * animation/AnimationTimeline.h:
+        * animation/KeyframeEffect.cpp:
+        (WebCore::KeyframeEffect::willChangeRenderer):
+        * animation/KeyframeEffect.h:
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::willChangeRenderer):
+        * animation/WebAnimation.h:
+        * rendering/updating/RenderTreeUpdater.cpp:
+        (WebCore::RenderTreeUpdater::tearDownRenderers):
+
 2020-02-03  Andres Gonzalez  <[email protected]>
 
         [WebAccessibilityObjectWrapper detach] should detach either the wrapped AXObject or the IsolatedObject but not both.

Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (255662 => 255663)


--- trunk/Source/WebCore/animation/AnimationTimeline.cpp	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/animation/AnimationTimeline.cpp	2020-02-04 05:56:04 UTC (rev 255663)
@@ -241,6 +241,12 @@
         animation->remove();
 }
 
+void AnimationTimeline::willChangeRendererForElement(Element& element)
+{
+    for (auto& animation : animationsForElement(element))
+        animation->willChangeRenderer();
+}
+
 void AnimationTimeline::cancelDeclarativeAnimationsForElement(Element& element)
 {
     for (auto& cssTransition : m_elementToCSSTransitionsMap.get(&element))

Modified: trunk/Source/WebCore/animation/AnimationTimeline.h (255662 => 255663)


--- trunk/Source/WebCore/animation/AnimationTimeline.h	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/animation/AnimationTimeline.h	2020-02-04 05:56:04 UTC (rev 255663)
@@ -61,6 +61,7 @@
     Vector<RefPtr<WebAnimation>> animationsForElement(Element&, Ordering ordering = Ordering::Unsorted) const;
     void elementWasRemoved(Element&);
     void removeAnimationsForElement(Element&);
+    void willChangeRendererForElement(Element&);
     void cancelDeclarativeAnimationsForElement(Element&);
     virtual void animationWasAddedToElement(WebAnimation&, Element&);
     virtual void animationWasRemovedFromElement(WebAnimation&, Element&);

Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (255662 => 255663)


--- trunk/Source/WebCore/animation/KeyframeEffect.cpp	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp	2020-02-04 05:56:04 UTC (rev 255663)
@@ -1395,6 +1395,12 @@
         addPendingAcceleratedAction(AcceleratedAction::Stop);
 }
 
+void KeyframeEffect::willChangeRenderer()
+{
+    if (m_isRunningAccelerated)
+        addPendingAcceleratedAction(AcceleratedAction::Stop);
+}
+
 void KeyframeEffect::animationSuspensionStateDidChange(bool animationIsSuspended)
 {
     if (m_isRunningAccelerated)

Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (255662 => 255663)


--- trunk/Source/WebCore/animation/KeyframeEffect.h	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h	2020-02-04 05:56:04 UTC (rev 255663)
@@ -122,6 +122,8 @@
     void animationTimingDidChange();
     void applyPendingAcceleratedActions();
 
+    void willChangeRenderer();
+
     void setAnimation(WebAnimation*) final;
 
     RenderElement* renderer() const override;

Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (255662 => 255663)


--- trunk/Source/WebCore/animation/WebAnimation.cpp	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp	2020-02-04 05:56:04 UTC (rev 255663)
@@ -675,6 +675,12 @@
         m_effect->animationWasCanceled();
 }
 
+void WebAnimation::willChangeRenderer()
+{
+    if (is<KeyframeEffect>(m_effect))
+        downcast<KeyframeEffect>(*m_effect).willChangeRenderer();
+}
+
 void WebAnimation::enqueueAnimationPlaybackEvent(const AtomString& type, Optional<Seconds> currentTime, Optional<Seconds> timelineTime)
 {
     auto event = AnimationPlaybackEvent::create(type, currentTime, timelineTime);

Modified: trunk/Source/WebCore/animation/WebAnimation.h (255662 => 255663)


--- trunk/Source/WebCore/animation/WebAnimation.h	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/animation/WebAnimation.h	2020-02-04 05:56:04 UTC (rev 255663)
@@ -123,6 +123,7 @@
     void effectTargetDidChange(Element* previousTarget, Element* newTarget);
     void acceleratedStateDidChange();
     void applyPendingAcceleratedActions();
+    void willChangeRenderer();
 
     bool isRunningAccelerated() const;
     bool isCompletelyAccelerated() const;

Modified: trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp (255662 => 255663)


--- trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp	2020-02-04 05:46:57 UTC (rev 255662)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeUpdater.cpp	2020-02-04 05:56:04 UTC (rev 255663)
@@ -561,7 +561,9 @@
         while (teardownStack.size() > depth) {
             auto& element = *teardownStack.takeLast();
 
-            if (teardownType == TeardownType::Full || teardownType == TeardownType::RendererUpdateCancelingAnimations) {
+            switch (teardownType) {
+            case TeardownType::Full:
+            case TeardownType::RendererUpdateCancelingAnimations:
                 if (timeline) {
                     if (document.renderTreeBeingDestroyed())
                         timeline->elementWasRemoved(element);
@@ -569,6 +571,11 @@
                         timeline->cancelDeclarativeAnimationsForElement(element);
                 }
                 animationController.cancelAnimations(element);
+                break;
+            case TeardownType::RendererUpdate:
+                if (timeline)
+                    timeline->willChangeRendererForElement(element);
+                break;
             }
 
             if (teardownType == TeardownType::Full)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to