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;