Changeset 261999 in webkit


Ignore:
Timestamp:
May 21, 2020 8:35:21 AM (4 years ago)
Author:
Simon Fraser
Message:

[macOS] Scrolling synchronization part 2: Have the scrolling thread detect when the main thread is slow to respond to start a rendering update
https://bugs.webkit.org/show_bug.cgi?id=212175

Reviewed by Tim Horton.

The scrolling thread now detects when a main thread rendering update is taking too long, going into
desynchronized mode when that happens.

However, there's another state that needs to be handled, which is the main thread being busy and
taking too long to start the rendering update. The scrolling thread gets a "displayDidRefresh" ping
and expects that the main thread will get the same ping, and use it to start the rendering update,
but a busy main thread won't respond to this ping promptly.

Detect this with a short-duration (1ms) timer that fires on the scrolling thread; if the timer fires
we go into desynchronized mode until the next update. The timer is canceled if the scrolling thread
receives the willStartRenderingUpdate().

  • page/scrolling/ThreadedScrollingTree.cpp:

(WebCore::ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout):
(WebCore::ThreadedScrollingTree::scheduleDelayedRenderingUpdateDetectionTimer):
(WebCore::ThreadedScrollingTree::delayedRenderingUpdateDetectionTimerFired):
(WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):

  • page/scrolling/ThreadedScrollingTree.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r261996 r261999  
     12020-05-21  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [macOS] Scrolling synchronization part 2: Have the scrolling thread detect when the main thread is slow to respond to start a rendering update
     4        https://bugs.webkit.org/show_bug.cgi?id=212175
     5
     6        Reviewed by Tim Horton.
     7
     8        The scrolling thread now detects when a main thread rendering update is taking too long, going into
     9        desynchronized mode when that happens.
     10
     11        However, there's another state that needs to be handled, which is the main thread being busy and
     12        taking too long to start the rendering update. The scrolling thread gets a "displayDidRefresh" ping
     13        and expects that the main thread will get the same ping, and use it to start the rendering update,
     14        but a busy main thread won't respond to this ping promptly.
     15
     16        Detect this with a short-duration (1ms) timer that fires on the scrolling thread; if the timer fires
     17        we go into desynchronized mode until the next update. The timer is canceled if the scrolling thread
     18        receives the willStartRenderingUpdate().
     19
     20        * page/scrolling/ThreadedScrollingTree.cpp:
     21        (WebCore::ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout):
     22        (WebCore::ThreadedScrollingTree::scheduleDelayedRenderingUpdateDetectionTimer):
     23        (WebCore::ThreadedScrollingTree::delayedRenderingUpdateDetectionTimerFired):
     24        (WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
     25        * page/scrolling/ThreadedScrollingTree.h:
     26
    1272020-05-21  Sergio Villar Senin  <svillar@igalia.com>
    228
  • trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp

    r261985 r261999  
    241241    ASSERT(m_treeMutex.isLocked());
    242242
     243    if (m_delayedRenderingUpdateDetectionTimer)
     244        m_delayedRenderingUpdateDetectionTimer->stop();
     245
    243246    auto startTime = MonotonicTime::now();
    244247    auto timeoutTime = startTime + maxAllowableRenderingUpdateDurationForSynchronization();
     
    271274}
    272275
     276void ThreadedScrollingTree::scheduleDelayedRenderingUpdateDetectionTimer(Seconds delay)
     277{
     278    ASSERT(ScrollingThread::isCurrentThread());
     279    ASSERT(m_treeMutex.isLocked());
     280
     281    if (!m_delayedRenderingUpdateDetectionTimer)
     282        m_delayedRenderingUpdateDetectionTimer = makeUnique<RunLoop::Timer<ThreadedScrollingTree>>(RunLoop::current(), this, &ThreadedScrollingTree::delayedRenderingUpdateDetectionTimerFired);
     283
     284    m_delayedRenderingUpdateDetectionTimer->startOneShot(delay);
     285}
     286
     287void ThreadedScrollingTree::delayedRenderingUpdateDetectionTimerFired()
     288{
     289    ASSERT(ScrollingThread::isCurrentThread());
     290
     291    LockHolder treeLocker(m_treeMutex);
     292    applyLayerPositionsInternal();
     293    m_state = SynchronizationState::Desynchronized;
     294}
     295
    273296void ThreadedScrollingTree::displayDidRefreshOnScrollingThread()
    274297{
     
    284307    case SynchronizationState::Idle: {
    285308        m_state = SynchronizationState::WaitingForRenderingUpdate;
     309        constexpr auto maxStartRenderingUpdateDelay = 1_ms;
     310        scheduleDelayedRenderingUpdateDetectionTimer(maxStartRenderingUpdateDelay);
    286311        break;
    287312    }
  • trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h

    r261985 r261999  
    3232#include <wtf/Condition.h>
    3333#include <wtf/RefPtr.h>
     34#include <wtf/RunLoop.h>
    3435
    3536namespace WebCore {
     
    8687    void displayDidRefreshOnScrollingThread();
    8788    void waitForRenderingUpdateCompletionOrTimeout();
    88    
     89
     90    void scheduleDelayedRenderingUpdateDetectionTimer(Seconds);
     91    void delayedRenderingUpdateDetectionTimerFired();
     92
    8993    Seconds maxAllowableRenderingUpdateDurationForSynchronization();
    9094
     
    100104    SynchronizationState m_state { SynchronizationState::Idle };
    101105    Condition m_stateCondition;
     106
     107    // Dynamically allocated because it has to use the ScrollingThread's runloop.
     108    std::unique_ptr<RunLoop::Timer<ThreadedScrollingTree>> m_delayedRenderingUpdateDetectionTimer;
    102109};
    103110
Note: See TracChangeset for help on using the changeset viewer.