Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: f27e060bbaf0b9b69e085ab05fbe447cc17536d0
https://github.com/WebKit/WebKit/commit/f27e060bbaf0b9b69e085ab05fbe447cc17536d0
Author: Antoine Quint <[email protected]>
Date: 2025-12-06 (Sat, 06 Dec 2025)
Changed paths:
A
LayoutTests/webanimations/threaded-animations/remote-progress-based-timeline-preservation-with-new-remote-animation-stack-expected.txt
A
LayoutTests/webanimations/threaded-animations/remote-progress-based-timeline-preservation-with-new-remote-animation-stack.html
M Source/WebCore/animation/AcceleratedEffectStackUpdater.cpp
M Source/WebCore/animation/AcceleratedEffectStackUpdater.h
M Source/WebCore/animation/AnimationTimeline.cpp
M Source/WebCore/animation/AnimationTimeline.h
M Source/WebCore/animation/KeyframeEffect.cpp
M Source/WebCore/animation/KeyframeEffect.h
M Source/WebCore/animation/ScrollTimeline.cpp
M Source/WebCore/animation/ScrollTimeline.h
M Source/WebCore/animation/ViewTimeline.cpp
M Source/WebCore/platform/animation/AcceleratedEffect.cpp
M Source/WebCore/platform/animation/AcceleratedEffect.h
M Source/WebCore/platform/animation/AcceleratedTimeline.cpp
M Source/WebCore/platform/animation/AcceleratedTimeline.h
M Source/WebCore/rendering/RenderLayerBacking.cpp
M Source/WebCore/testing/Internals.cpp
M Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTree.serialization.in
M Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h
M Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm
M
Source/WebKit/UIProcess/RemoteLayerTree/RemoteMonotonicTimelineRegistry.cpp
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteMonotonicTimelineRegistry.h
M
Source/WebKit/UIProcess/RemoteLayerTree/RemoteProgressBasedTimelineRegistry.cpp
M
Source/WebKit/UIProcess/RemoteLayerTree/RemoteProgressBasedTimelineRegistry.h
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.cpp
M Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.h
M
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.h
M
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm
M
Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h
M
Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.mm
M
Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteScrollingCoordinatorProxyMac.h
M
Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteScrollingCoordinatorProxyMac.mm
M Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm
Log Message:
-----------
[threaded-animations] creating a new animation removes the timeline for a
previous animation
https://bugs.webkit.org/show_bug.cgi?id=303655
rdar://165937022
Reviewed by Simon Fraser.
If a scroll-driven animation is created for a given target, and later on a
different
scroll-driven animation is created for another target, then the timeline for
the first
animation is removed from the remote layer tree.
This is due to our ill-conceived method to gather relevant timelines for a
given remote
layer tree transaction and updating them upon reception in the remote layer
tree. Indeed,
until now, when we would create an update, we would gather all elements marked
as required
an update in `AcceleratedEffectStackUpdater::update()` and keep a list of all
timelines
seen for animations targeting said elements. For each such update, that list of
timelines
would replace the one from the previous update, and would be made available in
the remote
layer tree transaction.
As such, if we weren't updating animations for the same elements that were
previously updated,
their timelines would be forgotten and the logic on the remote layer tree side
would assume
they needed to be removed.
Additionally, we also naively always considered that timelines were part of the
remote layer
tree transaction, assuming an empty list of timelines meant all timelines
needed to be removed.
This meant that, even on pages where we never had timelines, we would attempt
to update our
timelines registration on each remote layer tree transaction.
We overhaul this entire system by doing two main things.
First, we rethink the accelerated timeline ownership in the Web process such
that the only
object that has a strong pointer (`RefPtr`) are the accelerated effects that
are stored on
the GraphicsLayer matching the animation's target element. The
`AcceleratedEffectStackUpdater`
maintains a list of known timelines but keeps weak pointers (`WeakPtr`), so
does `AnimationTimeline`
for its accelerated representation. This now means that if, during an update,
all of the effects
linked to a given timeline are removed, the timeline will no longer have strong
references
and `AcceleratedEffectStackUpdater` will be able to check for null pointers and
determine these
timelines indeed need to be destroyed.
Second, we now have a dedicated `TimelinesUpdate` struct used in remote layer
tree transactions
sorting timelines in three categories: `created`, `modified` and `destroyed`.
In the new system
outlined above, `AcceleratedEffectStackUpdater` is able to determine, during an
update, how to
categorize timelines, making it clear on the receiving end, the remote layer
tree, which timelines
to register, update and remove. Additionally, we can now determine if the
remote layer tree
transaction contains any timelines to update and will do no processing
whatsoever if we figure
out there are no timelines in any of those three buckets.
A new test validates that this new approach works as expected and we can update
animations associated
with different targets across different updates.
Additional details as necessary in the function-per-function ChangeLog below.
Test:
webanimations/threaded-animations/remote-progress-based-timeline-preservation-with-new-remote-animation-stack.html
*
LayoutTests/webanimations/threaded-animations/remote-progress-based-timeline-preservation-with-new-remote-animation-stack-expected.txt:
Added.
*
LayoutTests/webanimations/threaded-animations/remote-progress-based-timeline-preservation-with-new-remote-animation-stack.html:
Added.
* Source/WebCore/animation/AcceleratedEffectStackUpdater.cpp:
(WebCore::AcceleratedEffectStackUpdater::update):
(WebCore::AcceleratedEffectStackUpdater::scrollTimelineDidChange):
(WebCore::AcceleratedEffectStackUpdater::takeTimelinesUpdate):
* Source/WebCore/animation/AcceleratedEffectStackUpdater.h:
(WebCore::AcceleratedEffectStackUpdater::timelines const): Deleted.
* Source/WebCore/animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::acceleratedRepresentation): Return a Ref that will
be stored by the `AcceleratedEffect` caller, keeping only a
weak pointer to that timeline as a member.
(WebCore::AnimationTimeline::runPostRenderingUpdateTasks): Make sure _not_ to
clear the accelerated representation pointer as we now want
to keep the `AcceleratedTimeline` instance as long as it is used by an
`AcceleratedEffect`.
* Source/WebCore/animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::acceleratedTimelineIdentifier const):
(WebCore::AnimationTimeline::acceleratedTimelineIdentifierForTesting const):
Deleted.
* Source/WebCore/animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::acceleratedRepresentation): Return a `Ref` instead of
a `RefPtr` now that we know `AcceleratedEffect` will also
return a `Ref` always.
(WebCore::KeyframeEffect::animationProgressBasedTimelineSourceDidChangeMetrics):
No need to trigger an animation update here, scroll timelines
themselves will inform `AcceleratedEffectStackUpdater` that they require an
update, not needing the animation stack to be updated.
(WebCore::KeyframeEffect::updatedAcceleratedRepresentation): Deleted.
* Source/WebCore/animation/KeyframeEffect.h:
* Source/WebCore/animation/ScrollTimeline.cpp:
(WebCore::ScrollTimeline::cacheCurrentTime):
(WebCore::ScrollTimeline::sourceMetricsDidChange): Introduce this new protected
method to be called also by `ViewTimeline` when metrics change,
informing `AcceleratedEffectStackUpdater` that the accelerated representation
needs to be updated.
(WebCore::ScrollTimeline::scheduleAcceleratedRepresentationUpdate):
(WebCore::ScrollTimeline::computeProgressResolutionData const): New function to
compute the `ProgressResolutionData` such that it can be used
both when an update is needed, or when the accelerated representation is
created.
(WebCore::ScrollTimeline::updateAcceleratedRepresentation):
(WebCore::ScrollTimeline::createAcceleratedRepresentation const):
(WebCore::ScrollTimeline::scrollingNodeIDForTesting const):
* Source/WebCore/animation/ScrollTimeline.h:
* Source/WebCore/animation/ViewTimeline.cpp:
(WebCore::ViewTimeline::cacheCurrentTime):
* Source/WebCore/platform/animation/AcceleratedEffect.cpp:
(WebCore::AcceleratedEffect::create): Switch this method to a `Ref` which is a
more common idiom that returning a `RefPtr`. The logic previously
used to determine whether this effect should be accelerated is now contained in
`RenderLayerBacking::updateAcceleratedEffectsAndBaseValues()`.
(WebCore::AcceleratedEffect::AcceleratedEffect): Create and store the
accelerated timeline as a strong pointer.
* Source/WebCore/platform/animation/AcceleratedEffect.h:
* Source/WebCore/platform/animation/AcceleratedTimeline.cpp:
(WebCore::AcceleratedTimeline::setProgressResolutionData):
* Source/WebCore/platform/animation/AcceleratedTimeline.h:
(WebCore::AcceleratedTimelinesUpdate::isEmpty const):
* Source/WebCore/rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateAcceleratedEffectsAndBaseValues):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::identifierForTimeline const):
* Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTree.serialization.in:
* Source/WebKit/Shared/RemoteLayerTree/RemoteLayerTreeTransaction.h:
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::updateTimelinesRegistration):
(WebKit::RemoteLayerTreeDrawingAreaProxy::animationStackForNodeWithIDForTesting
const):
(WebKit::RemoteLayerTreeDrawingAreaProxy::updateTimelineRegistration): Deleted.
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:
(WebKit::RemoteLayerTreeHost::updateLayerTree): Only initiate a timelines
registration update if we have any data.
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteMonotonicTimelineRegistry.cpp:
(WebKit::RemoteMonotonicTimelineRegistry::update): change the registration code
to work the new `TimelinesUpdate` struct and its
three `created`, `modified` and `destroyed` buckets.
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteMonotonicTimelineRegistry.h:
*
Source/WebKit/UIProcess/RemoteLayerTree/RemoteProgressBasedTimelineRegistry.cpp:
(WebKit::RemoteProgressBasedTimelineRegistry::update): change the registration
code to work the new `TimelinesUpdate` struct and
its three `created`, `modified` and `destroyed` buckets.
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteProgressBasedTimelineRegistry.h:
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
(WebKit::RemoteScrollingCoordinatorProxy::updateTimelinesRegistration):
(WebKit::RemoteScrollingCoordinatorProxy::updateTimelineRegistration): Deleted.
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.cpp:
(WebKit::RemoteScrollingTree::updateTimelinesRegistration):
(WebKit::RemoteScrollingTree::updateTimelineRegistration): Deleted.
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingTree.h:
*
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.h:
*
Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteScrollingCoordinatorProxyIOS.mm:
(WebKit::RemoteScrollingCoordinatorProxyIOS::updateTimelinesRegistration):
(WebKit::RemoteScrollingCoordinatorProxyIOS::updateTimelineRegistration):
Deleted.
* Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h:
* Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.mm:
(WebKit::RemoteLayerTreeEventDispatcher::updateTimelinesRegistration):
(WebKit::RemoteLayerTreeEventDispatcher::updateTimelineRegistration): Deleted.
*
Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteScrollingCoordinatorProxyMac.h:
*
Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteScrollingCoordinatorProxyMac.mm:
(WebKit::RemoteScrollingCoordinatorProxyMac::updateTimelinesRegistration):
(WebKit::RemoteScrollingCoordinatorProxyMac::updateTimelineRegistration):
Deleted.
* Source/WebKit/WebProcess/WebPage/Cocoa/WebPageCocoa.mm:
(WebKit::WebPage::willCommitLayerTree): Assemble all the `TimelinesUpdate` for
all documents into a single update.
Canonical link: https://commits.webkit.org/304042@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications