⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 272004 in webkit


Ignore:
Timestamp:
Jan 27, 2021, 10:54:42 PM (6 years ago)
Author:
graouts@webkit.org
Message:

REGRESSION(r268615): images flicker on apple.com/ios/ios-14
​https://bugs.webkit.org/show_bug.cgi?id=221054
<rdar://problem/72880447>

Reviewed by Dean Jackson.

Source/WebCore:

When we added support for accelerated animations of individual transform properties in r268615 (bug 217842),
we made it so that base values of each transform-related property had a non-interpolating animation in the
Core Animation animations list that would combine with interpolating animations for that property as additive
animations. Prior to any of those animations, we'd reset the combined transform with an identity transform
as another non-interpolating animation.

However, we neglected to consider the case where one of the interpolating animations would not start right
away if a positive delay was set. In the case of this apple.com page, the target element would be composited
due to a "will-change: transform" style, and a non-animated "transform" was set as well as an animation for
the "transform" property with a delay.

Since we had a "transform" animation, we'd create a Core Animation animations lists as follows:

  1. non-interpolating, non-additive animation set to the identity matrix
  2. interpolating, additive animation with the keyframes set in the CSS animation, with a begin time set to the current time plus the specified delay

The result of this was that during the animation delay, the static "transform" property was overridden
by animation #1 until animation #2 would kick in.

We now make it so that for each transform-related property, we create a non-interpoloating, additive animation
to represent the static value for that property for the duration of any potential delay until the first
interpolating animation for this property starts.

In this example, the Core Animation animations list is now as follows:

  1. non-interpolating, non-additive animation set to the identity matrix
  2. non-interpolating, additive animation set to the static transform value
  3. interpolating, additive animation with the keyframes set in the CSS animation, with a begin time set to the current time plus the specified delay

We implement this with a new lambda function within GraphicsLayerCA::updateAnimations() called
addAnimationsForProperty() which adds a non-interpolating animation in two cases:

  1. if there is no animation for this property at all, making it last forever
  2. if all animations have a delay, making it last until the first animation starts

Tests: webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html

webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html
webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html
webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html
webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::updateAnimations):

LayoutTests:

Add a series of tests ensuring that starting an animation for transform-related properties does not clobber the static
value for this property. We only run those tests on WK2 because running those in WK1 is flaky as there doesn't seem
to be a solid test utility to determine that Core Animation animations have been committed, even with long delays
that would make tests run slow.

  • TestExpectations:
  • platform/ios-wk2/TestExpectations:
  • platform/mac-wk2/TestExpectations:
  • webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer-expected.html: Added.
  • webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html: Added.
  • webanimations/resources/wait-until-animations-are-committed.js: Added.
  • webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer-expected.html: Added.
  • webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html: Added.
  • webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer-expected.html: Added.
  • webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html: Added.
  • webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer-expected.html: Added.
  • webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html: Added.
  • webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer-expected.html: Added.
  • webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html: Added.
Location:
trunk
Files:
11 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r271992 r272004  
     12021-01-27  Antoine Quint  <graouts@webkit.org>
     2
     3        REGRESSION(r268615): images flicker on apple.com/ios/ios-14
     4        https://bugs.webkit.org/show_bug.cgi?id=221054
     5        <rdar://problem/72880447>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Add a series of tests ensuring that starting an animation for transform-related properties does not clobber the static
     10        value for this property. We only run those tests on WK2 because running those in WK1 is flaky as there doesn't seem
     11        to be a solid test utility to determine that Core Animation animations have been committed, even with long delays
     12        that would make tests run slow.
     13
     14        * TestExpectations:
     15        * platform/ios-wk2/TestExpectations:
     16        * platform/mac-wk2/TestExpectations:
     17        * webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer-expected.html: Added.
     18        * webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html: Added.
     19        * webanimations/resources/wait-until-animations-are-committed.js: Added.
     20        * webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer-expected.html: Added.
     21        * webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html: Added.
     22        * webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer-expected.html: Added.
     23        * webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html: Added.
     24        * webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer-expected.html: Added.
     25        * webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html: Added.
     26        * webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer-expected.html: Added.
     27        * webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html: Added.
     28
    1292021-01-27  Sam Weinig  <weinig@apple.com>
    230
  • trunk/LayoutTests/TestExpectations

    r271992 r272004  
    45964596webkit.org/b/220325 http/wpt/css/css-highlight-api/highlight-text-cascade.html [ ImageOnlyFailure ]
    45974597
     4598# These are only enabled on Cocoa WK2 ports
     4599webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html [ Skip ]
     4600webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html [ Skip ]
     4601webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html [ Skip ]
     4602webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html [ Skip ]
     4603webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html [ Skip ]
     4604
    45984605# Unsupported css color() variants
    45994606webkit.org/b/220928 imported/w3c/web-platform-tests/css/css-color/predefined-003.html [ ImageOnlyFailure ] # Invalid test, no colorspace specified
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r271788 r272004  
    18971897
    18981898webkit.org/b/219438 [ Release ] ast/canvas/canvas-overflow-hidden-animation.html [ Pass ImageOnlyFailure ]
     1899
     1900webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html [ Pass ]
     1901webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html [ Pass ]
     1902webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html [ Pass ]
     1903webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html [ Pass ]
     1904webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html [ Pass ]
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r271878 r272004  
    13231323webkit.org/b/219516 http/wpt/service-workers/service-worker-spinning-install.https.html [ Pass Failure ]
    13241324
     1325webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html [ Pass ]
     1326webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html [ Pass ]
     1327webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html [ Pass ]
     1328webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html [ Pass ]
     1329webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html [ Pass ]
  • trunk/Source/WebCore/ChangeLog

    r271994 r272004  
     12021-01-27  Antoine Quint  <graouts@webkit.org>
     2
     3        REGRESSION(r268615): images flicker on apple.com/ios/ios-14
     4        https://bugs.webkit.org/show_bug.cgi?id=221054
     5        <rdar://problem/72880447>
     6
     7        Reviewed by Dean Jackson.
     8
     9        When we added support for accelerated animations of individual transform properties in r268615 (bug 217842),
     10        we made it so that base values of each transform-related property had a non-interpolating animation in the
     11        Core Animation animations list that would combine with interpolating animations for that property as additive
     12        animations. Prior to any of those animations, we'd reset the combined transform with an identity transform
     13        as another non-interpolating animation.
     14
     15        However, we neglected to consider the case where one of the interpolating animations would not start right
     16        away if a positive delay was set. In the case of this apple.com page, the target element would be composited
     17        due to a "will-change: transform" style, and a non-animated "transform" was set as well as an animation for
     18        the "transform" property with a delay.
     19
     20        Since we had a "transform" animation, we'd create a Core Animation animations lists as follows:
     21       
     22            1. non-interpolating, non-additive animation set to the identity matrix
     23            2. interpolating, additive animation with the keyframes set in the CSS animation, with a begin time
     24               set to the current time plus the specified delay
     25
     26        The result of this was that during the animation delay, the static "transform" property was overridden
     27        by animation #1 until animation #2 would kick in.
     28
     29        We now make it so that for each transform-related property, we create a non-interpoloating, additive animation
     30        to represent the static value for that property for the duration of any potential delay until the first
     31        interpolating animation for this property starts.
     32
     33        In this example, the Core Animation animations list is now as follows:
     34
     35            1. non-interpolating, non-additive animation set to the identity matrix
     36            2. non-interpolating, additive animation set to the static transform value
     37            3. interpolating, additive animation with the keyframes set in the CSS animation, with a begin time
     38               set to the current time plus the specified delay
     39
     40        We implement this with a new lambda function within GraphicsLayerCA::updateAnimations() called
     41        addAnimationsForProperty() which adds a non-interpolating animation in two cases:
     42       
     43            1. if there is no animation for this property at all, making it last forever
     44            2. if all animations have a delay, making it last until the first animation starts
     45
     46        Tests: webanimations/multiple-transform-properties-and-multiple-transform-properties-animation-with-delay-on-forced-layer.html
     47               webanimations/rotate-property-and-rotate-animation-with-delay-on-forced-layer.html
     48               webanimations/scale-property-and-scale-animation-with-delay-on-forced-layer.html
     49               webanimations/transform-property-and-transform-animation-with-delay-on-forced-layer.html
     50               webanimations/translate-property-and-translate-animation-with-delay-on-forced-layer.html
     51
     52        * platform/graphics/ca/GraphicsLayerCA.cpp:
     53        (WebCore::GraphicsLayerCA::updateAnimations):
     54
    1552021-01-27  Dean Jackson  <dino@apple.com>
    256
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r271699 r272004  
    29202920
    29212921    enum class TransformationMatrixSource { UseIdentityMatrix, AskClient };
    2922     auto addBaseValueTransformAnimation = [&](AnimatedPropertyID property, TransformationMatrixSource matrixSource = TransformationMatrixSource::AskClient) {
     2922    auto addBaseValueTransformAnimation = [&](AnimatedPropertyID property, TransformationMatrixSource matrixSource = TransformationMatrixSource::AskClient, Seconds beginTimeOfEarliestPropertyAnimation = 0_s) {
    29232923        // A base value transform animation can either be set to the identity matrix or to read the underlying
    29242924        // value from the GraphicsLayerClient. If we didn't explicitly ask for an identity matrix, we can skip
    … …  
    29282928            return;
    29292929
    2930         // A base value transform animation needs to last forever and use the same value for its from and to values.
     2930        auto delay = beginTimeOfEarliestPropertyAnimation > currentTime ? beginTimeOfEarliestPropertyAnimation - currentTime : 0_s;
     2931
     2932        // A base value transform animation needs to last forever and use the same value for its from and to values,
     2933        // unless we're just filling until an animation for this property starts, in which case it must last for duration
     2934        // of the delay until that animation.
    29312935        auto caAnimation = createPlatformCAAnimation(PlatformCAAnimation::Basic, propertyIdToString(property));
    2932         caAnimation->setDuration(Seconds::infinity().seconds());
     2936        caAnimation->setDuration((delay ? delay : Seconds::infinity()).seconds());
    29332937        caAnimation->setFromValue(matrix);
    29342938        caAnimation->setToValue(matrix);
    … …  
    29362940        auto animation = LayerPropertyAnimation(WTFMove(caAnimation), "base-transform-" + createCanonicalUUIDString(), property, 0, 0, 0_s);
    29372941        // To ensure the base value transform is applied along with all the interpolating animations, we set it to have started
    2938         // as early as possible, which combined with the infinite duration ensures it's current for any given CA media time.
    2939         animation.m_beginTime = baseTransformAnimationBeginTime;
     2942        // as early as possible, which combined with the infinite duration ensures it's current for any given CA media time,
     2943        // unless we're just filling until an animation for this property starts, in which case it must start now.
     2944        animation.m_beginTime = delay ? currentTime : baseTransformAnimationBeginTime;
    29402945
    29412946        // Additivity will depend on the source of the matrix, if it was explicitly provided as an identity matrix, it
    … …  
    29742979    LayerPropertyAnimation* scaleAnimation = nullptr;
    29752980    LayerPropertyAnimation* rotateAnimation = nullptr;
     2981    Vector<LayerPropertyAnimation*> translateAnimations;
     2982    Vector<LayerPropertyAnimation*> scaleAnimations;
     2983    Vector<LayerPropertyAnimation*> rotateAnimations;
    29762984    Vector<LayerPropertyAnimation*> transformAnimations;
    29772985
    … …  
    30113019    }
    30123020
     3021    if (translateAnimation)
     3022        translateAnimations.append(translateAnimation);
     3023    if (scaleAnimation)
     3024        scaleAnimations.append(scaleAnimation);
     3025    if (rotateAnimation)
     3026        rotateAnimations.append(rotateAnimation);
     3027
    30133028    // Now we can apply the transform-related animations, taking care to add them in the right order
    30143029    // (translate/scale/rotate/transform) and generate non-interpolating base value transform animations
    30153030    // for each property that is not otherwise interpolated.
    3016     if (translateAnimation || scaleAnimation || rotateAnimation || !transformAnimations.isEmpty()) {
     3031    if (!translateAnimations.isEmpty() || !scaleAnimations.isEmpty() || !rotateAnimations.isEmpty() || !transformAnimations.isEmpty()) {
    30173032        // Start with a base identity transform to override the transform applied to the layer and have a
    30183033        // sound base to add animations on top of with additivity enabled.
    … …  
    30213036        // Core Animation might require additive animations to be applied in the reverse order.
    30223037#if !PLATFORM(WIN) && !HAVE(CA_WHERE_ADDITIVE_TRANSFORMS_ARE_REVERSED)
    3023         if (translateAnimation)
    3024             addAnimation(*translateAnimation);
    3025         else
    3026             addBaseValueTransformAnimation(AnimatedPropertyTranslate);
    3027 
    3028         if (rotateAnimation)
    3029             addAnimation(*rotateAnimation);
    3030         else
    3031             addBaseValueTransformAnimation(AnimatedPropertyRotate);
    3032 
    3033         if (scaleAnimation)
    3034             addAnimation(*scaleAnimation);
    3035         else
    3036             addBaseValueTransformAnimation(AnimatedPropertyScale);
    3037 
    3038         for (auto* animation : transformAnimations)
    3039             addAnimation(*animation);
    3040         if (transformAnimations.isEmpty())
    3041             addBaseValueTransformAnimation(AnimatedPropertyTransform);
     3038        auto addAnimationsForProperty = [&](const Vector<LayerPropertyAnimation*>& animations, AnimatedPropertyID property) {
     3039            if (animations.isEmpty()) {
     3040                addBaseValueTransformAnimation(property);
     3041                return;
     3042            }
     3043
     3044            Seconds earliestBeginTime = 0_s;
     3045            for (auto* animation : animations) {
     3046                if (auto beginTime = animation->computedBeginTime()) {
     3047                    if (!earliestBeginTime || earliestBeginTime > *beginTime)
     3048                        earliestBeginTime = *beginTime;
     3049                }
     3050            }
     3051
     3052            if (earliestBeginTime > currentTime)
     3053                addBaseValueTransformAnimation(property, TransformationMatrixSource::AskClient, earliestBeginTime);
     3054
     3055            for (auto* animation : animations)
     3056                addAnimation(*animation);
     3057        };
     3058
     3059        addAnimationsForProperty(translateAnimations, AnimatedPropertyTranslate);
     3060        addAnimationsForProperty(rotateAnimations, AnimatedPropertyRotate);
     3061        addAnimationsForProperty(scaleAnimations, AnimatedPropertyScale);
     3062        addAnimationsForProperty(transformAnimations, AnimatedPropertyTransform);
    30423063#else
    3043         for (auto* animation : WTF::makeReversedRange(transformAnimations))
    3044             addAnimation(*animation);
    3045         if (transformAnimations.isEmpty())
    3046             addBaseValueTransformAnimation(AnimatedPropertyTransform);
    3047 
    3048         if (scaleAnimation)
    3049             addAnimation(*scaleAnimation);
    3050         else
    3051             addBaseValueTransformAnimation(AnimatedPropertyScale);
    3052 
    3053         if (rotateAnimation)
    3054             addAnimation(*rotateAnimation);
    3055         else
    3056             addBaseValueTransformAnimation(AnimatedPropertyRotate);
    3057 
    3058         if (translateAnimation)
    3059             addAnimation(*translateAnimation);
    3060         else
    3061             addBaseValueTransformAnimation(AnimatedPropertyTranslate);
     3064        auto addAnimationsForProperty = [&](const Vector<LayerPropertyAnimation*>& animations, AnimatedPropertyID property) {
     3065            if (animations.isEmpty()) {
     3066                addBaseValueTransformAnimation(property);
     3067                return;
     3068            }
     3069
     3070            Seconds earliestBeginTime = 0_s;
     3071            for (auto* animation : WTF::makeReversedRange(animations)) {
     3072                if (auto beginTime = animation->computedBeginTime()) {
     3073                    if (!earliestBeginTime || earliestBeginTime > *beginTime)
     3074                        earliestBeginTime = *beginTime;
     3075                }
     3076                addAnimation(*animation);
     3077            }
     3078
     3079            if (earliestBeginTime > currentTime)
     3080                addBaseValueTransformAnimation(property, TransformationMatrixSource::AskClient, earliestBeginTime);
     3081        };
     3082
     3083        addAnimationsForProperty(transformAnimations, AnimatedPropertyTransform);
     3084        addAnimationsForProperty(scaleAnimations, AnimatedPropertyScale);
     3085        addAnimationsForProperty(rotateAnimations, AnimatedPropertyRotate);
     3086        addAnimationsForProperty(translateAnimations, AnimatedPropertyTranslate);
    30623087#endif
    30633088    }
Note: See TracChangeset for help on using the changeset viewer.