Skip to content

Avoid updating UI-side layer positions for no-op transactions#63293

Merged
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
smfr:eng/Avoid-updating-UI-side-layer-positions-for-no-op-transactions
Apr 23, 2026
Merged

Avoid updating UI-side layer positions for no-op transactions#63293
webkit-commit-queue merged 1 commit into
WebKit:mainfrom
smfr:eng/Avoid-updating-UI-side-layer-positions-for-no-op-transactions

Conversation

@smfr
Copy link
Copy Markdown
Contributor

@smfr smfr commented Apr 22, 2026

8ff9ee2

Avoid updating UI-side layer positions for no-op transactions
https://bugs.webkit.org/show_bug.cgi?id=312959
rdar://175308880

Reviewed by Brent Fulgham.

Currently, after every RemoteLayerTree commit that is received by the UI process,
we call `applyScrollingTreeLayerPositionsAfterCommit()`, which traverses the scrolling
tree and updates CALayer positions.

If the transaction contains no scrolling tree changes, then this is not necessary;
`applyLayerPositions()` only needs to be called after a scrolling tree state change,
or after a user scroll.

Track this state via `ScrollingTree::m_needsApplyLayerPositions()`, and set the flag
under `commitTreeState()` and `scrollingTreeNodeDidScroll()`. It's the `commitTreeState(()`
call that's skipped when `stateTree->hasChangedProperties()` is false.

This should be a minor power saving.

* Source/WebCore/page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::scrollingTreeNodeDidScroll):
(WebCore::ScrollingTree::commitTreeStateInternal):
(WebCore::ScrollingTree::applyLayerPositions):
* Source/WebCore/page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::setNeedsApplyLayerPositions):

Canonical link: https://commits.webkit.org/311816@main

50ea6df

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows Apple Internal
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win ⏳ 🛠 ios-apple
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ✅ 🧪 win-tests ⏳ 🛠 mac-apple
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe ⏳ 🛠 vision-apple
✅ 🧪 ios-wk2-wpt 🧪 api-mac-debug ✅ 🛠 gtk3-libwebrtc
✅ 🧪 api-ios ✅ 🧪 mac-wk1 ✅ 🛠 gtk
✅ 🛠 ios-safer-cpp ✅ 🧪 mac-wk2 ✅ 🧪 gtk-wk2
✅ 🛠 vision ✅ 🧪 mac-AS-debug-wk2 ✅ 🧪 api-gtk
✅ 🛠 🧪 merge ✅ 🛠 vision-sim ✅ 🧪 mac-wk2-stress ✅ 🛠 playstation
✅ 🧪 vision-wk2 ✅ 🧪 mac-intel-wk2
✅ 🛠 tv ✅ 🛠 mac-safer-cpp
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@smfr smfr requested a review from cdumez as a code owner April 22, 2026 04:22
@smfr smfr self-assigned this Apr 22, 2026
@smfr smfr added the Scrolling Bugs related to main thread and off-main thread scrolling label Apr 22, 2026

m_needsApplyLayerPositions = false;

Locker locker { m_treeLock };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to lock before the check? Otherwise won't we have potentially multiple applyLayerPositions() queued that will still think they need to apply later positions even after the first one goes through?

@@ -125,6 +125,8 @@ class ScrollingTree : public ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<Scr
bool commitTreeStateInternal(std::unique_ptr<ScrollingStateTree>&&, std::optional<LayerHostingContextIdentifier>) WTF_REQUIRES_LOCK(m_treeLock);

WEBCORE_EXPORT virtual void applyLayerPositions();
void setNeedsApplyLayerPositions() { m_needsApplyLayerPositions = true; }
bool needsApplyLayerPositions() const { return m_needsApplyLayerPositions; }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never called?

Comment on lines +590 to +593
if (!m_needsApplyLayerPositions)
return;

m_needsApplyLayerPositions = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since std::atomic<bool> m_needsApplyLayerPositions, shouldn't you atomically, get and reset m_needsApplyLayerPositions to false? Then the winning thread can proceed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use m_needsApplyLayerPositions.exchange()

@smfr smfr force-pushed the eng/Avoid-updating-UI-side-layer-positions-for-no-op-transactions branch from 21eb1ea to 50ea6df Compare April 22, 2026 16:55
Copy link
Copy Markdown
Contributor

@brentfulgham brentfulgham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. r=me

@smfr smfr added the merge-queue Applied to send a pull request to merge-queue label Apr 22, 2026
https://bugs.webkit.org/show_bug.cgi?id=312959
rdar://175308880

Reviewed by Brent Fulgham.

Currently, after every RemoteLayerTree commit that is received by the UI process,
we call `applyScrollingTreeLayerPositionsAfterCommit()`, which traverses the scrolling
tree and updates CALayer positions.

If the transaction contains no scrolling tree changes, then this is not necessary;
`applyLayerPositions()` only needs to be called after a scrolling tree state change,
or after a user scroll.

Track this state via `ScrollingTree::m_needsApplyLayerPositions()`, and set the flag
under `commitTreeState()` and `scrollingTreeNodeDidScroll()`. It's the `commitTreeState(()`
call that's skipped when `stateTree->hasChangedProperties()` is false.

This should be a minor power saving.

* Source/WebCore/page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::scrollingTreeNodeDidScroll):
(WebCore::ScrollingTree::commitTreeStateInternal):
(WebCore::ScrollingTree::applyLayerPositions):
* Source/WebCore/page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::setNeedsApplyLayerPositions):

Canonical link: https://commits.webkit.org/311816@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/Avoid-updating-UI-side-layer-positions-for-no-op-transactions branch from 50ea6df to 8ff9ee2 Compare April 23, 2026 00:11
@webkit-commit-queue
Copy link
Copy Markdown
Collaborator

Committed 311816@main (8ff9ee2): https://commits.webkit.org/311816@main

Reviewed commits have been landed. Closing PR #63293 and removing active labels.

@webkit-commit-queue webkit-commit-queue merged commit 8ff9ee2 into WebKit:main Apr 23, 2026
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Apr 23, 2026
@smfr smfr deleted the eng/Avoid-updating-UI-side-layer-positions-for-no-op-transactions branch May 15, 2026 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scrolling Bugs related to main thread and off-main thread scrolling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants