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

Reply via email to