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

Changeset 286919 in webkit


Ignore:
Timestamp:
Dec 11, 2021, 4:38:08 PM (5 years ago)
Author:
timothy_horton@apple.com
Message:

Momentum Event Dispatcher: Tail frames are the wrong velocity if momentum event dispatch rate doesn't match screen refresh rate
https://bugs.webkit.org/show_bug.cgi?id=234168
<rdar://problem/86247557>

Reviewed by Simon Fraser.

In r286671, I scaled the tail frames into the momentum event disaptch
rate, but they are actually always dispatched at display refresh
frequency. In many cases these things are the same, but in some
cases can differ (most commonly a 120Hz display with 60Hz event dispatch),
so to always have the tail move at the right rate, scale into the display
refresh rate instead).

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::windowScreenDidChange):

  • WebProcess/WebPage/EventDispatcher.cpp:

(WebKit::EventDispatcher::pageScreenDidChange):

  • WebProcess/WebPage/EventDispatcher.h:
  • WebProcess/WebPage/EventDispatcher.messages.in:
  • WebProcess/WebPage/MomentumEventDispatcher.cpp:

(WebKit::MomentumEventDispatcher::didStartMomentumPhase):
(WebKit::MomentumEventDispatcher::displayProperties const):
(WebKit::MomentumEventDispatcher::startDisplayLink):
(WebKit::MomentumEventDispatcher::stopDisplayLink):
(WebKit::MomentumEventDispatcher::pageScreenDidChange):
(WebKit::MomentumEventDispatcher::displayWasRefreshed):
(WebKit::MomentumEventDispatcher::displayID const): Deleted.

  • WebProcess/WebPage/MomentumEventDispatcher.h:

Plumb and store the nominal display refresh rate.

(WebKit::MomentumEventDispatcher::buildOffsetTableWithInitialDelta):
Scale the tail frames from the 60Hz ideal rate into the display refresh
rate, instead of the event dispatch rate.

Incoming events still scale *in* from the event dispatch rate, since
that's... the rate they come at.

Location:
trunk/Source/WebKit
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r286917 r286919  
     12021-12-11  Tim Horton  <timothy_horton@apple.com>
     2
     3        Momentum Event Dispatcher: Tail frames are the wrong velocity if momentum event dispatch rate doesn't match screen refresh rate
     4        https://bugs.webkit.org/show_bug.cgi?id=234168
     5        <rdar://problem/86247557>
     6
     7        Reviewed by Simon Fraser.
     8
     9        In r286671, I scaled the tail frames into the momentum event disaptch
     10        rate, but they are actually always dispatched at display refresh
     11        frequency. In many cases these things are the same, but in some
     12        cases can differ (most commonly a 120Hz display with 60Hz event dispatch),
     13        so to always have the tail move at the right rate, scale into the display
     14        refresh rate instead).
     15
     16        * UIProcess/WebPageProxy.cpp:
     17        (WebKit::WebPageProxy::windowScreenDidChange):
     18        * WebProcess/WebPage/EventDispatcher.cpp:
     19        (WebKit::EventDispatcher::pageScreenDidChange):
     20        * WebProcess/WebPage/EventDispatcher.h:
     21        * WebProcess/WebPage/EventDispatcher.messages.in:
     22        * WebProcess/WebPage/MomentumEventDispatcher.cpp:
     23        (WebKit::MomentumEventDispatcher::didStartMomentumPhase):
     24        (WebKit::MomentumEventDispatcher::displayProperties const):
     25        (WebKit::MomentumEventDispatcher::startDisplayLink):
     26        (WebKit::MomentumEventDispatcher::stopDisplayLink):
     27        (WebKit::MomentumEventDispatcher::pageScreenDidChange):
     28        (WebKit::MomentumEventDispatcher::displayWasRefreshed):
     29        (WebKit::MomentumEventDispatcher::displayID const): Deleted.
     30        * WebProcess/WebPage/MomentumEventDispatcher.h:
     31        Plumb and store the nominal display refresh rate.
     32
     33        (WebKit::MomentumEventDispatcher::buildOffsetTableWithInitialDelta):
     34        Scale the tail frames from the 60Hz ideal rate into the display refresh
     35        rate, instead of the event dispatch rate.
     36
     37        Incoming events still scale *in* from the event dispatch rate, since
     38        that's... the rate they come at.
     39
    1402021-12-11  Don Olmstead  <don.olmstead@sony.com>
    241
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r286911 r286919  
    39763976        return;
    39773977
    3978     send(Messages::EventDispatcher::PageScreenDidChange(m_webPageID, displayID));
     3978    send(Messages::EventDispatcher::PageScreenDidChange(m_webPageID, displayID, nominalFramesPerSecond));
    39793979    send(Messages::WebPage::WindowScreenDidChange(displayID, nominalFramesPerSecond));
    39803980#if HAVE(CVDISPLAYLINK)
  • trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp

    r286346 r286919  
    324324#endif
    325325
    326 void EventDispatcher::pageScreenDidChange(PageIdentifier pageID, PlatformDisplayID displayID)
    327 {
    328 #if ENABLE(MOMENTUM_EVENT_DISPATCHER)
    329     m_momentumEventDispatcher->pageScreenDidChange(pageID, displayID);
     326void EventDispatcher::pageScreenDidChange(PageIdentifier pageID, PlatformDisplayID displayID, std::optional<unsigned> nominalFramesPerSecond)
     327{
     328#if ENABLE(MOMENTUM_EVENT_DISPATCHER)
     329    m_momentumEventDispatcher->pageScreenDidChange(pageID, displayID, nominalFramesPerSecond);
    330330#else
    331331    UNUSED_PARAM(pageID);
  • trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.h

    r286512 r286919  
    126126#endif
    127127
    128     void pageScreenDidChange(WebCore::PageIdentifier, WebCore::PlatformDisplayID);
     128    void pageScreenDidChange(WebCore::PageIdentifier, WebCore::PlatformDisplayID, std::optional<unsigned> nominalFramesPerSecond);
    129129
    130130    Ref<WorkQueue> m_queue;
  • trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.messages.in

    r286346 r286919  
    3737    SetScrollingAccelerationCurve(WebCore::PageIdentifier pageID, std::optional<WebKit::ScrollingAccelerationCurve> curve)
    3838#endif
    39     PageScreenDidChange(WebCore::PageIdentifier pageID, uint32_t displayID)
     39    PageScreenDidChange(WebCore::PageIdentifier pageID, uint32_t displayID, std::optional<unsigned> nominalFramesPerSecond)
    4040}
  • trunk/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.cpp

    r286858 r286919  
    4141static constexpr Seconds deltaHistoryMaximumAge = 500_ms;
    4242static constexpr Seconds deltaHistoryMaximumInterval = 150_ms;
    43 static constexpr float idealCurveFrameRate = 60;
     43static constexpr WebCore::FramesPerSecond idealCurveFrameRate = 60;
    4444static constexpr Seconds idealCurveFrameInterval = 1_s / idealCurveFrameRate;
    4545
     
    185185void MomentumEventDispatcher::didStartMomentumPhase(WebCore::PageIdentifier pageIdentifier, const WebWheelEvent& event)
    186186{
     187    auto displayProperties = this->displayProperties(pageIdentifier);
     188    if (!displayProperties)
     189        return;
     190
    187191    tracePoint(SyntheticMomentumStart);
    188192
     
    194198    m_currentGesture.currentOffset = { };
    195199    m_currentGesture.startTime = MonotonicTime::now() - momentumStartInterval;
     200    m_currentGesture.displayNominalFrameRate = displayProperties->nominalFrameRate;
    196201    m_currentGesture.accelerationCurve = [&] () -> std::optional<ScrollingAccelerationCurve> {
    197202        auto curveIterator = m_accelerationCurves.find(m_currentGesture.pageIdentifier);
     
    242247}
    243248
    244 WebCore::PlatformDisplayID MomentumEventDispatcher::displayID() const
    245 {
    246     ASSERT(m_currentGesture.pageIdentifier);
    247     auto displayIDIterator = m_displayIDs.find(m_currentGesture.pageIdentifier);
    248     if (displayIDIterator == m_displayIDs.end())
    249         return { };
    250     return displayIDIterator->value;
     249std::optional<MomentumEventDispatcher::DisplayProperties> MomentumEventDispatcher::displayProperties(WebCore::PageIdentifier pageIdentifier) const
     250{
     251    ASSERT(pageIdentifier);
     252    auto displayPropertiesIterator = m_displayProperties.find(pageIdentifier);
     253    if (displayPropertiesIterator == m_displayProperties.end())
     254        return std::nullopt;
     255    return { displayPropertiesIterator->value };
    251256}
    252257
    253258void MomentumEventDispatcher::startDisplayLink()
    254259{
    255     auto displayID = this->displayID();
    256     if (!displayID) {
     260    auto displayProperties = this->displayProperties(m_currentGesture.pageIdentifier);
     261    if (!displayProperties) {
    257262        RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher failed to start display link");
    258263        return;
     
    260265
    261266    // FIXME: Switch down to lower-than-full-speed frame rates for the tail end of the curve.
    262     WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StartDisplayLink(m_observerID, displayID, WebCore::FullSpeedFramesPerSecond), 0);
    263 #if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
    264     RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher starting display link for display %d", displayID);
     267    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StartDisplayLink(m_observerID, displayProperties->displayID, WebCore::FullSpeedFramesPerSecond), 0);
     268#if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
     269    RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher starting display link for display %d", displayProperties->displayID);
    265270#endif
    266271}
     
    268273void MomentumEventDispatcher::stopDisplayLink()
    269274{
    270     auto displayID = this->displayID();
    271     if (!displayID) {
     275    auto displayProperties = this->displayProperties(m_currentGesture.pageIdentifier);
     276    if (!displayProperties) {
    272277        RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher failed to stop display link");
    273278        return;
    274279    }
    275280
    276     WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StopDisplayLink(m_observerID, displayID), 0);
    277 #if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
    278     RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher stopping display link for display %d", displayID);
    279 #endif
    280 }
    281 
    282 void MomentumEventDispatcher::pageScreenDidChange(WebCore::PageIdentifier pageID, WebCore::PlatformDisplayID displayID)
     281    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StopDisplayLink(m_observerID, displayProperties->displayID), 0);
     282#if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
     283    RELEASE_LOG(ScrollAnimations, "MomentumEventDispatcher stopping display link for display %d", displayProperties->displayID);
     284#endif
     285}
     286
     287void MomentumEventDispatcher::pageScreenDidChange(WebCore::PageIdentifier pageID, WebCore::PlatformDisplayID displayID, std::optional<unsigned> nominalFramesPerSecond)
    283288{
    284289    bool affectsCurrentGesture = (pageID == m_currentGesture.pageIdentifier);
     
    286291        stopDisplayLink();
    287292
    288     m_displayIDs.set(pageID, displayID);
     293    DisplayProperties properties;
     294    properties.displayID = displayID;
     295    properties.nominalFrameRate = nominalFramesPerSecond.value_or(WebCore::FullSpeedFramesPerSecond);
     296    m_displayProperties.set(pageID, WTFMove(properties));
    289297
    290298    if (affectsCurrentGesture)
     
    320328        return;
    321329
    322     if (displayID != this->displayID())
     330    auto displayProperties = this->displayProperties(m_currentGesture.pageIdentifier);
     331    if (!displayProperties || displayID != displayProperties->displayID)
    323332        return;
    324333
     
    371380    WebCore::FloatSize unacceleratedDelta = initialUnacceleratedDelta;
    372381
    373     float physicalCurveMultiplier = idealCurveFrameRate / m_currentGesture.accelerationCurve->frameRate();
     382    // Tail deltas will be dispatched at the screen refresh rate, not the momentum
     383    // dispatch rate, so we need to scale from 60Hz into screen refresh rate.
     384    float tailCurveMultiplier = static_cast<float>(idealCurveFrameRate) / m_currentGesture.displayNominalFrameRate;
    374385    bool inTail = false;
    375386    WebCore::FloatSize tailCarry;
     
    386397
    387398        if (inTail) {
    388             auto tailDelta = acceleratedDelta * physicalCurveMultiplier;
     399            auto tailDelta = acceleratedDelta * tailCurveMultiplier;
    389400            auto deltaWithCarry = tailDelta + tailCarry;
    390401            auto quantizedDelta = roundedIntSize(deltaWithCarry);
  • trunk/Source/WebKit/WebProcess/WebPage/MomentumEventDispatcher.h

    r286671 r286919  
    4343namespace WebCore {
    4444struct DisplayUpdate;
     45using FramesPerSecond = unsigned;
    4546using PlatformDisplayID = uint32_t;
    4647}
     
    6364    void displayWasRefreshed(WebCore::PlatformDisplayID, const WebCore::DisplayUpdate&);
    6465
    65     void pageScreenDidChange(WebCore::PageIdentifier, WebCore::PlatformDisplayID);
     66    void pageScreenDidChange(WebCore::PageIdentifier, WebCore::PlatformDisplayID, std::optional<unsigned> nominalFramesPerSecond);
    6667
    6768private:
     
    7475    void stopDisplayLink();
    7576
    76     WebCore::PlatformDisplayID displayID() const;
     77    struct DisplayProperties {
     78        WebCore::PlatformDisplayID displayID;
     79        WebCore::FramesPerSecond nominalFrameRate;
     80    };
     81    std::optional<DisplayProperties> displayProperties(WebCore::PageIdentifier) const;
    7782
    7883    void dispatchSyntheticMomentumEvent(WebWheelEvent::Phase, WebCore::FloatSize delta);
     
    138143        unsigned currentTailDeltaIndex { 0 };
    139144
     145        WebCore::FramesPerSecond displayNominalFrameRate { 0 };
     146
    140147#if ENABLE(MOMENTUM_EVENT_DISPATCHER_TEMPORARY_LOGGING)
    141148        WebCore::FloatSize accumulatedEventOffset;
     
    149156
    150157    DisplayLinkObserverID m_observerID;
    151     HashMap<WebCore::PageIdentifier, WebCore::PlatformDisplayID> m_displayIDs;
     158
     159    HashMap<WebCore::PageIdentifier, DisplayProperties> m_displayProperties;
    152160    HashMap<WebCore::PageIdentifier, std::optional<ScrollingAccelerationCurve>> m_accelerationCurves;
    153161    EventDispatcher& m_dispatcher;
Note: See TracChangeset for help on using the changeset viewer.