Title: [251706] trunk/Source/WebCore
Revision
251706
Author
grao...@webkit.org
Date
2019-10-29 09:14:58 -0700 (Tue, 29 Oct 2019)

Log Message

[Web Animations] Optimize blending for CSS Transitions
https://bugs.webkit.org/show_bug.cgi?id=203561

Reviewed by Simon Fraser.

The work performed in KeyframeEffect::setAnimatedPropertiesInStyle() has a level of complexity warranted by the
flexibility of how keyframes can be specified via the Web Animations JS API. However, in the case of CSS Transitions,
we already know that there are only two keyframes, one where offset=0 and one where offset=1, and that only a single
CSS property is specified so we can simplify the process greatly.

To ensure we only perform this quicker blending operation for keyframes computed for a CSS Transition and that no
modification to the keyframes have been applied via the Web Animations JS API after the fact, we now keep track
of whether the blending keyframes (KeyframeList) were generated for a CSS Transition or a CSS Animation and only
use this information to decide whether we're blending for declarative animations.

* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::processKeyframes):
(WebCore::KeyframeEffect::clearBlendingKeyframes):
(WebCore::KeyframeEffect::computeCSSAnimationBlendingKeyframes):
(WebCore::KeyframeEffect::computeCSSTransitionBlendingKeyframes):
(WebCore::KeyframeEffect::setTarget):
(WebCore::KeyframeEffect::setAnimatedPropertiesInStyle):
* animation/KeyframeEffect.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (251705 => 251706)


--- trunk/Source/WebCore/ChangeLog	2019-10-29 16:09:10 UTC (rev 251705)
+++ trunk/Source/WebCore/ChangeLog	2019-10-29 16:14:58 UTC (rev 251706)
@@ -1,3 +1,29 @@
+2019-10-29  Antoine Quint  <grao...@apple.com>
+
+        [Web Animations] Optimize blending for CSS Transitions
+        https://bugs.webkit.org/show_bug.cgi?id=203561
+
+        Reviewed by Simon Fraser.
+
+        The work performed in KeyframeEffect::setAnimatedPropertiesInStyle() has a level of complexity warranted by the
+        flexibility of how keyframes can be specified via the Web Animations JS API. However, in the case of CSS Transitions,
+        we already know that there are only two keyframes, one where offset=0 and one where offset=1, and that only a single
+        CSS property is specified so we can simplify the process greatly.
+
+        To ensure we only perform this quicker blending operation for keyframes computed for a CSS Transition and that no
+        modification to the keyframes have been applied via the Web Animations JS API after the fact, we now keep track
+        of whether the blending keyframes (KeyframeList) were generated for a CSS Transition or a CSS Animation and only
+        use this information to decide whether we're blending for declarative animations.
+
+        * animation/KeyframeEffect.cpp:
+        (WebCore::KeyframeEffect::processKeyframes):
+        (WebCore::KeyframeEffect::clearBlendingKeyframes):
+        (WebCore::KeyframeEffect::computeCSSAnimationBlendingKeyframes):
+        (WebCore::KeyframeEffect::computeCSSTransitionBlendingKeyframes):
+        (WebCore::KeyframeEffect::setTarget):
+        (WebCore::KeyframeEffect::setAnimatedPropertiesInStyle):
+        * animation/KeyframeEffect.h:
+
 2019-10-29  Adrian Perez de Castro  <ape...@igalia.com>
 
         [GTK][WPE] Fix non-unified build after r251691

Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (251705 => 251706)


--- trunk/Source/WebCore/animation/KeyframeEffect.cpp	2019-10-29 16:09:10 UTC (rev 251705)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp	2019-10-29 16:14:58 UTC (rev 251706)
@@ -726,7 +726,7 @@
 
     m_parsedKeyframes = WTFMove(parsedKeyframes);
 
-    m_blendingKeyframes.clear();
+    clearBlendingKeyframes();
 
     return { };
 }
@@ -772,6 +772,13 @@
     return true;
 }
 
+
+void KeyframeEffect::clearBlendingKeyframes()
+{
+    m_blendingKeyframesSource = BlendingKeyframesSource::WebAnimation;
+    m_blendingKeyframes.clear();
+}
+
 void KeyframeEffect::setBlendingKeyframes(KeyframeList& blendingKeyframes)
 {
     m_blendingKeyframes = WTFMove(blendingKeyframes);
@@ -909,6 +916,7 @@
             Style::loadPendingResources(*style, m_target->document(), m_target.get());
     }
 
+    m_blendingKeyframesSource = BlendingKeyframesSource::CSSAnimation;
     setBlendingKeyframes(keyframeList);
 }
 
@@ -936,6 +944,7 @@
     toKeyframeValue.addProperty(property);
     keyframeList.insert(WTFMove(toKeyframeValue));
 
+    m_blendingKeyframesSource = BlendingKeyframesSource::CSSTransition;
     setBlendingKeyframes(keyframeList);
 }
 
@@ -988,7 +997,7 @@
     if (auto* effectAnimation = animation())
         effectAnimation->effectTargetDidChange(previousTarget.get(), m_target.get());
 
-    m_blendingKeyframes.clear();
+    clearBlendingKeyframes();
 
     // We need to invalidate the effect now that the target has changed
     // to ensure the effect's styles are applied to the new target right away.
@@ -1054,6 +1063,15 @@
 
 void KeyframeEffect::setAnimatedPropertiesInStyle(RenderStyle& targetStyle, double iterationProgress)
 {
+    // In the case of CSS Transitions we already know that there are only two keyframes, one where offset=0 and one where offset=1,
+    // and only a single CSS property so we can simply blend based on the style available on those keyframes with the provided iteration
+    // progress which already accounts for the transition's timing function.
+    if (m_blendingKeyframesSource == BlendingKeyframesSource::CSSTransition) {
+        ASSERT(is<CSSTransition>(animation()));
+        CSSPropertyAnimation::blendProperties(this, downcast<CSSTransition>(animation())->property(), &targetStyle, m_blendingKeyframes[0].style(), m_blendingKeyframes[1].style(), iterationProgress);
+        return;
+    }
+
     // 4.4.3. The effect value of a keyframe effect
     // https://drafts.csswg.org/web-animations-1/#the-effect-value-of-a-keyframe-animation-effect
     //
@@ -1064,9 +1082,6 @@
     if (m_blendingKeyframes.isEmpty())
         return;
 
-    bool isCSSAnimation = is<CSSAnimation>(animation());
-    bool isCSSTransition = is<CSSTransition>(animation());
-
     for (auto cssPropertyId : m_blendingKeyframes.properties()) {
         // 1. If iteration progress is unresolved abort this procedure.
         // 2. Let target property be the longhand property for which the effect value is to be calculated.
@@ -1085,7 +1100,7 @@
             if (!keyframe.containsProperty(cssPropertyId)) {
                 // If we're dealing with a CSS animation, we consider the first and last keyframes to always have the property listed
                 // since the underlying style was provided and should be captured.
-                if (!isCSSAnimation || (offset && offset < 1))
+                if (m_blendingKeyframesSource == BlendingKeyframesSource::WebAnimation || (offset && offset < 1))
                     continue;
             }
             if (!offset)
@@ -1184,10 +1199,8 @@
 
         // 17. Let transformed distance be the result of evaluating the timing function associated with the first keyframe in interval endpoints
         //     passing interval distance as the input progress.
-        // We do not need to do this for CSS Transitions since the timing function is applied to the AnimationEffect as a whole and thus
-        // iterationProgress is already transformed.
         auto transformedDistance = intervalDistance;
-        if (!isCSSTransition && startKeyframeIndex) {
+        if (startKeyframeIndex) {
             if (auto duration = iterationDuration()) {
                 auto rangeDuration = (endOffset - startOffset) * duration.seconds();
                 if (auto* timingFunction = timingFunctionForKeyframeAtIndex(startKeyframeIndex.value()))

Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (251705 => 251706)


--- trunk/Source/WebCore/animation/KeyframeEffect.h	2019-10-29 16:09:10 UTC (rev 251705)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h	2019-10-29 16:14:58 UTC (rev 251706)
@@ -141,6 +141,7 @@
     KeyframeEffect(Element*);
 
     enum class AcceleratedAction : uint8_t { Play, Pause, Seek, Stop };
+    enum class BlendingKeyframesSource : uint8_t { CSSAnimation, CSSTransition, WebAnimation };
 
     void copyPropertiesFromSource(Ref<KeyframeEffect>&&);
     ExceptionOr<void> processKeyframes(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&);
@@ -151,6 +152,7 @@
     Ref<const Animation> backingAnimationForCompositedRenderer() const;
     void computedNeedsForcedLayout();
     void computeStackingContextImpact();
+    void clearBlendingKeyframes();
     void updateBlendingKeyframes(RenderStyle&);
     void computeCSSAnimationBlendingKeyframes();
     void computeCSSTransitionBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle);
@@ -170,6 +172,7 @@
     RefPtr<Element> m_target;
 
     AcceleratedAction m_lastRecordedAcceleratedAction { AcceleratedAction::Stop };
+    BlendingKeyframesSource m_blendingKeyframesSource { BlendingKeyframesSource::WebAnimation };
     IterationCompositeOperation m_iterationCompositeOperation { IterationCompositeOperation::Replace };
     CompositeOperation m_compositeOperation { CompositeOperation::Replace };
     bool m_shouldRunAccelerated { false };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to