Title: [289598] trunk
Revision
289598
Author
[email protected]
Date
2022-02-10 18:03:18 -0800 (Thu, 10 Feb 2022)

Log Message

[web-animations] accelerated animations should not run accelerated
https://bugs.webkit.org/show_bug.cgi?id=236447
<rdar://problem/88756985>

Reviewed by Dean Jackson.

Source/WebCore:

Until we can tackle the complex task of supporting accelerated additive animations
(bug 232081), we need to run animations targeting properties that we would otherwise
known how to accelerate in software if it is additive or if another effect in the
effect stack is itself additive.

We add two new boolean flags on KeyframeEffect that will help us determine whether
that effect can run accelerated.

The first flag, m_hasKeyframeComposingAcceleratedProperty, indicates whether any of
the keyframes targeting a property that supports acceleration uses additivity or
accumulation.

With the help of this flag, we can make KeyframeEffect::canBeAccelerated() return false
not only if the effect has effect-wide additivity or accumulation, but also if one of
its keyframes does.

The second flag, m_hasImplicitKeyframeForAcceleratedProperty, indicates whether any
of the properties found in one of the keyframes is absent from either the 0% or 100%
keyframes. This is important because if an effect uses an implicit value for an
acclerated property, then that effect automatically depends on other effects lower
down the effect stack it belongs to being able to use an accelerated animation to
itself run accelerated.

With the help of this second flag, we can accurately determine when trying to start
an accelerated animation in the startAnimation() lambda within applyPendingAcceleratedActions()
whether the keyframe effect stack contains another effect that will fail to run
accelerated, and prevent this effect from running accelerated itself. Unless if
it does not rely on implicit keyframes, in which case effects lower down the stack
should not be accounted for, as we wouldn't have gone this far if this effect was
using additivity or accumulation, per the canBeAccelerated() improvements.

To allow the effect stack to determine whether any of its effects could be accelerated,
but fails to actually run accelerated, we've added a new KeyframeEffect::canBeAccelerated()
method that the new KeyframeEffectStack::containsEffectThatPreventsAccelerationOfEffect()
calls to determine if any effect other than the one provided should prevent acceleration.

Test: webanimations/accelerated-animations-and-composite.html

* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::setBlendingKeyframes):
(WebCore::KeyframeEffect::canBeAccelerated const):
(WebCore::KeyframeEffect::preventsAcceleration const):
(WebCore::KeyframeEffect::applyPendingAcceleratedActions):
(WebCore::KeyframeEffect::computeHasImplicitKeyframeForAcceleratedProperty):
(WebCore::KeyframeEffect::computeHasKeyframeComposingAcceleratedProperty):
* animation/KeyframeEffect.h:
* animation/KeyframeEffectStack.cpp:
(WebCore::KeyframeEffectStack::containsEffectThatPreventsAccelerationOfEffect):
* animation/KeyframeEffectStack.h:
* platform/graphics/ca/GraphicsLayerCA.cpp:

LayoutTests:

Add a new test which runs through all the various scenarios where additivity
should or should not prevent other animations from running accelerated.

* webanimations/accelerated-animations-and-composite-expected.txt: Added.
* webanimations/accelerated-animations-and-composite.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (289597 => 289598)


--- trunk/LayoutTests/ChangeLog	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/LayoutTests/ChangeLog	2022-02-11 02:03:18 UTC (rev 289598)
@@ -1,3 +1,17 @@
+2022-02-10  Antoine Quint  <[email protected]>
+
+        [web-animations] accelerated animations should not run accelerated
+        https://bugs.webkit.org/show_bug.cgi?id=236447
+        <rdar://problem/88756985>
+
+        Reviewed by Dean Jackson.
+
+        Add a new test which runs through all the various scenarios where additivity
+        should or should not prevent other animations from running accelerated.
+
+        * webanimations/accelerated-animations-and-composite-expected.txt: Added.
+        * webanimations/accelerated-animations-and-composite.html: Added.
+
 2022-02-10  Andres Gonzalez  <[email protected]>
 
         Make accessibility/mac/line-index-for-textmarker.html run faster.

Added: trunk/LayoutTests/webanimations/accelerated-animations-and-composite-expected.txt (0 => 289598)


--- trunk/LayoutTests/webanimations/accelerated-animations-and-composite-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webanimations/accelerated-animations-and-composite-expected.txt	2022-02-11 02:03:18 UTC (rev 289598)
@@ -0,0 +1,8 @@
+
+PASS Setting 'composite' to 'add' should prevent acceleration
+PASS Setting 'composite' to 'add' on a keyframe should prevent acceleration
+PASS Setting 'composite' to 'add' on an animation further up the stack should prevent lower animations in the stack from being accelerated
+PASS Setting 'composite' to 'add' on an animation lower down the stack should allow replace animations further up the stack to be accelerated
+PASS Setting 'composite' to 'add' on an animation lower down the stack should prevent replace animations with an implicity keyframe further up the stack to be accelerated
+PASS Setting 'composite' to 'add' on an animation lower down the stack targeting a property that isn't accelerated should allow replace animations with implicit keyframes further up the stack to be accelerated
+

Added: trunk/LayoutTests/webanimations/accelerated-animations-and-composite.html (0 => 289598)


--- trunk/LayoutTests/webanimations/accelerated-animations-and-composite.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/accelerated-animations-and-composite.html	2022-02-11 02:03:18 UTC (rev 289598)
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+<script src=""
+<style>
+
+div {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100px;
+    height: 100px;
+    background-color: black;
+}
+
+</style>
+<script>
+
+const createDiv = test => {
+    const div = document.createElement("div");
+    test.add_cleanup(() => div.remove());
+    return document.body.appendChild(div);
+}
+
+const animationReadyToAnimateAccelerated = async animation => {
+    await animation.ready;
+    // Wait two frames for the potential accelerated animation to be committed.
+    await new Promise(requestAnimationFrame);
+    await new Promise(requestAnimationFrame);
+    await new Promise(requestAnimationFrame);
+}
+
+const duration = 1000 * 1000; // 1000s.
+
+promise_test(async test => {
+    const target = createDiv(test);
+    const animation = target.animate(
+        { transform: "translateX(100px)" },
+        { composite: "add", duration }
+    );
+    await animationReadyToAnimateAccelerated(animation);
+    assert_equals(internals.acceleratedAnimationsForElement(target).length, 0);
+}, "Setting 'composite' to 'add' should prevent acceleration");
+
+promise_test(async test => {
+    const target = createDiv(test);
+    const animation = target.animate(
+        [{ offset: 1, composite: "add", transform: "translateX(100px)" }],
+        { duration }
+    );
+    await animationReadyToAnimateAccelerated(animation);
+    assert_equals(internals.acceleratedAnimationsForElement(target).length, 0);
+}, "Setting 'composite' to 'add' on a keyframe should prevent acceleration");
+
+promise_test(async test => {
+    const target = createDiv(test);
+    const animations = [];
+    // First add a replace animation that could be accelerated by itself.
+    animations.push(target.animate(
+        { transform: "translateX(100px)" },
+        { duration }
+    ));
+    // Then, add a composing animation that prevents the whole stack to be accelerated.
+    animations.push(target.animate(
+        { transform: "translateY(100px)" },
+        { composite: "add", duration }
+    ));
+    await Promise.all(animations.map(animation => animationReadyToAnimateAccelerated(animation)));
+    assert_equals(internals.acceleratedAnimationsForElement(target).length, 0);
+}, "Setting 'composite' to 'add' on an animation further up the stack should prevent lower animations in the stack from being accelerated");
+
+promise_test(async test => {
+    const target = createDiv(test);
+    const animations = [];
+    // First add a composing animation that cannot be run accelerated on its own.
+    animations.push(target.animate(
+        { transform: "translateX(100px)" },
+        { composite: "add", duration }
+    ));
+    // Then, add a replace animation that should be accelerated since it completely obliterates
+    // the previous composing animation.
+    animations.push(target.animate(
+        { transform: ["none", "translateY(100px)"] },
+        { duration }
+    ));
+    await Promise.all(animations.map(animation => animationReadyToAnimateAccelerated(animation)));
+    assert_equals(internals.acceleratedAnimationsForElement(target).length, 1);
+}, "Setting 'composite' to 'add' on an animation lower down the stack should allow replace animations further up the stack to be accelerated");
+
+promise_test(async test => {
+    const target = createDiv(test);
+    const animations = [];
+    // First add a composing animation that cannot be run accelerated on its own.
+    animations.push(target.animate(
+        { transform: "translateX(100px)" },
+        { composite: "add", duration }
+    ));
+    // Then, add a replace animation that should be accelerated except it can't because
+    // it contains an implicit keyframe derived from the output of the previous animation.
+    animations.push(target.animate(
+        { transform: "translateX(100px)" },
+        { duration }
+    ));
+    await Promise.all(animations.map(animation => animationReadyToAnimateAccelerated(animation)));
+    assert_equals(internals.acceleratedAnimationsForElement(target).length, 0);
+}, "Setting 'composite' to 'add' on an animation lower down the stack should prevent replace animations with an implicity keyframe further up the stack to be accelerated");
+
+promise_test(async test => {
+    const target = createDiv(test);
+    const animations = [];
+    // First add a composing animation that cannot be run accelerated on its own.
+    animations.push(target.animate(
+        { marginLeft: "100px" },
+        { composite: "add", duration }
+    ));
+    // Then, add a replace animation with an implicit keyframes that can be accelerated
+    // since there are no other composing animations below it in the stack that target
+    // that property.
+    animations.push(target.animate(
+        { transform: "translateX(100px)" },
+        { duration }
+    ));
+    await Promise.all(animations.map(animation => animationReadyToAnimateAccelerated(animation)));
+    assert_equals(internals.acceleratedAnimationsForElement(target).length, 1);
+}, "Setting 'composite' to 'add' on an animation lower down the stack targeting a property that isn't accelerated should allow replace animations with implicit keyframes further up the stack to be accelerated");
+
+</script>
+</body>

Modified: trunk/Source/WebCore/ChangeLog (289597 => 289598)


--- trunk/Source/WebCore/ChangeLog	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/Source/WebCore/ChangeLog	2022-02-11 02:03:18 UTC (rev 289598)
@@ -1,3 +1,62 @@
+2022-02-10  Antoine Quint  <[email protected]>
+
+        [web-animations] accelerated animations should not run accelerated
+        https://bugs.webkit.org/show_bug.cgi?id=236447
+        <rdar://problem/88756985>
+
+        Reviewed by Dean Jackson.
+
+        Until we can tackle the complex task of supporting accelerated additive animations
+        (bug 232081), we need to run animations targeting properties that we would otherwise
+        known how to accelerate in software if it is additive or if another effect in the
+        effect stack is itself additive.
+
+        We add two new boolean flags on KeyframeEffect that will help us determine whether
+        that effect can run accelerated.
+
+        The first flag, m_hasKeyframeComposingAcceleratedProperty, indicates whether any of
+        the keyframes targeting a property that supports acceleration uses additivity or
+        accumulation.
+
+        With the help of this flag, we can make KeyframeEffect::canBeAccelerated() return false
+        not only if the effect has effect-wide additivity or accumulation, but also if one of
+        its keyframes does.
+
+        The second flag, m_hasImplicitKeyframeForAcceleratedProperty, indicates whether any
+        of the properties found in one of the keyframes is absent from either the 0% or 100%
+        keyframes. This is important because if an effect uses an implicit value for an
+        acclerated property, then that effect automatically depends on other effects lower
+        down the effect stack it belongs to being able to use an accelerated animation to
+        itself run accelerated.
+
+        With the help of this second flag, we can accurately determine when trying to start
+        an accelerated animation in the startAnimation() lambda within applyPendingAcceleratedActions()
+        whether the keyframe effect stack contains another effect that will fail to run
+        accelerated, and prevent this effect from running accelerated itself. Unless if
+        it does not rely on implicit keyframes, in which case effects lower down the stack
+        should not be accounted for, as we wouldn't have gone this far if this effect was
+        using additivity or accumulation, per the canBeAccelerated() improvements.
+
+        To allow the effect stack to determine whether any of its effects could be accelerated,
+        but fails to actually run accelerated, we've added a new KeyframeEffect::canBeAccelerated()
+        method that the new KeyframeEffectStack::containsEffectThatPreventsAccelerationOfEffect()
+        calls to determine if any effect other than the one provided should prevent acceleration.
+
+        Test: webanimations/accelerated-animations-and-composite.html
+
+        * animation/KeyframeEffect.cpp:
+        (WebCore::KeyframeEffect::setBlendingKeyframes):
+        (WebCore::KeyframeEffect::canBeAccelerated const):
+        (WebCore::KeyframeEffect::preventsAcceleration const):
+        (WebCore::KeyframeEffect::applyPendingAcceleratedActions):
+        (WebCore::KeyframeEffect::computeHasImplicitKeyframeForAcceleratedProperty):
+        (WebCore::KeyframeEffect::computeHasKeyframeComposingAcceleratedProperty):
+        * animation/KeyframeEffect.h:
+        * animation/KeyframeEffectStack.cpp:
+        (WebCore::KeyframeEffectStack::containsEffectThatPreventsAccelerationOfEffect):
+        * animation/KeyframeEffectStack.h:
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+
 2022-02-10  Brandon Stewart  <[email protected]>
 
         Check bidiLevels are valid before reordering

Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (289597 => 289598)


--- trunk/Source/WebCore/animation/KeyframeEffect.cpp	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp	2022-02-11 02:03:18 UTC (rev 289598)
@@ -920,6 +920,8 @@
     computeStackingContextImpact();
     computeAcceleratedPropertiesState();
     computeSomeKeyframesUseStepsTimingFunction();
+    computeHasImplicitKeyframeForAcceleratedProperty();
+    computeHasKeyframeComposingAcceleratedProperty();
 
     checkForMatchingTransformFunctionLists();
     checkForMatchingFilterFunctionLists();
@@ -1625,9 +1627,26 @@
 
 bool KeyframeEffect::canBeAccelerated() const
 {
-    return m_acceleratedPropertiesState != AcceleratedProperties::None && !m_someKeyframesUseStepsTimingFunction && !is<StepsTimingFunction>(timingFunction());
+    if (m_acceleratedPropertiesState == AcceleratedProperties::None)
+        return false;
+
+    if (m_someKeyframesUseStepsTimingFunction || is<StepsTimingFunction>(timingFunction()))
+        return false;
+
+    if (m_compositeOperation != CompositeOperation::Replace)
+        return false;
+
+    if (m_hasKeyframeComposingAcceleratedProperty)
+        return false;
+
+    return true;
 }
 
+bool KeyframeEffect::preventsAcceleration() const
+{
+    return m_acceleratedPropertiesState != AcceleratedProperties::None && !canBeAccelerated();
+}
+
 void KeyframeEffect::updateAcceleratedActions()
 {
     auto* renderer = this->renderer();
@@ -1779,16 +1798,18 @@
         if (m_runningAccelerated == RunningAccelerated::Yes)
             renderer->animationFinished(m_blendingKeyframes.animationName());
 
-        if (!m_blendingKeyframes.hasImplicitKeyframes())
+        if (!m_hasImplicitKeyframeForAcceleratedProperty)
             return renderer->startAnimation(timeOffset, backingAnimationForCompositedRenderer(), m_blendingKeyframes) ? RunningAccelerated::Yes : RunningAccelerated::No;
 
         ASSERT(m_target);
+        auto* effectStack = m_target->keyframeEffectStack(m_pseudoId);
+        ASSERT(effectStack);
 
+        if (effectStack->containsEffectThatPreventsAccelerationOfEffect(*this))
+            return RunningAccelerated::No;
+
         // We need to resolve all animations up to this point to ensure any forward-filling
         // effect is accounted for when computing the "from" value for the accelerated animation.
-        auto* effectStack = m_target->keyframeEffectStack(m_pseudoId);
-        ASSERT(effectStack);
-
         auto underlyingStyle = [&]() {
             if (auto* lastStyleChangeEventStyle = m_target->lastStyleChangeEventStyle(m_pseudoId))
                 return RenderStyle::clonePtr(*lastStyleChangeEventStyle);
@@ -2169,4 +2190,115 @@
         downcast<CSSAnimation>(*animation()).effectCompositeOperationWasSetUsingBindings();
 }
 
+void KeyframeEffect::computeHasImplicitKeyframeForAcceleratedProperty()
+{
+    m_hasImplicitKeyframeForAcceleratedProperty = [&]() {
+        if (m_acceleratedPropertiesState == AcceleratedProperties::None)
+            return false;
+
+        if (!m_blendingKeyframes.isEmpty()) {
+            // We make a list of all animated properties and consider them all
+            // implicit until proven otherwise as we iterate through all keyframes.
+            auto implicitZeroProperties = m_blendingKeyframes.properties();
+            auto implicitOneProperties = m_blendingKeyframes.properties();
+            implicitZeroProperties.remove(CSSPropertyCustom);
+            implicitOneProperties.remove(CSSPropertyCustom);
+            for (auto& keyframe : m_blendingKeyframes) {
+                // If the keyframe is for 0% or 100%, let's remove all of its properties from
+                // our list of implicit properties.
+                if (!implicitZeroProperties.isEmpty() && !keyframe.key()) {
+                    for (auto property : keyframe.properties())
+                        implicitZeroProperties.remove(property);
+                }
+                if (!implicitOneProperties.isEmpty() && keyframe.key() == 1) {
+                    for (auto property : keyframe.properties())
+                        implicitOneProperties.remove(property);
+                }
+            }
+            // The only properties left are known to be implicit properties, so we must
+            // check them for any accelerated property.
+            for (auto implicitProperty : implicitZeroProperties) {
+                if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(implicitProperty))
+                    return true;
+            }
+            for (auto implicitProperty : implicitOneProperties) {
+                if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(implicitProperty))
+                    return true;
+            }
+            return false;
+        }
+
+        // We may not have computed keyframes yet, so we should check our parsed keyframes in the
+        // same way we checked computed keyframes.
+        for (auto& keyframe : m_parsedKeyframes) {
+            // We keep three property lists, one which contains all properties seen across keyframes
+            // which will be filtered eventually to only contain implicit properties, one containing
+            // properties seen on the 0% keyframe and one containing properties seen on the 100% keyframe.
+            HashSet<CSSPropertyID> implicitProperties;
+            HashSet<CSSPropertyID> explicitZeroProperties;
+            HashSet<CSSPropertyID> explicitOneProperties;
+            auto styleProperties = keyframe.style;
+            for (unsigned i = 0; i < styleProperties->propertyCount(); ++i) {
+                auto property = styleProperties->propertyAt(i).id();
+                // All properties may end up being implicit.
+                implicitProperties.add(property);
+                if (!keyframe.computedOffset)
+                    explicitZeroProperties.add(property);
+                else if (keyframe.computedOffset == 1)
+                    explicitOneProperties.add(property);
+            }
+            // Let's remove all properties found on the 0% and 100% keyframes from the list of potential implicit properties.
+            for (auto explicitProperty : explicitZeroProperties)
+                implicitProperties.remove(explicitProperty);
+            for (auto explicitProperty : explicitOneProperties)
+                implicitProperties.remove(explicitProperty);
+            // At this point all properties left in implicitProperties are known to be implicit,
+            // so we must check them for any accelerated property.
+            for (auto implicitProperty : implicitProperties) {
+                if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(implicitProperty))
+                    return true;
+            }
+        }
+        return false;
+    }();
+}
+
+void KeyframeEffect::computeHasKeyframeComposingAcceleratedProperty()
+{
+    m_hasKeyframeComposingAcceleratedProperty = [&]() {
+        if (m_acceleratedPropertiesState == AcceleratedProperties::None)
+            return false;
+
+        if (!m_blendingKeyframes.isEmpty()) {
+            for (auto& keyframe : m_blendingKeyframes) {
+                // If we find a keyframe with a composite operation, we check whether one
+                // of its properties is accelerated.
+                if (auto keyframeComposite = keyframe.compositeOperation()) {
+                    if (*keyframeComposite != CompositeOperation::Replace) {
+                        for (auto property : keyframe.properties()) {
+                            if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(property))
+                                return true;
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+
+        // We may not have computed keyframes yet, so we should check our parsed keyframes in the
+        // same way we checked computed keyframes.
+        for (auto& keyframe : m_parsedKeyframes) {
+            if (keyframe.composite != CompositeOperationOrAuto::Add && keyframe.composite != CompositeOperationOrAuto::Accumulate)
+                continue;
+            auto styleProperties = keyframe.style;
+            for (unsigned i = 0; i < styleProperties->propertyCount(); ++i) {
+                auto property = styleProperties->propertyAt(i).id();
+                if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(property))
+                    return true;
+            }
+        }
+        return false;
+    }();
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (289597 => 289598)


--- trunk/Source/WebCore/animation/KeyframeEffect.h	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h	2022-02-11 02:03:18 UTC (rev 289598)
@@ -168,6 +168,8 @@
 
     void keyframesRuleDidChange();
 
+    bool preventsAcceleration() const;
+
     static String CSSPropertyIDToIDLAttributeName(CSSPropertyID);
 
 private:
@@ -208,6 +210,8 @@
 #if ENABLE(FILTERS_LEVEL_2)
     void checkForMatchingBackdropFilterFunctionLists();
 #endif
+    void computeHasImplicitKeyframeForAcceleratedProperty();
+    void computeHasKeyframeComposingAcceleratedProperty();
 
     // AnimationEffect
     bool isKeyframeEffect() const final { return true; }
@@ -245,6 +249,8 @@
     bool m_colorFilterFunctionListsMatch { false };
     bool m_inTargetEffectStack { false };
     bool m_someKeyframesUseStepsTimingFunction { false };
+    bool m_hasImplicitKeyframeForAcceleratedProperty { false };
+    bool m_hasKeyframeComposingAcceleratedProperty { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/KeyframeEffectStack.cpp (289597 => 289598)


--- trunk/Source/WebCore/animation/KeyframeEffectStack.cpp	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/Source/WebCore/animation/KeyframeEffectStack.cpp	2022-02-11 02:03:18 UTC (rev 289598)
@@ -185,4 +185,18 @@
     m_invalidCSSAnimationNames.add(name);
 }
 
+bool KeyframeEffectStack::containsEffectThatPreventsAccelerationOfEffect(const KeyframeEffect& potentiallyAcceleratedEffect)
+{
+    ensureEffectsAreSorted();
+
+    for (auto& effect : m_effects) {
+        if (effect.get() == &potentiallyAcceleratedEffect)
+            continue;
+        if (effect->preventsAcceleration())
+            return true;
+    }
+
+    return false;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/KeyframeEffectStack.h (289597 => 289598)


--- trunk/Source/WebCore/animation/KeyframeEffectStack.h	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/Source/WebCore/animation/KeyframeEffectStack.h	2022-02-11 02:03:18 UTC (rev 289598)
@@ -57,6 +57,8 @@
     OptionSet<AnimationImpact> applyKeyframeEffects(RenderStyle& targetStyle, const RenderStyle& previousLastStyleChangeEventStyle, const Style::ResolutionContext&);
     bool hasEffectWithImplicitKeyframes() const;
 
+    bool containsEffectThatPreventsAccelerationOfEffect(const KeyframeEffect&);
+
     void stopAcceleratingTransformRelatedProperties(UseAcceleratedAction);
 
     void clearInvalidCSSAnimationNames();

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (289597 => 289598)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2022-02-11 01:47:41 UTC (rev 289597)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2022-02-11 02:03:18 UTC (rev 289598)
@@ -4838,6 +4838,8 @@
     Vector<std::pair<String, double>> animations;
 
     for (auto& animation : m_animations) {
+        if (animation.m_pendingRemoval)
+            continue;
         if (auto caAnimation = animatedLayer(animation.m_property)->animationForKey(animation.animationIdentifier()))
             animations.append({ animatedPropertyIDAsString(animation.m_property), caAnimation->speed() });
         else
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to