Title: [275163] trunk/Source
Revision
275163
Author
[email protected]
Date
2021-03-29 10:21:03 -0700 (Mon, 29 Mar 2021)

Log Message

Plumb DisplayUpdate through the display refresh monitors
https://bugs.webkit.org/show_bug.cgi?id=223847

Reviewed by Sam Weinig.

Future work will allow DisplayRefreshMonitorClients to request different frame rates, which
are whole fractions of the display's nominal refresh rate. These various frame rate requests
flow up through the DisplayRefreshMonitors, and in WebKit2, up through IPC to the
per-display DisplayLink which may even service multiple processes.

For power reasons, we don't want to trigger display refresh notifications down the chain at
the highest possible frequency; at various stages of propagation the rate might be halved if
that's necessary for downstream clients.

To make this frequency splitting logic simple, this patch introduces DisplayUpdate, which
represents an update of the display, and contains data about it in the form of a numerator
is the frame index, and the denominator is the nominal frame rate. Frame index wraps to zero
every second.

For example, a 60Hz display will generate display refreshes with DisplayUpdates which
sequentially will be { 0, 60 }, { 1, 60 }, { 2, 60 } ... { 59, 60 }, { 0, 60 }. The
zeroth frame is at some arbitrary time and not aligned with wallclock time.

Thus a client with a 30Hz update requirement can simply ignore every odd-numbered frame, and
a client downstream from it with a 15Hz requirement, which only receives those even-numbered
frames, still has enough information to compute which frames to ignore.

Classes which are sources of callbacks for DisplayRefreshMonitor need to generate these
DisplayUpdates; that includes the various platform DisplayRefreshMonitor subclasses in
WebCore, and those in WebKit that live in the UI process and trigger updates over IPC.

Source/WebCore:

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* loader/EmptyClients.cpp:
* platform/graphics/AnimationFrameRate.cpp:
* platform/graphics/AnimationFrameRate.h:
* platform/graphics/DisplayRefreshMonitor.cpp:
(WebCore::DisplayRefreshMonitor::displayLinkFired):
(WebCore::DisplayRefreshMonitor::dispatchDisplayDidRefresh):
(WebCore::DisplayRefreshMonitor::displayDidRefresh):
* platform/graphics/DisplayRefreshMonitor.h:
* platform/graphics/DisplayRefreshMonitorManager.cpp:
(WebCore::DisplayRefreshMonitorManager::displayWasUpdated):
* platform/graphics/DisplayRefreshMonitorManager.h:
* platform/graphics/DisplayUpdate.cpp: Copied from Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.h.
(WebCore::operator<<):
* platform/graphics/DisplayUpdate.h: Copied from Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.h.
(WebCore::DisplayUpdate::didUpdate):
(WebCore::DisplayUpdate::encode const):
(WebCore::DisplayUpdate::decode):
* platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp: Assume a 60fps refresh rate but this code
should probably use gdk_frame_clock_get_refresh_info() to get the correct rate.
(WebCore::onFrameClockUpdate):
(WebCore::DisplayRefreshMonitorGtk::displayLinkCallbackFired):
(WebCore::DisplayRefreshMonitorGtk::startNotificationMechanism):
* platform/graphics/gtk/DisplayRefreshMonitorGtk.h:
* platform/graphics/ios/DisplayRefreshMonitorIOS.h:
* platform/graphics/ios/DisplayRefreshMonitorIOS.mm:
(-[WebDisplayLinkHandler initWithMonitor:]):
(-[WebDisplayLinkHandler handleDisplayLink:]):
(WebCore::DisplayRefreshMonitorIOS::displayLinkCallbackFired):
(WebCore::DisplayRefreshMonitorIOS::startNotificationMechanism):
(-[WebDisplayLinkHandler setPreferredFramesPerSecond:]): Deleted.
* platform/graphics/mac/LegacyDisplayRefreshMonitorMac.cpp:
(WebCore::displayLinkCallback):
(WebCore::LegacyDisplayRefreshMonitorMac::displayLinkCallbackFired):
(WebCore::LegacyDisplayRefreshMonitorMac::dispatchDisplayDidRefresh):
(WebCore::LegacyDisplayRefreshMonitorMac::nominalFramesPerSecondFromDisplayLink):
(WebCore::LegacyDisplayRefreshMonitorMac::startNotificationMechanism):
* platform/graphics/mac/LegacyDisplayRefreshMonitorMac.h:
(WebCore::LegacyDisplayRefreshMonitorMac::currentUpdate const):
* platform/graphics/win/DisplayRefreshMonitorWin.cpp:
(WebCore::DisplayRefreshMonitorWin::DisplayRefreshMonitorWin):
(WebCore::DisplayRefreshMonitorWin::displayLinkCallbackFired):
* platform/graphics/win/DisplayRefreshMonitorWin.h:

Source/WebKit:

* Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp:
(WebKit::ThreadedDisplayRefreshMonitor::invalidate):
(WebKit::ThreadedDisplayRefreshMonitor::displayRefreshCallback):
(WebKit::ThreadedDisplayRefreshMonitor::ThreadedDisplayRefreshMonitor): Deleted.
* Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.h:
* UIProcess/mac/DisplayLink.cpp:
(WebKit::DisplayLink::addObserver):
(WebKit::DisplayLink::notifyObserversDisplayWasRefreshed):
* UIProcess/mac/DisplayLink.h:
* WebProcess/WebPage/EventDispatcher.cpp:
(WebKit::EventDispatcher::displayWasRefreshed):
* WebProcess/WebPage/EventDispatcher.h:
* WebProcess/WebPage/EventDispatcher.messages.in:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm:
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::RemoteLayerTreeDisplayRefreshMonitor):
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond):
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::didUpdateLayers):
* WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp:
(WebKit::DisplayRefreshMonitorMac::dispatchDisplayDidRefresh):
* WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h:
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::displayWasRefreshed):
* WebProcess/WebProcess.h:
* WebProcess/WebProcess.messages.in:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (275162 => 275163)


--- trunk/Source/WebCore/ChangeLog	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/ChangeLog	2021-03-29 17:21:03 UTC (rev 275163)
@@ -1,3 +1,81 @@
+2021-03-28  Simon Fraser  <[email protected]>
+
+        Plumb DisplayUpdate through the display refresh monitors
+        https://bugs.webkit.org/show_bug.cgi?id=223847
+
+        Reviewed by Sam Weinig.
+
+        Future work will allow DisplayRefreshMonitorClients to request different frame rates, which
+        are whole fractions of the display's nominal refresh rate. These various frame rate requests
+        flow up through the DisplayRefreshMonitors, and in WebKit2, up through IPC to the
+        per-display DisplayLink which may even service multiple processes.
+
+        For power reasons, we don't want to trigger display refresh notifications down the chain at
+        the highest possible frequency; at various stages of propagation the rate might be halved if
+        that's necessary for downstream clients.
+        
+        To make this frequency splitting logic simple, this patch introduces DisplayUpdate, which
+        represents an update of the display, and contains data about it in the form of a numerator
+        is the frame index, and the denominator is the nominal frame rate. Frame index wraps to zero
+        every second.
+        
+        For example, a 60Hz display will generate display refreshes with DisplayUpdates which
+        sequentially will be { 0, 60 }, { 1, 60 }, { 2, 60 } ... { 59, 60 }, { 0, 60 }. The
+        zeroth frame is at some arbitrary time and not aligned with wallclock time.
+        
+        Thus a client with a 30Hz update requirement can simply ignore every odd-numbered frame, and
+        a client downstream from it with a 15Hz requirement, which only receives those even-numbered
+        frames, still has enough information to compute which frames to ignore.
+        
+        Classes which are sources of callbacks for DisplayRefreshMonitor need to generate these
+        DisplayUpdates; that includes the various platform DisplayRefreshMonitor subclasses in
+        WebCore, and those in WebKit that live in the UI process and trigger updates over IPC.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/EmptyClients.cpp:
+        * platform/graphics/AnimationFrameRate.cpp:
+        * platform/graphics/AnimationFrameRate.h:
+        * platform/graphics/DisplayRefreshMonitor.cpp:
+        (WebCore::DisplayRefreshMonitor::displayLinkFired):
+        (WebCore::DisplayRefreshMonitor::dispatchDisplayDidRefresh):
+        (WebCore::DisplayRefreshMonitor::displayDidRefresh):
+        * platform/graphics/DisplayRefreshMonitor.h:
+        * platform/graphics/DisplayRefreshMonitorManager.cpp:
+        (WebCore::DisplayRefreshMonitorManager::displayWasUpdated):
+        * platform/graphics/DisplayRefreshMonitorManager.h:
+        * platform/graphics/DisplayUpdate.cpp: Copied from Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.h.
+        (WebCore::operator<<):
+        * platform/graphics/DisplayUpdate.h: Copied from Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.h.
+        (WebCore::DisplayUpdate::didUpdate):
+        (WebCore::DisplayUpdate::encode const):
+        (WebCore::DisplayUpdate::decode):
+        * platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp: Assume a 60fps refresh rate but this code
+        should probably use gdk_frame_clock_get_refresh_info() to get the correct rate.
+        (WebCore::onFrameClockUpdate):
+        (WebCore::DisplayRefreshMonitorGtk::displayLinkCallbackFired):
+        (WebCore::DisplayRefreshMonitorGtk::startNotificationMechanism):
+        * platform/graphics/gtk/DisplayRefreshMonitorGtk.h:
+        * platform/graphics/ios/DisplayRefreshMonitorIOS.h:
+        * platform/graphics/ios/DisplayRefreshMonitorIOS.mm:
+        (-[WebDisplayLinkHandler initWithMonitor:]):
+        (-[WebDisplayLinkHandler handleDisplayLink:]):
+        (WebCore::DisplayRefreshMonitorIOS::displayLinkCallbackFired):
+        (WebCore::DisplayRefreshMonitorIOS::startNotificationMechanism):
+        (-[WebDisplayLinkHandler setPreferredFramesPerSecond:]): Deleted.
+        * platform/graphics/mac/LegacyDisplayRefreshMonitorMac.cpp:
+        (WebCore::displayLinkCallback):
+        (WebCore::LegacyDisplayRefreshMonitorMac::displayLinkCallbackFired):
+        (WebCore::LegacyDisplayRefreshMonitorMac::dispatchDisplayDidRefresh):
+        (WebCore::LegacyDisplayRefreshMonitorMac::nominalFramesPerSecondFromDisplayLink):
+        (WebCore::LegacyDisplayRefreshMonitorMac::startNotificationMechanism):
+        * platform/graphics/mac/LegacyDisplayRefreshMonitorMac.h:
+        (WebCore::LegacyDisplayRefreshMonitorMac::currentUpdate const):
+        * platform/graphics/win/DisplayRefreshMonitorWin.cpp:
+        (WebCore::DisplayRefreshMonitorWin::DisplayRefreshMonitorWin):
+        (WebCore::DisplayRefreshMonitorWin::displayLinkCallbackFired):
+        * platform/graphics/win/DisplayRefreshMonitorWin.h:
+
 2021-03-29  Aditya Keerthi  <[email protected]>
 
         Use enum classes and OptionSets for ControlStates::States

Modified: trunk/Source/WebCore/Headers.cmake (275162 => 275163)


--- trunk/Source/WebCore/Headers.cmake	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/Headers.cmake	2021-03-29 17:21:03 UTC (rev 275163)
@@ -1189,6 +1189,7 @@
     platform/graphics/DisplayRefreshMonitorClient.h
     platform/graphics/DisplayRefreshMonitorFactory.h
     platform/graphics/DisplayRefreshMonitorManager.h
+    platform/graphics/DisplayUpdate.h
     platform/graphics/ExtensionsGL.h
     platform/graphics/FloatLine.h
     platform/graphics/FloatPoint.h

Modified: trunk/Source/WebCore/Sources.txt (275162 => 275163)


--- trunk/Source/WebCore/Sources.txt	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/Sources.txt	2021-03-29 17:21:03 UTC (rev 275163)
@@ -1943,6 +1943,7 @@
 platform/graphics/DisplayRefreshMonitor.cpp
 platform/graphics/DisplayRefreshMonitorClient.cpp
 platform/graphics/DisplayRefreshMonitorManager.cpp
+platform/graphics/DisplayUpdate.cpp
 platform/graphics/FloatLine.cpp
 platform/graphics/FloatPoint.cpp
 platform/graphics/FloatPoint3D.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (275162 => 275163)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-03-29 17:21:03 UTC (rev 275163)
@@ -345,6 +345,7 @@
 		0FB6252F18DE1B1500A07C05 /* GeometryUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB6252D18DE1B1500A07C05 /* GeometryUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FB8890F167D30160010CDA5 /* ScrollingStateStickyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB8890D167D30160010CDA5 /* ScrollingStateStickyNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FBB5FBE260991D20054572C /* DisplayRefreshMonitorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBB5FBD26095A9C0054572C /* DisplayRefreshMonitorFactory.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		0FBB5FCC260E9E070054572C /* DisplayUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBB5FCB260E9B440054572C /* DisplayUpdate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FC4B00622B9A02D00CF3B1E /* ScrollingTreeOverflowScrollProxyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC4B00422B9A02C00CF3B1E /* ScrollingTreeOverflowScrollProxyNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FCF332F0F2B9A25004B6795 /* WebLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCF332B0F2B9A25004B6795 /* WebLayer.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FD3080F117CF7E700A791F7 /* RenderFrameBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3080D117CF7E700A791F7 /* RenderFrameBase.h */; };
@@ -6204,6 +6205,8 @@
 		0FB8890C167D30160010CDA5 /* ScrollingStateStickyNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollingStateStickyNode.cpp; sourceTree = "<group>"; };
 		0FB8890D167D30160010CDA5 /* ScrollingStateStickyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingStateStickyNode.h; sourceTree = "<group>"; };
 		0FBB5FBD26095A9C0054572C /* DisplayRefreshMonitorFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorFactory.h; sourceTree = "<group>"; };
+		0FBB5FC9260E9B430054572C /* DisplayUpdate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayUpdate.cpp; sourceTree = "<group>"; };
+		0FBB5FCB260E9B440054572C /* DisplayUpdate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayUpdate.h; sourceTree = "<group>"; };
 		0FBFCE24256CBD9A00A0B489 /* DisplayBoxClip.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayBoxClip.cpp; sourceTree = "<group>"; };
 		0FBFCE26256CBD9A00A0B489 /* DisplayBoxClip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayBoxClip.h; sourceTree = "<group>"; };
 		0FC05168219B5EBE0031C39E /* ScrollingTreeOverflowScrollingNodeMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeOverflowScrollingNodeMac.mm; sourceTree = "<group>"; };
@@ -26777,6 +26780,8 @@
 				0FBB5FBD26095A9C0054572C /* DisplayRefreshMonitorFactory.h */,
 				2D29ECC3192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp */,
 				2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */,
+				0FBB5FC9260E9B430054572C /* DisplayUpdate.cpp */,
+				0FBB5FCB260E9B440054572C /* DisplayUpdate.h */,
 				6E67D2A81280E8BD008758F7 /* ExtensionsGL.h */,
 				2E888CA925F6A4110057914A /* FloatLine.cpp */,
 				2E888CA825F6A4110057914A /* FloatLine.h */,
@@ -32114,6 +32119,7 @@
 				0FBB5FBE260991D20054572C /* DisplayRefreshMonitorFactory.h in Headers */,
 				2D29ECCA192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h in Headers */,
 				2D29ECC8192ECC8300984B78 /* DisplayRefreshMonitorManager.h in Headers */,
+				0FBB5FCC260E9E070054572C /* DisplayUpdate.h in Headers */,
 				0F790F432517CE6E009BA034 /* DisplayView.h in Headers */,
 				FD31609112B026F700C1A359 /* Distance.h in Headers */,
 				83040283249A7A6200A90D8D /* DistanceModelType.h in Headers */,

Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (275162 => 275163)


--- trunk/Source/WebCore/loader/EmptyClients.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -133,7 +133,7 @@
         return adoptRef(*new EmptyDisplayRefreshMonitor(displayID));
     }
 
-    void displayLinkFired() final { }
+    void displayLinkFired(const DisplayUpdate&) final { }
     bool requestRefreshCallback() final { return false; }
     void stop() final { }
 

Modified: trunk/Source/WebCore/platform/graphics/AnimationFrameRate.cpp (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/AnimationFrameRate.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/AnimationFrameRate.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -26,6 +26,7 @@
 
 #include "config.h"
 #include "AnimationFrameRate.h"
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 

Modified: trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -26,9 +26,13 @@
 #pragma once
 
 #include <wtf/OptionSet.h>
+#include <wtf/Optional.h>
 #include <wtf/Seconds.h>
-#include <wtf/text/TextStream.h>
 
+namespace WTF {
+class TextStream;
+}
+
 namespace WebCore {
 
 using FramesPerSecond = unsigned;
@@ -54,6 +58,6 @@
 WEBCORE_EXPORT Seconds preferredFrameInterval(const OptionSet<ThrottlingReason>&, Optional<FramesPerSecond> nominalFramesPerSecond);
 WEBCORE_EXPORT FramesPerSecond preferredFramesPerSecondFromInterval(Seconds);
 
-WEBCORE_EXPORT TextStream& operator<<(TextStream&, const OptionSet<ThrottlingReason>&);
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const OptionSet<ThrottlingReason>&);
 
-}
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -128,7 +128,7 @@
     return m_unscheduledFireCount > m_maxUnscheduledFireCount;
 }
 
-void DisplayRefreshMonitor::displayLinkFired()
+void DisplayRefreshMonitor::displayLinkFired(const DisplayUpdate& displayUpdate)
 {
     {
         auto locker = holdLock(m_lock);
@@ -146,19 +146,22 @@
         setIsScheduled(false);
         setIsPreviousFrameDone(false);
     }
-    dispatchDisplayDidRefresh();
+    dispatchDisplayDidRefresh(displayUpdate);
 }
 
-void DisplayRefreshMonitor::dispatchDisplayDidRefresh()
+void DisplayRefreshMonitor::dispatchDisplayDidRefresh(const DisplayUpdate& displayUpdate)
 {
     ASSERT(isMainThread());
-    displayDidRefresh();
+    displayDidRefresh(displayUpdate);
 }
 
-void DisplayRefreshMonitor::displayDidRefresh()
+void DisplayRefreshMonitor::displayDidRefresh(const DisplayUpdate& displayUpdate)
 {
     ASSERT(isMainThread());
 
+    UNUSED_PARAM(displayUpdate);
+    LOG_WITH_STREAM(DisplayLink, stream << "DisplayRefreshMonitor::displayDidRefresh for display " << displayID() << " update " << displayUpdate);
+
     // The call back can cause all our clients to be unregistered, so we need to protect
     // against deletion until the end of the method.
     Ref<DisplayRefreshMonitor> protectedThis(*this);

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "AnimationFrameRate.h"
+#include "DisplayUpdate.h"
 #include "PlatformScreen.h"
 #include <wtf/HashSet.h>
 #include <wtf/Lock.h>
@@ -61,12 +62,12 @@
     PlatformDisplayID displayID() const { return m_displayID; }
 
     static RefPtr<DisplayRefreshMonitor> createDefaultDisplayRefreshMonitor(PlatformDisplayID);
-    WEBCORE_EXPORT virtual void displayLinkFired();
+    WEBCORE_EXPORT virtual void displayLinkFired(const DisplayUpdate&);
 
 protected:
     WEBCORE_EXPORT explicit DisplayRefreshMonitor(PlatformDisplayID);
 
-    WEBCORE_EXPORT virtual void dispatchDisplayDidRefresh();
+    WEBCORE_EXPORT virtual void dispatchDisplayDidRefresh(const DisplayUpdate&);
 
     Lock& lock() { return m_lock; }
     void setMaxUnscheduledFireCount(unsigned count) { m_maxUnscheduledFireCount = count; }
@@ -81,7 +82,7 @@
     bool isPreviousFrameDone() const { return m_previousFrameDone; }
     void setIsPreviousFrameDone(bool done) { m_previousFrameDone = done; }
 
-    WEBCORE_EXPORT void displayDidRefresh();
+    WEBCORE_EXPORT void displayDidRefresh(const DisplayUpdate&);
 
 private:
     bool firedAndReachedMaxUnscheduledFireCount();

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -108,11 +108,11 @@
         scheduleAnimation(client);
 }
 
-void DisplayRefreshMonitorManager::displayWasUpdated(PlatformDisplayID displayID)
+void DisplayRefreshMonitorManager::displayWasUpdated(PlatformDisplayID displayID, const DisplayUpdate& displayUpdate)
 {
     auto* monitor = monitorForDisplayID(displayID);
     if (monitor)
-        monitor->displayLinkFired();
+        monitor->displayLinkFired(displayUpdate);
 }
 
 size_t DisplayRefreshMonitorManager::findMonitorForDisplayID(PlatformDisplayID displayID) const

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -34,6 +34,8 @@
 
 namespace WebCore {
 
+struct DisplayUpdate;
+
 class DisplayRefreshMonitorManager {
     friend class NeverDestroyed<DisplayRefreshMonitorManager>;
     friend class DisplayRefreshMonitor;
@@ -46,7 +48,7 @@
     bool scheduleAnimation(DisplayRefreshMonitorClient&);
     void windowScreenDidChange(PlatformDisplayID, DisplayRefreshMonitorClient&);
 
-    WEBCORE_EXPORT void displayWasUpdated(PlatformDisplayID);
+    WEBCORE_EXPORT void displayWasUpdated(PlatformDisplayID, const DisplayUpdate&);
 
 private:
     DisplayRefreshMonitorManager() = default;

Copied: trunk/Source/WebCore/platform/graphics/DisplayUpdate.cpp (from rev 275162, trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.h) (0 => 275163)


--- trunk/Source/WebCore/platform/graphics/DisplayUpdate.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/DisplayUpdate.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "DisplayUpdate.h"
+
+#include <wtf/text/TextStream.h>
+
+namespace WebCore {
+
+TextStream& operator<<(TextStream& ts, const DisplayUpdate& update)
+{
+    ts << update.updateIndex << "/" << update.updatesPerSecond;
+    return ts;
+}
+
+} // namespace WebCore

Copied: trunk/Source/WebCore/platform/graphics/DisplayUpdate.h (from rev 275162, trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.h) (0 => 275163)


--- trunk/Source/WebCore/platform/graphics/DisplayUpdate.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/DisplayUpdate.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "AnimationFrameRate.h"
+#include <wtf/Optional.h>
+
+namespace WTF {
+class TextStream;
+}
+
+namespace WebCore {
+
+// Used to represent a given update. An value of { 3, 60 } indicates that this is the third update in a 1-second interval
+// on a 60fps cadence. updateIndex will reset to zero every second, so { 59, 60 } is followed by { 0, 60 }.
+struct DisplayUpdate {
+    unsigned updateIndex { 0 };
+    FramesPerSecond updatesPerSecond { 0 };
+    
+    DisplayUpdate nextUpdate() const
+    {
+        return { (updateIndex + 1) % updatesPerSecond, updatesPerSecond };
+    }
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<DisplayUpdate> decode(Decoder&);
+};
+
+template<class Encoder>
+void DisplayUpdate::encode(Encoder& encoder) const
+{
+    encoder << updateIndex;
+    encoder << updatesPerSecond;
+}
+
+template<class Decoder>
+Optional<DisplayUpdate> DisplayUpdate::decode(Decoder& decoder)
+{
+    Optional<unsigned> updateIndex;
+    decoder >> updateIndex;
+    if (!updateIndex)
+        return WTF::nullopt;
+
+    Optional<FramesPerSecond> updatesPerSecond;
+    decoder >> updatesPerSecond;
+    if (!updatesPerSecond)
+        return WTF::nullopt;
+
+    return {{ *updateIndex, *updatesPerSecond }};
+}
+
+WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const DisplayUpdate&);
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -33,6 +33,8 @@
 
 namespace WebCore {
 
+constexpr FramesPerSecond DefaultFramesPerSecond = 60;
+
 DisplayRefreshMonitorGtk::DisplayRefreshMonitorGtk(PlatformDisplayID displayID)
     : DisplayRefreshMonitor(displayID)
 {
@@ -45,9 +47,15 @@
 
 static void onFrameClockUpdate(GdkFrameClock*, DisplayRefreshMonitorGtk* monitor)
 {
-    monitor->displayLinkFired();
+    monitor->displayLinkCallbackFired();
 }
 
+void DisplayRefreshMonitorGtk::displayLinkCallbackFired()
+{
+    displayLinkFired(m_currentUpdate);
+    m_currentUpdate = m_currentUpdate.nextUpdate();
+}
+
 void DisplayRefreshMonitorGtk::stop()
 {
     if (!m_window)
@@ -81,6 +89,9 @@
     ASSERT(frameClock);
     gdk_frame_clock_begin_updating(frameClock);
 
+    // FIXME: Use gdk_frame_clock_get_refresh_info to get the correct frame rate.
+    m_currentUpdate = { 0, DefaultFramesPerSecond };
+
     m_clockIsActive = true;
     return true;
 }

Modified: trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/gtk/DisplayRefreshMonitorGtk.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -42,6 +42,8 @@
 
     virtual ~DisplayRefreshMonitorGtk();
 
+    void displayLinkCallbackFired();
+
 private:
     explicit DisplayRefreshMonitorGtk(PlatformDisplayID);
 
@@ -50,6 +52,7 @@
     void stopNotificationMechanism() final;
 
     GtkWidget* m_window { nullptr };
+    DisplayUpdate m_currentUpdate;
     bool m_clockIsActive { false };
 };
 

Modified: trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -43,6 +43,8 @@
     
     virtual ~DisplayRefreshMonitorIOS();
 
+    void displayLinkCallbackFired();
+
 private:
     explicit DisplayRefreshMonitorIOS(PlatformDisplayID);
 
@@ -51,6 +53,7 @@
     void stopNotificationMechanism() final;
 
     RetainPtr<WebDisplayLinkHandler> m_handler;
+    DisplayUpdate m_currentUpdate;
     bool m_displayLinkIsActive { false };
 };
 

Modified: trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm	2021-03-29 17:21:03 UTC (rev 275163)
@@ -28,6 +28,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#import "DisplayUpdate.h"
 #import "Logging.h"
 #import "WebCoreThread.h"
 #import <QuartzCore/CADisplayLink.h>
@@ -36,6 +37,8 @@
 
 using WebCore::DisplayRefreshMonitorIOS;
 
+constexpr WebCore::FramesPerSecond DisplayLinkFramesPerSecond = 60;
+
 @interface WebDisplayLinkHandler : NSObject
 {
     DisplayRefreshMonitorIOS* m_monitor;
@@ -43,7 +46,6 @@
 }
 
 - (id)initWithMonitor:(DisplayRefreshMonitorIOS*)monitor;
-- (void)setPreferredFramesPerSecond:(NSInteger)preferredFramesPerSecond;
 - (void)handleDisplayLink:(CADisplayLink *)sender;
 - (void)setPaused:(BOOL)paused;
 - (void)invalidate;
@@ -59,7 +61,7 @@
         // Note that CADisplayLink retains its target (self), so a call to -invalidate is needed on teardown.
         m_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
         [m_displayLink addToRunLoop:WebThreadNSRunLoop() forMode:NSDefaultRunLoopMode];
-        m_displayLink.preferredFramesPerSecond = 60;
+        m_displayLink.preferredFramesPerSecond = DisplayLinkFramesPerSecond;
     }
     return self;
 }
@@ -70,16 +72,12 @@
     [super dealloc];
 }
 
-- (void)setPreferredFramesPerSecond:(NSInteger)preferredFramesPerSecond
-{
-    m_displayLink.preferredFramesPerSecond = preferredFramesPerSecond;
-}
-
 - (void)handleDisplayLink:(CADisplayLink *)sender
 {
     UNUSED_PARAM(sender);
     ASSERT(isMainThread());
-    m_monitor->displayLinkFired();
+    
+    m_monitor->displayLinkCallbackFired();
 }
 
 - (void)setPaused:(BOOL)paused
@@ -116,6 +114,12 @@
     m_handler = nil;
 }
 
+void DisplayRefreshMonitorIOS::displayLinkCallbackFired()
+{
+    displayLinkFired(m_currentUpdate);
+    m_currentUpdate = m_currentUpdate.nextUpdate();
+}
+
 bool DisplayRefreshMonitorIOS::startNotificationMechanism()
 {
     if (m_displayLinkIsActive)
@@ -128,7 +132,10 @@
 
     LOG_WITH_STREAM(DisplayLink, stream << "DisplayRefreshMonitorIOS::startNotificationMechanism - starting WebDisplayLinkHandler");
     [m_handler setPaused:NO];
+
+    m_currentUpdate = { 0, DisplayLinkFramesPerSecond };
     m_displayLinkIsActive = true;
+
     return true;
 }
 

Modified: trunk/Source/WebCore/platform/graphics/mac/LegacyDisplayRefreshMonitorMac.cpp (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/mac/LegacyDisplayRefreshMonitorMac.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/mac/LegacyDisplayRefreshMonitorMac.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -61,18 +61,30 @@
 static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* data)
 {
     LegacyDisplayRefreshMonitorMac* monitor = static_cast<LegacyDisplayRefreshMonitorMac*>(data);
-    monitor->displayLinkFired();
+    monitor->displayLinkCallbackFired();
     return kCVReturnSuccess;
 }
 
-void LegacyDisplayRefreshMonitorMac::dispatchDisplayDidRefresh()
+void LegacyDisplayRefreshMonitorMac::displayLinkCallbackFired()
 {
-    RunLoop::main().dispatch([this, protectedThis = makeRef(*this)] {
+    displayLinkFired(m_currentUpdate);
+    m_currentUpdate = m_currentUpdate.nextUpdate();
+}
+
+void LegacyDisplayRefreshMonitorMac::dispatchDisplayDidRefresh(const DisplayUpdate& displayUpdate)
+{
+    RunLoop::main().dispatch([this, displayUpdate, protectedThis = makeRef(*this)] {
         if (m_displayLink)
-            displayDidRefresh();
+            displayDidRefresh(displayUpdate);
     });
 }
 
+WebCore::FramesPerSecond LegacyDisplayRefreshMonitorMac::nominalFramesPerSecondFromDisplayLink(CVDisplayLinkRef displayLink)
+{
+    CVTime refreshPeriod = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(displayLink);
+    return round((double)refreshPeriod.timeScale / (double)refreshPeriod.timeValue);
+}
+
 bool LegacyDisplayRefreshMonitorMac::startNotificationMechanism()
 {
     if (!m_displayLink) {
@@ -83,6 +95,8 @@
         error = CVDisplayLinkSetOutputCallback(m_displayLink, displayLinkCallback, this);
         if (error)
             return false;
+
+        m_currentUpdate = { 0, nominalFramesPerSecondFromDisplayLink(m_displayLink) };
     }
 
     if (!m_displayLinkIsActive) {
@@ -93,6 +107,7 @@
             return false;
         
         m_displayLinkIsActive = true;
+        m_currentUpdate.updateIndex = 0;
     }
 
     return true;

Modified: trunk/Source/WebCore/platform/graphics/mac/LegacyDisplayRefreshMonitorMac.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/mac/LegacyDisplayRefreshMonitorMac.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/mac/LegacyDisplayRefreshMonitorMac.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -43,10 +43,12 @@
     
     virtual ~LegacyDisplayRefreshMonitorMac();
 
+    void displayLinkCallbackFired();
+
 private:
     explicit LegacyDisplayRefreshMonitorMac(PlatformDisplayID);
 
-    void dispatchDisplayDidRefresh() final;
+    void dispatchDisplayDidRefresh(const DisplayUpdate&) final;
 
     void stop() final;
 
@@ -53,7 +55,11 @@
     bool startNotificationMechanism() final;
     void stopNotificationMechanism() final;
 
+    static FramesPerSecond nominalFramesPerSecondFromDisplayLink(CVDisplayLinkRef);
+
     CVDisplayLinkRef m_displayLink { nullptr };
+    
+    DisplayUpdate m_currentUpdate;
     bool m_displayLinkIsActive { false };
 };
 

Modified: trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.cpp (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -28,6 +28,8 @@
 
 namespace WebCore {
 
+constexpr FramesPerSecond DefaultFramesPerSecond = 60;
+
 RefPtr<DisplayRefreshMonitorWin> DisplayRefreshMonitorWin::create(PlatformDisplayID displayID)
 {
     return adoptRef(*new DisplayRefreshMonitorWin(displayID));
@@ -35,10 +37,17 @@
 
 DisplayRefreshMonitorWin::DisplayRefreshMonitorWin(PlatformDisplayID displayID)
     : DisplayRefreshMonitor(displayID)
-    , m_timer(RunLoop::main(), this, &DisplayRefreshMonitor::displayLinkFired)
+    , m_timer(RunLoop::main(), this, &DisplayRefreshMonitorWin::displayLinkCallbackFired)
+    , m_currentUpdate({ 0, DefaultFramesPerSecond })
 {
 }
 
+void DisplayRefreshMonitorWin::displayLinkCallbackFired()
+{
+    displayLinkFired(m_currentUpdate);
+    m_currentUpdate = m_currentUpdate.nextUpdate();
+}
+
 bool DisplayRefreshMonitorWin::startNotificationMechanism()
 {
     if (!m_timer.isActive())

Modified: trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.h (275162 => 275163)


--- trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebCore/platform/graphics/win/DisplayRefreshMonitorWin.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -39,8 +39,11 @@
 
     bool startNotificationMechanism() final;
     void stopNotificationMechanism() final;
+    
+    void displayLinkCallbackFired();
 
     RunLoop::Timer<DisplayRefreshMonitorWin> m_timer;
+    DisplayUpdate m_currentUpdate;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (275162 => 275163)


--- trunk/Source/WebKit/ChangeLog	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/ChangeLog	2021-03-29 17:21:03 UTC (rev 275163)
@@ -1,3 +1,62 @@
+2021-03-28  Simon Fraser  <[email protected]>
+
+        Plumb DisplayUpdate through the display refresh monitors
+        https://bugs.webkit.org/show_bug.cgi?id=223847
+
+        Reviewed by Sam Weinig.
+
+        Future work will allow DisplayRefreshMonitorClients to request different frame rates, which
+        are whole fractions of the display's nominal refresh rate. These various frame rate requests
+        flow up through the DisplayRefreshMonitors, and in WebKit2, up through IPC to the
+        per-display DisplayLink which may even service multiple processes.
+
+        For power reasons, we don't want to trigger display refresh notifications down the chain at
+        the highest possible frequency; at various stages of propagation the rate might be halved if
+        that's necessary for downstream clients.
+        
+        To make this frequency splitting logic simple, this patch introduces DisplayUpdate, which
+        represents an update of the display, and contains data about it in the form of a numerator
+        is the frame index, and the denominator is the nominal frame rate. Frame index wraps to zero
+        every second.
+        
+        For example, a 60Hz display will generate display refreshes with DisplayUpdates which
+        sequentially will be { 0, 60 }, { 1, 60 }, { 2, 60 } ... { 59, 60 }, { 0, 60 }. The
+        zeroth frame is at some arbitrary time and not aligned with wallclock time.
+        
+        Thus a client with a 30Hz update requirement can simply ignore every odd-numbered frame, and
+        a client downstream from it with a 15Hz requirement, which only receives those even-numbered
+        frames, still has enough information to compute which frames to ignore.
+        
+        Classes which are sources of callbacks for DisplayRefreshMonitor need to generate these
+        DisplayUpdates; that includes the various platform DisplayRefreshMonitor subclasses in
+        WebCore, and those in WebKit that live in the UI process and trigger updates over IPC.
+
+        * Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp:
+        (WebKit::ThreadedDisplayRefreshMonitor::invalidate):
+        (WebKit::ThreadedDisplayRefreshMonitor::displayRefreshCallback):
+        (WebKit::ThreadedDisplayRefreshMonitor::ThreadedDisplayRefreshMonitor): Deleted.
+        * Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.h:
+        * UIProcess/mac/DisplayLink.cpp:
+        (WebKit::DisplayLink::addObserver):
+        (WebKit::DisplayLink::notifyObserversDisplayWasRefreshed):
+        * UIProcess/mac/DisplayLink.h:
+        * WebProcess/WebPage/EventDispatcher.cpp:
+        (WebKit::EventDispatcher::displayWasRefreshed):
+        * WebProcess/WebPage/EventDispatcher.h:
+        * WebProcess/WebPage/EventDispatcher.messages.in:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm:
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::RemoteLayerTreeDisplayRefreshMonitor):
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond):
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::didUpdateLayers):
+        * WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp:
+        (WebKit::DisplayRefreshMonitorMac::dispatchDisplayDidRefresh):
+        * WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h:
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::displayWasRefreshed):
+        * WebProcess/WebProcess.h:
+        * WebProcess/WebProcess.messages.in:
+
 2021-03-29  Youenn Fablet  <[email protected]>
 
         Promote WKWebView getUserMedia SPI to API

Modified: trunk/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp (275162 => 275163)


--- trunk/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -37,10 +37,14 @@
 
 namespace WebKit {
 
+// FIXME: Use the correct frame rate.
+constexpr WebCore::FramesPerSecond DefaultFramesPerSecond = 60;
+
 ThreadedDisplayRefreshMonitor::ThreadedDisplayRefreshMonitor(WebCore::PlatformDisplayID displayID, Client& client)
     : WebCore::DisplayRefreshMonitor(displayID)
     , m_displayRefreshTimer(RunLoop::main(), this, &ThreadedDisplayRefreshMonitor::displayRefreshCallback)
     , m_client(&client)
+    , m_currentUpdate({ 0, DefaultFramesPerSecond })
 {
 #if USE(GLIB_EVENT_LOOP)
     m_displayRefreshTimer.setPriority(RunLoopSourcePriority::DisplayRefreshMonitorTimer);
@@ -90,8 +94,10 @@
         auto locker = holdLock(lock());
         wasScheduled = isScheduled();
     }
-    if (wasScheduled)
-        displayDidRefresh();
+    if (wasScheduled) {
+        displayDidRefresh(m_currentUpdate);
+        m_currentUpdate = m_currentUpdate.nextUpdate();
+    }
     m_client = nullptr;
 }
 
@@ -106,8 +112,10 @@
             setIsPreviousFrameDone(false);
     }
 
-    if (shouldHandleDisplayRefreshNotification)
-        displayDidRefresh();
+    if (shouldHandleDisplayRefreshNotification) {
+        displayDidRefresh(m_currentUpdate);
+        m_currentUpdate = m_currentUpdate.nextUpdate();
+    }
 
     // Retrieve the scheduled status for this DisplayRefreshMonitor.
     bool hasBeenRescheduled { false };

Modified: trunk/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.h (275162 => 275163)


--- trunk/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedDisplayRefreshMonitor.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -63,6 +63,7 @@
     void displayRefreshCallback();
     RunLoop::Timer<ThreadedDisplayRefreshMonitor> m_displayRefreshTimer;
     Client* m_client;
+    WebCore::DisplayUpdate m_currentUpdate;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp (275162 => 275163)


--- trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/UIProcess/mac/DisplayLink.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -97,6 +97,8 @@
         CVReturn error = CVDisplayLinkStart(m_displayLink);
         if (error)
             WTFLogAlways("Could not start the display link: %d", error);
+
+        m_currentUpdate = { 0, m_displayNominalFramesPerSecond };
     }
 }
 
@@ -152,12 +154,15 @@
     m_fireCountWithoutObservers = 0;
 
     for (auto& connection : m_observers.keys()) {
-        LOG_WITH_STREAM(DisplayLink, stream << "[UI ] DisplayLink for display " << m_displayID << " sending for connection " << connection->uniqueID() << " on background queue " << shouldSendIPCOnBackgroundQueue);
+        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);
+
         if (shouldSendIPCOnBackgroundQueue)
-            connection->send(Messages::EventDispatcher::DisplayWasRefreshed(m_displayID), 0);
+            connection->send(Messages::EventDispatcher::DisplayWasRefreshed(m_displayID, m_currentUpdate), 0);
         else
-            connection->send(Messages::WebProcess::DisplayWasRefreshed(m_displayID), 0);
+            connection->send(Messages::WebProcess::DisplayWasRefreshed(m_displayID, m_currentUpdate), 0);
     }
+
+    m_currentUpdate = m_currentUpdate.nextUpdate();
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/mac/DisplayLink.h (275162 => 275163)


--- trunk/Source/WebKit/UIProcess/mac/DisplayLink.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/UIProcess/mac/DisplayLink.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -30,6 +30,7 @@
 #include "DisplayLinkObserverID.h"
 #include <CoreVideo/CVDisplayLink.h>
 #include <WebCore/AnimationFrameRate.h>
+#include <WebCore/DisplayUpdate.h>
 #include <WebCore/PlatformScreen.h>
 #include <wtf/HashMap.h>
 #include <wtf/Lock.h>
@@ -69,6 +70,7 @@
     HashMap<RefPtr<IPC::Connection>, Vector<DisplayLinkObserverID>> m_observers;
     WebCore::PlatformDisplayID m_displayID;
     WebCore::FramesPerSecond m_displayNominalFramesPerSecond { 0 };
+    WebCore::DisplayUpdate m_currentUpdate;
     unsigned m_fireCountWithoutObservers { 0 };
     static bool shouldSendIPCOnBackgroundQueue;
 };

Modified: trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp (275162 => 275163)


--- trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -33,6 +33,7 @@
 #include "WebProcess.h"
 #include "WebTouchEvent.h"
 #include "WebWheelEvent.h"
+#include <WebCore/DisplayUpdate.h>
 #include <WebCore/Page.h>
 #include <WebCore/WheelEventTestMonitor.h>
 #include <wtf/MainThread.h>
@@ -288,13 +289,13 @@
 }
 
 #if HAVE(CVDISPLAYLINK)
-void EventDispatcher::displayWasRefreshed(PlatformDisplayID displayID)
+void EventDispatcher::displayWasRefreshed(PlatformDisplayID displayID, const DisplayUpdate& displayUpdate)
 {
     ASSERT(!RunLoop::isMain());
     notifyScrollingTreesDisplayWasRefreshed(displayID);
 
-    RunLoop::main().dispatch([displayID]() {
-        DisplayRefreshMonitorManager::sharedManager().displayWasUpdated(displayID);
+    RunLoop::main().dispatch([displayID, displayUpdate]() {
+        DisplayRefreshMonitorManager::sharedManager().displayWasUpdated(displayID, displayUpdate);
     });
 }
 #endif

Modified: trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.h (275162 => 275163)


--- trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -43,6 +43,7 @@
 #endif
 
 namespace WebCore {
+struct DisplayUpdate;
 class ThreadedScrollingTree;
 using PlatformDisplayID = uint32_t;
 }
@@ -107,7 +108,7 @@
 #endif
 
 #if PLATFORM(MAC)
-    void displayWasRefreshed(WebCore::PlatformDisplayID);
+    void displayWasRefreshed(WebCore::PlatformDisplayID, const WebCore::DisplayUpdate&);
 #endif
 
 #if ENABLE(SCROLLING_THREAD)

Modified: trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.messages.in (275162 => 275163)


--- trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.messages.in	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.messages.in	2021-03-29 17:21:03 UTC (rev 275163)
@@ -30,6 +30,6 @@
     GestureEvent(WebCore::PageIdentifier pageID, WebKit::WebGestureEvent event)
 #endif
 #if HAVE(CVDISPLAYLINK)
-    DisplayWasRefreshed(uint32_t displayID)
+    DisplayWasRefreshed(uint32_t displayID, struct WebCore::DisplayUpdate update)
 #endif
 }

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


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -53,6 +53,9 @@
     void stopNotificationMechanism() final { }
 
     WeakPtr<RemoteLayerTreeDrawingArea> m_drawingArea;
+
+    WebCore::FramesPerSecond m_preferredFramesPerSecond;
+    WebCore::DisplayUpdate m_currentUpdate;
 };
 
-}
+} // namespace WebKit

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


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2021-03-29 17:21:03 UTC (rev 275163)
@@ -32,9 +32,13 @@
 namespace WebKit {
 using namespace WebCore;
 
+constexpr FramesPerSecond DefaultPreferredFramesPerSecond = 60;
+
 RemoteLayerTreeDisplayRefreshMonitor::RemoteLayerTreeDisplayRefreshMonitor(PlatformDisplayID displayID, RemoteLayerTreeDrawingArea& drawingArea)
     : DisplayRefreshMonitor(displayID)
     , m_drawingArea(makeWeakPtr(drawingArea))
+    , m_preferredFramesPerSecond(DefaultPreferredFramesPerSecond)
+    , m_currentUpdate({ 0, m_preferredFramesPerSecond })
 {
 }
 
@@ -46,6 +50,12 @@
 
 void RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
 {
+    if (preferredFramesPerSecond == m_preferredFramesPerSecond)
+        return;
+
+    m_preferredFramesPerSecond = preferredFramesPerSecond;
+    m_currentUpdate = { 0, m_preferredFramesPerSecond };
+
     if (m_drawingArea)
         m_drawingArea->setPreferredFramesPerSecond(preferredFramesPerSecond);
 }
@@ -72,7 +82,8 @@
         return;
 
     setIsPreviousFrameDone(false);
-    displayDidRefresh();
+    displayDidRefresh(m_currentUpdate);
+    m_currentUpdate = m_currentUpdate.nextUpdate();
 }
 
 void RemoteLayerTreeDisplayRefreshMonitor::updateDrawingArea(RemoteLayerTreeDrawingArea& drawingArea)
@@ -80,4 +91,4 @@
     m_drawingArea = makeWeakPtr(drawingArea);
 }
 
-}
+} // namespace WebKit

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


--- trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -56,12 +56,13 @@
     ASSERT(!m_displayLinkIsActive);
 }
 
-void DisplayRefreshMonitorMac::dispatchDisplayDidRefresh()
+void DisplayRefreshMonitorMac::dispatchDisplayDidRefresh(const DisplayUpdate& displayUpdate)
 {
+    // FIXME: This will perturb displayUpdate.
     if (!m_firstCallbackInCurrentRunloop)
         return;
 
-    DisplayRefreshMonitor::dispatchDisplayDidRefresh();
+    DisplayRefreshMonitor::dispatchDisplayDidRefresh(displayUpdate);
 }
 
 bool DisplayRefreshMonitorMac::startNotificationMechanism()

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


--- trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/DisplayRefreshMonitorMac.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -45,7 +45,7 @@
 private:
     explicit DisplayRefreshMonitorMac(WebCore::PlatformDisplayID);
 
-    void dispatchDisplayDidRefresh() final;
+    void dispatchDisplayDidRefresh(const WebCore::DisplayUpdate&) final;
 
     bool startNotificationMechanism() final;
     void stopNotificationMechanism() final;

Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (275162 => 275163)


--- trunk/Source/WebKit/WebProcess/WebProcess.cpp	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp	2021-03-29 17:21:03 UTC (rev 275163)
@@ -1893,11 +1893,11 @@
 }
 
 #if HAVE(CVDISPLAYLINK)
-void WebProcess::displayWasRefreshed(uint32_t displayID)
+void WebProcess::displayWasRefreshed(uint32_t displayID, const DisplayUpdate& displayUpdate)
 {
     ASSERT(RunLoop::isMain());
     m_eventDispatcher->notifyScrollingTreesDisplayWasRefreshed(displayID);
-    DisplayRefreshMonitorManager::sharedManager().displayWasUpdated(displayID);
+    DisplayRefreshMonitorManager::sharedManager().displayWasUpdated(displayID, displayUpdate);
 }
 #endif
 

Modified: trunk/Source/WebKit/WebProcess/WebProcess.h (275162 => 275163)


--- trunk/Source/WebKit/WebProcess/WebProcess.h	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebProcess.h	2021-03-29 17:21:03 UTC (rev 275163)
@@ -94,6 +94,7 @@
 enum class EventMakesGamepadsVisible : bool;
 
 struct BackForwardItemIdentifier;
+struct DisplayUpdate;
 struct MessagePortIdentifier;
 struct MessageWithMessagePorts;
 struct MockMediaDevice;
@@ -507,7 +508,7 @@
 #endif
 
 #if HAVE(CVDISPLAYLINK)
-    void displayWasRefreshed(uint32_t displayID);
+    void displayWasRefreshed(uint32_t displayID, const WebCore::DisplayUpdate&);
 #endif
 
 #if PLATFORM(MAC)

Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (275162 => 275163)


--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2021-03-29 16:32:58 UTC (rev 275162)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in	2021-03-29 17:21:03 UTC (rev 275163)
@@ -188,7 +188,7 @@
 #endif
 
 #if HAVE(CVDISPLAYLINK)
-    DisplayWasRefreshed(uint32_t displayID)
+    DisplayWasRefreshed(uint32_t displayID, struct WebCore::DisplayUpdate update)
 #endif
 
 #if PLATFORM(MAC)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to