Bug 215229 - Step animations invalidate style on every rendering update whether or not they need to
Summary: Step animations invalidate style on every rendering update whether or not the...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Animations (show other bugs)
Version: Safari Technology Preview
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-08-06 11:17 PDT by Simon Fraser (smfr)
Modified: 2020-08-27 22:26 PDT (History)
6 users (show)

See Also:


Attachments
wip (2.52 KB, patch)
2020-08-27 06:11 PDT, Antti Koivisto
no flags Details | Formatted Diff | Diff
patch (2.78 KB, patch)
2020-08-27 07:29 PDT, Antti Koivisto
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Fraser (smfr) 2020-08-06 11:17:08 PDT
DocumentTimelinesController::updateAnimationsAndSendEvents() is called on every rendering update. It calls DeclarativeAnimation::tick(), which calls down to KeyframeEffect::invalidate() for every animation that is not suspended, unconditionally.

That means that every rendering update (which may be triggered by something other than animations) invalidates style, thus causing a style update, which is a power hit.


  * frame #0: 0x000000069a53549c WebCore`WebCore::KeyframeEffect::invalidate(this=0x00000006bbcc6ae0) at KeyframeEffect.cpp:1241:23
    frame #1: 0x000000069a53608d WebCore`WebCore::KeyframeEffect::animationDidTick(this=0x00000006bbcc6ae0) at KeyframeEffect.cpp:1547:5
    frame #2: 0x000000069a53ec3d WebCore`WebCore::WebAnimation::tick(this=0x00000006bbbd3c50) at WebAnimation.cpp:1238:19
    frame #3: 0x000000069a500c65 WebCore`WebCore::DeclarativeAnimation::tick(this=0x00000006bbbd3c50) at DeclarativeAnimation.cpp:68:19
    frame #4: 0x000000069a52b768 WebCore`WebCore::DocumentTimelinesController::updateAnimationsAndSendEvents(this=0x00000006bbc16550, timestamp=(m_value = 24.493000000000002)) at DocumentTimelinesController.cpp:117:24
    frame #5: 0x000000069b8ef2cc WebCore`WebCore::Page::updateRendering(this=0x00000006bbc72a58, document={ origin = file://, url = file:///Volumes/Data/Development/system/webkit/testcontent/scrolling/scrolling-tree/fixed-node-order.html, inMainFrame = 1, backForwardCacheState = NotInBackForwardCache })::$_23::operator()(WebCore::Document&) const at Page.cpp:1479:34
    frame #6: 0x000000069b8ef233 WebCore`WTF::Detail::CallableWrapper<WebCore::Page::updateRendering()::$_23, void, WebCore::Document&>::call(this=0x00000006bbc72a50, in={ origin = file://, url = file:///Volumes/Data/Development/system/webkit/testcontent/scrolling/scrolling-tree/fixed-node-order.html, inMainFrame = 1, backForwardCacheState = NotInBackForwardCache }) at Function.h:52:39
    frame #7: 0x000000069b8b826a WebCore`WTF::Function<void (WebCore::Document&)>::operator(this=0x00007ffee2261028, in={ origin = file://, url = file:///Volumes/Data/Development/system/webkit/testcontent/scrolling/scrolling-tree/fixed-node-order.html, inMainFrame = 1, backForwardCacheState = NotInBackForwardCache })(WebCore::Document&) const at Function.h:83:35
    frame #8: 0x000000069b8aa9dc WebCore`WebCore::Page::forEachDocument(this=0x00000006bd9fa000, functor=0x00007ffee2261028)> const&) const at Page.cpp:3109:9
    frame #9: 0x000000069b8b115d WebCore`WebCore::Page::updateRendering(this=0x00000006bd9fa000) at Page.cpp:1474:5
    frame #10: 0x000000010f36a056 WebKit`WebKit::WebPage::updateRendering(this=0x00007f8839009008) at WebPage.cpp:3864:13
    frame #11: 0x000000010edbb4e0 WebKit`WebKit::TiledCoreAnimationDrawingArea::updateRendering(this=0x00000006bbced880, flushType=Normal) at TiledCoreAnimationDrawingArea.mm:459:19
    frame #12: 0x000000010edbfded WebKit`WebKit::TiledCoreAnimationDrawingArea::updateRenderingRunLoopCallback(this=0x00000006bbced880) at TiledCoreAnimationDrawingArea.mm:911:5
    frame #13: 0x000000010edd0168 WebKit`WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea(this=0x00000006bbcfafb8)::$_0::operator()() const at TiledCoreAnimationDrawingArea.mm:88:15
Comment 1 Radar WebKit Bug Importer 2020-08-06 11:17:36 PDT
<rdar://problem/66636153>
Comment 2 Simon Fraser (smfr) 2020-08-06 12:51:26 PDT
This is tested by the (failing) animations/steps-transform-rendering-updates.html
Comment 3 Antti Koivisto 2020-08-27 06:11:38 PDT
Created attachment 407395 [details]
wip
Comment 4 Antti Koivisto 2020-08-27 07:15:10 PDT
This bug is specific to step timing functions. Rendering updates will tick animations only if DocumentTimeline::m_animationResolutionScheduled bit is set which correctly doesn't happen during accelerated animations.

Step timing functions with transforms try and fail to start accelerated which causes them to repeatedly schedule unnecessary rendering updates.
Comment 5 Antti Koivisto 2020-08-27 07:29:22 PDT
Created attachment 407397 [details]
patch
Comment 6 EWS 2020-08-27 08:42:12 PDT
Committed r266232: <https://trac.webkit.org/changeset/266232>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 407397 [details].
Comment 7 Simon Fraser (smfr) 2020-08-27 09:46:52 PDT
Comment on attachment 407397 [details]
patch

View in context: https://bugs.webkit.org/attachment.cgi?id=407397&action=review

> Source/WebCore/animation/KeyframeEffect.cpp:1498
> +    if (m_acceleratedPropertiesState == AcceleratedProperties::None || m_someKeyframesUseStepsTimingFunction || is<StepsTimingFunction>(timingFunction()))

It's GraphicsLayerCA that decides that it can't accelerate animations with steps() timing functions, so adding this code here is spreading that logic around into two places. Not great.
Comment 8 Antti Koivisto 2020-08-27 12:16:17 PDT
GraphicsLayerCA is a totally wrong place for that sort of logic. Duplication can be removed after the legacy animation code is removed.
Comment 9 Simon Fraser (smfr) 2020-08-27 12:36:58 PDT
But the idea is that some native platforms might be able to support steps() natively. You're hard-coding Core Animation limitations into cross-platform code.
Comment 10 Antti Koivisto 2020-08-27 13:30:25 PDT
We should have a better way to communicate that sort of information to the animation engine (when we actually have a reason to abstract it).
Comment 11 Antoine Quint 2020-08-27 15:10:32 PDT
We can probably have this logic sit somewhere in between GraphicsLayerCA and KeyframeEffect that would allow for some platform-specific logic.
Comment 12 Antti Koivisto 2020-08-27 22:26:14 PDT
Specific accelerated properties are already hardcoded in animation code. This seems like a much bigger deal if we want to be (unnecessarily?) generic.