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

Changeset 277587 in webkit


Ignore:
Timestamp:
May 17, 2021, 10:59:47 AM (5 years ago)
Author:
Simon Fraser
Message:

Allow wheel events to be coalesced during scroll deceleration
​https://bugs.webkit.org/show_bug.cgi?id=225834
<rdar://70402512>

Reviewed by Tim Horton.

When scrolling slows down towards the tail end of a momentum scroll, we can reduce our
commit frequency to save power, but we only want to do this on displays whose refresh rate
is higher than the default "update rendering" frequency.

We do this by leveraging the existing WebWheelEventCoalescer, which coalesces events
in the UI process. It tracks time since previous event, and coalesces when the
instantaneous velocity is less than 320 points per second (matching other frameworks
on the system).

WebWheelEventCoalescer needs to know when to enable coalescing, which it computes
on creation, and when the window is moved to a different screen with potentially
a different refresh rate.

  • Shared/WebWheelEventCoalescer.cpp:

(WebKit::WebWheelEventCoalescer::isInMomentumPhase):
(WebKit::WebWheelEventCoalescer::shouldDispatchEvent):

  • Shared/WebWheelEventCoalescer.h:

(WebKit::WebWheelEventCoalescer::shouldCoalesceEventsDuringDeceleration const):
(WebKit::WebWheelEventCoalescer::setShouldCoalesceEventsDuringDeceleration):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::wheelEventCoalescer):
(WebKit::WebPageProxy::shouldCoalesceWheelEventsDuringDeceleration const):
(WebKit::WebPageProxy::windowScreenDidChange):

  • UIProcess/WebPageProxy.h:
Location:
trunk/Source/WebKit
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r277584 r277587  
     12021-05-14  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Allow wheel events to be coalesced during scroll deceleration
     4        https://bugs.webkit.org/show_bug.cgi?id=225834
     5        <rdar://70402512>
     6
     7        Reviewed by Tim Horton.
     8
     9        When scrolling slows down towards the tail end of a momentum scroll, we can reduce our
     10        commit frequency to save power, but we only want to do this on displays whose refresh rate
     11        is higher than the default "update rendering" frequency.
     12
     13        We do this by leveraging the existing WebWheelEventCoalescer, which coalesces events
     14        in the UI process. It tracks time since previous event, and coalesces when the
     15        instantaneous velocity is less than 320 points per second (matching other frameworks
     16        on the system).
     17
     18        WebWheelEventCoalescer needs to know when to enable coalescing, which it computes
     19        on creation, and when the window is moved to a different screen with potentially
     20        a different refresh rate.
     21
     22        * Shared/WebWheelEventCoalescer.cpp:
     23        (WebKit::WebWheelEventCoalescer::isInMomentumPhase):
     24        (WebKit::WebWheelEventCoalescer::shouldDispatchEvent):
     25        * Shared/WebWheelEventCoalescer.h:
     26        (WebKit::WebWheelEventCoalescer::shouldCoalesceEventsDuringDeceleration const):
     27        (WebKit::WebWheelEventCoalescer::setShouldCoalesceEventsDuringDeceleration):
     28        * UIProcess/WebPageProxy.cpp:
     29        (WebKit::WebPageProxy::wheelEventCoalescer):
     30        (WebKit::WebPageProxy::shouldCoalesceWheelEventsDuringDeceleration const):
     31        (WebKit::WebPageProxy::windowScreenDidChange):
     32        * UIProcess/WebPageProxy.h:
     33
    1342021-05-17  Peng Liu  <peng.liu6@apple.com>
    235
  • trunk/Source/WebKit/Shared/WebWheelEventCoalescer.cpp

    r268522 r277587  
    3030#include "NativeWebWheelEvent.h"
    3131#include "WebEventConversion.h"
     32#include <WebCore/AnimationFrameRate.h>
    3233#include <wtf/text/TextStream.h>
    3334
    … …  
    8788}
    8889
     90bool WebWheelEventCoalescer::isMomentumPhaseEvent(const WebWheelEvent& event)
     91{
     92    return event.phase() == WebWheelEvent::Phase::PhaseNone && event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged;
     93}
     94
    8995bool WebWheelEventCoalescer::shouldDispatchEventNow(const WebWheelEvent& event) const
    9096{
    … …  
    136142bool WebWheelEventCoalescer::shouldDispatchEvent(const NativeWebWheelEvent& event)
    137143{
    138     LOG_WITH_STREAM(WheelEvents, stream << "WebWheelEventCoalescer::shouldDispatchEvent " << event << " (" << m_wheelEventQueue.size() << " events in the queue, " << m_eventsBeingProcessed.size() << " event sequences being processed)");
     144    LOG_WITH_STREAM(WheelEvents, stream << "WebWheelEventCoalescer::shouldDispatchEvent " << event << " (" << m_wheelEventQueue.size() << " events in the queue, " << m_eventsBeingProcessed.size() << " event sequences being processed, coalesce during decleration " << m_shouldCoalesceEventsDuringDeceleration << ")");
    139145
    140146    m_wheelEventQueue.append(event);
     147
     148    auto lastEventInterval = event.timestamp() - m_lastEventTime;
     149    m_lastEventTime = event.timestamp();
     150
     151    if (isMomentumPhaseEvent(event) && shouldCoalesceEventsDuringDeceleration() && lastEventInterval) {
     152        constexpr double momentumVelocityEventFrequencyReductionThreashold = 320.0; // Points per second.
     153        auto instantaneousVelocity = std::max(std::abs(event.delta().width()), std::abs(event.delta().height())) / lastEventInterval.seconds();
     154
     155        constexpr auto maxCoalescingInterval = WebCore::FullSpeedAnimationInterval;
     156        auto lastDispatchedEventInterval = event.timestamp() - m_lastDispatchedEventTime;
     157
     158        if (instantaneousVelocity < momentumVelocityEventFrequencyReductionThreashold && lastDispatchedEventInterval < maxCoalescingInterval) {
     159            LOG_WITH_STREAM(WheelEvents, stream << " coalesced event that came within " << lastDispatchedEventInterval.milliseconds() << " of previous dispatch");
     160            return false;
     161        }
     162    }
    141163
    142164    if (!m_eventsBeingProcessed.isEmpty()) {
    … …  
    149171    }
    150172
     173    m_lastDispatchedEventTime = event.timestamp();
    151174    return true;
    152175}
  • trunk/Source/WebKit/Shared/WebWheelEventCoalescer.h

    r268287 r277587  
    2929#include <wtf/Deque.h>
    3030#include <wtf/FastMalloc.h>
     31#include <wtf/WallTime.h>
    3132
    3233namespace WebKit {
    … …  
    3839    bool shouldDispatchEvent(const NativeWebWheelEvent&);
    3940    Optional<WebWheelEvent> nextEventToDispatch();
    40    
     41
    4142    NativeWebWheelEvent takeOldestEventBeingProcessed();
    4243
    4344    bool hasEventsBeingProcessed() const { return !m_eventsBeingProcessed.isEmpty(); }
    4445   
     46    bool shouldCoalesceEventsDuringDeceleration() const { return m_shouldCoalesceEventsDuringDeceleration; }
     47    void setShouldCoalesceEventsDuringDeceleration(bool shouldCoalsce) { m_shouldCoalesceEventsDuringDeceleration = shouldCoalsce; }
     48
    4549    void clear();
    4650
    … …  
    5155    static WebWheelEvent coalesce(const WebWheelEvent&, const WebWheelEvent&);
    5256
     57    static bool isMomentumPhaseEvent(const WebWheelEvent&);
     58
    5359    bool shouldDispatchEventNow(const WebWheelEvent&) const;
    5460
    5561    Deque<NativeWebWheelEvent, 2> m_wheelEventQueue;
    5662    Deque<std::unique_ptr<CoalescedEventSequence>> m_eventsBeingProcessed;
     63
     64    WallTime m_lastEventTime;
     65    WallTime m_lastDispatchedEventTime;
     66    bool m_shouldCoalesceEventsDuringDeceleration { false };
    5767};
    5868
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r277573 r277587  
    28522852WebWheelEventCoalescer& WebPageProxy::wheelEventCoalescer()
    28532853{
    2854     if (!m_wheelEventCoalescer)
     2854    if (!m_wheelEventCoalescer) {
    28552855        m_wheelEventCoalescer = makeUnique<WebWheelEventCoalescer>();
     2856        m_wheelEventCoalescer->setShouldCoalesceEventsDuringDeceleration(shouldCoalesceWheelEventsDuringDeceleration());
     2857    }
    28562858
    28572859    return *m_wheelEventCoalescer;
     2860}
     2861
     2862bool WebPageProxy::shouldCoalesceWheelEventsDuringDeceleration() const
     2863{
     2864#if HAVE(CVDISPLAYLINK)
     2865    if (!m_displayID)
     2866        return false;
     2867
     2868    auto framesPerSecond = m_process->processPool().nominalFramesPerSecondForDisplay(*m_displayID);
     2869    return framesPerSecond > WebCore::FullSpeedFramesPerSecond;
     2870#else
     2871    return false;
     2872#endif
    28582873}
    28592874
    … …  
    38713886{
    38723887    m_displayID = displayID;
     3888
     3889    if (m_wheelEventCoalescer)
     3890        m_wheelEventCoalescer->setShouldCoalesceEventsDuringDeceleration(shouldCoalesceWheelEventsDuringDeceleration());
    38733891
    38743892    if (!hasRunningProcess())
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r277505 r277587  
    23362336
    23372337    WebWheelEventCoalescer& wheelEventCoalescer();
     2338    bool shouldCoalesceWheelEventsDuringDeceleration() const;
    23382339
    23392340#if HAVE(CVDISPLAYLINK)
Note: See TracChangeset for help on using the changeset viewer.