Changeset 240012 in webkit


Ignore:
Timestamp:
Jan 15, 2019 3:06:11 PM (5 years ago)
Author:
Simon Fraser
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):

Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r240011 r240012  
     12019-01-15  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Animations should only trigger layer recomposite when necessary
     4        https://bugs.webkit.org/show_bug.cgi?id=193450
     5
     6        Reviewed by Antoine Quint.
     7
     8        Animations only need to trigger compositing updates when their states change in a way
     9        that affects compositing. RenderLayerCompositor::requiresCompositingForAnimation() checks for
     10        running animations of properties that can be accelerated, so this patch fixes the legacy
     11        animation logic to only set 'shouldRecompositeLayer' in TreeResolver::createAnimatedElementUpdate()
     12        when the running state of such an animation changes.
     13
     14        ImplicitAnimation::animate() and KeyframeAnimation::animate() now return OptionSet<AnimateChange>.
     15        This contains information about whether the running state changed, so CompositeAnimation::animate()
     16        asks about whether the running state of an accelerated property changed, and returns this in
     17        the AnimationUpdate result.
     18
     19        * page/animation/AnimationBase.h:
     20        (WebCore::AnimationBase::isPausedState):
     21        (WebCore::AnimationBase::isRunningState):
     22        (WebCore::AnimationBase::inPausedState const):
     23        (WebCore::AnimationBase::inRunningState const):
     24        (WebCore::AnimationBase::isAnimatingProperty const):
     25        * page/animation/CSSAnimationController.h:
     26        * page/animation/CompositeAnimation.cpp:
     27        (WebCore::CompositeAnimation::animate):
     28        * page/animation/ImplicitAnimation.cpp:
     29        (WebCore::ImplicitAnimation::animate):
     30        (WebCore::ImplicitAnimation::affectsAcceleratedProperty const):
     31        * page/animation/ImplicitAnimation.h:
     32        * page/animation/KeyframeAnimation.cpp:
     33        (WebCore::KeyframeAnimation::KeyframeAnimation):
     34        (WebCore::KeyframeAnimation::animate):
     35        (WebCore::KeyframeAnimation::computeStackingContextImpact): Deleted.
     36        * page/animation/KeyframeAnimation.h:
     37        * style/StyleTreeResolver.cpp:
     38        (WebCore::Style::TreeResolver::createAnimatedElementUpdate):
     39
    1402019-01-15  Simon Fraser  <simon.fraser@apple.com>
    241
  • trunk/Source/WebCore/page/animation/AnimationBase.h

    r239985 r240012  
    4545class TimingFunction;
    4646
     47enum class AnimateChange {
     48    StyleBlended            = 1 << 0, // Style was changed.
     49    StateChange             = 1 << 1, // Animation state() changed.
     50    RunningStateChange      = 1 << 2, // Animation "running or paused" changed.
     51};
     52
    4753class AnimationBase : public RefCounted<AnimationBase>
    4854    , public CSSPropertyBlendingClient {
     
    123129    bool running() const { return !isNew() && !postActive(); }
    124130    bool paused() const { return m_pauseTime || m_animationState == AnimationState::PausedNew; }
    125     bool inPausedState() const { return m_animationState >= AnimationState::PausedNew && m_animationState <= AnimationState::PausedRun; }
     131
     132    static bool isPausedState(AnimationState state) { return state >= AnimationState::PausedNew && state <= AnimationState::PausedRun; }
     133    static bool isRunningState(AnimationState state) { return state >= AnimationState::StartWaitStyleAvailable && state < AnimationState::Done; }
     134
     135    bool inPausedState() const { return isPausedState(m_animationState); }
     136    bool inRunningState() const { return isRunningState(m_animationState); }
     137
    126138    bool isNew() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::PausedNew; }
    127139    bool waitingForStartTime() const { return m_animationState == AnimationState::StartWaitResponse; }
     
    164176            return false;
    165177
    166         if (inPausedState())
    167             return true;
    168 
    169         if (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState < AnimationState::Done)
    170             return true;
    171 
    172         return false;
     178        return inRunningState() || inPausedState();
    173179    }
    174180
  • trunk/Source/WebCore/page/animation/CSSAnimationController.h

    r239985 r240012  
    4545struct AnimationUpdate {
    4646    std::unique_ptr<RenderStyle> style;
    47     bool stateChanged { false };
     47    bool animationChangeRequiresRecomposite { false };
    4848};
    4949
  • trunk/Source/WebCore/page/animation/CompositeAnimation.cpp

    r239985 r240012  
    287287    m_keyframeAnimations.checkConsistency();
    288288
    289     bool animationStateChanged = false;
     289    bool animationChangeRequiresRecomposite = false;
    290290    bool forceStackingContext = false;
    291291
     
    297297        bool checkForStackingContext = false;
    298298        for (auto& transition : m_transitions.values()) {
    299             bool didBlendStyle = false;
    300             if (transition->animate(*this, targetStyle, animatedStyle, didBlendStyle))
    301                 animationStateChanged = true;
    302 
    303             if (didBlendStyle)
     299            auto changes = transition->animate(*this, targetStyle, animatedStyle);
     300            if (changes.contains(AnimateChange::StyleBlended))
    304301                checkForStackingContext |= WillChangeData::propertyCreatesStackingContext(transition->animatingProperty());
     302
     303            animationChangeRequiresRecomposite = changes.contains(AnimateChange::RunningStateChange) && transition->affectsAcceleratedProperty();
    305304        }
    306305
     
    327326        RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(name);
    328327        if (keyframeAnim) {
    329             bool didBlendStyle = false;
    330             if (keyframeAnim->animate(*this, targetStyle, animatedStyle, didBlendStyle))
    331                 animationStateChanged = true;
    332 
    333             forceStackingContext |= didBlendStyle && keyframeAnim->triggersStackingContext();
     328            auto changes = keyframeAnim->animate(*this, targetStyle, animatedStyle);
     329            animationChangeRequiresRecomposite = changes.contains(AnimateChange::RunningStateChange) && keyframeAnim->affectsAcceleratedProperty();
     330            forceStackingContext |= changes.contains(AnimateChange::StyleBlended) && keyframeAnim->triggersStackingContext();
    334331            m_hasAnimationThatDependsOnLayout |= keyframeAnim->dependsOnLayout();
    335332        }
     
    345342    }
    346343
    347     return { WTFMove(animatedStyle), animationStateChanged };
     344    return { WTFMove(animatedStyle), animationChangeRequiresRecomposite };
    348345}
    349346
  • trunk/Source/WebCore/page/animation/ImplicitAnimation.cpp

    r239427 r240012  
    6262}
    6363
    64 bool ImplicitAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle)
     64OptionSet<AnimateChange> ImplicitAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle)
    6565{
    6666    // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
    6767    // So just return. Everything is already all cleaned up.
    6868    if (postActive())
    69         return false;
     69        return { };
    7070
    7171    AnimationState oldState = state();
     
    8686    // Fire the start timeout if needed
    8787    fireAnimationEventsIfNeeded();
    88    
    89     didBlendStyle = true;
    90     return state() != oldState;
     88
     89    OptionSet<AnimateChange> change(AnimateChange::StyleBlended);
     90    if (state() != oldState)
     91        change.add(AnimateChange::StateChange);
     92
     93    if ((isPausedState(oldState) || isRunningState(oldState)) != (isPausedState(state()) || isRunningState(state())))
     94        change.add(AnimateChange::RunningStateChange);
     95
     96    return change;
    9197}
    9298
     
    130136    bounds = unionRect(startBounds, endBounds);
    131137    return true;
     138}
     139
     140bool ImplicitAnimation::affectsAcceleratedProperty() const
     141{
     142    return CSSPropertyAnimation::animationOfPropertyIsAccelerated(m_animatingProperty);
    132143}
    133144
  • trunk/Source/WebCore/page/animation/ImplicitAnimation.h

    r239427 r240012  
    5454    void endAnimation(bool fillingForwards = false) override;
    5555
    56     bool animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle);
     56    OptionSet<AnimateChange> animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle);
    5757    void getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle) override;
    5858    void reset(const RenderStyle& to, CompositeAnimation&);
    5959
    6060    bool computeExtentOfTransformAnimation(LayoutRect&) const override;
     61
     62    bool affectsAcceleratedProperty() const;
    6163
    6264    void setOverridden(bool);
  • trunk/Source/WebCore/page/animation/KeyframeAnimation.cpp

    r239965 r240012  
    6161    checkForMatchingColorFilterFunctionLists();
    6262
    63     computeStackingContextImpact();
     63    for (auto propertyID : m_keyframes.properties()) {
     64        if (WillChangeData::propertyCreatesStackingContext(propertyID))
     65            m_triggersStackingContext = true;
     66       
     67        if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(propertyID))
     68            m_hasAcceleratedProperty = true;
     69       
     70        if (m_triggersStackingContext && m_hasAcceleratedProperty)
     71            break;
     72    }
     73
    6474    computeLayoutDependency();
    6575}
     
    7080    if (!postActive())
    7181        endAnimation();
    72 }
    73 
    74 void KeyframeAnimation::computeStackingContextImpact()
    75 {
    76     for (auto propertyID : m_keyframes.properties()) {
    77         if (WillChangeData::propertyCreatesStackingContext(propertyID)) {
    78             m_triggersStackingContext = true;
    79             break;
    80         }
    81     }
    8282}
    8383
     
    157157}
    158158
    159 bool KeyframeAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle)
     159OptionSet<AnimateChange> KeyframeAnimation::animate(CompositeAnimation& compositeAnimation, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle)
    160160{
    161161    AnimationState oldState = state();
     
    172172    }
    173173
    174     // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
     174    // If we get this far and the animation is done, it means we are cleaning up a just-finished animation.
    175175    // If so, we need to send back the targetStyle.
    176176    if (postActive()) {
    177177        if (!animatedStyle)
    178178            animatedStyle = RenderStyle::clonePtr(targetStyle);
    179         return false;
     179        return { };
    180180    }
    181181
     
    186186    // through to the style blend so that we get the fromStyle.
    187187    if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards())
    188         return false;
     188        return { };
    189189   
    190190    // If we have no keyframes, don't animate.
    191191    if (!m_keyframes.size()) {
    192192        updateStateMachine(AnimationStateInput::EndAnimation, -1);
    193         return false;
     193        return { };
    194194    }
    195195
     
    210210        CSSPropertyAnimation::blendProperties(this, propertyID, animatedStyle.get(), fromStyle, toStyle, progress);
    211211    }
    212    
    213     didBlendStyle = true;
    214     return state() != oldState;
     212
     213    OptionSet<AnimateChange> change(AnimateChange::StyleBlended);
     214    if (state() != oldState)
     215        change.add(AnimateChange::StateChange);
     216
     217    if ((isPausedState(oldState) || isRunningState(oldState)) != (isPausedState(state()) || isRunningState(state())))
     218        change.add(AnimateChange::RunningStateChange);
     219
     220    return change;
    215221}
    216222
  • trunk/Source/WebCore/page/animation/KeyframeAnimation.h

    r239427 r240012  
    4545        return adoptRef(*new KeyframeAnimation(animation, element, compositeAnimation, unanimatedStyle));
    4646    }
    47 
    48     bool animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle, bool& didBlendStyle);
     47   
     48    OptionSet<AnimateChange> animate(CompositeAnimation&, const RenderStyle& targetStyle, std::unique_ptr<RenderStyle>& animatedStyle);
    4949    void getAnimatedStyle(std::unique_ptr<RenderStyle>&) override;
    5050
     
    5959    bool triggersStackingContext() const { return m_triggersStackingContext; }
    6060    bool dependsOnLayout() const { return m_dependsOnLayout; }
     61    bool affectsAcceleratedProperty() const { return m_hasAcceleratedProperty; }
    6162
    6263    void setUnanimatedStyle(std::unique_ptr<RenderStyle> style) { m_unanimatedStyle = WTFMove(style); }
     
    8586    bool computeExtentOfAnimationForMatchingTransformLists(const FloatRect& rendererBox, LayoutRect&) const;
    8687
    87     void computeStackingContextImpact();
    8888    void computeLayoutDependency();
    8989    void resolveKeyframeStyles();
     
    108108    bool m_startEventDispatched { false };
    109109    bool m_triggersStackingContext { false };
     110    bool m_hasAcceleratedProperty { false };
    110111    bool m_dependsOnLayout { false };
    111112};
  • trunk/Source/WebCore/style/StyleTreeResolver.cpp

    r239965 r240012  
    307307
    308308        auto animationUpdate = animationController.updateAnimations(element, *newStyle, oldStyle);
    309         shouldRecompositeLayer = animationUpdate.stateChanged; // FIXME: constrain this to just property animations triggering acceleration.
     309        shouldRecompositeLayer = animationUpdate.animationChangeRequiresRecomposite;
    310310
    311311        if (animationUpdate.style)
Note: See TracChangeset for help on using the changeset viewer.