Title: [240012] trunk/Source/WebCore
Revision
240012
Author
[email protected]
Date
2019-01-15 15:06:11 -0800 (Tue, 15 Jan 2019)

Log Message

Animations should only trigger layer recomposite when necessary
https://bugs.webkit.org/show_bug.cgi?id=193450

Reviewed by Antoine Quint.

Animations only need to trigger compositing updates when their states change in a way
that affects compositing. RenderLayerCompositor::requiresCompositingForAnimation() checks for
running animations of properties that can be accelerated, so this patch fixes the legacy
animation logic to only set 'shouldRecompositeLayer' in TreeResolver::createAnimatedElementUpdate()
when the running state of such an animation changes.

ImplicitAnimation::animate() and KeyframeAnimation::animate() now return OptionSet<AnimateChange>.
This contains information about whether the running state changed, so CompositeAnimation::animate()
asks about whether the running state of an accelerated property changed, and returns this in
the AnimationUpdate result.

* page/animation/AnimationBase.h:
(WebCore::AnimationBase::isPausedState):
(WebCore::AnimationBase::isRunningState):
(WebCore::AnimationBase::inPausedState const):
(WebCore::AnimationBase::inRunningState const):
(WebCore::AnimationBase::isAnimatingProperty const):
* page/animation/CSSAnimationController.h:
* page/animation/CompositeAnimation.cpp:
(WebCore::CompositeAnimation::animate):
* page/animation/ImplicitAnimation.cpp:
(WebCore::ImplicitAnimation::animate):
(WebCore::ImplicitAnimation::affectsAcceleratedProperty const):
* page/animation/ImplicitAnimation.h:
* page/animation/KeyframeAnimation.cpp:
(WebCore::KeyframeAnimation::KeyframeAnimation):
(WebCore::KeyframeAnimation::animate):
(WebCore::KeyframeAnimation::computeStackingContextImpact): Deleted.
* page/animation/KeyframeAnimation.h:
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::createAnimatedElementUpdate):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (240011 => 240012)


--- trunk/Source/WebCore/ChangeLog	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/ChangeLog	2019-01-15 23:06:11 UTC (rev 240012)
@@ -1,5 +1,44 @@
 2019-01-15  Simon Fraser  <[email protected]>
 
+        Animations should only trigger layer recomposite when necessary
+        https://bugs.webkit.org/show_bug.cgi?id=193450
+
+        Reviewed by Antoine Quint.
+
+        Animations only need to trigger compositing updates when their states change in a way
+        that affects compositing. RenderLayerCompositor::requiresCompositingForAnimation() checks for
+        running animations of properties that can be accelerated, so this patch fixes the legacy
+        animation logic to only set 'shouldRecompositeLayer' in TreeResolver::createAnimatedElementUpdate()
+        when the running state of such an animation changes.
+
+        ImplicitAnimation::animate() and KeyframeAnimation::animate() now return OptionSet<AnimateChange>.
+        This contains information about whether the running state changed, so CompositeAnimation::animate()
+        asks about whether the running state of an accelerated property changed, and returns this in
+        the AnimationUpdate result.
+
+        * page/animation/AnimationBase.h:
+        (WebCore::AnimationBase::isPausedState):
+        (WebCore::AnimationBase::isRunningState):
+        (WebCore::AnimationBase::inPausedState const):
+        (WebCore::AnimationBase::inRunningState const):
+        (WebCore::AnimationBase::isAnimatingProperty const):
+        * page/animation/CSSAnimationController.h:
+        * page/animation/CompositeAnimation.cpp:
+        (WebCore::CompositeAnimation::animate):
+        * page/animation/ImplicitAnimation.cpp:
+        (WebCore::ImplicitAnimation::animate):
+        (WebCore::ImplicitAnimation::affectsAcceleratedProperty const):
+        * page/animation/ImplicitAnimation.h:
+        * page/animation/KeyframeAnimation.cpp:
+        (WebCore::KeyframeAnimation::KeyframeAnimation):
+        (WebCore::KeyframeAnimation::animate):
+        (WebCore::KeyframeAnimation::computeStackingContextImpact): Deleted.
+        * page/animation/KeyframeAnimation.h:
+        * style/StyleTreeResolver.cpp:
+        (WebCore::Style::TreeResolver::createAnimatedElementUpdate):
+
+2019-01-15  Simon Fraser  <[email protected]>
+
         Clean up code related to the updating of Dashboard and touch event regions
         https://bugs.webkit.org/show_bug.cgi?id=193460
 

Modified: trunk/Source/WebCore/page/animation/AnimationBase.h (240011 => 240012)


--- trunk/Source/WebCore/page/animation/AnimationBase.h	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/AnimationBase.h	2019-01-15 23:06:11 UTC (rev 240012)
@@ -44,6 +44,12 @@
 class RenderStyle;
 class TimingFunction;
 
+enum class AnimateChange {
+    StyleBlended            = 1 << 0, // Style was changed.
+    StateChange             = 1 << 1, // Animation state() changed.
+    RunningStateChange      = 1 << 2, // Animation "running or paused" changed.
+};
+
 class AnimationBase : public RefCounted<AnimationBase>
     , public CSSPropertyBlendingClient {
     friend class CompositeAnimation;
@@ -122,7 +128,13 @@
     bool active() const { return !postActive() && !preActive(); }
     bool running() const { return !isNew() && !postActive(); }
     bool paused() const { return m_pauseTime || m_animationState == AnimationState::PausedNew; }
-    bool inPausedState() const { return m_animationState >= AnimationState::PausedNew && m_animationState <= AnimationState::PausedRun; }
+
+    static bool isPausedState(AnimationState state) { return state >= AnimationState::PausedNew && state <= AnimationState::PausedRun; }
+    static bool isRunningState(AnimationState state) { return state >= AnimationState::StartWaitStyleAvailable && state < AnimationState::Done; }
+
+    bool inPausedState() const { return isPausedState(m_animationState); }
+    bool inRunningState() const { return isRunningState(m_animationState); }
+
     bool isNew() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::PausedNew; }
     bool waitingForStartTime() const { return m_animationState == AnimationState::StartWaitResponse; }
     bool waitingForStyleAvailable() const { return m_animationState == AnimationState::StartWaitStyleAvailable; }
@@ -163,13 +175,7 @@
         if (!affectsProperty(property))
             return false;
 
-        if (inPausedState())
-            return true;
-
-        if (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState < AnimationState::Done)
-            return true;
-
-        return false;
+        return inRunningState() || inPausedState();
     }
 
     bool transformFunctionListsMatch() const override { return m_transformFunctionListsMatch; }

Modified: trunk/Source/WebCore/page/animation/CSSAnimationController.h (240011 => 240012)


--- trunk/Source/WebCore/page/animation/CSSAnimationController.h	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/CSSAnimationController.h	2019-01-15 23:06:11 UTC (rev 240012)
@@ -44,7 +44,7 @@
 
 struct AnimationUpdate {
     std::unique_ptr<RenderStyle> style;
-    bool stateChanged { false };
+    bool animationChangeRequiresRecomposite { false };
 };
 
 class CSSAnimationController {

Modified: trunk/Source/WebCore/page/animation/CompositeAnimation.cpp (240011 => 240012)


--- trunk/Source/WebCore/page/animation/CompositeAnimation.cpp	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/CompositeAnimation.cpp	2019-01-15 23:06:11 UTC (rev 240012)
@@ -286,7 +286,7 @@
     updateKeyframeAnimations(element, currentStyle, targetStyle);
     m_keyframeAnimations.checkConsistency();
 
-    bool animationStateChanged = false;
+    bool animationChangeRequiresRecomposite = false;
     bool forceStackingContext = false;
 
     std::unique_ptr<RenderStyle> animatedStyle;
@@ -296,12 +296,11 @@
         // to fill in a RenderStyle*& only if needed.
         bool checkForStackingContext = false;
         for (auto& transition : m_transitions.values()) {
-            bool didBlendStyle = false;
-            if (transition->animate(*this, targetStyle, animatedStyle, didBlendStyle))
-                animationStateChanged = true;
+            auto changes = transition->animate(*this, targetStyle, animatedStyle);
+            if (changes.contains(AnimateChange::StyleBlended))
+                checkForStackingContext |= WillChangeData::propertyCreatesStackingContext(transition->animatingProperty());
 
-            if (didBlendStyle)
-                checkForStackingContext |= WillChangeData::propertyCreatesStackingContext(transition->animatingProperty());
+            animationChangeRequiresRecomposite = changes.contains(AnimateChange::RunningStateChange) && transition->affectsAcceleratedProperty();
         }
 
         if (animatedStyle && checkForStackingContext) {
@@ -326,11 +325,9 @@
     for (auto& name : m_keyframeAnimationOrderMap) {
         RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(name);
         if (keyframeAnim) {
-            bool didBlendStyle = false;
-            if (keyframeAnim->animate(*this, targetStyle, animatedStyle, didBlendStyle))
-                animationStateChanged = true;
-
-            forceStackingContext |= didBlendStyle && keyframeAnim->triggersStackingContext();
+            auto changes = keyframeAnim->animate(*this, targetStyle, animatedStyle);
+            animationChangeRequiresRecomposite = changes.contains(AnimateChange::RunningStateChange) && keyframeAnim->affectsAcceleratedProperty();
+            forceStackingContext |= changes.contains(AnimateChange::StyleBlended) && keyframeAnim->triggersStackingContext();
             m_hasAnimationThatDependsOnLayout |= keyframeAnim->dependsOnLayout();
         }
     }
@@ -344,7 +341,7 @@
             animatedStyle->setZIndex(0);
     }
 
-    return { WTFMove(animatedStyle), animationStateChanged };
+    return { WTFMove(animatedStyle), animationChangeRequiresRecomposite };
 }
 
 std::unique_ptr<RenderStyle> CompositeAnimation::getAnimatedStyle() const

Modified: trunk/Source/WebCore/page/animation/ImplicitAnimation.cpp (240011 => 240012)


--- trunk/Source/WebCore/page/animation/ImplicitAnimation.cpp	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/ImplicitAnimation.cpp	2019-01-15 23:06:11 UTC (rev 240012)
@@ -61,12 +61,12 @@
     return element()->document().hasListenerType(inListenerType);
 }
 
-bool ImplicitAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle)
+OptionSet<AnimateChange> ImplicitAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle)
 {
     // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
     // So just return. Everything is already all cleaned up.
     if (postActive())
-        return false;
+        return { };
 
     AnimationState oldState = state();
 
@@ -85,9 +85,15 @@
 
     // Fire the start timeout if needed
     fireAnimationEventsIfNeeded();
-    
-    didBlendStyle = true;
-    return state() != oldState;
+
+    OptionSet<AnimateChange> change(AnimateChange::StyleBlended);
+    if (state() != oldState)
+        change.add(AnimateChange::StateChange);
+
+    if ((isPausedState(oldState) || isRunningState(oldState)) != (isPausedState(state()) || isRunningState(state())))
+        change.add(AnimateChange::RunningStateChange);
+
+    return change;
 }
 
 void ImplicitAnimation::getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle)
@@ -131,6 +137,11 @@
     return true;
 }
 
+bool ImplicitAnimation::affectsAcceleratedProperty() const
+{
+    return CSSPropertyAnimation::animationOfPropertyIsAccelerated(m_animatingProperty);
+}
+
 bool ImplicitAnimation::startAnimation(double timeOffset)
 {
     if (auto* renderer = compositedRenderer())

Modified: trunk/Source/WebCore/page/animation/ImplicitAnimation.h (240011 => 240012)


--- trunk/Source/WebCore/page/animation/ImplicitAnimation.h	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/ImplicitAnimation.h	2019-01-15 23:06:11 UTC (rev 240012)
@@ -53,12 +53,14 @@
     void pauseAnimation(double timeOffset) override;
     void endAnimation(bool fillingForwards = false) override;
 
-    bool animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle);
+    OptionSet<AnimateChange> animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle);
     void getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle) override;
     void reset(const RenderStyle& to, CompositeAnimation&);
 
     bool computeExtentOfTransformAnimation(LayoutRect&) const override;
 
+    bool affectsAcceleratedProperty() const;
+
     void setOverridden(bool);
     bool overridden() const override { return m_overridden; }
 

Modified: trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp (240011 => 240012)


--- trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp	2019-01-15 23:06:11 UTC (rev 240012)
@@ -60,7 +60,17 @@
 #endif
     checkForMatchingColorFilterFunctionLists();
 
-    computeStackingContextImpact();
+    for (auto propertyID : m_keyframes.properties()) {
+        if (WillChangeData::propertyCreatesStackingContext(propertyID))
+            m_triggersStackingContext = true;
+        
+        if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(propertyID))
+            m_hasAcceleratedProperty = true;
+        
+        if (m_triggersStackingContext && m_hasAcceleratedProperty)
+            break;
+    }
+
     computeLayoutDependency();
 }
 
@@ -71,16 +81,6 @@
         endAnimation();
 }
 
-void KeyframeAnimation::computeStackingContextImpact()
-{
-    for (auto propertyID : m_keyframes.properties()) {
-        if (WillChangeData::propertyCreatesStackingContext(propertyID)) {
-            m_triggersStackingContext = true;
-            break;
-        }
-    }
-}
-
 void KeyframeAnimation::computeLayoutDependency()
 {
     if (!m_keyframes.containsProperty(CSSPropertyTransform))
@@ -156,7 +156,7 @@
     prog = progress(scale, offset, prevKeyframe.timingFunction());
 }
 
-bool KeyframeAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle)
+OptionSet<AnimateChange> KeyframeAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle)
 {
     AnimationState oldState = state();
 
@@ -171,12 +171,12 @@
             updateStateMachine(AnimationStateInput::PlayStatePaused, -1);
     }
 
-    // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
+    // If we get this far and the animation is done, it means we are cleaning up a just-finished animation.
     // If so, we need to send back the targetStyle.
     if (postActive()) {
         if (!animatedStyle)
             animatedStyle = RenderStyle::clonePtr(targetStyle);
-        return false;
+        return { };
     }
 
     // If we are waiting for the start timer, we don't want to change the style yet.
@@ -185,12 +185,12 @@
     // Special case 2 - if there is a backwards fill mode, then we want to continue
     // through to the style blend so that we get the fromStyle.
     if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards())
-        return false;
+        return { };
     
     // If we have no keyframes, don't animate.
     if (!m_keyframes.size()) {
         updateStateMachine(AnimationStateInput::EndAnimation, -1);
-        return false;
+        return { };
     }
 
     // Run a cycle of animation.
@@ -209,9 +209,15 @@
 
         CSSPropertyAnimation::blendProperties(this, propertyID, animatedStyle.get(), fromStyle, toStyle, progress);
     }
-    
-    didBlendStyle = true;
-    return state() != oldState;
+
+    OptionSet<AnimateChange> change(AnimateChange::StyleBlended);
+    if (state() != oldState)
+        change.add(AnimateChange::StateChange);
+
+    if ((isPausedState(oldState) || isRunningState(oldState)) != (isPausedState(state()) || isRunningState(state())))
+        change.add(AnimateChange::RunningStateChange);
+
+    return change;
 }
 
 void KeyframeAnimation::getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle)

Modified: trunk/Source/WebCore/page/animation/KeyframeAnimation.h (240011 => 240012)


--- trunk/Source/WebCore/page/animation/KeyframeAnimation.h	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/page/animation/KeyframeAnimation.h	2019-01-15 23:06:11 UTC (rev 240012)
@@ -44,8 +44,8 @@
     {
         return adoptRef(*new KeyframeAnimation(animation, element, compositeAnimation, unanimatedStyle));
     }
-
-    bool animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle);
+    
+    OptionSet<AnimateChange> animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle);
     void getAnimatedStyle(std::unique_ptr<RenderStyle>&) override;
 
     bool computeExtentOfTransformAnimation(LayoutRect&) const override;
@@ -58,6 +58,7 @@
 
     bool triggersStackingContext() const { return m_triggersStackingContext; }
     bool dependsOnLayout() const { return m_dependsOnLayout; }
+    bool affectsAcceleratedProperty() const { return m_hasAcceleratedProperty; }
 
     void setUnanimatedStyle(std::unique_ptr<RenderStyle> style) { m_unanimatedStyle = WTFMove(style); }
     const RenderStyle& unanimatedStyle() const override { return *m_unanimatedStyle; }
@@ -84,7 +85,6 @@
 
     bool computeExtentOfAnimationForMatchingTransformLists(const FloatRect& rendererBox, LayoutRect&) const;
 
-    void computeStackingContextImpact();
     void computeLayoutDependency();
     void resolveKeyframeStyles();
     void validateTransformFunctionList();
@@ -107,6 +107,7 @@
 
     bool m_startEventDispatched { false };
     bool m_triggersStackingContext { false };
+    bool m_hasAcceleratedProperty { false };
     bool m_dependsOnLayout { false };
 };
 

Modified: trunk/Source/WebCore/style/StyleTreeResolver.cpp (240011 => 240012)


--- trunk/Source/WebCore/style/StyleTreeResolver.cpp	2019-01-15 22:57:27 UTC (rev 240011)
+++ trunk/Source/WebCore/style/StyleTreeResolver.cpp	2019-01-15 23:06:11 UTC (rev 240012)
@@ -306,7 +306,7 @@
         auto& animationController = m_document.frame()->animation();
 
         auto animationUpdate = animationController.updateAnimations(element, *newStyle, oldStyle);
-        shouldRecompositeLayer = animationUpdate.stateChanged; // FIXME: constrain this to just property animations triggering acceleration.
+        shouldRecompositeLayer = animationUpdate.animationChangeRequiresRecomposite;
 
         if (animationUpdate.style)
             newStyle = WTFMove(animationUpdate.style);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to