Skip to content

Commit

Permalink
[threaded-animation-resolution] Schedule animation updates from Remot…
Browse files Browse the repository at this point in the history
…eLayerTreeEventDispatcher on the scrolling thread.

https://bugs.webkit.org/show_bug.cgi?id=266026
<rdar://119341112>

Reviewed by Simon Fraser.

RemoteLayerTreeEventDispatcher can update the current set of animations at the
same time it applies any asynchronous scrolls.

This should align them with rendering updates (when scroll synchronisation
succeeds), and make it simpler to integrate scroll-linked animations

iOS doesn't use RemoteLayerTreeEventDispatcher/scrolling thread, so will
need a separate solution to schedule animation updates.

* Source/WebKit/UIProcess/RemoteLayerTree/RemoteAcceleratedEffectStack.h:
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteAcceleratedEffectStack.mm:
(WebKit::RemoteAcceleratedEffectStack::initEffectsFromMainThread):
(WebKit::RemoteAcceleratedEffectStack::applyEffectsFromScrollingThread const):
(WebKit::RemoteAcceleratedEffectStack::clear):
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
(WebKit::RemoteLayerTreeDrawingAreaProxy::animationCurrentTime const):
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTreeTransaction):
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.h:
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeHost.mm:
(WebKit::RemoteLayerTreeHost::animationCurrentTime const):
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.h:
(WebKit::RemoteLayerTreeNode::effectStack const):
* Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.mm:
(WebKit::RemoteLayerTreeNode::~RemoteLayerTreeNode):
(WebKit::RemoteLayerTreeNode::setAcceleratedEffectsAndBaseValues):
* Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.cpp:
(WebKit::RemoteLayerTreeEventDispatcher::startOrStopDisplayLinkOnMainThread):
(WebKit::RemoteLayerTreeEventDispatcher::didRefreshDisplay):
(WebKit::RemoteLayerTreeEventDispatcher::delayedRenderingUpdateDetectionTimerFired):
(WebKit::RemoteLayerTreeEventDispatcher::waitForRenderingUpdateCompletionOrTimeout):
(WebKit::RemoteLayerTreeEventDispatcher::scrollingTreeWasRecentlyActive):
(WebKit::RemoteLayerTreeEventDispatcher::lockForAnimationChanges):
(WebKit::RemoteLayerTreeEventDispatcher::unlockForAnimationChanges):
(WebKit::RemoteLayerTreeEventDispatcher::animationsWereAddedToNode):
(WebKit::RemoteLayerTreeEventDispatcher::animationsWereRemovedFromNode):
(WebKit::RemoteLayerTreeEventDispatcher::updateAnimations):
* Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.h:
(WebKit::RemoteLayerTreeEventDispatcher::animationsLock):
* Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteScrollingCoordinatorProxyMac.mm:
(WebKit::RemoteScrollingCoordinatorProxyMac::willCommitLayerAndScrollingTrees):
(WebKit::RemoteScrollingCoordinatorProxyMac::didCommitLayerAndScrollingTrees):

Canonical link: https://commits.webkit.org/273391@main
  • Loading branch information
mattwoodrow committed Jan 24, 2024
1 parent 8118734 commit e183df8
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#if ENABLE(THREADED_ANIMATION_RESOLUTION)

#include <WebCore/AcceleratedEffectStack.h>
#include <WebCore/PlatformLayer.h>

namespace WebKit {

Expand All @@ -36,6 +37,13 @@ class RemoteAcceleratedEffectStack final : public WebCore::AcceleratedEffectStac
public:
static Ref<RemoteAcceleratedEffectStack> create(Seconds);

#if PLATFORM(MAC)
void initEffectsFromMainThread(PlatformLayer*, MonotonicTime now);
void applyEffectsFromScrollingThread(MonotonicTime now) const;
#endif

void clear(PlatformLayer*);

private:
explicit RemoteAcceleratedEffectStack(Seconds);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@
{
}

#if PLATFORM(MAC)
void RemoteAcceleratedEffectStack::initEffectsFromMainThread(PlatformLayer*, MonotonicTime)
{
}

void RemoteAcceleratedEffectStack::applyEffectsFromScrollingThread(MonotonicTime) const
{
}
#endif

void RemoteAcceleratedEffectStack::clear(PlatformLayer*)
{
}

} // namespace WebKit

#endif // ENABLE(THREADED_ANIMATION_RESOLUTION)
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class RemoteLayerTreeDrawingAreaProxy : public DrawingAreaProxy {
void animationsWereAddedToNode(RemoteLayerTreeNode&);
void animationsWereRemovedFromNode(RemoteLayerTreeNode&);
Seconds acceleratedTimelineTimeOrigin() const { return m_acceleratedTimelineTimeOrigin; }
MonotonicTime animationCurrentTime() const { return m_animationCurrentTime; }
#endif

// For testing.
Expand Down Expand Up @@ -186,6 +187,7 @@ class RemoteLayerTreeDrawingAreaProxy : public DrawingAreaProxy {

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
Seconds m_acceleratedTimelineTimeOrigin;
MonotonicTime m_animationCurrentTime;
#endif
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
m_acceleratedTimelineTimeOrigin = layerTreeTransaction.acceleratedTimelineTimeOrigin();
m_animationCurrentTime = MonotonicTime::now();
#endif

webPageProxy->scrollingCoordinatorProxy()->willCommitLayerAndScrollingTrees();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class RemoteLayerTreeHost {

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
Seconds acceleratedTimelineTimeOrigin() const;
MonotonicTime animationCurrentTime() const;
#endif

void remotePageProcessCrashed(WebCore::ProcessIdentifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,11 @@ static void recursivelyMapIOSurfaceBackingStore(CALayer *layer)
{
return m_drawingArea->acceleratedTimelineTimeOrigin();
}

MonotonicTime RemoteLayerTreeHost::animationCurrentTime() const
{
return m_drawingArea->animationCurrentTime();
}
#endif

void RemoteLayerTreeHost::remotePageProcessCrashed(WebCore::ProcessIdentifier processIdentifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class RemoteLayerTreeNode : public CanMakeWeakPtr<RemoteLayerTreeNode> {

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
void setAcceleratedEffectsAndBaseValues(const WebCore::AcceleratedEffects&, const WebCore::AcceleratedEffectValues&, RemoteLayerTreeHost&);
const RemoteAcceleratedEffectStack* effectStack() const { return m_effectStack.get(); }
RefPtr<RemoteAcceleratedEffectStack> takeEffectStack() { return std::exchange(m_effectStack, nullptr); }
#endif

Expand Down
12 changes: 11 additions & 1 deletion Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@

RemoteLayerTreeNode::~RemoteLayerTreeNode()
{
#if ENABLE(THREADED_ANIMATION_RESOLUTION)
if (m_effectStack)
m_effectStack->clear(layer());
#endif
[layer() setValue:nil forKey:WKRemoteLayerTreeNodePropertyKey];
#if ENABLE(INTERACTION_REGIONS_IN_EVENT_REGION)
removeInteractionRegionsContainer();
Expand Down Expand Up @@ -248,8 +252,10 @@
{
ASSERT(isUIThread());

if (m_effectStack)
if (m_effectStack) {
m_effectStack->clear(layer());
host.animationsWereRemovedFromNode(*this);
}

if (effects.isEmpty())
return;
Expand All @@ -262,6 +268,10 @@
m_effectStack->setEffects(WTFMove(clonedEffects));
m_effectStack->setBaseValues(WTFMove(clonedBaseValues));

#if PLATFORM(MAC)
m_effectStack->initEffectsFromMainThread(layer(), host.animationCurrentTime());
#endif

host.animationsWereAddedToNode(*this);
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,12 @@ void RemoteLayerTreeEventDispatcher::startOrStopDisplayLinkOnMainThread()
if (m_wheelEventActivityHysteresis.state() == PAL::HysteresisState::Started)
return true;

{
Locker lock { m_effectStacksLock };
if (!m_effectStacks.isEmpty())
return true;
}

auto scrollingTree = this->scrollingTree();
return scrollingTree && scrollingTree->hasNodeWithActiveScrollAnimations();
}();
Expand Down Expand Up @@ -440,8 +446,10 @@ void RemoteLayerTreeEventDispatcher::didRefreshDisplay(PlatformDisplayID display

scrollingTree->displayDidRefresh(displayID);

if (m_state != SynchronizationState::Idle)
if (m_state != SynchronizationState::Idle) {
scrollingTree->tryToApplyLayerPositions();
updateAnimations();
}

switch (m_state) {
case SynchronizationState::Idle: {
Expand Down Expand Up @@ -473,6 +481,7 @@ void RemoteLayerTreeEventDispatcher::delayedRenderingUpdateDetectionTimerFired()

if (auto scrollingTree = this->scrollingTree())
scrollingTree->tryToApplyLayerPositions();
updateAnimations();
}

void RemoteLayerTreeEventDispatcher::waitForRenderingUpdateCompletionOrTimeout()
Expand Down Expand Up @@ -510,6 +519,7 @@ void RemoteLayerTreeEventDispatcher::waitForRenderingUpdateCompletionOrTimeout()
ScrollingThread::dispatch([protectedThis = Ref { *this }]() {
if (auto scrollingTree = protectedThis->scrollingTree())
scrollingTree->tryToApplyLayerPositions();
protectedThis->updateAnimations();
});
tracePoint(ScrollingThreadRenderUpdateSyncEnd, 1);
} else
Expand All @@ -522,7 +532,11 @@ bool RemoteLayerTreeEventDispatcher::scrollingTreeWasRecentlyActive()
if (!scrollingTree)
return false;

return scrollingTree->hasRecentActivity();
if (scrollingTree->hasRecentActivity())
return true;

Locker lock { m_effectStacksLock };
return !m_effectStacks.isEmpty();
}

void RemoteLayerTreeEventDispatcher::mainThreadDisplayDidRefresh(PlatformDisplayID)
Expand Down Expand Up @@ -558,17 +572,56 @@ void RemoteLayerTreeEventDispatcher::renderingUpdateComplete()
}

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
void RemoteLayerTreeEventDispatcher::lockForAnimationChanges()
{
ASSERT(isMainRunLoop());
m_effectStacksLock.lock();
}

void RemoteLayerTreeEventDispatcher::unlockForAnimationChanges()
{
ASSERT(isMainRunLoop());
m_effectStacksLock.unlock();
startOrStopDisplayLink();
}

void RemoteLayerTreeEventDispatcher::animationsWereAddedToNode(RemoteLayerTreeNode& node)
{
ASSERT(isMainRunLoop());
assertIsHeld(m_effectStacksLock);
auto effectStack = node.takeEffectStack();
ASSERT(effectStack);
m_effectStacks.set(node.layerID(), effectStack.releaseNonNull());
}

void RemoteLayerTreeEventDispatcher::animationsWereRemovedFromNode(RemoteLayerTreeNode& node)
{
ASSERT(isMainRunLoop());
assertIsHeld(m_effectStacksLock);
m_effectStacks.remove(node.layerID());
}

void RemoteLayerTreeEventDispatcher::updateAnimations()
{
ASSERT(!isMainRunLoop());
Locker lock { m_effectStacksLock };

// FIXME: Rather than using 'now' at the point this is called, we
// should probably be using the timestamp of the (next?) display
// link update or vblank refresh.
auto now = MonotonicTime::now();

auto effectStacks = std::exchange(m_effectStacks, { });
for (auto& [layerID, effectStack] : effectStacks) {
effectStack->applyEffectsFromScrollingThread(now);

// We can clear the effect stack if it's empty, but the previous
// call to applyEffects() is important so that the base values
// were re-applied.
if (effectStack->hasEffects())
m_effectStacks.set(layerID, WTFMove(effectStack));
}
}
#endif

void RemoteLayerTreeEventDispatcher::windowScreenWillChange()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,11 @@ class RemoteLayerTreeEventDispatcher : public ThreadSafeRefCounted<RemoteLayerTr
void renderingUpdateComplete();

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
void lockForAnimationChanges() WTF_ACQUIRES_LOCK(m_effectStacksLock);
void unlockForAnimationChanges() WTF_RELEASES_LOCK(m_effectStacksLock);
void animationsWereAddedToNode(RemoteLayerTreeNode&);
void animationsWereRemovedFromNode(RemoteLayerTreeNode&);
void updateAnimations();
#endif

private:
Expand Down Expand Up @@ -166,7 +169,10 @@ class RemoteLayerTreeEventDispatcher : public ThreadSafeRefCounted<RemoteLayerTr
std::unique_ptr<RunLoop::Timer> m_delayedRenderingUpdateDetectionTimer;

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
HashMap<WebCore::PlatformLayerIdentifier, Ref<RemoteAcceleratedEffectStack>> m_effectStacks;
// For WTF_ACQUIRES_LOCK
friend class RemoteScrollingCoordinatorProxyMac;
Lock m_effectStacksLock;
HashMap<WebCore::PlatformLayerIdentifier, Ref<RemoteAcceleratedEffectStack>> m_effectStacks WTF_GUARDED_BY_LOCK(m_effectStacksLock);
#endif

#if ENABLE(MOMENTUM_EVENT_DISPATCHER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#if PLATFORM(MAC) && ENABLE(UI_SIDE_COMPOSITING)

#include "RemoteLayerTreeEventDispatcher.h"
#include "RemoteScrollingCoordinatorProxy.h"

namespace WebKit {
Expand Down Expand Up @@ -65,13 +66,17 @@ class RemoteScrollingCoordinatorProxyMac final : public RemoteScrollingCoordinat
void windowScreenWillChange() override;
void windowScreenDidChange(WebCore::PlatformDisplayID, std::optional<WebCore::FramesPerSecond>) override;

void willCommitLayerAndScrollingTrees() override;
void didCommitLayerAndScrollingTrees() override;
void applyScrollingTreeLayerPositionsAfterCommit() override;

#if ENABLE(THREADED_ANIMATION_RESOLUTION)
void willCommitLayerAndScrollingTrees() override WTF_ACQUIRES_LOCK(m_eventDispatcher->m_effectStacksLock);
void didCommitLayerAndScrollingTrees() override WTF_RELEASES_LOCK(m_eventDispatcher->m_effectStacksLock);

void animationsWereAddedToNode(RemoteLayerTreeNode&) override;
void animationsWereRemovedFromNode(RemoteLayerTreeNode&) override;
#else
void willCommitLayerAndScrollingTrees() override;
void didCommitLayerAndScrollingTrees() override;
#endif

#if ENABLE(SCROLLING_THREAD)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,17 @@
void RemoteScrollingCoordinatorProxyMac::willCommitLayerAndScrollingTrees()
{
scrollingTree()->lockLayersForHitTesting();
#if ENABLE(THREADED_ANIMATION_RESOLUTION)
m_eventDispatcher->lockForAnimationChanges();
#endif
}

void RemoteScrollingCoordinatorProxyMac::didCommitLayerAndScrollingTrees()
{
scrollingTree()->unlockLayersForHitTesting();
#if ENABLE(THREADED_ANIMATION_RESOLUTION)
m_eventDispatcher->unlockForAnimationChanges();
#endif
}

void RemoteScrollingCoordinatorProxyMac::applyScrollingTreeLayerPositionsAfterCommit()
Expand Down

0 comments on commit e183df8

Please sign in to comment.