⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286410 in webkit


Ignore:
Timestamp:
Dec 1, 2021, 8:58:49 PM (5 years ago)
Author:
Simon Fraser
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:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286406 r286410  
     12021-12-01  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Scrolling complex websites can stutter: scrolling thread commit can get blocked on scroll synchronization
     4        https://bugs.webkit.org/show_bug.cgi?id=233738
     5        rdar://85880147
     6
     7        Reviewed by Tim Horton.
     8       
     9        The scroll synchronization added in r261985 can cause dropped frames while scrolling. This
     10        occurs when ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout(), which is
     11        called at the start of a rendering update on the main thread, starts at a time when it will
     12        delay the handling of displayDidRefreshOnScrollingThread(). This can result in delaying the
     13        CA commit for that frame on the scrolling thread.
     14
     15        The solution is to clamp the duration that waitForRenderingUpdateCompletionOrTimeout() waits
     16        on the condition, so that it doesn't exceed the next expected display refresh time.
     17
     18        * page/scrolling/ThreadedScrollingTree.cpp:
     19        (WebCore::ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout):
     20        (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
     21        * page/scrolling/ThreadedScrollingTree.h:
     22
    1232021-12-01  Chris Fleizach  <cfleizach@apple.com>
    224
  • trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp

    r286352 r286410  
    403403        m_delayedRenderingUpdateDetectionTimer->stop();
    404404
    405     auto startTime = MonotonicTime::now();
    406     auto timeoutTime = startTime + maxAllowableRenderingUpdateDurationForSynchronization();
     405    auto currentTime = MonotonicTime::now();
     406    auto estimatedNextDisplayRefreshTime = std::max(m_lastDisplayDidRefreshTime + frameDuration(), currentTime);
     407    auto timeoutTime = std::min(currentTime + maxAllowableRenderingUpdateDurationForSynchronization(), estimatedNextDisplayRefreshTime);
    407408
    408409    bool becameIdle = m_stateCondition.waitUntil(m_treeLock, timeoutTime, [&] {
     
    463464    Locker locker { m_treeLock };
    464465   
    465     serviceScrollAnimations(MonotonicTime::now());
     466    auto now = MonotonicTime::now();
     467    m_lastDisplayDidRefreshTime = now;
     468    serviceScrollAnimations(now);
    466469
    467470    if (m_state != SynchronizationState::Idle && canUpdateLayersOnScrollingThread())
  • trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h

    r286352 r286410  
    124124    bool m_receivedBeganEventFromMainThread WTF_GUARDED_BY_LOCK(m_treeLock) { false };
    125125    Condition m_waitingForBeganEventCondition;
     126   
     127    MonotonicTime m_lastDisplayDidRefreshTime;
    126128
    127129    // Dynamically allocated because it has to use the ScrollingThread's runloop.
Note: See TracChangeset for help on using the changeset viewer.