Title: [255383] trunk
Revision
255383
Author
grao...@webkit.org
Date
2020-01-29 14:11:51 -0800 (Wed, 29 Jan 2020)

Log Message

[Web Animations] Animations should run accelerated even if other animations targeting the same element are not accelerated
https://bugs.webkit.org/show_bug.cgi?id=206890
<rdar://problem/58961750>

Reviewed by Simon Fraser.

Source/WebCore:

Test: webanimations/width-and-opacity-separate-animation-yields-compositing.html

In the Web Animations implementation, when an element has some animated properties that can be accelerated and some that cannot be, we would never
run accelerated animations at all. However, in the "legacy" animation engine, we would animate properties that can be acclerated if possible.
We now attempt to run accelerated animations provided at least one animation is accelerated.

To do that, we now keep track of whether none, some or all of the animated properties of a given KeyframeEffect are accelerated using the new
m_acceleratedPropertiesState instance variable. We compute this property when creating the blending keyframes for the effect.

Then, as time progresses and the effect is resolved, updateAcceleratedActions() is called and we simply use the effect's phase to determine
whether we need to enqueue actions to start, pause, seek or end accelerated animations. This is an improvement over how this method used to work
since we would run accelerated animations while in their delay phase, which did not match the "legacy" animation engine's behavior.

We've also removed the single method that provided the accelerated characteristics of a KeyframeEffect, isAccelerated(), with a few more methods:

    - isRunningAccelerated(): the effect is currently running accelerated animations.
    - isAboutToRunAccelerated(): the effect has pending accelerated actions that should make it run accelerated animations when accelerated actions
    are updated next.
    - isCompletelyAccelerated(): the effect animates only accelerated properties.
    - isCurrentlyAffectingProperty(property, accelerated): the effect is currently animating the given property, with the option to specify whether
    that animation is accelerated.

We use this information in a few new places. If an effect returns true for either isRunningAccelerated() or isAboutToRunAccelerated() when
Element::applyKeyframeEffects() is called, we set the AnimationImpact::RequiresRecomposite flag. In RenderLayerCompositor::requiresCompositingForAnimation(),
if an effect returns true for isCurrentlyAffectingProperty() with the accelerated flag set to true, the method returns true, matching the logic
used by the "legacy" animation engine.

All in all, this better aligns the behavior of the "legacy" and Web Animations engines to run accelerated animations in the same circumstances.

* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::updateCSSTransitionsForElementAndProperty): Use KeyframeEfffect::isRunningAccelerated() instead of KeyframeEffect::isAccelerated().
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::isRunningAcceleratedAnimationOnRenderer const): Use KeyframeEffect::isCurrentlyAffectingProperty() instead of checking both
isRunningAccelerated() and manually looking at the effect's animated properties.
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::setBlendingKeyframes): Call computeAcceleratedPropertiesState() instead of the now-defunct computeShouldRunAccelerated().
(WebCore::KeyframeEffect::apply): Keep track of the newly computed phase so that we may use it in the new isCurrentlyAffectingProperty() without having
to recompute it on each call.
(WebCore::KeyframeEffect::isCurrentlyAffectingProperty const): Indicates whether a given property is currently animated (active phase) with the option
to specify whether that animation is accelerated.
(WebCore::KeyframeEffect::computeAcceleratedPropertiesState): Compute whether none, some or all of the animated properties of the given effect can be accelerated.
(WebCore::KeyframeEffect::updateAcceleratedActions): Use the phase to determine which accelerated actions to enqueue.
(WebCore::KeyframeEffect::animationDidSeek): Use the new m_isRunningAccelerated state to determine whether the animation is presently running accelerated.
(WebCore::KeyframeEffect::animationWasCanceled): Use the new m_isRunningAccelerated state to determine whether the animation is presently running accelerated.
(WebCore::KeyframeEffect::animationSuspensionStateDidChange): Use the new m_isRunningAccelerated state to determine whether the animation is presently running accelerated.
(WebCore::KeyframeEffect::applyPendingAcceleratedActions):
* animation/KeyframeEffect.h:
(WebCore::KeyframeEffect::isRunningAccelerated const):
(WebCore::KeyframeEffect::isAboutToRunAccelerated const):
(WebCore::KeyframeEffect::isCompletelyAccelerated const):
* animation/KeyframeEffectStack.cpp:
(WebCore::KeyframeEffectStack::isCurrentlyAffectingProperty const): Indicates whether any of the effects in the stack animates a given property, with the option
to specify whether the animation should be accelerated.
* animation/KeyframeEffectStack.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::effectTargetDidChange): Ensure we schedule an animation update if an effect is no longer animating a given element or newly animating an element,
to ensure that replaced animations may be removed.
(WebCore::WebAnimation::isCompletelyAccelerated const): Convenience function to call isCompletelyAccelerated() on the animation's effect.
(WebCore::WebAnimation::computeRelevance): Check the replaced state when computing relevance.
(WebCore::WebAnimation::timeToNextTick const): Schedule an immediate update if a given animation is not _completely_ accelerated.
* animation/WebAnimation.h:
* dom/Element.cpp:
(WebCore::Element::keyframeEffectStack const):
(WebCore::Element::applyKeyframeEffects): Set the AnimationImpact::RequiresRecomposite flag when the animation is either currently running accelerated or expected
to be in the next accelerated animation update.
* dom/Element.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::requiresCompositingForAnimation const): Use the same logic as for the "legacy" animation engine to determine whether an animation
requires compositing using the new KeyframeEffect::isCurrentlyAffectingProperty() method.
(WebCore::RenderLayerCompositor::isRunningTransformAnimation const): Refactor some code to use the new KeyframeEffect::isCurrentlyAffectingProperty() method.

LayoutTests:

Update some tests that assumed a mix of accelerated and non-accelerated properties would not yield accelerated animations.
We also make some WK1-specific expectation due to compositing being disabled when opacity is the only potentially-accelerated
property to be animated.

* platform/mac-wk1/imported/w3c/web-platform-tests/css/css-color/animation/opacity-interpolation-expected.txt: Added.
* platform/mac-wk1/webanimations/opacity-animation-yields-compositing-expected.txt: Added.
* platform/mac-wk1/webanimations/opacity-animation-yields-compositing-span-expected.txt: Added.
* platform/mac-wk1/webanimations/partly-accelerated-transition-by-removing-property-expected.txt: Added.
* platform/mac-wk1/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt: Added.
* webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt: Removed.
* webanimations/partly-accelerated-transition-by-removing-property-expected.txt:
* webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt: Added.
* webanimations/width-and-opacity-separate-animation-yields-compositing.html: Renamed from LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html.
* webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt: Removed.
* webanimations/width-and-opacity-separate-animation-yields-no-compositing.html: Removed.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (255382 => 255383)


--- trunk/LayoutTests/ChangeLog	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/ChangeLog	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1,3 +1,27 @@
+2020-01-28  Antoine Quint  <grao...@apple.com>
+
+        [Web Animations] Animations should run accelerated even if other animations targeting the same element are not accelerated
+        https://bugs.webkit.org/show_bug.cgi?id=206890
+        <rdar://problem/58961750>
+
+        Reviewed by Simon Fraser.
+
+        Update some tests that assumed a mix of accelerated and non-accelerated properties would not yield accelerated animations.
+        We also make some WK1-specific expectation due to compositing being disabled when opacity is the only potentially-accelerated
+        property to be animated.
+
+        * platform/mac-wk1/imported/w3c/web-platform-tests/css/css-color/animation/opacity-interpolation-expected.txt: Added.
+        * platform/mac-wk1/webanimations/opacity-animation-yields-compositing-expected.txt: Added.
+        * platform/mac-wk1/webanimations/opacity-animation-yields-compositing-span-expected.txt: Added.
+        * platform/mac-wk1/webanimations/partly-accelerated-transition-by-removing-property-expected.txt: Added.
+        * platform/mac-wk1/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt: Added.
+        * webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt: Removed.
+        * webanimations/partly-accelerated-transition-by-removing-property-expected.txt:
+        * webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt: Added.
+        * webanimations/width-and-opacity-separate-animation-yields-compositing.html: Renamed from LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html.
+        * webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt: Removed.
+        * webanimations/width-and-opacity-separate-animation-yields-no-compositing.html: Removed.
+
 2020-01-29  Jason Lawrence  <lawrenc...@apple.com>
 
         [ Mojave wk2 ] media/media-fragments/TC0035.html is flaky failing.

Added: trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-color/animation/opacity-interpolation-expected.txt (0 => 255383)


--- trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-color/animation/opacity-interpolation-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/css/css-color/animation/opacity-interpolation-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1,122 @@
+
+PASS CSS Transitions: property <opacity> from neutral to [0.2] at (-0.3) should be [0.07] 
+PASS CSS Transitions: property <opacity> from neutral to [0.2] at (0) should be [0.1] 
+PASS CSS Transitions: property <opacity> from neutral to [0.2] at (0.3) should be [0.13] 
+PASS CSS Transitions: property <opacity> from neutral to [0.2] at (0.6) should be [0.16] 
+PASS CSS Transitions: property <opacity> from neutral to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions: property <opacity> from neutral to [0.2] at (1.5) should be [0.25] 
+PASS CSS Transitions with transition: all: property <opacity> from neutral to [0.2] at (-0.3) should be [0.07] 
+PASS CSS Transitions with transition: all: property <opacity> from neutral to [0.2] at (0) should be [0.1] 
+PASS CSS Transitions with transition: all: property <opacity> from neutral to [0.2] at (0.3) should be [0.13] 
+PASS CSS Transitions with transition: all: property <opacity> from neutral to [0.2] at (0.6) should be [0.16] 
+PASS CSS Transitions with transition: all: property <opacity> from neutral to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions with transition: all: property <opacity> from neutral to [0.2] at (1.5) should be [0.25] 
+PASS CSS Animations: property <opacity> from neutral to [0.2] at (-0.3) should be [0.07] 
+PASS CSS Animations: property <opacity> from neutral to [0.2] at (0) should be [0.1] 
+PASS CSS Animations: property <opacity> from neutral to [0.2] at (0.3) should be [0.13] 
+PASS CSS Animations: property <opacity> from neutral to [0.2] at (0.6) should be [0.16] 
+PASS CSS Animations: property <opacity> from neutral to [0.2] at (1) should be [0.2] 
+PASS CSS Animations: property <opacity> from neutral to [0.2] at (1.5) should be [0.25] 
+PASS Web Animations: property <opacity> from neutral to [0.2] at (-0.3) should be [0.07] 
+FAIL Web Animations: property <opacity> from neutral to [0.2] at (0) should be [0.1] assert_equals: expected "0.1 " but got "0.07 "
+FAIL Web Animations: property <opacity> from neutral to [0.2] at (0.3) should be [0.13] assert_equals: expected "0.13 " but got "0.11 "
+PASS Web Animations: property <opacity> from neutral to [0.2] at (0.6) should be [0.16] 
+PASS Web Animations: property <opacity> from neutral to [0.2] at (1) should be [0.2] 
+FAIL Web Animations: property <opacity> from neutral to [0.2] at (1.5) should be [0.25] assert_equals: expected "0.25 " but got "0.2 "
+PASS CSS Transitions: property <opacity> from [initial] to [0.2] at (-0.3) should be [1] 
+PASS CSS Transitions: property <opacity> from [initial] to [0.2] at (0) should be [1] 
+PASS CSS Transitions: property <opacity> from [initial] to [0.2] at (0.3) should be [0.76] 
+PASS CSS Transitions: property <opacity> from [initial] to [0.2] at (0.6) should be [0.52] 
+PASS CSS Transitions: property <opacity> from [initial] to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions: property <opacity> from [initial] to [0.2] at (1.5) should be [0] 
+PASS CSS Transitions with transition: all: property <opacity> from [initial] to [0.2] at (-0.3) should be [1] 
+PASS CSS Transitions with transition: all: property <opacity> from [initial] to [0.2] at (0) should be [1] 
+PASS CSS Transitions with transition: all: property <opacity> from [initial] to [0.2] at (0.3) should be [0.76] 
+PASS CSS Transitions with transition: all: property <opacity> from [initial] to [0.2] at (0.6) should be [0.52] 
+PASS CSS Transitions with transition: all: property <opacity> from [initial] to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions with transition: all: property <opacity> from [initial] to [0.2] at (1.5) should be [0] 
+PASS CSS Animations: property <opacity> from [initial] to [0.2] at (-0.3) should be [1] 
+PASS CSS Animations: property <opacity> from [initial] to [0.2] at (0) should be [1] 
+PASS CSS Animations: property <opacity> from [initial] to [0.2] at (0.3) should be [0.76] 
+PASS CSS Animations: property <opacity> from [initial] to [0.2] at (0.6) should be [0.52] 
+PASS CSS Animations: property <opacity> from [initial] to [0.2] at (1) should be [0.2] 
+PASS CSS Animations: property <opacity> from [initial] to [0.2] at (1.5) should be [0] 
+PASS Web Animations: property <opacity> from [initial] to [0.2] at (-0.3) should be [1] 
+PASS Web Animations: property <opacity> from [initial] to [0.2] at (0) should be [1] 
+PASS Web Animations: property <opacity> from [initial] to [0.2] at (0.3) should be [0.76] 
+PASS Web Animations: property <opacity> from [initial] to [0.2] at (0.6) should be [0.52] 
+PASS Web Animations: property <opacity> from [initial] to [0.2] at (1) should be [0.2] 
+PASS Web Animations: property <opacity> from [initial] to [0.2] at (1.5) should be [0] 
+PASS CSS Transitions: property <opacity> from [inherit] to [0.2] at (-0.3) should be [0.98] 
+PASS CSS Transitions: property <opacity> from [inherit] to [0.2] at (0) should be [0.8] 
+PASS CSS Transitions: property <opacity> from [inherit] to [0.2] at (0.3) should be [0.62] 
+PASS CSS Transitions: property <opacity> from [inherit] to [0.2] at (0.6) should be [0.44] 
+PASS CSS Transitions: property <opacity> from [inherit] to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions: property <opacity> from [inherit] to [0.2] at (1.5) should be [0] 
+PASS CSS Transitions with transition: all: property <opacity> from [inherit] to [0.2] at (-0.3) should be [0.98] 
+PASS CSS Transitions with transition: all: property <opacity> from [inherit] to [0.2] at (0) should be [0.8] 
+PASS CSS Transitions with transition: all: property <opacity> from [inherit] to [0.2] at (0.3) should be [0.62] 
+PASS CSS Transitions with transition: all: property <opacity> from [inherit] to [0.2] at (0.6) should be [0.44] 
+PASS CSS Transitions with transition: all: property <opacity> from [inherit] to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions with transition: all: property <opacity> from [inherit] to [0.2] at (1.5) should be [0] 
+FAIL CSS Animations: property <opacity> from [inherit] to [0.2] at (-0.3) should be [0.98] assert_equals: expected "0.98 " but got "0.07 "
+FAIL CSS Animations: property <opacity> from [inherit] to [0.2] at (0) should be [0.8] assert_equals: expected "0.8 " but got "0.1 "
+FAIL CSS Animations: property <opacity> from [inherit] to [0.2] at (0.3) should be [0.62] assert_equals: expected "0.62 " but got "0.13 "
+FAIL CSS Animations: property <opacity> from [inherit] to [0.2] at (0.6) should be [0.44] assert_equals: expected "0.44 " but got "0.16 "
+PASS CSS Animations: property <opacity> from [inherit] to [0.2] at (1) should be [0.2] 
+FAIL CSS Animations: property <opacity> from [inherit] to [0.2] at (1.5) should be [0] assert_equals: expected "0 " but got "0.25 "
+FAIL Web Animations: property <opacity> from [inherit] to [0.2] at (-0.3) should be [0.98] assert_equals: expected "0.98 " but got "0.07 "
+FAIL Web Animations: property <opacity> from [inherit] to [0.2] at (0) should be [0.8] assert_equals: expected "0.8 " but got "0.07 "
+FAIL Web Animations: property <opacity> from [inherit] to [0.2] at (0.3) should be [0.62] assert_equals: expected "0.62 " but got "0.11 "
+FAIL Web Animations: property <opacity> from [inherit] to [0.2] at (0.6) should be [0.44] assert_equals: expected "0.44 " but got "0.16 "
+PASS Web Animations: property <opacity> from [inherit] to [0.2] at (1) should be [0.2] 
+FAIL Web Animations: property <opacity> from [inherit] to [0.2] at (1.5) should be [0] assert_equals: expected "0 " but got "0.2 "
+PASS CSS Transitions: property <opacity> from [unset] to [0.2] at (-0.3) should be [1] 
+PASS CSS Transitions: property <opacity> from [unset] to [0.2] at (0) should be [1] 
+PASS CSS Transitions: property <opacity> from [unset] to [0.2] at (0.3) should be [0.76] 
+PASS CSS Transitions: property <opacity> from [unset] to [0.2] at (0.6) should be [0.52] 
+PASS CSS Transitions: property <opacity> from [unset] to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions: property <opacity> from [unset] to [0.2] at (1.5) should be [0] 
+PASS CSS Transitions with transition: all: property <opacity> from [unset] to [0.2] at (-0.3) should be [1] 
+PASS CSS Transitions with transition: all: property <opacity> from [unset] to [0.2] at (0) should be [1] 
+PASS CSS Transitions with transition: all: property <opacity> from [unset] to [0.2] at (0.3) should be [0.76] 
+PASS CSS Transitions with transition: all: property <opacity> from [unset] to [0.2] at (0.6) should be [0.52] 
+PASS CSS Transitions with transition: all: property <opacity> from [unset] to [0.2] at (1) should be [0.2] 
+PASS CSS Transitions with transition: all: property <opacity> from [unset] to [0.2] at (1.5) should be [0] 
+PASS CSS Animations: property <opacity> from [unset] to [0.2] at (-0.3) should be [1] 
+PASS CSS Animations: property <opacity> from [unset] to [0.2] at (0) should be [1] 
+PASS CSS Animations: property <opacity> from [unset] to [0.2] at (0.3) should be [0.76] 
+PASS CSS Animations: property <opacity> from [unset] to [0.2] at (0.6) should be [0.52] 
+PASS CSS Animations: property <opacity> from [unset] to [0.2] at (1) should be [0.2] 
+PASS CSS Animations: property <opacity> from [unset] to [0.2] at (1.5) should be [0] 
+PASS Web Animations: property <opacity> from [unset] to [0.2] at (-0.3) should be [1] 
+PASS Web Animations: property <opacity> from [unset] to [0.2] at (0) should be [1] 
+PASS Web Animations: property <opacity> from [unset] to [0.2] at (0.3) should be [0.76] 
+PASS Web Animations: property <opacity> from [unset] to [0.2] at (0.6) should be [0.52] 
+PASS Web Animations: property <opacity> from [unset] to [0.2] at (1) should be [0.2] 
+PASS Web Animations: property <opacity> from [unset] to [0.2] at (1.5) should be [0] 
+PASS CSS Transitions: property <opacity> from [0] to [1] at (-0.3) should be [0] 
+PASS CSS Transitions: property <opacity> from [0] to [1] at (0) should be [0] 
+PASS CSS Transitions: property <opacity> from [0] to [1] at (0.3) should be [0.3] 
+PASS CSS Transitions: property <opacity> from [0] to [1] at (0.6) should be [0.6] 
+PASS CSS Transitions: property <opacity> from [0] to [1] at (1) should be [1] 
+PASS CSS Transitions: property <opacity> from [0] to [1] at (1.5) should be [1] 
+PASS CSS Transitions with transition: all: property <opacity> from [0] to [1] at (-0.3) should be [0] 
+PASS CSS Transitions with transition: all: property <opacity> from [0] to [1] at (0) should be [0] 
+PASS CSS Transitions with transition: all: property <opacity> from [0] to [1] at (0.3) should be [0.3] 
+PASS CSS Transitions with transition: all: property <opacity> from [0] to [1] at (0.6) should be [0.6] 
+PASS CSS Transitions with transition: all: property <opacity> from [0] to [1] at (1) should be [1] 
+PASS CSS Transitions with transition: all: property <opacity> from [0] to [1] at (1.5) should be [1] 
+PASS CSS Animations: property <opacity> from [0] to [1] at (-0.3) should be [0] 
+PASS CSS Animations: property <opacity> from [0] to [1] at (0) should be [0] 
+PASS CSS Animations: property <opacity> from [0] to [1] at (0.3) should be [0.3] 
+PASS CSS Animations: property <opacity> from [0] to [1] at (0.6) should be [0.6] 
+PASS CSS Animations: property <opacity> from [0] to [1] at (1) should be [1] 
+PASS CSS Animations: property <opacity> from [0] to [1] at (1.5) should be [1] 
+PASS Web Animations: property <opacity> from [0] to [1] at (-0.3) should be [0] 
+PASS Web Animations: property <opacity> from [0] to [1] at (0) should be [0] 
+PASS Web Animations: property <opacity> from [0] to [1] at (0.3) should be [0.3] 
+PASS Web Animations: property <opacity> from [0] to [1] at (0.6) should be [0.6] 
+PASS Web Animations: property <opacity> from [0] to [1] at (1) should be [1] 
+PASS Web Animations: property <opacity> from [0] to [1] at (1.5) should be [1] 
+

Copied: trunk/LayoutTests/platform/mac-wk1/webanimations/opacity-animation-yields-compositing-expected.txt (from rev 255382, trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt) (0 => 255383)


--- trunk/LayoutTests/platform/mac-wk1/webanimations/opacity-animation-yields-compositing-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/webanimations/opacity-animation-yields-compositing-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1 @@
+

Added: trunk/LayoutTests/platform/mac-wk1/webanimations/opacity-animation-yields-compositing-span-expected.txt (0 => 255383)


--- trunk/LayoutTests/platform/mac-wk1/webanimations/opacity-animation-yields-compositing-span-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/webanimations/opacity-animation-yields-compositing-span-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1 @@
+Foo

Copied: trunk/LayoutTests/platform/mac-wk1/webanimations/partly-accelerated-transition-by-removing-property-expected.txt (from rev 255382, trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property-expected.txt) (0 => 255383)


--- trunk/LayoutTests/platform/mac-wk1/webanimations/partly-accelerated-transition-by-removing-property-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/webanimations/partly-accelerated-transition-by-removing-property-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1 @@
+

Copied: trunk/LayoutTests/platform/mac-wk1/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt (from rev 255382, trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt) (0 => 255383)


--- trunk/LayoutTests/platform/mac-wk1/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1 @@
+

Deleted: trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt (255382 => 255383)


--- trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1 +0,0 @@
-

Deleted: trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html (255382 => 255383)


--- trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1,15 +0,0 @@
-<pre id="results"></pre>
-<div id="target" style="width: 100px; height: 100px; background-color: black;"></div>
-<script>
-
-const animation = new Animation(new KeyframeEffect(document.getElementById("target"), [
-    { left: 0, opacity: 1 },
-    { left: "100px", opacity: 0 }
-]));
-animation.startTime = 0;
-animation.effect.updateTiming({ duration : 1000 });
-
-testRunner.dumpAsText();
-document.getElementById("results").innerText = internals.layerTreeAsText(document);
-
-</script>

Modified: trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property-expected.txt (255382 => 255383)


--- trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property-expected.txt	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1 +1,19 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (children 1
+        (GraphicsLayer
+          (position 100.00 0.00)
+          (bounds 100.00 100.00)
+          (opacity 0.50)
+          (contentsOpaque 1)
+        )
+      )
+    )
+  )
+)
 

Modified: trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property.html (255382 => 255383)


--- trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property.html	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/webanimations/partly-accelerated-transition-by-removing-property.html	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1,7 +1,7 @@
 <!DOCTYPE html><!-- webkit-test-runner [ experimental:WebAnimationsCSSIntegrationEnabled=true ] -->
 <body>
 <pre id="results"></pre>
-<div id="target" style="width: 100px; height: 100px; background-color: black;"></div>
+<div id="target" style="position: absolute; top: 0; left: 0; width: 100px; height: 100px; background-color: black;"></div>
 <script>
 
 if (window.testRunner) {

Added: trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt (0 => 255383)


--- trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-compositing-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1,18 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (children 1
+        (GraphicsLayer
+          (position 8.00 8.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+        )
+      )
+    )
+  )
+)
+

Copied: trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-compositing.html (from rev 255382, trunk/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html) (0 => 255383)


--- trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-compositing.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-compositing.html	2020-01-29 22:11:51 UTC (rev 255383)
@@ -0,0 +1,13 @@
+<pre id="results"></pre>
+<div id="target" style="width: 100px; height: 100px; background-color: black;"></div>
+<script>
+
+target.animate([
+    { opacity: 1, width: "100px" },
+    { opacity: 0, width: "200px" }
+], 1000);
+
+testRunner.dumpAsText();
+document.getElementById("results").innerText = internals.layerTreeAsText(document);
+
+</script>

Deleted: trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt (255382 => 255383)


--- trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1 +0,0 @@
-

Deleted: trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing.html (255382 => 255383)


--- trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing.html	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing.html	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1,22 +0,0 @@
-<pre id="results"></pre>
-<div id="target" style="width: 100px; height: 100px; background-color: black;"></div>
-<script>
-
-const opacityAnimation = new Animation(new KeyframeEffect(document.getElementById("target"), [
-    { opacity: 1 },
-    { opacity: 0 }
-]));
-opacityAnimation.startTime = 0;
-opacityAnimation.effect.updateTiming({ duration : 1000 });
-
-const widthAnimation = new Animation(new KeyframeEffect(document.getElementById("target"), [
-    { width: "100px" },
-    { width: "200px" }
-]));
-widthAnimation.startTime = 0;
-widthAnimation.effect.updateTiming({ duration : 1000 });
-
-testRunner.dumpAsText();
-document.getElementById("results").innerText = internals.layerTreeAsText(document);
-
-</script>

Modified: trunk/Source/WebCore/ChangeLog (255382 => 255383)


--- trunk/Source/WebCore/ChangeLog	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/ChangeLog	2020-01-29 22:11:51 UTC (rev 255383)
@@ -1,3 +1,82 @@
+2020-01-28  Antoine Quint  <grao...@apple.com>
+
+        [Web Animations] Animations should run accelerated even if other animations targeting the same element are not accelerated
+        https://bugs.webkit.org/show_bug.cgi?id=206890
+        <rdar://problem/58961750>
+
+        Reviewed by Simon Fraser.
+
+        Test: webanimations/width-and-opacity-separate-animation-yields-compositing.html
+
+        In the Web Animations implementation, when an element has some animated properties that can be accelerated and some that cannot be, we would never
+        run accelerated animations at all. However, in the "legacy" animation engine, we would animate properties that can be acclerated if possible.
+        We now attempt to run accelerated animations provided at least one animation is accelerated.
+
+        To do that, we now keep track of whether none, some or all of the animated properties of a given KeyframeEffect are accelerated using the new
+        m_acceleratedPropertiesState instance variable. We compute this property when creating the blending keyframes for the effect. 
+        
+        Then, as time progresses and the effect is resolved, updateAcceleratedActions() is called and we simply use the effect's phase to determine
+        whether we need to enqueue actions to start, pause, seek or end accelerated animations. This is an improvement over how this method used to work
+        since we would run accelerated animations while in their delay phase, which did not match the "legacy" animation engine's behavior.
+
+        We've also removed the single method that provided the accelerated characteristics of a KeyframeEffect, isAccelerated(), with a few more methods:
+
+            - isRunningAccelerated(): the effect is currently running accelerated animations.
+            - isAboutToRunAccelerated(): the effect has pending accelerated actions that should make it run accelerated animations when accelerated actions
+            are updated next.
+            - isCompletelyAccelerated(): the effect animates only accelerated properties.
+            - isCurrentlyAffectingProperty(property, accelerated): the effect is currently animating the given property, with the option to specify whether
+            that animation is accelerated.
+
+        We use this information in a few new places. If an effect returns true for either isRunningAccelerated() or isAboutToRunAccelerated() when
+        Element::applyKeyframeEffects() is called, we set the AnimationImpact::RequiresRecomposite flag. In RenderLayerCompositor::requiresCompositingForAnimation(),
+        if an effect returns true for isCurrentlyAffectingProperty() with the accelerated flag set to true, the method returns true, matching the logic
+        used by the "legacy" animation engine.
+
+        All in all, this better aligns the behavior of the "legacy" and Web Animations engines to run accelerated animations in the same circumstances.
+
+        * animation/AnimationTimeline.cpp:
+        (WebCore::AnimationTimeline::updateCSSTransitionsForElementAndProperty): Use KeyframeEfffect::isRunningAccelerated() instead of KeyframeEffect::isAccelerated().
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::isRunningAcceleratedAnimationOnRenderer const): Use KeyframeEffect::isCurrentlyAffectingProperty() instead of checking both
+        isRunningAccelerated() and manually looking at the effect's animated properties.
+        * animation/KeyframeEffect.cpp:
+        (WebCore::KeyframeEffect::setBlendingKeyframes): Call computeAcceleratedPropertiesState() instead of the now-defunct computeShouldRunAccelerated().
+        (WebCore::KeyframeEffect::apply): Keep track of the newly computed phase so that we may use it in the new isCurrentlyAffectingProperty() without having
+        to recompute it on each call.
+        (WebCore::KeyframeEffect::isCurrentlyAffectingProperty const): Indicates whether a given property is currently animated (active phase) with the option
+        to specify whether that animation is accelerated.
+        (WebCore::KeyframeEffect::computeAcceleratedPropertiesState): Compute whether none, some or all of the animated properties of the given effect can be accelerated.
+        (WebCore::KeyframeEffect::updateAcceleratedActions): Use the phase to determine which accelerated actions to enqueue.
+        (WebCore::KeyframeEffect::animationDidSeek): Use the new m_isRunningAccelerated state to determine whether the animation is presently running accelerated.
+        (WebCore::KeyframeEffect::animationWasCanceled): Use the new m_isRunningAccelerated state to determine whether the animation is presently running accelerated.
+        (WebCore::KeyframeEffect::animationSuspensionStateDidChange): Use the new m_isRunningAccelerated state to determine whether the animation is presently running accelerated.
+        (WebCore::KeyframeEffect::applyPendingAcceleratedActions): 
+        * animation/KeyframeEffect.h:
+        (WebCore::KeyframeEffect::isRunningAccelerated const):
+        (WebCore::KeyframeEffect::isAboutToRunAccelerated const):
+        (WebCore::KeyframeEffect::isCompletelyAccelerated const):
+        * animation/KeyframeEffectStack.cpp:
+        (WebCore::KeyframeEffectStack::isCurrentlyAffectingProperty const): Indicates whether any of the effects in the stack animates a given property, with the option
+        to specify whether the animation should be accelerated.
+        * animation/KeyframeEffectStack.h:
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::effectTargetDidChange): Ensure we schedule an animation update if an effect is no longer animating a given element or newly animating an element,
+        to ensure that replaced animations may be removed.
+        (WebCore::WebAnimation::isCompletelyAccelerated const): Convenience function to call isCompletelyAccelerated() on the animation's effect.
+        (WebCore::WebAnimation::computeRelevance): Check the replaced state when computing relevance.
+        (WebCore::WebAnimation::timeToNextTick const): Schedule an immediate update if a given animation is not _completely_ accelerated.
+        * animation/WebAnimation.h:
+        * dom/Element.cpp:
+        (WebCore::Element::keyframeEffectStack const):
+        (WebCore::Element::applyKeyframeEffects): Set the AnimationImpact::RequiresRecomposite flag when the animation is either currently running accelerated or expected
+        to be in the next accelerated animation update.
+        * dom/Element.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::requiresCompositingForAnimation const): Use the same logic as for the "legacy" animation engine to determine whether an animation
+        requires compositing using the new KeyframeEffect::isCurrentlyAffectingProperty() method.
+        (WebCore::RenderLayerCompositor::isRunningTransformAnimation const): Refactor some code to use the new KeyframeEffect::isCurrentlyAffectingProperty() method.
+
 2020-01-29  Ross Kirsling  <ross.kirsl...@sony.com>
 
         Unreviewed !ENABLE(ACCESSIBILITY) build fix.

Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (255382 => 255383)


--- trunk/Source/WebCore/animation/AnimationTimeline.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/AnimationTimeline.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -446,7 +446,7 @@
             auto* runningTransition = runningTransitionsByProperty.get(property);
             if (is<KeyframeEffect>(runningTransition->effect())) {
                 auto& keyframeEffect = *downcast<KeyframeEffect>(runningTransition->effect());
-                if (keyframeEffect.isAccelerated()) {
+                if (keyframeEffect.isRunningAccelerated()) {
                     auto animatedStyle = RenderStyle::clonePtr(currentStyle);
                     runningTransition->resolve(*animatedStyle);
                     return *animatedStyle;

Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (255382 => 255383)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -598,7 +598,7 @@
         auto* effect = animation->effect();
         if (is<KeyframeEffect>(effect)) {
             auto* keyframeEffect = downcast<KeyframeEffect>(effect);
-            if (keyframeEffect->isRunningAccelerated() && keyframeEffect->animatedProperties().contains(property))
+            if (keyframeEffect->isCurrentlyAffectingProperty(property, KeyframeEffect::Accelerated::Yes))
                 return true;
         }
     }

Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (255382 => 255383)


--- trunk/Source/WebCore/animation/KeyframeEffect.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -801,7 +801,7 @@
 
     computedNeedsForcedLayout();
     computeStackingContextImpact();
-    computeShouldRunAccelerated();
+    computeAcceleratedPropertiesState();
 
     checkForMatchingTransformFunctionLists();
     checkForMatchingFilterFunctionLists();
@@ -1084,8 +1084,9 @@
     updateBlendingKeyframes(targetStyle);
 
     auto computedTiming = getComputedTiming();
+    m_phaseAtLastApplication = computedTiming.phase;
 
-    updateAcceleratedAnimationState(computedTiming);
+    updateAcceleratedActions(computedTiming);
 
     InspectorInstrumentation::willApplyKeyframeEffect(*m_target, *this, computedTiming);
 
@@ -1095,20 +1096,43 @@
     setAnimatedPropertiesInStyle(targetStyle, computedTiming.progress.value());
 }
 
+bool KeyframeEffect::isCurrentlyAffectingProperty(CSSPropertyID property, Accelerated accelerated) const
+{
+    if (accelerated == Accelerated::Yes && !isRunningAccelerated() && !isAboutToRunAccelerated())
+        return false;
+
+    if (!m_blendingKeyframes.properties().contains(property))
+        return false;
+
+    return m_phaseAtLastApplication == AnimationEffectPhase::Active;
+}
+
 void KeyframeEffect::invalidate()
 {
     invalidateElement(m_target.get());
 }
 
-void KeyframeEffect::computeShouldRunAccelerated()
+void KeyframeEffect::computeAcceleratedPropertiesState()
 {
-    m_shouldRunAccelerated = hasBlendingKeyframes();
+    bool hasSomeAcceleratedProperties = false;
+    bool hasSomeUnacceleratedProperties = false;
+
     for (auto cssPropertyId : m_blendingKeyframes.properties()) {
-        if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
-            m_shouldRunAccelerated = false;
-            return;
-        }
+        // If any animated property can be accelerated, then the animation should run accelerated.
+        if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId))
+            hasSomeAcceleratedProperties = true;
+        else
+            hasSomeUnacceleratedProperties = true;
+        if (hasSomeAcceleratedProperties && hasSomeUnacceleratedProperties)
+            break;
     }
+
+    if (!hasSomeAcceleratedProperties && !hasSomeUnacceleratedProperties)
+        m_acceleratedPropertiesState = AcceleratedProperties::None;
+    else if (hasSomeUnacceleratedProperties)
+        m_acceleratedPropertiesState = AcceleratedProperties::Some;
+    else
+        m_acceleratedPropertiesState = AcceleratedProperties::All;
 }
 
 void KeyframeEffect::getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyle)
@@ -1305,28 +1329,28 @@
     return nullptr;
 }
 
-void KeyframeEffect::updateAcceleratedAnimationState(ComputedEffectTiming computedTiming)
+void KeyframeEffect::updateAcceleratedActions(ComputedEffectTiming computedTiming)
 {
-    if (!m_shouldRunAccelerated)
+    if (m_acceleratedPropertiesState == AcceleratedProperties::None)
         return;
 
-    if (!renderer()) {
-        if (isRunningAccelerated())
-            addPendingAcceleratedAction(AcceleratedAction::Stop);
+    // If we're not already running accelerated, the only thing we're interested in is whether we need to start the animation
+    // which we need to do once we're in the active phase. Otherwise, there's no change in accelerated state to consider.
+    bool isActive = computedTiming.phase == AnimationEffectPhase::Active;
+    if (!m_isRunningAccelerated) {
+        if (isActive && animation()->playState() == WebAnimation::PlayState::Running)
+            addPendingAcceleratedAction(AcceleratedAction::Play);
         return;
     }
 
-    auto localTime = animation()->currentTime();
-
-    // If we don't have a localTime or localTime < 0, we either don't have a start time or we're before the startTime
-    // so we shouldn't be running.
-    if (!localTime || localTime.value() < 0_s) {
-        if (isRunningAccelerated())
-            addPendingAcceleratedAction(AcceleratedAction::Stop);
+    // If we're no longer active, we need to remove the accelerated animation.
+    if (!isActive) {
+        addPendingAcceleratedAction(AcceleratedAction::Stop);
         return;
     }
 
     auto playState = animation()->playState();
+    // The only thing left to consider is whether we need to pause or resume the animation following a change of play-state.
     if (playState == WebAnimation::PlayState::Paused) {
         if (m_lastRecordedAcceleratedAction != AcceleratedAction::Pause) {
             if (m_lastRecordedAcceleratedAction == AcceleratedAction::Stop)
@@ -1333,18 +1357,9 @@
                 addPendingAcceleratedAction(AcceleratedAction::Play);
             addPendingAcceleratedAction(AcceleratedAction::Pause);
         }
-        return;
-    }
-
-    if (playState == WebAnimation::PlayState::Finished) {
-        addPendingAcceleratedAction(AcceleratedAction::Stop);
-        return;
-    }
-
-    if (playState == WebAnimation::PlayState::Running && computedTiming.phase == AnimationEffectPhase::Active) {
+    } else if (playState == WebAnimation::PlayState::Running && isActive) {
         if (m_lastRecordedAcceleratedAction != AcceleratedAction::Play)
             addPendingAcceleratedAction(AcceleratedAction::Play);
-        return;
     }
 }
 
@@ -1365,19 +1380,19 @@
 {
     // There is no need to seek if we're not playing an animation already. If seeking
     // means we're moving into an active lexicalGlobalObject, we'll pick this up in apply().
-    if (m_shouldRunAccelerated && isRunningAccelerated())
+    if (m_isRunningAccelerated)
         addPendingAcceleratedAction(AcceleratedAction::Seek);
 }
 
 void KeyframeEffect::animationWasCanceled()
 {
-    if (m_shouldRunAccelerated && isRunningAccelerated())
+    if (m_isRunningAccelerated)
         addPendingAcceleratedAction(AcceleratedAction::Stop);
 }
 
 void KeyframeEffect::animationSuspensionStateDidChange(bool animationIsSuspended)
 {
-    if (m_shouldRunAccelerated)
+    if (m_isRunningAccelerated)
         addPendingAcceleratedAction(animationIsSuspended ? AcceleratedAction::Pause : AcceleratedAction::Play);
 }
 
@@ -1391,22 +1406,17 @@
     if (m_pendingAcceleratedActions.isEmpty())
         return;
 
-    // In the case where we have a composited renderer, we'll be applying all pending accelerated actions.
-    // In case we don't have a composited renderer, then we won't be able to apply the pending accelerated
-    // actions. In both cases, we can clear the pending accelerated actions.
-    auto pendingAcceleratedActions = m_pendingAcceleratedActions;
-    m_pendingAcceleratedActions.clear();
-
     auto* renderer = this->renderer();
     if (!renderer || !renderer->isComposited()) {
-        // If we don't have a composited renderer when we were supposed to be applying an accelerated action other
-        // than to stop a running animation, then we won't manage to apply accelerations in the future either, so
-        // we should reset the flag to run accelerated.
-        m_lastRecordedAcceleratedAction = AcceleratedAction::Stop;
+        // The renderer may no longer be composited because the accelerated animation ended before we had a chance to update it,
+        // in which case if we asked for the animation to stop, we can discard the current set of accelerated actions.
+        if (m_lastRecordedAcceleratedAction == AcceleratedAction::Stop)
+            m_pendingAcceleratedActions.clear();
         return;
     }
 
-    auto* compositedRenderer = downcast<RenderBoxModelObject>(renderer);
+    auto pendingAcceleratedActions = m_pendingAcceleratedActions;
+    m_pendingAcceleratedActions.clear();
 
     // To simplify the code we use a default of 0s for an unresolved current time since for a Stop action that is acceptable.
     auto timeOffset = animation()->currentTime().valueOr(0_s).seconds() - delay().seconds();
@@ -1414,23 +1424,23 @@
     for (const auto& action : pendingAcceleratedActions) {
         switch (action) {
         case AcceleratedAction::Play:
-            if (!compositedRenderer->startAnimation(timeOffset, backingAnimationForCompositedRenderer(), m_blendingKeyframes)) {
-                m_shouldRunAccelerated = false;
+            m_isRunningAccelerated = renderer->startAnimation(timeOffset, backingAnimationForCompositedRenderer(), m_blendingKeyframes);
+            if (!m_isRunningAccelerated) {
                 m_lastRecordedAcceleratedAction = AcceleratedAction::Stop;
-                animation()->acceleratedStateDidChange();
                 return;
             }
             break;
         case AcceleratedAction::Pause:
-            compositedRenderer->animationPaused(timeOffset, m_blendingKeyframes.animationName());
+            renderer->animationPaused(timeOffset, m_blendingKeyframes.animationName());
             break;
         case AcceleratedAction::Seek:
-            compositedRenderer->animationSeeked(timeOffset, m_blendingKeyframes.animationName());
+            renderer->animationSeeked(timeOffset, m_blendingKeyframes.animationName());
             break;
         case AcceleratedAction::Stop:
-            compositedRenderer->animationFinished(m_blendingKeyframes.animationName());
+            renderer->animationFinished(m_blendingKeyframes.animationName());
             if (!m_target->document().renderTreeBeingDestroyed())
                 m_target->invalidateStyleAndLayerComposition();
+            m_isRunningAccelerated = false;
             break;
         }
     }

Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (255382 => 255383)


--- trunk/Source/WebCore/animation/KeyframeEffect.h	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h	2020-01-29 22:11:51 UTC (rev 255383)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "AnimationEffect.h"
+#include "AnimationEffectPhase.h"
 #include "CSSPropertyBlendingClient.h"
 #include "CompositeOperation.h"
 #include "CompositeOperationOrAuto.h"
@@ -118,15 +119,15 @@
     void animationTimelineDidChange(AnimationTimeline*) final;
     void animationTimingDidChange();
     void applyPendingAcceleratedActions();
-    bool isRunningAccelerated() const { return m_lastRecordedAcceleratedAction != AcceleratedAction::Stop; }
-    bool hasPendingAcceleratedAction() const { return !m_pendingAcceleratedActions.isEmpty() && isRunningAccelerated(); }
 
     void setAnimation(WebAnimation*) final;
 
     RenderElement* renderer() const override;
     const RenderStyle& currentStyle() const override;
-    bool isAccelerated() const { return m_shouldRunAccelerated; }
     bool triggersStackingContext() const { return m_triggersStackingContext; }
+    bool isRunningAccelerated() const { return m_isRunningAccelerated; }
+    bool isAboutToRunAccelerated() const { return m_acceleratedPropertiesState != AcceleratedProperties::None && m_lastRecordedAcceleratedAction != AcceleratedAction::Stop; }
+    bool isCompletelyAccelerated() const { return m_acceleratedPropertiesState == AcceleratedProperties::All; }
     bool filterFunctionListsMatch() const override { return m_filterFunctionListsMatch; }
     bool transformFunctionListsMatch() const override { return m_transformFunctionListsMatch; }
 #if ENABLE(FILTERS_LEVEL_2)
@@ -143,17 +144,21 @@
     bool computeTransformedExtentViaMatrix(const FloatRect&, const RenderStyle&, LayoutRect&) const;
     bool forceLayoutIfNeeded();
 
+    enum class Accelerated : uint8_t { Yes, No };
+    bool isCurrentlyAffectingProperty(CSSPropertyID, Accelerated = Accelerated::No) const;
+
 private:
     KeyframeEffect(Element*);
 
     enum class AcceleratedAction : uint8_t { Play, Pause, Seek, Stop };
     enum class BlendingKeyframesSource : uint8_t { CSSAnimation, CSSTransition, WebAnimation };
+    enum class AcceleratedProperties : uint8_t { None, Some, All };
 
     void updateEffectStackMembership();
     void copyPropertiesFromSource(Ref<KeyframeEffect>&&);
     ExceptionOr<void> processKeyframes(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&);
     void addPendingAcceleratedAction(AcceleratedAction);
-    void updateAcceleratedAnimationState(ComputedEffectTiming);
+    void updateAcceleratedActions(ComputedEffectTiming);
     void setAnimatedPropertiesInStyle(RenderStyle&, double);
     TimingFunction* timingFunctionForKeyframeAtIndex(size_t);
     Ref<const Animation> backingAnimationForCompositedRenderer() const;
@@ -163,7 +168,7 @@
     void updateBlendingKeyframes(RenderStyle&);
     void computeCSSAnimationBlendingKeyframes();
     void computeCSSTransitionBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle);
-    void computeShouldRunAccelerated();
+    void computeAcceleratedPropertiesState();
     void setBlendingKeyframes(KeyframeList&);
     void checkForMatchingTransformFunctionLists();
     void checkForMatchingFilterFunctionLists();
@@ -182,7 +187,9 @@
     BlendingKeyframesSource m_blendingKeyframesSource { BlendingKeyframesSource::WebAnimation };
     IterationCompositeOperation m_iterationCompositeOperation { IterationCompositeOperation::Replace };
     CompositeOperation m_compositeOperation { CompositeOperation::Replace };
-    bool m_shouldRunAccelerated { false };
+    AcceleratedProperties m_acceleratedPropertiesState { AcceleratedProperties::None };
+    AnimationEffectPhase m_phaseAtLastApplication { AnimationEffectPhase::Idle };
+    bool m_isRunningAccelerated { false };
     bool m_needsForcedLayout { false };
     bool m_triggersStackingContext { false };
     bool m_transformFunctionListsMatch { false };

Modified: trunk/Source/WebCore/animation/KeyframeEffectStack.cpp (255382 => 255383)


--- trunk/Source/WebCore/animation/KeyframeEffectStack.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/KeyframeEffectStack.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -60,6 +60,15 @@
     m_effects.removeFirst(&effect);
 }
 
+bool KeyframeEffectStack::isCurrentlyAffectingProperty(CSSPropertyID property) const
+{
+    for (auto& effect : m_effects) {
+        if (effect->isCurrentlyAffectingProperty(property))
+            return true;
+    }
+    return false;
+}
+
 Vector<WeakPtr<KeyframeEffect>> KeyframeEffectStack::sortedEffects()
 {
     ensureEffectsAreSorted();

Modified: trunk/Source/WebCore/animation/KeyframeEffectStack.h (255382 => 255383)


--- trunk/Source/WebCore/animation/KeyframeEffectStack.h	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/KeyframeEffectStack.h	2020-01-29 22:11:51 UTC (rev 255383)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "AnimationList.h"
+#include "CSSPropertyNames.h"
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
 
@@ -45,6 +46,7 @@
     Vector<WeakPtr<KeyframeEffect>> sortedEffects();
     const AnimationList* cssAnimationList() const { return m_cssAnimationList.get(); }
     void setCSSAnimationList(RefPtr<const AnimationList>&&);
+    bool isCurrentlyAffectingProperty(CSSPropertyID) const;
 
 private:
     void ensureEffectsAreSorted();

Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (255382 => 255383)


--- trunk/Source/WebCore/animation/WebAnimation.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -257,6 +257,9 @@
 
     if (newTarget)
         m_timeline->animationWasAddedToElement(*this, *newTarget);
+
+    // This could have changed whether we have replaced animations, so we may need to schedule an update.
+    m_timeline->animationTimingDidChange(*this);
 }
 
 Optional<double> WebAnimation::startTime() const
@@ -1137,6 +1140,11 @@
     return is<KeyframeEffect>(m_effect) && downcast<KeyframeEffect>(*m_effect).isRunningAccelerated();
 }
 
+bool WebAnimation::isCompletelyAccelerated() const
+{
+    return is<KeyframeEffect>(m_effect) && downcast<KeyframeEffect>(*m_effect).isCompletelyAccelerated();
+}
+
 bool WebAnimation::needsTick() const
 {
     return pending() || playState() == PlayState::Running;
@@ -1237,6 +1245,9 @@
     if (!m_effect)
         return false;
 
+    if (m_replaceState == ReplaceState::Removed)
+        return false;
+
     auto timing = m_effect->getBasicTiming();
 
     // An animation effect is in effect if its active time is not unresolved.
@@ -1376,7 +1387,6 @@
 
 Seconds WebAnimation::timeToNextTick() const
 {
-    // Any animation that is pending needs immediate resolution.
     if (pending())
         return 0_s;
 
@@ -1393,7 +1403,7 @@
         return (effect.delay() - timing.localTime.value()) / playbackRate;
     case AnimationEffectPhase::Active:
         // Non-accelerated animations in the "active" phase will need to update their animated value at the immediate next opportunity.
-        if (!isRunningAccelerated())
+        if (!isCompletelyAccelerated())
             return 0_s;
         // Accelerated CSS Animations need to trigger "animationiteration" events, in this case we can wait until the next iteration.
         if (isCSSAnimation()) {

Modified: trunk/Source/WebCore/animation/WebAnimation.h (255382 => 255383)


--- trunk/Source/WebCore/animation/WebAnimation.h	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/animation/WebAnimation.h	2020-01-29 22:11:51 UTC (rev 255383)
@@ -119,6 +119,7 @@
     void applyPendingAcceleratedActions();
 
     bool isRunningAccelerated() const;
+    bool isCompletelyAccelerated() const;
     bool isRelevant() const { return m_isRelevant; }
     void updateRelevance();
     void effectTimingDidChange();

Modified: trunk/Source/WebCore/dom/Element.cpp (255382 => 255383)


--- trunk/Source/WebCore/dom/Element.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/dom/Element.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -3709,6 +3709,11 @@
 
 #endif
 
+KeyframeEffectStack* Element::keyframeEffectStack() const
+{
+    return hasRareData() ? elementRareData()->keyframeEffectStack() : nullptr;
+}
+
 KeyframeEffectStack& Element::ensureKeyframeEffectStack()
 {
     auto& rareData = ensureElementRareData();
@@ -3734,7 +3739,7 @@
         ASSERT(effect->animation());
         effect->animation()->resolve(targetStyle);
 
-        if (effect->isAccelerated())
+        if (effect->isRunningAccelerated() || effect->isAboutToRunAccelerated())
             impact.add(AnimationImpact::RequiresRecomposite);
 
         if (effect->triggersStackingContext())

Modified: trunk/Source/WebCore/dom/Element.h (255382 => 255383)


--- trunk/Source/WebCore/dom/Element.h	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/dom/Element.h	2020-01-29 22:11:51 UTC (rev 255383)
@@ -482,6 +482,7 @@
     void setHasCSSAnimation();
     void clearHasCSSAnimation();
 
+    KeyframeEffectStack* keyframeEffectStack() const;
     KeyframeEffectStack& ensureKeyframeEffectStack();
     bool hasKeyframeEffects() const;
     OptionSet<AnimationImpact> applyKeyframeEffects(RenderStyle&);

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (255382 => 255383)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2020-01-29 21:49:27 UTC (rev 255382)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2020-01-29 22:11:51 UTC (rev 255383)
@@ -32,7 +32,6 @@
 #include "CanvasRenderingContext.h"
 #include "Chrome.h"
 #include "ChromeClient.h"
-#include "DocumentTimeline.h"
 #include "Frame.h"
 #include "FrameView.h"
 #include "FullscreenManager.h"
@@ -42,6 +41,7 @@
 #include "HTMLNames.h"
 #include "HitTestResult.h"
 #include "InspectorInstrumentation.h"
+#include "KeyframeEffectStack.h"
 #include "LayerAncestorClippingStack.h"
 #include "LayerOverlapMap.h"
 #include "Logging.h"
@@ -2778,9 +2778,14 @@
         return false;
 
     if (auto* element = renderer.element()) {
-        if (auto* timeline = element->document().existingTimeline()) {
-            if (timeline->runningAnimationsForElementAreAllAccelerated(*element))
-                return true;
+        if (auto* effectsStack = element->keyframeEffectStack()) {
+            return (effectsStack->isCurrentlyAffectingProperty(CSSPropertyOpacity)
+                && (usesCompositing() || (m_compositingTriggers & ChromeClient::AnimatedOpacityTrigger)))
+                || effectsStack->isCurrentlyAffectingProperty(CSSPropertyFilter)
+#if ENABLE(FILTERS_LEVEL_2)
+                || effectsStack->isCurrentlyAffectingProperty(CSSPropertyWebkitBackdropFilter)
+#endif
+                || effectsStack->isCurrentlyAffectingProperty(CSSPropertyTransform);
         }
     }
 
@@ -3337,13 +3342,14 @@
     if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
         return false;
 
-    if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
-        if (auto* element = renderer.element()) {
-            if (auto* timeline = element->document().existingTimeline())
-                return timeline->isRunningAnimationOnRenderer(renderer, CSSPropertyTransform);
-        }
+    if (auto* element = renderer.element()) {
+        if (auto* effectsStack = element->keyframeEffectStack())
+            return effectsStack->isCurrentlyAffectingProperty(CSSPropertyTransform);
+    }
+
+    if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
         return false;
-    }
+
     return renderer.animation().isRunningAnimationOnRenderer(renderer, CSSPropertyTransform);
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to