Source/WebCore:
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 24 Nov 2017 09:45:30 +0000 (09:45 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 24 Nov 2017 09:45:30 +0000 (09:45 +0000)
[Web Animations] Perform accelerated animations when possible
https://bugs.webkit.org/show_bug.cgi?id=179973
<rdar://problem/34953922>

Reviewed by Dean Jackson.

When we're entering and leaving the active duration of an animation effect, we now check
whether the animation can be accelerated, using the existing CSSPropertyAnimation::animationOfPropertyIsAccelerated()
utility, and start and stop animations using the startAnimation() and animationFinished() functions on RenderBoxModelObject.

This patch is only a first step towards full support for accelerated animations,
there are two known issues at the moment. Because we're not blending the styles to perform
the animation, getComputedStyle() will not return the animated value (webkit.org/b/179974).
Additionally, if other animations happen to run later during the active state of an animation
that can run accelerated, we will not fall back to software-only animation for this
element and these animations will appear not to run (webkit.org/b/179975). These will be
addressed in follow-up patches.

Tests: webanimations/left-and-opacity-animation-yields-no-compositing.html
       webanimations/opacity-animation-no-longer-composited-upon-completion.html
       webanimations/opacity-animation-yields-compositing.html
       webanimations/width-and-opacity-separate-animation-yields-no-compositing.html

* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::updateAnimations): Check in the map of pending accelerated animations
to see if any animation requires toggling their active state after their styles have been invalidated.
(WebCore::DocumentTimeline::animationAcceleratedRunningStateDidChange): New function to
let animations indicate that they need to have their accelerated backing animation toggled after
style invalidation has been completed.
(WebCore::DocumentTimeline::runningAnimationsForElementAreAllAccelerated): This function is used
in RenderLayerCompositor::requiresCompositingForAnimation() to identify whether an element requires
hardware compositing due to running accelerated animations. We check all running animations for the
provided element to see if they can all be running accelerated and return true in this situation only.
* animation/DocumentTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::applyAtLocalTime): Identify if we're crossing into or out of the active state
for an animation and check if it will be or has been running accelerated such that we can notify the
DocumentTimeline, through the associated animation, that the accelerated backing animation will need to
be toggled after style invalidation has been completed.
(WebCore::KeyframeEffect::shouldRunAccelerated): Check that all properties for this animation
effect can be accelerated according to CSSPropertyAnimation::animationOfPropertyIsAccelerated().
(WebCore::KeyframeEffect::startOrStopAccelerated): Start or stop the associated accelerated
animation through the associated element's RenderBoxModelObject renderer.
* animation/KeyframeEffect.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::acceleratedRunningStateDidChange): Called from AnimationEffect::applyAtLocalTime(),
we forward to the DocumentTimeline the information that the animation will cross an active state boundary while
allowing to be backed by hardware compositing.
(WebCore::WebAnimation::startOrStopAccelerated): Forward to the associated KeyframeEffect that accelerated
animation backing should be toggled.
* animation/WebAnimation.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::requiresCompositingForAnimation const): Check via the renderer's element's
DocumentTimeline that all running animations for this particular element are accelerated to ensure that
the element will be hardware-composited.

LayoutTests:
[Web Animations] Perform hardware-composited animations when possible
https://bugs.webkit.org/show_bug.cgi?id=179973
<rdar://problem/34953922>

Reviewed by Dean Jackson.

Add a series of tests to check that we use hardware-compositing for animations when possible.
Specifically, we check that:

1. Specifying both accelerated and non-accelerated properties for a single animation does *not*
yield hardware compositing (left-and-opacity-animation-yields-no-compositing.html).

2. Specifying both accelerated and non-accelerated properties via multiple animations does *not*
yield hardware compositing (width-and-opacity-separate-animation-yields-no-compositing.html).

3. Specifying only accelerated properties *does* yield hardware compositing
(opacity-animation-yields-compositing.html).

4. Hardware-composited animations no longer enforce hardware compositing after their completion
(opacity-animation-no-longer-composited-upon-completion.html).

* webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt: Added.
* webanimations/left-and-opacity-animation-yields-no-compositing.html: Added.
* webanimations/opacity-animation-no-longer-composited-upon-completion-expected.txt: Added.
* webanimations/opacity-animation-no-longer-composited-upon-completion.html: Added.
* webanimations/opacity-animation-yields-compositing-expected.txt: Added.
* webanimations/opacity-animation-yields-compositing.html: Added.
* webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt: Added.
* webanimations/width-and-opacity-separate-animation-yields-no-compositing.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@225128 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt [new file with mode: 0644]
LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html [new file with mode: 0644]
LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion-expected.txt [new file with mode: 0644]
LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion.html [new file with mode: 0644]
LayoutTests/webanimations/opacity-animation-yields-compositing-expected.txt [new file with mode: 0644]
LayoutTests/webanimations/opacity-animation-yields-compositing.html [new file with mode: 0644]
LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt [new file with mode: 0644]
LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/DocumentTimeline.h
Source/WebCore/animation/KeyframeEffect.cpp
Source/WebCore/animation/KeyframeEffect.h
Source/WebCore/animation/WebAnimation.cpp
Source/WebCore/animation/WebAnimation.h
Source/WebCore/rendering/RenderLayerCompositor.cpp

index 888669a..2752991 100644 (file)
@@ -1,3 +1,35 @@
+2017-11-23  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Perform hardware-composited animations when possible
+        https://bugs.webkit.org/show_bug.cgi?id=179973
+        <rdar://problem/34953922>
+
+        Reviewed by Dean Jackson.
+
+        Add a series of tests to check that we use hardware-compositing for animations when possible.
+        Specifically, we check that:
+        
+        1. Specifying both accelerated and non-accelerated properties for a single animation does *not*
+        yield hardware compositing (left-and-opacity-animation-yields-no-compositing.html).
+
+        2. Specifying both accelerated and non-accelerated properties via multiple animations does *not*
+        yield hardware compositing (width-and-opacity-separate-animation-yields-no-compositing.html).
+
+        3. Specifying only accelerated properties *does* yield hardware compositing
+        (opacity-animation-yields-compositing.html).
+
+        4. Hardware-composited animations no longer enforce hardware compositing after their completion
+        (opacity-animation-no-longer-composited-upon-completion.html).
+
+        * webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt: Added.
+        * webanimations/left-and-opacity-animation-yields-no-compositing.html: Added.
+        * webanimations/opacity-animation-no-longer-composited-upon-completion-expected.txt: Added.
+        * webanimations/opacity-animation-no-longer-composited-upon-completion.html: Added.
+        * webanimations/opacity-animation-yields-compositing-expected.txt: Added.
+        * webanimations/opacity-animation-yields-compositing.html: Added.
+        * webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt: Added.
+        * webanimations/width-and-opacity-separate-animation-yields-no-compositing.html: Added.
+
 2017-11-23  Carlos Alberto Lopez Perez  <clopez@igalia.com>
 
         REGRESSION(r225098): [GTK] Gardening of tests after r225098.
diff --git a/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt b/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing-expected.txt
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html b/LayoutTests/webanimations/left-and-opacity-animation-yields-no-compositing.html
new file mode 100644 (file)
index 0000000..9ee7110
--- /dev/null
@@ -0,0 +1,15 @@
+<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.timing.duration = 1000;
+
+testRunner.dumpAsText();
+document.getElementById("results").innerText = internals.layerTreeAsText(document);
+
+</script>
diff --git a/LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion-expected.txt b/LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion-expected.txt
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion.html b/LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion.html
new file mode 100644 (file)
index 0000000..9126f33
--- /dev/null
@@ -0,0 +1,20 @@
+<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"), [
+    { opacity: 1 },
+    { opacity: 0 }
+]));
+animation.startTime = 0;
+animation.effect.timing.duration = 100;
+
+testRunner.waitUntilDone();
+testRunner.dumpAsText();
+
+setTimeout(() => {
+    document.getElementById("results").innerText = internals.layerTreeAsText(document);
+    testRunner.notifyDone();
+}, animation.effect.timing.duration + 500);
+
+</script>
diff --git a/LayoutTests/webanimations/opacity-animation-yields-compositing-expected.txt b/LayoutTests/webanimations/opacity-animation-yields-compositing-expected.txt
new file mode 100644 (file)
index 0000000..2fc6d00
--- /dev/null
@@ -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)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/webanimations/opacity-animation-yields-compositing.html b/LayoutTests/webanimations/opacity-animation-yields-compositing.html
new file mode 100644 (file)
index 0000000..9932c87
--- /dev/null
@@ -0,0 +1,15 @@
+<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"), [
+    { opacity: 1 },
+    { opacity: 0 }
+]));
+animation.startTime = 0;
+animation.effect.timing.duration = 1000;
+
+testRunner.dumpAsText();
+document.getElementById("results").innerText = internals.layerTreeAsText(document);
+
+</script>
diff --git a/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt b/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing-expected.txt
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing.html b/LayoutTests/webanimations/width-and-opacity-separate-animation-yields-no-compositing.html
new file mode 100644 (file)
index 0000000..cbb4d7c
--- /dev/null
@@ -0,0 +1,22 @@
+<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.timing.duration = 1000;
+
+const widthAnimation = new Animation(new KeyframeEffect(document.getElementById("target"), [
+    { width: "100px" },
+    { width: "200px" }
+]));
+widthAnimation.startTime = 0;
+widthAnimation.effect.timing.duration = 1000;
+
+testRunner.dumpAsText();
+document.getElementById("results").innerText = internals.layerTreeAsText(document);
+
+</script>
index 70761c6..e48fe1f 100644 (file)
@@ -1,3 +1,61 @@
+2017-11-23  Antoine Quint  <graouts@apple.com>
+
+        [Web Animations] Perform accelerated animations when possible
+        https://bugs.webkit.org/show_bug.cgi?id=179973
+        <rdar://problem/34953922>
+
+        Reviewed by Dean Jackson.
+
+        When we're entering and leaving the active duration of an animation effect, we now check
+        whether the animation can be accelerated, using the existing CSSPropertyAnimation::animationOfPropertyIsAccelerated()
+        utility, and start and stop animations using the startAnimation() and animationFinished() functions on RenderBoxModelObject.
+
+        This patch is only a first step towards full support for accelerated animations,
+        there are two known issues at the moment. Because we're not blending the styles to perform
+        the animation, getComputedStyle() will not return the animated value (webkit.org/b/179974).
+        Additionally, if other animations happen to run later during the active state of an animation
+        that can run accelerated, we will not fall back to software-only animation for this
+        element and these animations will appear not to run (webkit.org/b/179975). These will be
+        addressed in follow-up patches.
+
+        Tests: webanimations/left-and-opacity-animation-yields-no-compositing.html
+               webanimations/opacity-animation-no-longer-composited-upon-completion.html
+               webanimations/opacity-animation-yields-compositing.html
+               webanimations/width-and-opacity-separate-animation-yields-no-compositing.html
+
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::updateAnimations): Check in the map of pending accelerated animations
+        to see if any animation requires toggling their active state after their styles have been invalidated.
+        (WebCore::DocumentTimeline::animationAcceleratedRunningStateDidChange): New function to
+        let animations indicate that they need to have their accelerated backing animation toggled after
+        style invalidation has been completed.
+        (WebCore::DocumentTimeline::runningAnimationsForElementAreAllAccelerated): This function is used
+        in RenderLayerCompositor::requiresCompositingForAnimation() to identify whether an element requires
+        hardware compositing due to running accelerated animations. We check all running animations for the
+        provided element to see if they can all be running accelerated and return true in this situation only.
+        * animation/DocumentTimeline.h:
+        * animation/KeyframeEffect.cpp:
+        (WebCore::KeyframeEffect::applyAtLocalTime): Identify if we're crossing into or out of the active state
+        for an animation and check if it will be or has been running accelerated such that we can notify the
+        DocumentTimeline, through the associated animation, that the accelerated backing animation will need to
+        be toggled after style invalidation has been completed.
+        (WebCore::KeyframeEffect::shouldRunAccelerated): Check that all properties for this animation
+        effect can be accelerated according to CSSPropertyAnimation::animationOfPropertyIsAccelerated().
+        (WebCore::KeyframeEffect::startOrStopAccelerated): Start or stop the associated accelerated
+        animation through the associated element's RenderBoxModelObject renderer.
+        * animation/KeyframeEffect.h:
+        * animation/WebAnimation.cpp:
+        (WebCore::WebAnimation::acceleratedRunningStateDidChange): Called from AnimationEffect::applyAtLocalTime(),
+        we forward to the DocumentTimeline the information that the animation will cross an active state boundary while
+        allowing to be backed by hardware compositing.
+        (WebCore::WebAnimation::startOrStopAccelerated): Forward to the associated KeyframeEffect that accelerated
+        animation backing should be toggled.
+        * animation/WebAnimation.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::requiresCompositingForAnimation const): Check via the renderer's element's
+        DocumentTimeline that all running animations for this particular element are accelerated to ensure that
+        the element will be hardware-composited.
+
 2017-11-23  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         [Win] PasteboardWin.cpp(653): error C2039: 'containsOnlyASCII': is not a member of 'WTF::String'
index b0fd6d7..72576cb 100644 (file)
@@ -32,6 +32,7 @@
 #include "DisplayRefreshMonitor.h"
 #include "DisplayRefreshMonitorManager.h"
 #include "Document.h"
+#include "KeyframeEffect.h"
 #include "Page.h"
 
 static const Seconds animationInterval { 15_ms };
@@ -165,10 +166,32 @@ void DocumentTimeline::updateAnimations()
         m_document->updateStyleIfNeeded();
     }
 
+    for (auto animation : m_acceleratedAnimationsPendingRunningStateChange)
+        animation->startOrStopAccelerated();
+    m_acceleratedAnimationsPendingRunningStateChange.clear();
+
     // Time has advanced, the timing model requires invalidation now.
     animationTimingModelDidChange();
 }
 
+void DocumentTimeline::animationAcceleratedRunningStateDidChange(WebAnimation& animation)
+{
+    m_acceleratedAnimationsPendingRunningStateChange.add(&animation);
+}
+
+bool DocumentTimeline::runningAnimationsForElementAreAllAccelerated(Element& element)
+{
+    // FIXME: This will let animations run using hardware compositing even if later in the active
+    // span of the current animations a new animation should require hardware compositing to be
+    // disabled (webkit.org/b/179974).
+    auto animations = animationsForElement(element);
+    for (const auto& animation : animations) {
+        if (animation->effect() && animation->effect()->isKeyframeEffect() && !downcast<KeyframeEffect>(animation->effect())->isRunningAccelerated())
+            return false;
+    }
+    return !animations.isEmpty();
+}
+
 void DocumentTimeline::windowScreenDidChange(PlatformDisplayID displayID)
 {
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
index 30060f6..8c22af3 100644 (file)
@@ -52,6 +52,8 @@ public:
     void animationTimingModelDidChange() override;
     void windowScreenDidChange(PlatformDisplayID);
 
+    void animationAcceleratedRunningStateDidChange(WebAnimation&);
+    bool runningAnimationsForElementAreAllAccelerated(Element&);
     void detachFromDocument();
 
 private:
@@ -70,6 +72,7 @@ private:
     GenericTaskQueue<Timer> m_invalidationTaskQueue;
     bool m_needsUpdateAnimationSchedule { false };
     Timer m_animationScheduleTimer;
+    HashSet<RefPtr<WebAnimation>> m_acceleratedAnimationsPendingRunningStateChange;
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     // Override for DisplayRefreshMonitorClient
index f28928f..39bc715 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "KeyframeEffect.h"
 
+#include "Animation.h"
 #include "CSSPropertyAnimation.h"
 #include "Element.h"
 #include "RenderStyle.h"
@@ -146,6 +147,11 @@ void KeyframeEffect::applyAtLocalTime(Seconds localTime, RenderStyle& targetStyl
     if (!m_target)
         return;
 
+    if (m_startedAccelerated && localTime >= timing()->duration()) {
+        m_startedAccelerated = false;
+        animation()->acceleratedRunningStateDidChange();
+    }
+
     // FIXME: Assume animations only apply in the range [0, duration[
     // until we support fill modes, delays and iterations.
     if (localTime < 0_s || localTime >= timing()->duration())
@@ -154,10 +160,21 @@ void KeyframeEffect::applyAtLocalTime(Seconds localTime, RenderStyle& targetStyl
     if (!timing()->duration())
         return;
 
-    float progress = localTime / timing()->duration();
+    bool needsToStartAccelerated = false;
+
+    if (!m_started && !m_startedAccelerated) {
+        needsToStartAccelerated = shouldRunAccelerated();
+        m_startedAccelerated = needsToStartAccelerated;
+        if (needsToStartAccelerated)
+            animation()->acceleratedRunningStateDidChange();
+    }
+    m_started = true;
 
-    for (auto cssPropertyId : m_keyframes.properties())
-        CSSPropertyAnimation::blendProperties(this, cssPropertyId, &targetStyle, m_keyframes[0].style(), m_keyframes[1].style(), progress);
+    if (!needsToStartAccelerated && !m_startedAccelerated) {
+        float progress = localTime / timing()->duration();
+        for (auto cssPropertyId : m_keyframes.properties())
+            CSSPropertyAnimation::blendProperties(this, cssPropertyId, &targetStyle, m_keyframes[0].style(), m_keyframes[1].style(), progress);
+    }
 
     // https://w3c.github.io/web-animations/#side-effects-section
     // For every property targeted by at least one animation effect that is current or in effect, the user agent
@@ -166,6 +183,33 @@ void KeyframeEffect::applyAtLocalTime(Seconds localTime, RenderStyle& targetStyl
         targetStyle.setZIndex(0);
 }
 
+bool KeyframeEffect::shouldRunAccelerated()
+{
+    for (auto cssPropertyId : m_keyframes.properties()) {
+        if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId))
+            return false;
+    }
+    return true;
+}
+
+void KeyframeEffect::startOrStopAccelerated()
+{
+    auto* renderer = this->renderer();
+    if (!renderer || !renderer->isComposited())
+        return;
+
+    auto* compositedRenderer = downcast<RenderBoxModelObject>(renderer);
+    if (m_startedAccelerated) {
+        auto animation = Animation::create();
+        animation->setDuration(timing()->duration().value());
+        compositedRenderer->startAnimation(0, animation.ptr(), m_keyframes);
+    } else {
+        compositedRenderer->animationFinished(m_keyframes.animationName());
+        if (!m_target->document().renderTreeBeingDestroyed())
+            m_target->invalidateStyleAndLayerComposition();
+    }
+}
+
 RenderElement* KeyframeEffect::renderer() const
 {
     return m_target ? m_target->renderer() : nullptr;
index bb49dfe..c3e5f41 100644 (file)
@@ -44,6 +44,8 @@ public:
     Element* target() const { return m_target.get(); }
     ExceptionOr<void> setKeyframes(JSC::ExecState&, JSC::Strong<JSC::JSObject>&&);
     void applyAtLocalTime(Seconds, RenderStyle&) override;
+    void startOrStopAccelerated();
+    bool isRunningAccelerated() const { return m_startedAccelerated; }
 
     RenderElement* renderer() const override;
     const RenderStyle& currentStyle() const override;
@@ -58,10 +60,13 @@ private:
     KeyframeEffect(Element*);
     ExceptionOr<void> processKeyframes(JSC::ExecState&, JSC::Strong<JSC::JSObject>&&);
     void computeStackingContextImpact();
+    bool shouldRunAccelerated();
 
     RefPtr<Element> m_target;
     KeyframeList m_keyframes;
     bool m_triggersStackingContext { false };
+    bool m_started { false };
+    bool m_startedAccelerated { false };
 
 };
 
index 54e2934..5d670e1 100644 (file)
@@ -243,6 +243,18 @@ void WebAnimation::resolve(RenderStyle& targetStyle)
         m_effect->applyAtLocalTime(currentTime().value(), targetStyle);
 }
 
+void WebAnimation::acceleratedRunningStateDidChange()
+{
+    if (m_timeline && m_timeline->isDocumentTimeline())
+        downcast<DocumentTimeline>(*m_timeline).animationAcceleratedRunningStateDidChange(*this);
+}
+
+void WebAnimation::startOrStopAccelerated()
+{
+    if (m_effect && m_effect->isKeyframeEffect())
+        downcast<KeyframeEffect>(*m_effect).startOrStopAccelerated();
+}
+
 String WebAnimation::description()
 {
     return "Animation";
index 0eb236f..ae9c28d 100644 (file)
@@ -65,6 +65,8 @@ public:
 
     Seconds timeToNextRequiredTick(Seconds) const;
     void resolve(RenderStyle&);
+    void acceleratedRunningStateDidChange();
+    void startOrStopAccelerated();
 
     String description();
 
index 5dd0065..42a4e62 100644 (file)
@@ -32,6 +32,7 @@
 #include "CanvasRenderingContext.h"
 #include "Chrome.h"
 #include "ChromeClient.h"
+#include "DocumentTimeline.h"
 #include "Frame.h"
 #include "FrameView.h"
 #include "GraphicsLayer.h"
@@ -2470,6 +2471,13 @@ bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObje
     if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
         return false;
 
+    if (auto* element = renderer.element()) {
+        if (auto* timeline = element->document().existingTimeline()) {
+            if (timeline->runningAnimationsForElementAreAllAccelerated(*element))
+                return true;
+        }
+    }
+
     const AnimationBase::RunningState activeAnimationState = AnimationBase::Running | AnimationBase::Paused;
     auto& animController = renderer.animation();
     return (animController.isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity, activeAnimationState)