Title: [275345] trunk/Source
Revision
275345
Author
simon.fra...@apple.com
Date
2021-03-31 21:03:47 -0700 (Wed, 31 Mar 2021)

Log Message

Feed preferred frames per second back to the UI process for each DisplayRefreshMonitor
https://bugs.webkit.org/show_bug.cgi?id=224023

Reviewed by Sam Weinig.

Source/WebCore:

DisplayRefreshMonitors should be responsive to the frame rate demands of their clients,
so move from a model where DisplayRefreshMonitor has setPreferredFramesPerSecond()
to one where it computes maxClientPreferredFramesPerSecond().

DisplayRefreshMonitor needs to recompute maxClientPreferredFramesPerSecond when clients
are added, removed, or when the preferred frame rate of a client changes.

For now, just one of the DisplayRefreshMonitor implementations responds to adjustPreferredFramesPerSecond:
DisplayRefreshMonitorMac sends IPC to the UI process, which DisplayLink can use on a per-connection
basis to throttle the frequency of display updates sent to that process (which is important
for power).

* platform/graphics/DisplayRefreshMonitor.cpp:
(WebCore::DisplayRefreshMonitor::addClient):
(WebCore::DisplayRefreshMonitor::removeClient):
(WebCore::DisplayRefreshMonitor::maximumClientPreferredFramesPerSecond const):
(WebCore::DisplayRefreshMonitor::computeMaxPreferredFramesPerSecond):
(WebCore::DisplayRefreshMonitor::clientPreferredFramesPerSecondChanged):
* platform/graphics/DisplayRefreshMonitor.h:
(WebCore::DisplayRefreshMonitor::maxClientPreferredFramesPerSecond const):
(WebCore::DisplayRefreshMonitor::adjustPreferredFramesPerSecond):
(WebCore::DisplayRefreshMonitor::setPreferredFramesPerSecond): Deleted.
* platform/graphics/DisplayRefreshMonitorClient.cpp:
(WebCore::DisplayRefreshMonitorClient::setPreferredFramesPerSecond):
* platform/graphics/DisplayRefreshMonitorManager.cpp:
(WebCore::DisplayRefreshMonitorManager::clientPreferredFramesPerSecondChanged):
(WebCore::DisplayRefreshMonitorManager::setPreferredFramesPerSecond): Deleted.
* platform/graphics/DisplayRefreshMonitorManager.h:

Source/WebKit:

DisplayLink needs to track the preferredFramesPerSecond of each of its client
observers. notifyObserversDisplayWasRefreshed() can then avoid sending IPC to
a process a frequency which is higher than that process needs.

* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(WebKit::WebProcessPool::startDisplayLink):
(WebKit::WebProcessPool::setDisplayLinkPreferredFramesPerSecond):
* UIProcess/WebProcessPool.h:
* UIProcess/WebProcessProxy.h:
* UIProcess/WebProcessProxy.messages.in:
* UIProcess/mac/DisplayLink.cpp:
(WebKit::DisplayLink::addObserver):
(WebKit::DisplayLink::removeObserver):
(WebKit::DisplayLink::removeObservers):
(WebKit::DisplayLink::setPreferredFramesPerSecond):
(WebKit::DisplayLink::notifyObserversDisplayWasRefreshed):
* UIProcess/mac/DisplayLink.h:
* UIProcess/mac/WebProcessProxyMac.mm:
(WebKit::WebProcessProxy::startDisplayLink):
(WebKit::WebProcessProxy::setDisplayLinkPreferredFramesPerSecond):
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm:
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::adjustPreferredFramesPerSecond):
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond): Deleted.
* WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp:
(WebKit::DisplayRefreshMonitorMac::startNotificationMechanism):
(WebKit::DisplayRefreshMonitorMac::adjustPreferredFramesPerSecond):
* WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (275344 => 275345)


--- trunk/Source/WebCore/ChangeLog	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebCore/ChangeLog	2021-04-01 04:03:47 UTC (rev 275345)
@@ -1,3 +1,39 @@
+2021-03-31  Simon Fraser  <simon.fra...@apple.com>
+
+        Feed preferred frames per second back to the UI process for each DisplayRefreshMonitor
+        https://bugs.webkit.org/show_bug.cgi?id=224023
+
+        Reviewed by Sam Weinig.
+
+        DisplayRefreshMonitors should be responsive to the frame rate demands of their clients,
+        so move from a model where DisplayRefreshMonitor has setPreferredFramesPerSecond()
+        to one where it computes maxClientPreferredFramesPerSecond().
+
+        DisplayRefreshMonitor needs to recompute maxClientPreferredFramesPerSecond when clients
+        are added, removed, or when the preferred frame rate of a client changes.
+
+        For now, just one of the DisplayRefreshMonitor implementations responds to adjustPreferredFramesPerSecond:
+        DisplayRefreshMonitorMac sends IPC to the UI process, which DisplayLink can use on a per-connection
+        basis to throttle the frequency of display updates sent to that process (which is important
+        for power).
+
+        * platform/graphics/DisplayRefreshMonitor.cpp:
+        (WebCore::DisplayRefreshMonitor::addClient):
+        (WebCore::DisplayRefreshMonitor::removeClient):
+        (WebCore::DisplayRefreshMonitor::maximumClientPreferredFramesPerSecond const):
+        (WebCore::DisplayRefreshMonitor::computeMaxPreferredFramesPerSecond):
+        (WebCore::DisplayRefreshMonitor::clientPreferredFramesPerSecondChanged):
+        * platform/graphics/DisplayRefreshMonitor.h:
+        (WebCore::DisplayRefreshMonitor::maxClientPreferredFramesPerSecond const):
+        (WebCore::DisplayRefreshMonitor::adjustPreferredFramesPerSecond):
+        (WebCore::DisplayRefreshMonitor::setPreferredFramesPerSecond): Deleted.
+        * platform/graphics/DisplayRefreshMonitorClient.cpp:
+        (WebCore::DisplayRefreshMonitorClient::setPreferredFramesPerSecond):
+        * platform/graphics/DisplayRefreshMonitorManager.cpp:
+        (WebCore::DisplayRefreshMonitorManager::clientPreferredFramesPerSecondChanged):
+        (WebCore::DisplayRefreshMonitorManager::setPreferredFramesPerSecond): Deleted.
+        * platform/graphics/DisplayRefreshMonitorManager.h:
+
 2021-03-31  Wenson Hsieh  <wenson_hs...@apple.com>
 
         List of extents should be bounds-checked when iterating display list items

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp (275344 => 275345)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp	2021-04-01 04:03:47 UTC (rev 275345)
@@ -90,7 +90,11 @@
 
 void DisplayRefreshMonitor::addClient(DisplayRefreshMonitorClient& client)
 {
-    m_clients.add(&client);
+    auto addResult = m_clients.add(&client);
+    if (addResult.isNewEntry) {
+        LOG_WITH_STREAM(DisplayLink, stream << "[Web] DisplayRefreshMonitor " << this << " addedClient - displayID " << m_displayID << " client " << &client << " client preferred fps " << client.preferredFramesPerSecond());
+        computeMaxPreferredFramesPerSecond();
+    }
 }
 
 bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient& client)
@@ -98,9 +102,40 @@
     if (m_clientsToBeNotified)
         m_clientsToBeNotified->remove(&client);
 
-    return m_clients.remove(&client);
+    bool removed = m_clients.remove(&client);
+    if (removed) {
+        LOG_WITH_STREAM(DisplayLink, stream << "[Web] DisplayRefreshMonitor " << this << " removedClient " << &client);
+        computeMaxPreferredFramesPerSecond();
+    }
+
+    return removed;
 }
 
+Optional<FramesPerSecond> DisplayRefreshMonitor::maximumClientPreferredFramesPerSecond() const
+{
+    Optional<FramesPerSecond> maxFramesPerSecond;
+    for (auto* client : m_clients)
+        maxFramesPerSecond = std::max<FramesPerSecond>(maxFramesPerSecond.valueOr(0), client->preferredFramesPerSecond());
+
+    return maxFramesPerSecond;
+}
+
+void DisplayRefreshMonitor::computeMaxPreferredFramesPerSecond()
+{
+    auto maxFramesPerSecond = maximumClientPreferredFramesPerSecond();
+    LOG_WITH_STREAM(DisplayLink, stream << "[Web] DisplayRefreshMonitor " << this << " computeMaxPreferredFramesPerSecond - displayID " << m_displayID << " adjusting max fps to " << maxFramesPerSecond);
+    if (maxFramesPerSecond != m_maxClientPreferredFramesPerSecond) {
+        m_maxClientPreferredFramesPerSecond = maxFramesPerSecond;
+        if (m_maxClientPreferredFramesPerSecond)
+            adjustPreferredFramesPerSecond(*m_maxClientPreferredFramesPerSecond);
+    }
+}
+
+void DisplayRefreshMonitor::clientPreferredFramesPerSecondChanged(DisplayRefreshMonitorClient&)
+{
+    computeMaxPreferredFramesPerSecond();
+}
+
 bool DisplayRefreshMonitor::requestRefreshCallback()
 {
     auto locker = holdLock(m_lock);

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h (275344 => 275345)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -47,8 +47,6 @@
     
     WEBCORE_EXPORT virtual void stop();
 
-    virtual void setPreferredFramesPerSecond(FramesPerSecond) { }
-
     // Return true if callback request was scheduled, false if it couldn't be
     // (e.g., hardware refresh is not available)
     WEBCORE_EXPORT virtual bool requestRefreshCallback();
@@ -59,6 +57,9 @@
     void addClient(DisplayRefreshMonitorClient&);
     bool removeClient(DisplayRefreshMonitorClient&);
 
+    void clientPreferredFramesPerSecondChanged(DisplayRefreshMonitorClient&);
+    Optional<FramesPerSecond> maxClientPreferredFramesPerSecond() const { return m_maxClientPreferredFramesPerSecond; }
+
     virtual Optional<FramesPerSecond> displayNominalFramesPerSecond() { return WTF::nullopt; }
 
     PlatformDisplayID displayID() const { return m_displayID; }
@@ -89,9 +90,16 @@
 private:
     bool firedAndReachedMaxUnscheduledFireCount();
 
+    virtual void adjustPreferredFramesPerSecond(FramesPerSecond) { }
+
+    Optional<FramesPerSecond> maximumClientPreferredFramesPerSecond() const;
+    void computeMaxPreferredFramesPerSecond();
+
     HashSet<DisplayRefreshMonitorClient*> m_clients;
     HashSet<DisplayRefreshMonitorClient*>* m_clientsToBeNotified { nullptr };
+
     PlatformDisplayID m_displayID { 0 };
+    Optional<FramesPerSecond> m_maxClientPreferredFramesPerSecond;
 
     Lock m_lock;
     bool m_scheduled { false };

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp (275344 => 275345)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp	2021-04-01 04:03:47 UTC (rev 275345)
@@ -40,7 +40,11 @@
 
 void DisplayRefreshMonitorClient::setPreferredFramesPerSecond(FramesPerSecond preferredFrameRate)
 {
+    if (preferredFrameRate == m_preferredFramesPerSecond)
+        return;
+
     m_preferredFramesPerSecond = preferredFrameRate;
+    DisplayRefreshMonitorManager::sharedManager().clientPreferredFramesPerSecondChanged(*this);
 }
 
 void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(const DisplayUpdate& displayUpdate)

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp (275344 => 275345)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2021-04-01 04:03:47 UTC (rev 275345)
@@ -70,10 +70,10 @@
     monitor->removeClient(client);
 }
 
-void DisplayRefreshMonitorManager::setPreferredFramesPerSecond(DisplayRefreshMonitorClient& client, FramesPerSecond preferredFramesPerSecond)
+void DisplayRefreshMonitorManager::clientPreferredFramesPerSecondChanged(DisplayRefreshMonitorClient& client)
 {
     if (auto* monitor = monitorForClient(client))
-        monitor->setPreferredFramesPerSecond(preferredFramesPerSecond);
+        monitor->clientPreferredFramesPerSecondChanged(client);
 }
 
 bool DisplayRefreshMonitorManager::scheduleAnimation(DisplayRefreshMonitorClient& client)

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h (275344 => 275345)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -44,12 +44,13 @@
 
     void unregisterClient(DisplayRefreshMonitorClient&);
 
-    void setPreferredFramesPerSecond(DisplayRefreshMonitorClient&, FramesPerSecond);
     bool scheduleAnimation(DisplayRefreshMonitorClient&);
     void windowScreenDidChange(PlatformDisplayID, DisplayRefreshMonitorClient&);
     
     Optional<FramesPerSecond> nominalFramesPerSecondForDisplay(PlatformDisplayID, DisplayRefreshMonitorFactory*);
 
+    void clientPreferredFramesPerSecondChanged(DisplayRefreshMonitorClient&);
+
     WEBCORE_EXPORT void displayWasUpdated(PlatformDisplayID, const DisplayUpdate&);
 
 private:

Modified: trunk/Source/WebKit/ChangeLog (275344 => 275345)


--- trunk/Source/WebKit/ChangeLog	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/ChangeLog	2021-04-01 04:03:47 UTC (rev 275345)
@@ -1,3 +1,39 @@
+2021-03-31  Simon Fraser  <simon.fra...@apple.com>
+
+        Feed preferred frames per second back to the UI process for each DisplayRefreshMonitor
+        https://bugs.webkit.org/show_bug.cgi?id=224023
+
+        Reviewed by Sam Weinig.
+
+        DisplayLink needs to track the preferredFramesPerSecond of each of its client
+        observers. notifyObserversDisplayWasRefreshed() can then avoid sending IPC to
+        a process a frequency which is higher than that process needs.
+
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (WebKit::WebProcessPool::startDisplayLink):
+        (WebKit::WebProcessPool::setDisplayLinkPreferredFramesPerSecond):
+        * UIProcess/WebProcessPool.h:
+        * UIProcess/WebProcessProxy.h:
+        * UIProcess/WebProcessProxy.messages.in:
+        * UIProcess/mac/DisplayLink.cpp:
+        (WebKit::DisplayLink::addObserver):
+        (WebKit::DisplayLink::removeObserver):
+        (WebKit::DisplayLink::removeObservers):
+        (WebKit::DisplayLink::setPreferredFramesPerSecond):
+        (WebKit::DisplayLink::notifyObserversDisplayWasRefreshed):
+        * UIProcess/mac/DisplayLink.h:
+        * UIProcess/mac/WebProcessProxyMac.mm:
+        (WebKit::WebProcessProxy::startDisplayLink):
+        (WebKit::WebProcessProxy::setDisplayLinkPreferredFramesPerSecond):
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm:
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::adjustPreferredFramesPerSecond):
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond): Deleted.
+        * WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp:
+        (WebKit::DisplayRefreshMonitorMac::startNotificationMechanism):
+        (WebKit::DisplayRefreshMonitorMac::adjustPreferredFramesPerSecond):
+        * WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h:
+
 2021-03-31  Patrick Angle  <pan...@apple.com>
 
         Web Inspector: [Cocoa] WKInspectorResourceURLSchemeHandler can exceed the soft thread limit when opening multiple inspectors simultaneously.

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2021-04-01 04:03:47 UTC (rev 275345)
@@ -72,6 +72,7 @@
 #import <wtf/cocoa/RuntimeApplicationChecksCocoa.h>
 #import <wtf/spi/darwin/SandboxSPI.h>
 #import <wtf/spi/darwin/dyldSPI.h>
+#import <wtf/text/TextStream.h>
 
 #if ENABLE(REMOTE_INSPECTOR)
 #import <_javascript_Core/RemoteInspector.h>
@@ -779,16 +780,16 @@
     return frameRate;
 }
 
-void WebProcessPool::startDisplayLink(IPC::Connection& connection, DisplayLinkObserverID observerID, PlatformDisplayID displayID)
+void WebProcessPool::startDisplayLink(IPC::Connection& connection, DisplayLinkObserverID observerID, PlatformDisplayID displayID, WebCore::FramesPerSecond preferredFramesPerSecond)
 {
     for (auto& displayLink : m_displayLinks) {
         if (displayLink->displayID() == displayID) {
-            displayLink->addObserver(connection, observerID);
+            displayLink->addObserver(connection, observerID, preferredFramesPerSecond);
             return;
         }
     }
     auto displayLink = makeUnique<DisplayLink>(displayID);
-    displayLink->addObserver(connection, observerID);
+    displayLink->addObserver(connection, observerID, preferredFramesPerSecond);
     m_displayLinks.append(WTFMove(displayLink));
 }
 
@@ -807,6 +808,18 @@
     for (auto& displayLink : m_displayLinks)
         displayLink->removeObservers(connection);
 }
+
+void WebProcessPool::setDisplayLinkPreferredFramesPerSecond(IPC::Connection& connection, DisplayLinkObserverID observerID, PlatformDisplayID displayID, WebCore::FramesPerSecond preferredFramesPerSecond)
+{
+    LOG_WITH_STREAM(DisplayLink, stream << "[UI ] WebProcessPool::setDisplayLinkPreferredFramesPerSecond - display " << displayID << " observer " << observerID << " fps " << preferredFramesPerSecond);
+
+    for (auto& displayLink : m_displayLinks) {
+        if (displayLink->displayID() == displayID) {
+            displayLink->setPreferredFramesPerSecond(connection, observerID, preferredFramesPerSecond);
+            return;
+        }
+    }
+}
 #endif // HAVE(CVDISPLAYLINK)
 
 // FIXME: Deprecated. Left here until a final decision is made.

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -238,9 +238,10 @@
 #endif
 
 #if HAVE(CVDISPLAYLINK)
-    Optional<unsigned> nominalFramesPerSecondForDisplay(WebCore::PlatformDisplayID);
-    void startDisplayLink(IPC::Connection&, DisplayLinkObserverID, WebCore::PlatformDisplayID);
+    Optional<WebCore::FramesPerSecond> nominalFramesPerSecondForDisplay(WebCore::PlatformDisplayID);
+    void startDisplayLink(IPC::Connection&, DisplayLinkObserverID, WebCore::PlatformDisplayID, WebCore::FramesPerSecond);
     void stopDisplayLink(IPC::Connection&, DisplayLinkObserverID, WebCore::PlatformDisplayID);
+    void setDisplayLinkPreferredFramesPerSecond(IPC::Connection&, DisplayLinkObserverID, WebCore::PlatformDisplayID, WebCore::FramesPerSecond);
     void stopDisplayLinks(IPC::Connection&);
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -77,6 +77,7 @@
 struct PrewarmInformation;
 struct SecurityOriginData;
 enum class ThirdPartyCookieBlockingMode : uint8_t;
+using FramesPerSecond = unsigned;
 using PlatformDisplayID = uint32_t;
 }
 
@@ -298,8 +299,9 @@
 #endif
 
 #if HAVE(CVDISPLAYLINK)
-    void startDisplayLink(DisplayLinkObserverID, WebCore::PlatformDisplayID);
+    void startDisplayLink(DisplayLinkObserverID, WebCore::PlatformDisplayID, WebCore::FramesPerSecond);
     void stopDisplayLink(DisplayLinkObserverID, WebCore::PlatformDisplayID);
+    void setDisplayLinkPreferredFramesPerSecond(DisplayLinkObserverID, WebCore::PlatformDisplayID, WebCore::FramesPerSecond);
 #endif
 
     // Called when the web process has crashed or we know that it will terminate soon.

Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.messages.in (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/WebProcessProxy.messages.in	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.messages.in	2021-04-01 04:03:47 UTC (rev 275345)
@@ -72,8 +72,9 @@
 #endif
 
 #if HAVE(CVDISPLAYLINK)
-    StartDisplayLink(WebKit::DisplayLinkObserverID observerID, uint32_t displayID)
+    StartDisplayLink(WebKit::DisplayLinkObserverID observerID, uint32_t displayID, unsigned preferredFramesPerSecond)
     StopDisplayLink(WebKit::DisplayLinkObserverID observerID, uint32_t displayID)
+    SetDisplayLinkPreferredFramesPerSecond(WebKit::DisplayLinkObserverID observerID, uint32_t displayID, unsigned preferredFramesPerSecond);
 #endif
 
 #if PLATFORM(GTK) || PLATFORM(WPE)

Modified: trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp	2021-04-01 04:03:47 UTC (rev 275345)
@@ -31,6 +31,7 @@
 #include "EventDispatcherMessages.h"
 #include "Logging.h"
 #include "WebProcessMessages.h"
+#include <WebCore/AnimationFrameRate.h>
 #include <wtf/ProcessPrivilege.h>
 #include <wtf/text/TextStream.h>
 
@@ -81,15 +82,15 @@
     return round((double)refreshPeriod.timeScale / (double)refreshPeriod.timeValue);
 }
 
-void DisplayLink::addObserver(IPC::Connection& connection, DisplayLinkObserverID observerID)
+void DisplayLink::addObserver(IPC::Connection& connection, DisplayLinkObserverID observerID, WebCore::FramesPerSecond preferredFramesPerSecond)
 {
     ASSERT(RunLoop::isMain());
 
     {
-        LockHolder locker(m_observersLock);
+        auto locker = holdLock(m_observersLock);
         m_observers.ensure(&connection, [] {
-            return Vector<DisplayLinkObserverID> { };
-        }).iterator->value.append(observerID);
+            return Vector<ObserverInfo> { };
+        }).iterator->value.append({ observerID, preferredFramesPerSecond });
     }
 
     if (!CVDisplayLinkIsRunning(m_displayLink)) {
@@ -106,12 +107,14 @@
 {
     ASSERT(RunLoop::isMain());
 
-    LockHolder locker(m_observersLock);
+    auto locker = holdLock(m_observersLock);
 
     auto it = m_observers.find(&connection);
     if (it == m_observers.end())
         return;
-    bool removed = it->value.removeFirst(observerID);
+    bool removed = it->value.removeFirstMatching([observerID](const auto& value) {
+        return value.observerID == observerID;
+    });
     ASSERT_UNUSED(removed, removed);
     if (it->value.isEmpty())
         m_observers.remove(it);
@@ -125,7 +128,7 @@
 {
     ASSERT(RunLoop::isMain());
 
-    LockHolder locker(m_observersLock);
+    auto locker = holdLock(m_observersLock);
     m_observers.remove(&connection);
 
     // We do not stop the display link right away when |m_observers| becomes empty. Instead, we
@@ -133,6 +136,24 @@
     // killing & restarting too many threads when observers gets removed & added in quick succession.
 }
 
+void DisplayLink::setPreferredFramesPerSecond(IPC::Connection& connection, DisplayLinkObserverID observerID, WebCore::FramesPerSecond preferredFramesPerSecond)
+{
+    LOG_WITH_STREAM(DisplayLink, stream << "[UI ] DisplayLink::setPreferredFramesPerSecond - display " << m_displayID << " observer " << observerID << " fps " << preferredFramesPerSecond);
+
+    auto locker = holdLock(m_observersLock);
+
+    auto it = m_observers.find(&connection);
+    if (it == m_observers.end())
+        return;
+
+    auto index = it->value.findMatching([observerID](const auto& observer) {
+        return observer.observerID == observerID;
+    });
+
+    if (index != notFound)
+        it->value[index].preferredFramesPerSecond = preferredFramesPerSecond;
+}
+
 CVReturn DisplayLink::displayLinkCallback(CVDisplayLinkRef displayLinkRef, const CVTimeStamp*, const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* data)
 {
     static_cast<DisplayLink*>(data)->notifyObserversDisplayWasRefreshed();
@@ -143,7 +164,7 @@
 {
     ASSERT(!RunLoop::isMain());
 
-    LockHolder locker(m_observersLock);
+    auto locker = holdLock(m_observersLock);
     if (m_observers.isEmpty()) {
         if (++m_fireCountWithoutObservers >= maxFireCountWithoutObservers) {
             LOG_WITH_STREAM(DisplayLink, stream << "[UI ] DisplayLink for display " << m_displayID << " fired " << m_fireCountWithoutObservers << " times with no observers; stopping CVDisplayLink");
@@ -153,9 +174,23 @@
     }
     m_fireCountWithoutObservers = 0;
 
-    for (auto& connection : m_observers.keys()) {
-        LOG_WITH_STREAM(DisplayLink, stream << "[UI ] DisplayLink for display " << m_displayID << " (display fps " << m_displayNominalFramesPerSecond << ") update " << m_currentUpdate << " connection " << connection->uniqueID() << " on background queue " << shouldSendIPCOnBackgroundQueue);
+    auto maxFramesPerSecond = [](const Vector<ObserverInfo>& observers) {
+        Optional<WebCore::FramesPerSecond> observersMaxFramesPerSecond;
+        for (const auto& observer : observers)
+            observersMaxFramesPerSecond = std::max(observersMaxFramesPerSecond.valueOr(0), observer.preferredFramesPerSecond);
+        return observersMaxFramesPerSecond;
+    };
 
+    for (auto& [connection, observers] : m_observers) {
+        auto observersMaxFramesPerSecond = maxFramesPerSecond(observers);
+        auto updateIsRelevant = m_currentUpdate.relevantForUpdateFrequency(observersMaxFramesPerSecond.valueOr(WebCore::FullSpeedFramesPerSecond));
+
+        LOG_WITH_STREAM(DisplayLink, stream << "[UI ] DisplayLink for display " << m_displayID << " (display fps " << m_displayNominalFramesPerSecond << ") update " << m_currentUpdate << " " << observers.size()
+            << " observers, on background queue " << shouldSendIPCOnBackgroundQueue << " maxFramesPerSecond " << observersMaxFramesPerSecond << " relevant " << updateIsRelevant);
+
+        if (!updateIsRelevant)
+            continue;
+
         if (shouldSendIPCOnBackgroundQueue)
             connection->send(Messages::EventDispatcher::DisplayWasRefreshed(m_displayID, m_currentUpdate), 0);
         else

Modified: trunk/Source/WebKit/UIProcess/mac/DisplayLink.h (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/mac/DisplayLink.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/mac/DisplayLink.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -47,10 +47,12 @@
     explicit DisplayLink(WebCore::PlatformDisplayID);
     ~DisplayLink();
     
-    void addObserver(IPC::Connection&, DisplayLinkObserverID);
+    void addObserver(IPC::Connection&, DisplayLinkObserverID, WebCore::FramesPerSecond);
     void removeObserver(IPC::Connection&, DisplayLinkObserverID);
     void removeObservers(IPC::Connection&);
 
+    void setPreferredFramesPerSecond(IPC::Connection&, DisplayLinkObserverID, WebCore::FramesPerSecond);
+
     WebCore::PlatformDisplayID displayID() const { return m_displayID; }
     
     WebCore::FramesPerSecond nominalFramesPerSecond() const { return m_displayNominalFramesPerSecond; }
@@ -65,9 +67,14 @@
     
     static WebCore::FramesPerSecond nominalFramesPerSecondFromDisplayLink(CVDisplayLinkRef);
 
+    struct ObserverInfo {
+        DisplayLinkObserverID observerID;
+        WebCore::FramesPerSecond preferredFramesPerSecond;
+    };
+
     CVDisplayLinkRef m_displayLink { nullptr };
     Lock m_observersLock;
-    HashMap<RefPtr<IPC::Connection>, Vector<DisplayLinkObserverID>> m_observers;
+    HashMap<RefPtr<IPC::Connection>, Vector<ObserverInfo>> m_observers;
     WebCore::PlatformDisplayID m_displayID;
     WebCore::FramesPerSecond m_displayNominalFramesPerSecond { 0 };
     WebCore::DisplayUpdate m_currentUpdate;

Modified: trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm (275344 => 275345)


--- trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/UIProcess/mac/WebProcessProxyMac.mm	2021-04-01 04:03:47 UTC (rev 275345)
@@ -59,11 +59,11 @@
     return !path.isEmpty() && !path.startsWith("/System/");
 }
 
-void WebProcessProxy::startDisplayLink(DisplayLinkObserverID observerID, WebCore::PlatformDisplayID displayID)
+void WebProcessProxy::startDisplayLink(DisplayLinkObserverID observerID, WebCore::PlatformDisplayID displayID, WebCore::FramesPerSecond preferredFramesPerSecond)
 {
     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
     ASSERT(connection());
-    processPool().startDisplayLink(*connection(), observerID, displayID);
+    processPool().startDisplayLink(*connection(), observerID, displayID, preferredFramesPerSecond);
 }
 
 void WebProcessProxy::stopDisplayLink(DisplayLinkObserverID observerID, WebCore::PlatformDisplayID displayID)
@@ -72,6 +72,12 @@
     processPool().stopDisplayLink(*connection(), observerID, displayID);
 }
 
+void WebProcessProxy::setDisplayLinkPreferredFramesPerSecond(DisplayLinkObserverID observerID, WebCore::PlatformDisplayID displayID, WebCore::FramesPerSecond preferredFramesPerSecond)
+{
+    ASSERT(connection());
+    processPool().setDisplayLinkPreferredFramesPerSecond(*connection(), observerID, displayID, preferredFramesPerSecond);
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)

Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h (275344 => 275345)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -40,7 +40,6 @@
     
     virtual ~RemoteLayerTreeDisplayRefreshMonitor();
 
-    void setPreferredFramesPerSecond(WebCore::FramesPerSecond) override;
     bool requestRefreshCallback() final;
 
     void didUpdateLayers();
@@ -53,6 +52,8 @@
     void stopNotificationMechanism() final { }
     Optional<WebCore::FramesPerSecond> displayNominalFramesPerSecond() final;
 
+    void adjustPreferredFramesPerSecond(WebCore::FramesPerSecond) final;
+
     WeakPtr<RemoteLayerTreeDrawingArea> m_drawingArea;
 
     WebCore::FramesPerSecond m_preferredFramesPerSecond;

Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm (275344 => 275345)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2021-04-01 04:03:47 UTC (rev 275345)
@@ -48,11 +48,13 @@
         m_drawingArea->willDestroyDisplayRefreshMonitor(this);
 }
 
-void RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+void RemoteLayerTreeDisplayRefreshMonitor::adjustPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
 {
     if (preferredFramesPerSecond == m_preferredFramesPerSecond)
         return;
 
+    LOG_WITH_STREAM(DisplayLink, stream << "RemoteLayerTreeDisplayRefreshMonitor::adjustMaxPreferredFramesPerSecond to " << preferredFramesPerSecond);
+
     m_preferredFramesPerSecond = preferredFramesPerSecond;
     m_currentUpdate = { 0, m_preferredFramesPerSecond };
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp (275344 => 275345)


--- trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp	2021-04-01 04:03:47 UTC (rev 275345)
@@ -32,6 +32,7 @@
 #include "WebProcess.h"
 #include "WebProcessProxy.h"
 #include "WebProcessProxyMessages.h"
+#include <WebCore/AnimationFrameRate.h>
 #include <WebCore/DisplayRefreshMonitor.h>
 #include <WebCore/RunLoopObserver.h>
 #include <wtf/text/TextStream.h>
@@ -71,7 +72,7 @@
         return true;
 
     LOG_WITH_STREAM(DisplayLink, stream << "DisplayRefreshMonitorMac::requestRefreshCallback - starting");
-    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StartDisplayLink(m_observerID, displayID()), 0);
+    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StartDisplayLink(m_observerID, displayID(), maxClientPreferredFramesPerSecond().valueOr(FullSpeedFramesPerSecond)), 0);
     if (!m_runLoopObserver) {
         // The RunLoopObserver repeats.
         m_runLoopObserver = makeUnique<RunLoopObserver>(kCFRunLoopEntry, [this]() {
@@ -97,6 +98,13 @@
     m_displayLinkIsActive = false;
 }
 
+void DisplayRefreshMonitorMac::adjustPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+{
+    LOG_WITH_STREAM(DisplayLink, stream << "DisplayRefreshMonitorMac::adjustPreferredFramesPerSecond for display link on display " << displayID() << " to " << preferredFramesPerSecond);
+    WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::SetDisplayLinkPreferredFramesPerSecond(m_observerID, displayID(), preferredFramesPerSecond), 0);
+
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)

Modified: trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h (275344 => 275345)


--- trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h	2021-04-01 03:18:20 UTC (rev 275344)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h	2021-04-01 04:03:47 UTC (rev 275345)
@@ -50,6 +50,8 @@
     bool startNotificationMechanism() final;
     void stopNotificationMechanism() final;
 
+    void adjustPreferredFramesPerSecond(FramesPerSecond) final;
+
     DisplayLinkObserverID m_observerID;
     std::unique_ptr<WebCore::RunLoopObserver> m_runLoopObserver;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to