Title: [286410] trunk/Source/WebCore
Revision
286410
Author
simon.fra...@apple.com
Date
2021-12-01 20:58:49 -0800 (Wed, 01 Dec 2021)

Log Message

Scrolling complex websites can stutter: scrolling thread commit can get blocked on scroll synchronization
https://bugs.webkit.org/show_bug.cgi?id=233738
rdar://85880147

Reviewed by Tim Horton.

The scroll synchronization added in r261985 can cause dropped frames while scrolling. This
occurs when ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout(), which is
called at the start of a rendering update on the main thread, starts at a time when it will
delay the handling of displayDidRefreshOnScrollingThread(). This can result in delaying the
CA commit for that frame on the scrolling thread.

The solution is to clamp the duration that waitForRenderingUpdateCompletionOrTimeout() waits
on the condition, so that it doesn't exceed the next expected display refresh time.

* page/scrolling/ThreadedScrollingTree.cpp:
(WebCore::ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout):
(WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
* page/scrolling/ThreadedScrollingTree.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (286409 => 286410)


--- trunk/Source/WebCore/ChangeLog	2021-12-02 03:00:13 UTC (rev 286409)
+++ trunk/Source/WebCore/ChangeLog	2021-12-02 04:58:49 UTC (rev 286410)
@@ -1,3 +1,25 @@
+2021-12-01  Simon Fraser  <simon.fra...@apple.com>
+
+        Scrolling complex websites can stutter: scrolling thread commit can get blocked on scroll synchronization
+        https://bugs.webkit.org/show_bug.cgi?id=233738
+        rdar://85880147
+
+        Reviewed by Tim Horton.
+        
+        The scroll synchronization added in r261985 can cause dropped frames while scrolling. This
+        occurs when ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout(), which is
+        called at the start of a rendering update on the main thread, starts at a time when it will
+        delay the handling of displayDidRefreshOnScrollingThread(). This can result in delaying the
+        CA commit for that frame on the scrolling thread.
+
+        The solution is to clamp the duration that waitForRenderingUpdateCompletionOrTimeout() waits
+        on the condition, so that it doesn't exceed the next expected display refresh time.
+
+        * page/scrolling/ThreadedScrollingTree.cpp:
+        (WebCore::ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout):
+        (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
+        * page/scrolling/ThreadedScrollingTree.h:
+
 2021-12-01  Chris Fleizach  <cfleiz...@apple.com>
 
         AX: Support accessibility attributes for <model>

Modified: trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp (286409 => 286410)


--- trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2021-12-02 03:00:13 UTC (rev 286409)
+++ trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp	2021-12-02 04:58:49 UTC (rev 286410)
@@ -402,8 +402,9 @@
     if (m_delayedRenderingUpdateDetectionTimer)
         m_delayedRenderingUpdateDetectionTimer->stop();
 
-    auto startTime = MonotonicTime::now();
-    auto timeoutTime = startTime + maxAllowableRenderingUpdateDurationForSynchronization();
+    auto currentTime = MonotonicTime::now();
+    auto estimatedNextDisplayRefreshTime = std::max(m_lastDisplayDidRefreshTime + frameDuration(), currentTime);
+    auto timeoutTime = std::min(currentTime + maxAllowableRenderingUpdateDurationForSynchronization(), estimatedNextDisplayRefreshTime);
 
     bool becameIdle = m_stateCondition.waitUntil(m_treeLock, timeoutTime, [&] {
         assertIsHeld(m_treeLock);
@@ -462,7 +463,9 @@
 
     Locker locker { m_treeLock };
     
-    serviceScrollAnimations(MonotonicTime::now());
+    auto now = MonotonicTime::now();
+    m_lastDisplayDidRefreshTime = now;
+    serviceScrollAnimations(now);
 
     if (m_state != SynchronizationState::Idle && canUpdateLayersOnScrollingThread())
         applyLayerPositionsInternal();

Modified: trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h (286409 => 286410)


--- trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2021-12-02 03:00:13 UTC (rev 286409)
+++ trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h	2021-12-02 04:58:49 UTC (rev 286410)
@@ -123,6 +123,8 @@
 
     bool m_receivedBeganEventFromMainThread WTF_GUARDED_BY_LOCK(m_treeLock) { false };
     Condition m_waitingForBeganEventCondition;
+    
+    MonotonicTime m_lastDisplayDidRefreshTime;
 
     // Dynamically allocated because it has to use the ScrollingThread's runloop.
     std::unique_ptr<RunLoop::Timer<ThreadedScrollingTree>> m_delayedRenderingUpdateDetectionTimer WTF_GUARDED_BY_LOCK(m_treeLock);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to