Title: [255158] trunk
Revision
255158
Author
[email protected]
Date
2020-01-27 11:54:41 -0800 (Mon, 27 Jan 2020)

Log Message

Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
https://bugs.webkit.org/show_bug.cgi?id=204713

Patch by Said Abou-Hallawa <[email protected]> on 2020-01-27
Reviewed by Simon Fraser.

Source/WebCore:

Test: fast/animation/request-animation-frame-throttling-outside-viewport.html

requestAnimationFrame is throttled by a timer although its callback are
serviced by the page RenderingUpdate. This led to excessive rAF firing
which makes it more than the preferred frame per seconds.

The solution is to have two throttling types:

1) Page throttling (or full throttling) which slows down all the steps of
   RenderingUpdate for the main document and all the sub-documents.
2) Document throttling (or partial throttling) which only slows down the
   rAF of a certain document.

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:

* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::animationInterval const):
(WebCore::DocumentTimeline::updateThrottlingState): Deleted.
* animation/DocumentTimeline.h:
There is no need to have DocumentTimeline throttling. It is already
throttled when the page RenderingUpdate is throttled.

* dom/Document.cpp:
(WebCore::Document::requestAnimationFrame):
(WebCore::Document::updateLastHandledUserGestureTimestamp):
LowPowerMode throttling is now handled by the page. So remove its handling
in the Document side.

* dom/ScriptedAnimationController.cpp:
(WebCore::ScriptedAnimationController::ScriptedAnimationController):
(WebCore::ScriptedAnimationController::page const):
(WebCore::ScriptedAnimationController::preferredScriptedAnimationInterval const):
(WebCore::ScriptedAnimationController::interval const):
(WebCore::ScriptedAnimationController::isThrottled const):
(WebCore::ScriptedAnimationController::isThrottledRelativeToPage const):
(WebCore::ScriptedAnimationController::shouldRescheduleRequestAnimationFrame const):
(WebCore::ScriptedAnimationController::registerCallback):
(WebCore::ScriptedAnimationController::cancelCallback):
(WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
(WebCore::ScriptedAnimationController::scheduleAnimation):
(WebCore::throttlingReasonToString): Deleted.
(WebCore::throttlingReasonsToString): Deleted.
(WebCore::ScriptedAnimationController::addThrottlingReason): Deleted.
(WebCore::ScriptedAnimationController::removeThrottlingReason): Deleted.
(WebCore::ScriptedAnimationController::animationTimerFired): Deleted.
* dom/ScriptedAnimationController.h:
(WebCore::ScriptedAnimationController::addThrottlingReason):
(WebCore::ScriptedAnimationController::removeThrottlingReason):
Get rid of the rAF throttling timer. Service the rAF callback only when
the period from the current time stamp till the last service time stamp
is greater than the preferred rAF interval .

* page/FrameView.cpp:
(WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState):
ThrottlingReason is now defined outside ScriptedAnimationController.

* page/Page.cpp:
(WebCore::Page::renderingUpdateThrottlingEnabled const):
(WebCore::Page::renderingUpdateThrottlingEnabledChanged):
(WebCore::Page::isRenderingUpdateThrottled const):

(WebCore::Page::preferredRenderingUpdateInterval const):
Calculate the preferred RenderingUpdate interval from the throttling
reasons.

(WebCore::Page::setIsVisuallyIdleInternal):
(WebCore::Page::handleLowModePowerChange):
Call adjustRenderingUpdateFrequency() when isLowPowerModeEnabled or
IsVisuallyIdle is toggled.

(WebCore::updateScriptedAnimationsThrottlingReason): Deleted.
* page/Page.h:

* page/RenderingUpdateScheduler.cpp:
(WebCore::RenderingUpdateScheduler::adjustFramesPerSecond):
(WebCore::RenderingUpdateScheduler::adjustRenderingUpdateFrequency):
Change the preferredFramesPerSecond of the DisplayRefreshMonitor if the
throttling is not aggressive e.g. 10_s. Otherwise use the timer.

(WebCore::RenderingUpdateScheduler::scheduleTimedRenderingUpdate):
Call adjustFramesPerSecond() when DisplayRefreshMonitor is created.

(WebCore::RenderingUpdateScheduler::startTimer):
* page/RenderingUpdateScheduler.h:

* page/Settings.yaml:
* page/SettingsBase.cpp:
(WebCore::SettingsBase::renderingUpdateThrottlingEnabledChanged):
* page/SettingsBase.h:
Add a setting to enable/disable RenderingUpdateThrottling.

* platform/graphics/AnimationFrameRate.h: Added.
(WebCore::preferredFrameInterval):
(WebCore::preferredFramesPerSecond):

* platform/graphics/DisplayRefreshMonitor.h:
(WebCore::DisplayRefreshMonitor::setPreferredFramesPerSecond):
* platform/graphics/DisplayRefreshMonitorManager.cpp:
(WebCore::DisplayRefreshMonitorManager::monitorForClient):
Rename createMonitorForClient() to monitorForClient() since it may return
a cached DisplayRefreshMonitor.

(WebCore::DisplayRefreshMonitorManager::setPreferredFramesPerSecond):
(WebCore::DisplayRefreshMonitorManager::scheduleAnimation):
(WebCore::DisplayRefreshMonitorManager::windowScreenDidChange):
No need to call registerClient(). This function was just ensuring the
DisplayRefreshMonitor is created. scheduleAnimation() does the same thing.

(WebCore::DisplayRefreshMonitorManager::createMonitorForClient): Deleted.
(WebCore::DisplayRefreshMonitorManager::registerClient): Deleted.
* platform/graphics/DisplayRefreshMonitorManager.h:
(WebCore::DisplayRefreshMonitorManager::DisplayRefreshMonitorManager): Deleted.

* platform/graphics/GraphicsLayerUpdater.cpp:
(WebCore::GraphicsLayerUpdater::GraphicsLayerUpdater):
* platform/graphics/ios/DisplayRefreshMonitorIOS.mm:
(-[WebDisplayLinkHandler setPreferredFramesPerSecond:]):
Set the preferredFramesPerSecond of the CADisplayLink.

Source/WebKit:

Create an IPC message on the DrawingArea to send a message from the
WebProcess to the UIProcess to setPreferredFramesPerSecond of the
DisplayRefreshMonitor.

* Shared/WebPreferences.yaml:
* UIProcess/API/C/WKPreferences.cpp:
(WKPreferencesSetRenderingUpdateThrottlingEnabled):
(WKPreferencesGetRenderingUpdateThrottlingEnabled):
* UIProcess/API/C/WKPreferencesRefPrivate.h:
Add a WKPreference key for RenderingUpdateThrottlingEnabled.

* UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in:

* UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler setPreferredFramesPerSecond:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::setPreferredFramesPerSecond):
Set the preferredFramesPerSecond of the CADisplayLink.

* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm:
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond):
Delegate the call to RemoteLayerTreeDrawingArea.

* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::setPreferredFramesPerSecond):
Send the IPC message from the WebProcess to the UIProcess.

Source/WebKitLegacy/mac:

Add a WKPreference key for RenderingUpdateThrottling.

* WebView/WebPreferenceKeysPrivate.h:
* WebView/WebPreferences.mm:
(+[WebPreferences initialize]):
(-[WebPreferences renderingUpdateThrottlingEnabled]):
(-[WebPreferences setRenderingUpdateThrottlingEnabled:]):
* WebView/WebPreferencesPrivate.h:
* WebView/WebView.mm:
(-[WebView _preferencesChanged:]):

Source/WebKitLegacy/win:

Add a WKPreference key for RenderingUpdateThrottling.

* Interfaces/IWebPreferencesPrivate.idl:
* WebPreferenceKeysPrivate.h:
* WebPreferences.cpp:
(WebPreferences::initializeDefaultSettings):
(WebPreferences::renderingUpdateThrottlingEnabled):
(WebPreferences::setRenderingUpdateThrottlingEnabled):
* WebPreferences.h:
* WebView.cpp:
(WebView::notifyPreferencesChanged):

Tools:

RenderingUpdateThrottling is enabled by default. Turn it off for DRT and
WTR. In some cases, the page may not get visually active while it's
waiting for rAF. Throttling tests will have to explicitly turn it on.

* DumpRenderTree/mac/DumpRenderTree.mm:
(resetWebPreferencesToConsistentValues):
* DumpRenderTree/win/DumpRenderTree.cpp:
(resetWebPreferencesToConsistentValues):
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::resetPreferencesToConsistentValues):

LayoutTests:

* fast/animation/css-animation-throttling-lowPowerMode.html:
* fast/animation/request-animation-frame-throttle-subframe.html:
* fast/animation/request-animation-frame-throttling-detached-iframe.html:
Enable RenderingUpdateThrottling for these tests.

* fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt:
* fast/animation/request-animation-frame-throttling-lowPowerMode.html:
Ensure the actual rAF interval is > 30ms for lowPowerMode.

* fast/animation/request-animation-frame-throttling-outside-viewport-expected.txt: Added.
* fast/animation/request-animation-frame-throttling-outside-viewport.html: Added.
* fast/animation/resources/frame-with-animation-2.html: Added.
Test the OutsideViewport throttling case.

* http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html:
Enable RenderingUpdateThrottling for this test.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (255157 => 255158)


--- trunk/LayoutTests/ChangeLog	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/ChangeLog	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,3 +1,27 @@
+2020-01-27  Said Abou-Hallawa  <[email protected]>
+
+        Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
+        https://bugs.webkit.org/show_bug.cgi?id=204713
+
+        Reviewed by Simon Fraser.
+
+        * fast/animation/css-animation-throttling-lowPowerMode.html:
+        * fast/animation/request-animation-frame-throttle-subframe.html:
+        * fast/animation/request-animation-frame-throttling-detached-iframe.html:
+        Enable RenderingUpdateThrottling for these tests.
+
+        * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt:
+        * fast/animation/request-animation-frame-throttling-lowPowerMode.html:
+        Ensure the actual rAF interval is > 30ms for lowPowerMode.
+
+        * fast/animation/request-animation-frame-throttling-outside-viewport-expected.txt: Added.
+        * fast/animation/request-animation-frame-throttling-outside-viewport.html: Added.
+        * fast/animation/resources/frame-with-animation-2.html: Added.
+        Test the OutsideViewport throttling case.
+
+        * http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html:
+        Enable RenderingUpdateThrottling for this test.
+
 2020-01-27  Devin Rousso  <[email protected]>
 
         REGRESSION: [ Mac Debug WK1 ] inspector/page/overrideSetting-ICECandidateFilteringEnabled.html is a flaky failure

Modified: trunk/LayoutTests/fast/animation/css-animation-throttling-lowPowerMode.html (255157 => 255158)


--- trunk/LayoutTests/fast/animation/css-animation-throttling-lowPowerMode.html	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/fast/animation/css-animation-throttling-lowPowerMode.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -25,6 +25,9 @@
 description("Tests that CSS animations are throttled in low power mode.");
 jsTestIsAsync = true;
 
+if (window.internals)
+  internals.settings.setRenderingUpdateThrottlingEnabled(true);
+
 const element = document.getElementById("testElement");
 element._onanimationstart_ = function() {
     element._onanimationstart_ = null;

Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html (255157 => 255158)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -6,6 +6,9 @@
 description("Tests that requestAnimationFrame is throttled in subframes that are outside the viewport");
 window.jsTestIsAsync = true;
 
+if (window.internals)
+    internals.settings.setRenderingUpdateThrottlingEnabled(true);
+
 function checkSubframesThrottled()
 {
     shouldBeTrue("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");

Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html (255157 => 255158)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -6,6 +6,9 @@
 description("Test that requestAnimationFrame gets the right throttling in an iframe when inserted into a document.");
 jsTestIsAsync = true;
 
+if (window.internals)
+    internals.settings.setRenderingUpdateThrottlingEnabled(true);
+
 let i = 0;
 function doWork()
 {

Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt (255157 => 255158)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt	2020-01-27 19:54:41 UTC (rev 255158)
@@ -3,23 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS internals.isRequestAnimationFrameThrottled() is false
-PASS internals.requestAnimationFrameInterval is Infinity
-rAFHandle = requestAnimationFrame(doWork);
-PASS internals.isRequestAnimationFrameThrottled() is false
-PASS internals.requestAnimationFrameInterval is 0.015
-internals.setLowPowerModeEnabled(true);
-PASS internals.isRequestAnimationFrameThrottled() is true
-PASS internals.requestAnimationFrameInterval is 0.030
-cancelAnimationFrame(rAFHandle);
-PASS internals.isRequestAnimationFrameThrottled() is true
-PASS internals.requestAnimationFrameInterval is 0.030
-rAFHandle = requestAnimationFrame(doWork);
-PASS internals.isRequestAnimationFrameThrottled() is true
-PASS internals.requestAnimationFrameInterval is 0.030
-internals.setLowPowerModeEnabled(false);
-PASS internals.isRequestAnimationFrameThrottled() is false
-PASS internals.requestAnimationFrameInterval is 0.015
+PASS farmesPerSecond < 35 is true
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html (255157 => 255158)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,36 +1,33 @@
 <!DOCTYPE html>
 <html>
 <body>
-<script src=""
-<script>
-description("Test that requestAnimationFrame gets throttled in low power mode.");
+    <script src=""
+    <script>
+        description("Test that requestAnimationFrame gets throttled in low power mode.");
+        window.jsTestIsAsync = true;
 
-let rAFHandle;
-let i = 0;
-function doWork()
-{
-    i++;
-    rAFHandle = requestAnimationFrame(doWork);
-}
+        if (window.internals) {
+            internals.settings.setRenderingUpdateThrottlingEnabled(true);
+            internals.setLowPowerModeEnabled(true);
+        }
 
-shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
-shouldBe("internals.requestAnimationFrameInterval", "Infinity");
-evalAndLog("rAFHandle = requestAnimationFrame(doWork);");
-shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
-shouldBe("internals.requestAnimationFrameInterval", "0.015");
-evalAndLog("internals.setLowPowerModeEnabled(true);");
-shouldBeTrue("internals.isRequestAnimationFrameThrottled()");
-shouldBe("internals.requestAnimationFrameInterval", "0.030");
-evalAndLog("cancelAnimationFrame(rAFHandle);");
-shouldBeTrue("internals.isRequestAnimationFrameThrottled()");
-shouldBe("internals.requestAnimationFrameInterval", "0.030");
-evalAndLog("rAFHandle = requestAnimationFrame(doWork);");
-shouldBeTrue("internals.isRequestAnimationFrameThrottled()");
-shouldBe("internals.requestAnimationFrameInterval", "0.030");
-evalAndLog("internals.setLowPowerModeEnabled(false);");
-shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
-shouldBe("internals.requestAnimationFrameInterval", "0.015");
-</script>
-<script src=""
+        var start = null;
+        var farmesPerSecond = 0;
+        function doWork(timestamp) {
+            if (!start)
+                start = timestamp;
+            if (timestamp - start < 1000) {
+                ++farmesPerSecond;
+                window.requestAnimationFrame(doWork);
+            }
+            else {
+                // The LowPowerMode throttling interval = 30_ms. The frame rate ~= 33.3 fps.
+                shouldBeTrue("farmesPerSecond < 35");
+                finishJSTest();
+            }
+        }
+        window.requestAnimationFrame(doWork);
+    </script>
+    <script src=""
 </body>
 </html>

Added: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-outside-viewport-expected.txt (0 => 255158)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-outside-viewport-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-outside-viewport-expected.txt	2020-01-27 19:54:41 UTC (rev 255158)
@@ -0,0 +1,11 @@
+Test that requestAnimationFrame gets the right throttling in an iframe when when it's outside the viewport.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS framesPerSecond > 0 is true
+PASS iframeFramesPerSecond == 0 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-outside-viewport.html (0 => 255158)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-outside-viewport.html	                        (rev 0)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-outside-viewport.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <div style="height: 1000px;"></div>
+    <script src=""
+    <script>
+        description("Test that requestAnimationFrame gets the right throttling in an iframe when when it's outside the viewport.");
+        jsTestIsAsync = true;
+
+        if (window.internals)
+            internals.settings.setRenderingUpdateThrottlingEnabled(true);
+
+        var framesPerSecond = 0;
+        var iframeFramesPerSecond = 0;
+
+        window._onmessage_ = function(e){
+            if (e.data == 'subFrameRAFMessage') {
+                ++iframeFramesPerSecond;
+            }
+        };
+
+        const frame = document.createElement("iframe");
+        frame.src = ""
+        frame._onload_ = function() {
+            var start = null;
+            function doWork(timestamp) {
+                if (!start)
+                    start = timestamp;
+                if (timestamp - start < 1000) {
+                    ++framesPerSecond;
+                    window.requestAnimationFrame(doWork);
+                }
+                else {
+                    shouldBeTrue("framesPerSecond > 0");
+
+                    // The OutsideViewport throttling = 10_s. subFrameRAFMessage
+                    // should not ever be received during the first second.
+                    shouldBeTrue("iframeFramesPerSecond == 0");
+                    finishJSTest();
+                }
+            }
+            window.requestAnimationFrame(doWork);
+        }
+        document.body.appendChild(frame);
+    </script>
+    <script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/animation/resources/frame-with-animation-2.html (0 => 255158)


--- trunk/LayoutTests/fast/animation/resources/frame-with-animation-2.html	                        (rev 0)
+++ trunk/LayoutTests/fast/animation/resources/frame-with-animation-2.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -0,0 +1,7 @@
+<script>
+	function doWork(timestamp) {
+		window.top.postMessage('subFrameRAFMessage', '*');
+		window.requestAnimationFrame(doWork);
+	}
+	window.requestAnimationFrame(doWork);
+</script>

Modified: trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html (255157 => 255158)


--- trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html	2020-01-27 19:54:41 UTC (rev 255158)
@@ -13,7 +13,10 @@
     <script>
     description("Tests that requestAnimationFrame is throttled in subframes that are cross-origin, and not in same-origin frames");
     window.jsTestIsAsync = true;
-    
+
+    if (window.internals)
+        internals.settings.setRenderingUpdateThrottlingEnabled(true);
+
     var crossOriginFrame;
     var sameOriginFrame
 

Modified: trunk/Source/WebCore/ChangeLog (255157 => 255158)


--- trunk/Source/WebCore/ChangeLog	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/ChangeLog	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,3 +1,130 @@
+2020-01-27  Said Abou-Hallawa  <[email protected]>
+
+        Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
+        https://bugs.webkit.org/show_bug.cgi?id=204713
+
+        Reviewed by Simon Fraser.
+
+        Test: fast/animation/request-animation-frame-throttling-outside-viewport.html
+
+        requestAnimationFrame is throttled by a timer although its callback are
+        serviced by the page RenderingUpdate. This led to excessive rAF firing
+        which makes it more than the preferred frame per seconds.
+
+        The solution is to have two throttling types:
+
+        1) Page throttling (or full throttling) which slows down all the steps of
+           RenderingUpdate for the main document and all the sub-documents.
+        2) Document throttling (or partial throttling) which only slows down the
+           rAF of a certain document.
+
+        * Headers.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::animationInterval const):
+        (WebCore::DocumentTimeline::updateThrottlingState): Deleted.
+        * animation/DocumentTimeline.h:
+        There is no need to have DocumentTimeline throttling. It is already 
+        throttled when the page RenderingUpdate is throttled.
+
+        * dom/Document.cpp:
+        (WebCore::Document::requestAnimationFrame):
+        (WebCore::Document::updateLastHandledUserGestureTimestamp):
+        LowPowerMode throttling is now handled by the page. So remove its handling
+        in the Document side.
+
+        * dom/ScriptedAnimationController.cpp:
+        (WebCore::ScriptedAnimationController::ScriptedAnimationController):
+        (WebCore::ScriptedAnimationController::page const):
+        (WebCore::ScriptedAnimationController::preferredScriptedAnimationInterval const):
+        (WebCore::ScriptedAnimationController::interval const):
+        (WebCore::ScriptedAnimationController::isThrottled const):
+        (WebCore::ScriptedAnimationController::isThrottledRelativeToPage const):
+        (WebCore::ScriptedAnimationController::shouldRescheduleRequestAnimationFrame const):
+        (WebCore::ScriptedAnimationController::registerCallback):
+        (WebCore::ScriptedAnimationController::cancelCallback):
+        (WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
+        (WebCore::ScriptedAnimationController::scheduleAnimation):
+        (WebCore::throttlingReasonToString): Deleted.
+        (WebCore::throttlingReasonsToString): Deleted.
+        (WebCore::ScriptedAnimationController::addThrottlingReason): Deleted.
+        (WebCore::ScriptedAnimationController::removeThrottlingReason): Deleted.
+        (WebCore::ScriptedAnimationController::animationTimerFired): Deleted.
+        * dom/ScriptedAnimationController.h:
+        (WebCore::ScriptedAnimationController::addThrottlingReason):
+        (WebCore::ScriptedAnimationController::removeThrottlingReason):
+        Get rid of the rAF throttling timer. Service the rAF callback only when
+        the period from the current time stamp till the last service time stamp
+        is greater than the preferred rAF interval .
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState):
+        ThrottlingReason is now defined outside ScriptedAnimationController.
+
+        * page/Page.cpp:
+        (WebCore::Page::renderingUpdateThrottlingEnabled const):
+        (WebCore::Page::renderingUpdateThrottlingEnabledChanged):
+        (WebCore::Page::isRenderingUpdateThrottled const):
+
+        (WebCore::Page::preferredRenderingUpdateInterval const):
+        Calculate the preferred RenderingUpdate interval from the throttling
+        reasons.
+
+        (WebCore::Page::setIsVisuallyIdleInternal):
+        (WebCore::Page::handleLowModePowerChange):
+        Call adjustRenderingUpdateFrequency() when isLowPowerModeEnabled or 
+        IsVisuallyIdle is toggled.
+
+        (WebCore::updateScriptedAnimationsThrottlingReason): Deleted.
+        * page/Page.h:
+
+        * page/RenderingUpdateScheduler.cpp:
+        (WebCore::RenderingUpdateScheduler::adjustFramesPerSecond):
+        (WebCore::RenderingUpdateScheduler::adjustRenderingUpdateFrequency):
+        Change the preferredFramesPerSecond of the DisplayRefreshMonitor if the
+        throttling is not aggressive e.g. 10_s. Otherwise use the timer.
+
+        (WebCore::RenderingUpdateScheduler::scheduleTimedRenderingUpdate):
+        Call adjustFramesPerSecond() when DisplayRefreshMonitor is created.
+
+        (WebCore::RenderingUpdateScheduler::startTimer):
+        * page/RenderingUpdateScheduler.h:
+
+        * page/Settings.yaml:
+        * page/SettingsBase.cpp:
+        (WebCore::SettingsBase::renderingUpdateThrottlingEnabledChanged):
+        * page/SettingsBase.h:
+        Add a setting to enable/disable RenderingUpdateThrottling.
+
+        * platform/graphics/AnimationFrameRate.h: Added.
+        (WebCore::preferredFrameInterval):
+        (WebCore::preferredFramesPerSecond):
+
+        * platform/graphics/DisplayRefreshMonitor.h:
+        (WebCore::DisplayRefreshMonitor::setPreferredFramesPerSecond):
+        * platform/graphics/DisplayRefreshMonitorManager.cpp:
+        (WebCore::DisplayRefreshMonitorManager::monitorForClient):
+        Rename createMonitorForClient() to monitorForClient() since it may return
+        a cached DisplayRefreshMonitor.
+
+        (WebCore::DisplayRefreshMonitorManager::setPreferredFramesPerSecond):
+        (WebCore::DisplayRefreshMonitorManager::scheduleAnimation):
+        (WebCore::DisplayRefreshMonitorManager::windowScreenDidChange):
+        No need to call registerClient(). This function was just ensuring the
+        DisplayRefreshMonitor is created. scheduleAnimation() does the same thing.
+
+        (WebCore::DisplayRefreshMonitorManager::createMonitorForClient): Deleted.
+        (WebCore::DisplayRefreshMonitorManager::registerClient): Deleted.
+        * platform/graphics/DisplayRefreshMonitorManager.h:
+        (WebCore::DisplayRefreshMonitorManager::DisplayRefreshMonitorManager): Deleted.
+
+        * platform/graphics/GraphicsLayerUpdater.cpp:
+        (WebCore::GraphicsLayerUpdater::GraphicsLayerUpdater):
+        * platform/graphics/ios/DisplayRefreshMonitorIOS.mm:
+        (-[WebDisplayLinkHandler setPreferredFramesPerSecond:]):
+        Set the preferredFramesPerSecond of the CADisplayLink.
+
 2020-01-27  Antti Koivisto  <[email protected]>
 
         Correct VTT Cue Style handling to match the specification

Modified: trunk/Source/WebCore/Headers.cmake (255157 => 255158)


--- trunk/Source/WebCore/Headers.cmake	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/Headers.cmake	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1035,6 +1035,7 @@
 
     platform/graphics/AlphaPremultiplication.h
     platform/graphics/ANGLEWebKitBridge.h
+    platform/graphics/AnimationFrameRate.h
     platform/graphics/AudioTrackPrivate.h
     platform/graphics/BitmapImage.h
     platform/graphics/Color.h

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (255157 => 255158)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-01-27 19:54:41 UTC (rev 255158)
@@ -2144,6 +2144,7 @@
 		72144333223EC8B000F12FF7 /* SVGProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 55EE5363223B2A2400FBA944 /* SVGProperty.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		72144334223EC91600F12FF7 /* SVGPropertyOwner.h in Headers */ = {isa = PBXBuildFile; fileRef = 55EE5360223B2A2100FBA944 /* SVGPropertyOwner.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		72283F0E230B268C00F5D828 /* ImagePaintingOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 72C18A3F230B04B7006847C7 /* ImagePaintingOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		722A815D238FDAF000C00583 /* AnimationFrameRate.h in Headers */ = {isa = PBXBuildFile; fileRef = 722A815C238FD50500C00583 /* AnimationFrameRate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		724ED3321A3A8B2300F5F13C /* JSEXTBlendMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 724ED3301A3A8B2300F5F13C /* JSEXTBlendMinMax.h */; };
 		724EE5501DC80D7F00A91FFB /* ActivityState.h in Headers */ = {isa = PBXBuildFile; fileRef = 724EE54E1DC7F25B00A91FFB /* ActivityState.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		724EE5511DC80D8400A91FFB /* ActivityStateChangeObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 724EE54F1DC7F25B00A91FFB /* ActivityStateChangeObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9639,6 +9640,7 @@
 		71FF851822A3F81F005D5959 /* NavigatorMaxTouchPoints.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorMaxTouchPoints.idl; sourceTree = "<group>"; };
 		721443452240C8BA00F12FF7 /* SVGAnimatedValueProperty.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedValueProperty.h; sourceTree = "<group>"; };
 		721443462240CAD200F12FF7 /* SVGValueProperty.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGValueProperty.h; sourceTree = "<group>"; };
+		722A815C238FD50500C00583 /* AnimationFrameRate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AnimationFrameRate.h; sourceTree = "<group>"; };
 		724ED3291A3A7E5400F5F13C /* EXTBlendMinMax.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXTBlendMinMax.cpp; sourceTree = "<group>"; };
 		724ED32A1A3A7E5400F5F13C /* EXTBlendMinMax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTBlendMinMax.h; sourceTree = "<group>"; };
 		724ED32B1A3A7E5400F5F13C /* EXTBlendMinMax.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EXTBlendMinMax.idl; sourceTree = "<group>"; };
@@ -25053,6 +25055,7 @@
 				7299BC6423D686A600CC6883 /* AlphaPremultiplication.h */,
 				490707E41219C04300D90E51 /* ANGLEWebKitBridge.cpp */,
 				490707E51219C04300D90E51 /* ANGLEWebKitBridge.h */,
+				722A815C238FD50500C00583 /* AnimationFrameRate.h */,
 				BEF29EE91715DD0900C4B4C9 /* AudioTrackPrivate.h */,
 				A89943270B42338700D7C802 /* BitmapImage.cpp */,
 				A89943260B42338700D7C802 /* BitmapImage.h */,
@@ -29099,6 +29102,7 @@
 				71EFCEDC202B38A900D7C411 /* AnimationEffect.h in Headers */,
 				71E2C42621C935280024F8C8 /* AnimationEffectPhase.h in Headers */,
 				319848011A1D817B00A13318 /* AnimationEvent.h in Headers */,
+				722A815D238FDAF000C00583 /* AnimationFrameRate.h in Headers */,
 				49E912AD0EFAC906009D0CAF /* AnimationList.h in Headers */,
 				714C7C661FDAD2A100F2BEE1 /* AnimationPlaybackEvent.h in Headers */,
 				714C7C671FDAD2A900F2BEE1 /* AnimationPlaybackEventInit.h in Headers */,

Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (255157 => 255158)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -44,9 +44,6 @@
 #include "RenderLayerBacking.h"
 #include <_javascript_Core/VM.h>
 
-static const Seconds defaultAnimationInterval { 15_ms };
-static const Seconds throttledAnimationInterval { 30_ms };
-
 namespace WebCore {
 
 Ref<DocumentTimeline> DocumentTimeline::create(Document& document)
@@ -198,16 +195,11 @@
     return animations;
 }
 
-void DocumentTimeline::updateThrottlingState()
-{
-    scheduleAnimationResolution();
-}
-
 Seconds DocumentTimeline::animationInterval() const
 {
     if (!m_document || !m_document->page())
         return Seconds::infinity();
-    return m_document->page()->isLowPowerModeEnabled() ? throttledAnimationInterval : defaultAnimationInterval;
+    return m_document->page()->preferredRenderingUpdateInterval();
 }
 
 void DocumentTimeline::suspendAnimations()

Modified: trunk/Source/WebCore/animation/DocumentTimeline.h (255157 => 255158)


--- trunk/Source/WebCore/animation/DocumentTimeline.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/animation/DocumentTimeline.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -74,7 +74,6 @@
     
     void updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp);
 
-    void updateThrottlingState();
     WEBCORE_EXPORT Seconds animationInterval() const;
     WEBCORE_EXPORT void suspendAnimations();
     WEBCORE_EXPORT void resumeAnimations();

Modified: trunk/Source/WebCore/dom/Document.cpp (255157 => 255158)


--- trunk/Source/WebCore/dom/Document.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/dom/Document.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -6504,11 +6504,8 @@
         if (!page() || page()->scriptedAnimationsSuspended())
             m_scriptedAnimationController->suspend();
 
-        if (page() && page()->isLowPowerModeEnabled())
-            m_scriptedAnimationController->addThrottlingReason(ScriptedAnimationController::ThrottlingReason::LowPowerMode);
-
         if (!topOrigin().canAccess(securityOrigin()) && !hasHadUserInteraction())
-            m_scriptedAnimationController->addThrottlingReason(ScriptedAnimationController::ThrottlingReason::NonInteractedCrossOriginFrame);
+            m_scriptedAnimationController->addThrottlingReason(ThrottlingReason::NonInteractedCrossOriginFrame);
     }
 
     return m_scriptedAnimationController->registerCallback(WTFMove(callback));
@@ -6747,7 +6744,7 @@
 
     if (static_cast<bool>(time) && m_scriptedAnimationController) {
         // It's OK to always remove NonInteractedCrossOriginFrame even if this frame isn't cross-origin.
-        m_scriptedAnimationController->removeThrottlingReason(ScriptedAnimationController::ThrottlingReason::NonInteractedCrossOriginFrame);
+        m_scriptedAnimationController->removeThrottlingReason(ThrottlingReason::NonInteractedCrossOriginFrame);
     }
 
     // DOM Timer alignment may depend on the user having interacted with the document.

Modified: trunk/Source/WebCore/dom/ScriptedAnimationController.cpp (255157 => 255158)


--- trunk/Source/WebCore/dom/ScriptedAnimationController.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,37 +27,16 @@
 #include "config.h"
 #include "ScriptedAnimationController.h"
 
-#include "Chrome.h"
-#include "ChromeClient.h"
-#include "CustomHeaderFields.h"
-#include "DOMWindow.h"
-#include "Document.h"
-#include "DocumentLoader.h"
-#include "Frame.h"
-#include "FrameView.h"
 #include "InspectorInstrumentation.h"
-#include "Logging.h"
 #include "Page.h"
 #include "RequestAnimationFrameCallback.h"
 #include "Settings.h"
-#include <algorithm>
-#include <wtf/Ref.h>
 #include <wtf/SystemTracing.h>
-#include <wtf/text/StringBuilder.h>
 
-// Allow a little more than 60fps to make sure we can at least hit that frame rate.
-static const Seconds fullSpeedAnimationInterval { 15_ms };
-// Allow a little more than 30fps to make sure we can at least hit that frame rate.
-static const Seconds halfSpeedThrottlingAnimationInterval { 30_ms };
-static const Seconds aggressiveThrottlingAnimationInterval { 10_s };
-
-#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(page() && page()->isAlwaysOnLoggingAllowed(), PerformanceLogging, "%p - ScriptedAnimationController::" fmt, this, ##__VA_ARGS__)
-
 namespace WebCore {
 
 ScriptedAnimationController::ScriptedAnimationController(Document& document)
     : m_document(makeWeakPtr(document))
-    , m_animationTimer(*this, &ScriptedAnimationController::animationTimerFired)
 {
 }
 
@@ -67,6 +47,25 @@
     return m_document && m_document->settings().requestAnimationFrameEnabled();
 }
 
+Page* ScriptedAnimationController::page() const
+{
+    return m_document ? m_document->page() : nullptr;
+}
+
+Seconds ScriptedAnimationController::preferredScriptedAnimationInterval() const
+{
+    if (auto* page = this->page())
+        return page->renderingUpdateThrottlingEnabled() ? preferredFrameInterval(m_throttlingReasons) : FullSpeedAnimationInterval;
+    return FullSpeedAnimationInterval;
+}
+
+Seconds ScriptedAnimationController::interval() const
+{
+    if (auto* page = this->page())
+        return std::max(preferredScriptedAnimationInterval(), page->preferredRenderingUpdateInterval());
+    return FullSpeedAnimationInterval;
+}
+
 void ScriptedAnimationController::suspend()
 {
     ++m_suspendCount;
@@ -83,110 +82,51 @@
         scheduleAnimation();
 }
 
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) && !RELEASE_LOG_DISABLED
-
-static const char* throttlingReasonToString(ScriptedAnimationController::ThrottlingReason reason)
+bool ScriptedAnimationController::isThrottled() const
 {
-    switch (reason) {
-    case ScriptedAnimationController::ThrottlingReason::VisuallyIdle:
-        return "VisuallyIdle";
-    case ScriptedAnimationController::ThrottlingReason::OutsideViewport:
-        return "OutsideViewport";
-    case ScriptedAnimationController::ThrottlingReason::LowPowerMode:
-        return "LowPowerMode";
-    case ScriptedAnimationController::ThrottlingReason::NonInteractedCrossOriginFrame:
-        return "NonInteractiveCrossOriginFrame";
-    }
+    if (auto* page = this->page())
+        return page->renderingUpdateThrottlingEnabled() && (page->isRenderingUpdateThrottled() || !m_throttlingReasons.isEmpty());
+    return false;
 }
 
-static String throttlingReasonsToString(OptionSet<ScriptedAnimationController::ThrottlingReason> reasons)
+bool ScriptedAnimationController::isThrottledRelativeToPage() const
 {
-    if (reasons.isEmpty())
-        return "[Unthrottled]"_s;
-
-    StringBuilder builder;
-    for (auto reason : reasons) {
-        if (!builder.isEmpty())
-            builder.append('|');
-        builder.append(throttlingReasonToString(reason));
-    }
-    return builder.toString();
+    if (auto* page = this->page())
+        return page->preferredRenderingUpdateInterval() < preferredScriptedAnimationInterval();
+    return false;
 }
 
-#endif
-
-void ScriptedAnimationController::addThrottlingReason(ThrottlingReason reason)
+bool ScriptedAnimationController::shouldRescheduleRequestAnimationFrame(DOMHighResTimeStamp timestamp) const
 {
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (m_throttlingReasons.contains(reason))
-        return;
-
-    m_throttlingReasons.add(reason);
-
-    RELEASE_LOG_IF_ALLOWED("addThrottlingReason(%s) -> %s", throttlingReasonToString(reason), throttlingReasonsToString(m_throttlingReasons).utf8().data());
-
-    if (m_animationTimer.isActive()) {
-        m_animationTimer.stop();
-        scheduleAnimation();
-    }
-#else
-    UNUSED_PARAM(reason);
-#endif
+    return isThrottledRelativeToPage() && Seconds(timestamp - m_lastAnimationFrameTimestamp) < preferredScriptedAnimationInterval();
 }
 
-void ScriptedAnimationController::removeThrottlingReason(ThrottlingReason reason)
-{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (!m_throttlingReasons.contains(reason))
-        return;
-
-    m_throttlingReasons.remove(reason);
-
-    RELEASE_LOG_IF_ALLOWED("removeThrottlingReason(%s) -> %s", throttlingReasonToString(reason), throttlingReasonsToString(m_throttlingReasons).utf8().data());
-
-    if (m_animationTimer.isActive()) {
-        m_animationTimer.stop();
-        scheduleAnimation();
-    }
-#else
-    UNUSED_PARAM(reason);
-#endif
-}
-
-bool ScriptedAnimationController::isThrottled() const
-{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    return !m_throttlingReasons.isEmpty();
-#else
-    return false;
-#endif
-}
-
 ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(Ref<RequestAnimationFrameCallback>&& callback)
 {
-    ScriptedAnimationController::CallbackId id = ++m_nextCallbackId;
+    CallbackId callbackId = ++m_nextCallbackId;
     callback->m_firedOrCancelled = false;
-    callback->m_id = id;
+    callback->m_id = callbackId;
     m_callbacks.append(WTFMove(callback));
 
     if (m_document)
-        InspectorInstrumentation::didRequestAnimationFrame(*m_document, id);
+        InspectorInstrumentation::didRequestAnimationFrame(*m_document, callbackId);
 
     if (!m_suspendCount)
         scheduleAnimation();
-    return id;
+    return callbackId;
 }
 
-void ScriptedAnimationController::cancelCallback(CallbackId id)
+void ScriptedAnimationController::cancelCallback(CallbackId callbackId)
 {
-    for (size_t i = 0; i < m_callbacks.size(); ++i) {
-        if (m_callbacks[i]->m_id == id) {
-            m_callbacks[i]->m_firedOrCancelled = true;
-            InspectorInstrumentation::didCancelAnimationFrame(*m_document, id);
-            m_callbacks.remove(i);
-            return;
-        }
-    }
+    bool cancelled = m_callbacks.removeFirstMatching([&](auto& callback) {
+        if (callback->m_id != callbackId)
+            return false;
+        callback->m_firedOrCancelled = true;
+        return true;
+    });
+
+    if (cancelled && m_document)
+        InspectorInstrumentation::didCancelAnimationFrame(*m_document, callbackId);
 }
 
 void ScriptedAnimationController::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
@@ -194,6 +134,11 @@
     if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
         return;
 
+    if (shouldRescheduleRequestAnimationFrame(timestamp)) {
+        scheduleAnimation();
+        return;
+    }
+    
     TraceScope tracingScope(RAFCallbackStart, RAFCallbackEnd);
 
     // We round this to the nearest microsecond so that we can return a time that matches what is returned by document.timeline.currentTime.
@@ -223,72 +168,19 @@
         return callback->m_firedOrCancelled;
     });
 
+    m_lastAnimationFrameTimestamp = timestamp;
+
     if (m_callbacks.size())
         scheduleAnimation();
 }
 
-Seconds ScriptedAnimationController::interval() const
-{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (m_throttlingReasons.contains(ThrottlingReason::VisuallyIdle) || m_throttlingReasons.contains(ThrottlingReason::OutsideViewport))
-        return aggressiveThrottlingAnimationInterval;
-
-    if (m_throttlingReasons.contains(ThrottlingReason::LowPowerMode))
-        return halfSpeedThrottlingAnimationInterval;
-
-    if (m_throttlingReasons.contains(ThrottlingReason::NonInteractedCrossOriginFrame))
-        return halfSpeedThrottlingAnimationInterval;
-
-    ASSERT(m_throttlingReasons.isEmpty());
-#endif
-    return fullSpeedAnimationInterval;
-}
-
-Page* ScriptedAnimationController::page() const
-{
-    return m_document ? m_document->page() : nullptr;
-}
-
 void ScriptedAnimationController::scheduleAnimation()
 {
     if (!requestAnimationFrameEnabled())
         return;
 
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (!m_isUsingTimer && !isThrottled()) {
-        if (auto* page = this->page()) {
-            page->renderingUpdateScheduler().scheduleTimedRenderingUpdate();
-            return;
-        }
-
-        m_isUsingTimer = true;
-    }
-#endif
-    if (m_animationTimer.isActive())
-        return;
-
-    Seconds animationInterval = interval();
-    Seconds scheduleDelay = std::max(animationInterval - Seconds(m_document->domWindow()->nowTimestamp() - m_lastAnimationFrameTimestamp), 0_s);
-
-    if (isThrottled()) {
-        // FIXME: not ideal to snapshot time both in now() and nowTimestamp(), the latter of which also has reduced resolution.
-        MonotonicTime now = MonotonicTime::now();
-
-        MonotonicTime fireTime = now + scheduleDelay;
-        Seconds alignmentInterval = 10_ms;
-        // Snap to the nearest alignmentInterval.
-        Seconds alignment = (fireTime + alignmentInterval / 2) % alignmentInterval;
-        MonotonicTime alignedFireTime = fireTime - alignment;
-        scheduleDelay = alignedFireTime - now;
-    }
-
-    m_animationTimer.startOneShot(scheduleDelay);
+    if (auto* page = this->page())
+        page->renderingUpdateScheduler().scheduleTimedRenderingUpdate();
 }
 
-void ScriptedAnimationController::animationTimerFired()
-{
-    m_lastAnimationFrameTimestamp = m_document->domWindow()->nowTimestamp();
-    serviceRequestAnimationFrameCallbacks(m_lastAnimationFrameTimestamp);
 }
-
-}

Modified: trunk/Source/WebCore/dom/ScriptedAnimationController.h (255157 => 255158)


--- trunk/Source/WebCore/dom/ScriptedAnimationController.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2019 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,12 +26,13 @@
 
 #pragma once
 
+#include "AnimationFrameRate.h"
 #include "DOMHighResTimeStamp.h"
-#include "Timer.h"
 #include <wtf/OptionSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
@@ -48,6 +50,7 @@
     ~ScriptedAnimationController();
     void clearDocumentPointer() { m_document = nullptr; }
     bool requestAnimationFrameEnabled() const;
+    WEBCORE_EXPORT Seconds interval() const;
 
     typedef int CallbackId;
 
@@ -57,41 +60,29 @@
 
     void suspend();
     void resume();
-
-    enum class ThrottlingReason {
-        VisuallyIdle                    = 1 << 0,
-        OutsideViewport                 = 1 << 1,
-        LowPowerMode                    = 1 << 2,
-        NonInteractedCrossOriginFrame   = 1 << 3,
-    };
-    void addThrottlingReason(ThrottlingReason);
-    void removeThrottlingReason(ThrottlingReason);
-
+    
+    void addThrottlingReason(ThrottlingReason reason) { m_throttlingReasons.add(reason); }
+    void removeThrottlingReason(ThrottlingReason reason) { m_throttlingReasons.remove(reason); }
     WEBCORE_EXPORT bool isThrottled() const;
-    WEBCORE_EXPORT Seconds interval() const;
 
 private:
     ScriptedAnimationController(Document&);
 
+    Page* page() const;
+    Seconds preferredScriptedAnimationInterval() const;
+    bool isThrottledRelativeToPage() const;
+    bool shouldRescheduleRequestAnimationFrame(DOMHighResTimeStamp) const;
     void scheduleAnimation();
-    void animationTimerFired();
 
-    Page* page() const;
-
-    typedef Vector<RefPtr<RequestAnimationFrameCallback>> CallbackList;
+    using CallbackList = Vector<RefPtr<RequestAnimationFrameCallback>>;
     CallbackList m_callbacks;
+    DOMHighResTimeStamp m_lastAnimationFrameTimestamp { 0 };
 
     WeakPtr<Document> m_document;
     CallbackId m_nextCallbackId { 0 };
     int m_suspendCount { 0 };
 
-    Timer m_animationTimer;
-    double m_lastAnimationFrameTimestamp { 0 };
-
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     OptionSet<ThrottlingReason> m_throttlingReasons;
-    bool m_isUsingTimer { false };
-#endif
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/FrameView.cpp (255157 => 255158)


--- trunk/Source/WebCore/page/FrameView.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/FrameView.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -2524,9 +2524,9 @@
 
     if (auto* scriptedAnimationController = document->scriptedAnimationController()) {
         if (shouldThrottle)
-            scriptedAnimationController->addThrottlingReason(ScriptedAnimationController::ThrottlingReason::OutsideViewport);
+            scriptedAnimationController->addThrottlingReason(ThrottlingReason::OutsideViewport);
         else
-            scriptedAnimationController->removeThrottlingReason(ScriptedAnimationController::ThrottlingReason::OutsideViewport);
+            scriptedAnimationController->removeThrottlingReason(ThrottlingReason::OutsideViewport);
     }
 
     document->setTimerThrottlingEnabled(shouldThrottle);

Modified: trunk/Source/WebCore/page/Page.cpp (255157 => 255158)


--- trunk/Source/WebCore/page/Page.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/Page.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -22,6 +22,7 @@
 
 #include "ActivityStateChangeObserver.h"
 #include "AlternativeTextClient.h"
+#include "AnimationFrameRate.h"
 #include "ApplicationCacheStorage.h"
 #include "AuthenticatorCoordinator.h"
 #include "BackForwardCache.h"
@@ -1371,34 +1372,50 @@
     });
 }
 
-enum class ThrottlingReasonOperation { Add, Remove };
-static void updateScriptedAnimationsThrottlingReason(Page& page, ThrottlingReasonOperation operation, ScriptedAnimationController::ThrottlingReason reason)
+bool Page::renderingUpdateThrottlingEnabled() const
 {
-    page.forEachDocument([&] (Document& document) {
-        if (auto* controller = document.scriptedAnimationController()) {
-            if (operation == ThrottlingReasonOperation::Add)
-                controller->addThrottlingReason(reason);
-            else
-                controller->removeThrottlingReason(reason);
-        }
-    });
+    return m_settings->renderingUpdateThrottlingEnabled();
 }
 
+void Page::renderingUpdateThrottlingEnabledChanged()
+{
+    renderingUpdateScheduler().adjustRenderingUpdateFrequency();
+}
+
+bool Page::isRenderingUpdateThrottled() const
+{
+    return renderingUpdateThrottlingEnabled() && !m_throttlingReasons.isEmpty();
+}
+
+Seconds Page::preferredRenderingUpdateInterval() const
+{
+    return renderingUpdateThrottlingEnabled() ? preferredFrameInterval(m_throttlingReasons) : FullSpeedAnimationInterval;
+}
+
 void Page::setIsVisuallyIdleInternal(bool isVisuallyIdle)
 {
-    updateScriptedAnimationsThrottlingReason(*this, isVisuallyIdle ? ThrottlingReasonOperation::Add : ThrottlingReasonOperation::Remove, ScriptedAnimationController::ThrottlingReason::VisuallyIdle);
+    if (isVisuallyIdle == m_throttlingReasons.contains(ThrottlingReason::VisuallyIdle))
+        return;
+
+    m_throttlingReasons = m_throttlingReasons ^ ThrottlingReason::VisuallyIdle;
+
+    if (renderingUpdateThrottlingEnabled())
+        renderingUpdateScheduler().adjustRenderingUpdateFrequency();
 }
 
 void Page::handleLowModePowerChange(bool isLowPowerModeEnabled)
 {
-    updateScriptedAnimationsThrottlingReason(*this, isLowPowerModeEnabled ? ThrottlingReasonOperation::Add : ThrottlingReasonOperation::Remove, ScriptedAnimationController::ThrottlingReason::LowPowerMode);
-    if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
-        forEachDocument([] (Document& document) {
-            if (auto timeline = document.existingTimeline())
-                timeline->updateThrottlingState();
-        });
-    } else
+    if (isLowPowerModeEnabled == m_throttlingReasons.contains(ThrottlingReason::LowPowerMode))
+        return;
+
+    m_throttlingReasons = m_throttlingReasons ^ ThrottlingReason::LowPowerMode;
+
+    if (renderingUpdateThrottlingEnabled())
+        renderingUpdateScheduler().adjustRenderingUpdateFrequency();
+
+    if (!RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
         mainFrame().animation().updateThrottlingState();
+
     updateDOMTimerAlignmentInterval();
 }
 

Modified: trunk/Source/WebCore/page/Page.h (255157 => 255158)


--- trunk/Source/WebCore/page/Page.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/Page.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -21,6 +21,7 @@
 #pragma once
 
 #include "ActivityState.h"
+#include "AnimationFrameRate.h"
 #include "DisabledAdaptations.h"
 #include "Document.h"
 #include "FindOptions.h"
@@ -697,6 +698,11 @@
     bool isLowPowerModeEnabled() const;
     WEBCORE_EXPORT void setLowPowerModeEnabledOverrideForTesting(Optional<bool>);
 
+    bool renderingUpdateThrottlingEnabled() const;
+    void renderingUpdateThrottlingEnabledChanged();
+    bool isRenderingUpdateThrottled() const;
+    Seconds preferredRenderingUpdateInterval() const;
+
     WEBCORE_EXPORT void applicationWillResignActive();
     WEBCORE_EXPORT void applicationDidEnterBackground();
     WEBCORE_EXPORT void applicationWillEnterForeground();
@@ -992,6 +998,7 @@
     bool m_inUpdateRendering { false };
     bool m_hasResourceLoadClient { false };
     Vector<UserContentURLPattern> m_corsDisablingPatterns;
+    OptionSet<ThrottlingReason> m_throttlingReasons;
 };
 
 inline PageGroup& Page::group()

Modified: trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp (255157 => 255158)


--- trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -42,6 +42,27 @@
 #endif
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) && PLATFORM(IOS_FAMILY)
+void RenderingUpdateScheduler::adjustFramesPerSecond()
+{
+    Seconds interval = m_page.preferredRenderingUpdateInterval();
+    // CADisplayLink.preferredFramesPerSecond is an integer. So a fraction PreferredFramesPerSecond can't be set.
+    if (interval < 1_s)
+        DisplayRefreshMonitorManager::sharedManager().setPreferredFramesPerSecond(*this, preferredFramesPerSecond(interval));
+}
+#endif
+
+void RenderingUpdateScheduler::adjustRenderingUpdateFrequency()
+{
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) && PLATFORM(IOS_FAMILY)
+    adjustFramesPerSecond();
+#endif
+    if (isScheduled()) {
+        clearScheduled();
+        scheduleTimedRenderingUpdate();
+    }
+}
+
 void RenderingUpdateScheduler::scheduleTimedRenderingUpdate()
 {
     if (isScheduled())
@@ -55,12 +76,25 @@
 
     tracePoint(ScheduleRenderingUpdate);
 
+    Seconds interval = m_page.preferredRenderingUpdateInterval();
+
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    if (!DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this))
+    // CADisplayLink.preferredFramesPerSecond is an integer. Fall back to timer if the PreferredFramesPerSecond is a fraction.
+    if (interval < 1_s) {
+#if PLATFORM(IOS_FAMILY)
+        if (!m_isMonitorCreated) {
+            adjustFramesPerSecond();
+            m_isMonitorCreated = true;
+        }
+#else
+        if (interval == FullSpeedAnimationInterval)
 #endif
-        startTimer(Seconds(1.0 / 60));
+            m_scheduled = DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
+    }
+#endif
 
-    m_scheduled = true;
+    if (!isScheduled())
+        startTimer(interval);
 }
 
 bool RenderingUpdateScheduler::isScheduled() const
@@ -74,6 +108,7 @@
     ASSERT(!isScheduled());
     m_refreshTimer = makeUnique<Timer>(*this, &RenderingUpdateScheduler::displayRefreshFired);
     m_refreshTimer->startOneShot(delay);
+    m_scheduled = true;
 }
 
 void RenderingUpdateScheduler::clearScheduled()

Modified: trunk/Source/WebCore/page/RenderingUpdateScheduler.h (255157 => 255158)


--- trunk/Source/WebCore/page/RenderingUpdateScheduler.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -46,6 +46,8 @@
     }
 
     RenderingUpdateScheduler(Page&);
+    
+    void adjustRenderingUpdateFrequency();
     void scheduleTimedRenderingUpdate();
     void scheduleImmediateRenderingUpdate();
     void scheduleRenderingUpdate();
@@ -56,6 +58,9 @@
 
 private:
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+#if PLATFORM(IOS_FAMILY)
+    void adjustFramesPerSecond();
+#endif
     RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const final;
     void displayRefreshFired() final;
 #else
@@ -67,6 +72,9 @@
     void clearScheduled();
 
     Page& m_page;
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) && PLATFORM(IOS_FAMILY)
+    bool m_isMonitorCreated;
+#endif
     bool m_scheduled { false };
     std::unique_ptr<Timer> m_refreshTimer;
 };

Modified: trunk/Source/WebCore/page/Settings.yaml (255157 => 255158)


--- trunk/Source/WebCore/page/Settings.yaml	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/Settings.yaml	2020-01-27 19:54:41 UTC (rev 255158)
@@ -765,6 +765,10 @@
   initial: false
   onChange: hiddenPageCSSAnimationSuspensionEnabledChanged
 
+renderingUpdateThrottlingEnabled:
+  initial: true
+  onChange: renderingUpdateThrottlingEnabledChanged
+
 storageBlockingPolicy:
   type: SecurityOrigin::StorageBlockingPolicy
   initial: SecurityOrigin::AllowAllStorage

Modified: trunk/Source/WebCore/page/SettingsBase.cpp (255157 => 255158)


--- trunk/Source/WebCore/page/SettingsBase.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/SettingsBase.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -407,6 +407,12 @@
         m_page->hiddenPageCSSAnimationSuspensionStateChanged();
 }
 
+void SettingsBase::renderingUpdateThrottlingEnabledChanged()
+{
+    if (m_page)
+        m_page->renderingUpdateThrottlingEnabledChanged();
+}
+
 void SettingsBase::resourceUsageOverlayVisibleChanged()
 {
 #if ENABLE(RESOURCE_USAGE)

Modified: trunk/Source/WebCore/page/SettingsBase.h (255157 => 255158)


--- trunk/Source/WebCore/page/SettingsBase.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/page/SettingsBase.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -194,6 +194,7 @@
     void scrollingPerformanceLoggingEnabledChanged();
     void hiddenPageDOMTimerThrottlingStateChanged();
     void hiddenPageCSSAnimationSuspensionEnabledChanged();
+    void renderingUpdateThrottlingEnabledChanged();
     void resourceUsageOverlayVisibleChanged();
     void iceCandidateFilteringEnabledChanged();
 #if ENABLE(TEXT_AUTOSIZING)

Added: trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h (0 => 255158)


--- trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 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 <wtf/OptionSet.h>
+#include <wtf/Seconds.h>
+
+namespace WebCore {
+
+using FramesPerSecond = unsigned;
+
+enum class ThrottlingReason {
+    VisuallyIdle                    = 1 << 0,
+    OutsideViewport                 = 1 << 1,
+    LowPowerMode                    = 1 << 2,
+    NonInteractedCrossOriginFrame   = 1 << 3,
+};
+
+// Allow a little more than 60fps to make sure we can at least hit that frame rate.
+constexpr const Seconds FullSpeedAnimationInterval { 15_ms };
+// Allow a little more than 30fps to make sure we can at least hit that frame rate.
+constexpr const Seconds HalfSpeedThrottlingAnimationInterval { 30_ms };
+constexpr const Seconds AggressiveThrottlingAnimationInterval { 10_s };
+
+constexpr const FramesPerSecond FullSpeedFramesPerSecond = 60;
+constexpr const FramesPerSecond HalfSpeedThrottlingFramesPerSecond = 30;
+constexpr const FramesPerSecond ZeroFramesPerSecond = 0;
+
+inline Seconds preferredFrameInterval(const OptionSet<ThrottlingReason>& throttlingReasons)
+{
+    if (throttlingReasons.containsAny({ ThrottlingReason::VisuallyIdle, ThrottlingReason::OutsideViewport }))
+        return AggressiveThrottlingAnimationInterval;
+
+    if (throttlingReasons.containsAny({ ThrottlingReason::LowPowerMode, ThrottlingReason::NonInteractedCrossOriginFrame }))
+        return HalfSpeedThrottlingAnimationInterval;
+
+    ASSERT(throttlingReasons.isEmpty());
+    return FullSpeedAnimationInterval;
+}
+
+inline FramesPerSecond preferredFramesPerSecond(Seconds preferredFrameInterval)
+{
+    if (preferredFrameInterval == FullSpeedAnimationInterval)
+        return FullSpeedFramesPerSecond;
+
+    if (preferredFrameInterval == HalfSpeedThrottlingAnimationInterval)
+        return HalfSpeedThrottlingFramesPerSecond;
+
+    ASSERT_NOT_REACHED();
+    return ZeroFramesPerSecond;
+}
+
+}

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h (255157 => 255158)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -27,6 +27,7 @@
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
+#include "AnimationFrameRate.h"
 #include "PlatformScreen.h"
 #include <wtf/HashSet.h>
 #include <wtf/Lock.h>
@@ -45,6 +46,8 @@
 
     virtual void displayLinkFired() { }
 
+    virtual void setPreferredFramesPerSecond(FramesPerSecond) { }
+
     // Return true if callback request was scheduled, false if it couldn't be
     // (e.g., hardware refresh is not available)
     virtual bool requestRefreshCallback() = 0;

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp (255157 => 255158)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -42,8 +42,11 @@
     return manager.get();
 }
 
-DisplayRefreshMonitor* DisplayRefreshMonitorManager::createMonitorForClient(DisplayRefreshMonitorClient& client)
+DisplayRefreshMonitor* DisplayRefreshMonitorManager::monitorForClient(DisplayRefreshMonitorClient& client)
 {
+    if (!client.hasDisplayID())
+        return nullptr;
+
     PlatformDisplayID clientDisplayID = client.displayID();
     if (auto* existingMonitor = monitorForDisplayID(clientDisplayID)) {
         existingMonitor->addClient(client);
@@ -54,7 +57,7 @@
     if (!monitor)
         return nullptr;
 
-    LOG(RequestAnimationFrame, "DisplayRefreshMonitorManager::createMonitorForClient() - created monitor %p", monitor.get());
+    LOG(RequestAnimationFrame, "DisplayRefreshMonitorManager::monitorForClient() - created monitor %p", monitor.get());
     monitor->addClient(client);
     DisplayRefreshMonitor* result = monitor.get();
     m_monitors.append({ WTFMove(monitor) });
@@ -61,14 +64,6 @@
     return result;
 }
 
-void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient& client)
-{
-    if (!client.hasDisplayID())
-        return;
-
-    createMonitorForClient(client);
-}
-
 void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient& client)
 {
     if (!client.hasDisplayID())
@@ -85,17 +80,19 @@
     }
 }
 
+void DisplayRefreshMonitorManager::setPreferredFramesPerSecond(DisplayRefreshMonitorClient& client, FramesPerSecond preferredFramesPerSecond)
+{
+    if (auto* monitor = monitorForClient(client))
+        monitor->setPreferredFramesPerSecond(preferredFramesPerSecond);
+}
+
 bool DisplayRefreshMonitorManager::scheduleAnimation(DisplayRefreshMonitorClient& client)
 {
-    if (!client.hasDisplayID())
-        return false;
-
-    DisplayRefreshMonitor* monitor = createMonitorForClient(client);
-    if (!monitor)
-        return false;
-
-    client.setIsScheduled(true);
-    return monitor->requestRefreshCallback();
+    if (auto* monitor = monitorForClient(client)) {
+        client.setIsScheduled(true);
+        return monitor->requestRefreshCallback();
+    }
+    return false;
 }
 
 void DisplayRefreshMonitorManager::displayDidRefresh(DisplayRefreshMonitor& monitor)
@@ -116,7 +113,6 @@
     
     unregisterClient(client);
     client.setDisplayID(displayID);
-    registerClient(client);
     if (client.isScheduled())
         scheduleAnimation(client);
 }

Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h (255157 => 255158)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -27,6 +27,7 @@
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
+#include "AnimationFrameRate.h"
 #include "DisplayRefreshMonitor.h"
 #include "PlatformScreen.h"
 #include <wtf/NeverDestroyed.h>
@@ -37,29 +38,28 @@
 
 class DisplayRefreshMonitorManager {
     friend class NeverDestroyed<DisplayRefreshMonitorManager>;
+    friend class DisplayRefreshMonitor;
 public:
     WEBCORE_EXPORT static DisplayRefreshMonitorManager& sharedManager();
-    
-    void registerClient(DisplayRefreshMonitorClient&);
+
     void unregisterClient(DisplayRefreshMonitorClient&);
 
+    void setPreferredFramesPerSecond(DisplayRefreshMonitorClient&, FramesPerSecond);
     bool scheduleAnimation(DisplayRefreshMonitorClient&);
     void windowScreenDidChange(PlatformDisplayID, DisplayRefreshMonitorClient&);
 
     WEBCORE_EXPORT void displayWasUpdated(PlatformDisplayID);
-    
+
 private:
-    friend class DisplayRefreshMonitor;
-    void displayDidRefresh(DisplayRefreshMonitor&);
-    
-    DisplayRefreshMonitorManager() { }
+    DisplayRefreshMonitorManager() = default;
     virtual ~DisplayRefreshMonitorManager();
 
+    void displayDidRefresh(DisplayRefreshMonitor&);
+
     size_t findMonitorForDisplayID(PlatformDisplayID) const;
     DisplayRefreshMonitor* monitorForDisplayID(PlatformDisplayID) const;
+    DisplayRefreshMonitor* monitorForClient(DisplayRefreshMonitorClient&);
 
-    DisplayRefreshMonitor* createMonitorForClient(DisplayRefreshMonitorClient&);
-
     struct DisplayRefreshMonitorWrapper {
         DisplayRefreshMonitorWrapper(DisplayRefreshMonitorWrapper&&) = default;
         ~DisplayRefreshMonitorWrapper()

Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp (255157 => 255158)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -35,7 +35,6 @@
 GraphicsLayerUpdater::GraphicsLayerUpdater(GraphicsLayerUpdaterClient& client, PlatformDisplayID displayID)
     : m_client(client)
 {
-    DisplayRefreshMonitorManager::sharedManager().registerClient(*this);
     DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, *this);
     DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
 }

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


--- trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -40,6 +40,7 @@
 }
 
 - (id)initWithMonitor:(DisplayRefreshMonitorIOS*)monitor;
+- (void)setPreferredFramesPerSecond:(NSInteger)preferredFramesPerSecond;
 - (void)handleDisplayLink:(CADisplayLink *)sender;
 - (void)invalidate;
 
@@ -65,6 +66,11 @@
     [super dealloc];
 }
 
+- (void)setPreferredFramesPerSecond:(NSInteger)preferredFramesPerSecond
+{
+    m_displayLink.preferredFramesPerSecond = preferredFramesPerSecond;
+}
+
 - (void)handleDisplayLink:(CADisplayLink *)sender
 {
     UNUSED_PARAM(sender);

Modified: trunk/Source/WebKit/ChangeLog (255157 => 255158)


--- trunk/Source/WebKit/ChangeLog	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/ChangeLog	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,3 +1,39 @@
+2020-01-27  Said Abou-Hallawa  <[email protected]>
+
+        Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
+        https://bugs.webkit.org/show_bug.cgi?id=204713
+
+        Reviewed by Simon Fraser.
+
+        Create an IPC message on the DrawingArea to send a message from the
+        WebProcess to the UIProcess to setPreferredFramesPerSecond of the
+        DisplayRefreshMonitor.
+
+        * Shared/WebPreferences.yaml:
+        * UIProcess/API/C/WKPreferences.cpp:
+        (WKPreferencesSetRenderingUpdateThrottlingEnabled):
+        (WKPreferencesGetRenderingUpdateThrottlingEnabled):
+        * UIProcess/API/C/WKPreferencesRefPrivate.h:
+        Add a WKPreference key for RenderingUpdateThrottlingEnabled.
+
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in:
+
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
+        (-[WKOneShotDisplayLinkHandler setPreferredFramesPerSecond:]):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::setPreferredFramesPerSecond):
+        Set the preferredFramesPerSecond of the CADisplayLink.
+
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm:
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond):
+        Delegate the call to RemoteLayerTreeDrawingArea.
+
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::setPreferredFramesPerSecond):
+        Send the IPC message from the WebProcess to the UIProcess.
+
 2020-01-27  Kate Cheney  <[email protected]>
 
         Delete the ITP storage file that is not being used (plist or database file) when switching to a new storage type

Modified: trunk/Source/WebKit/Shared/WebPreferences.yaml (255157 => 255158)


--- trunk/Source/WebKit/Shared/WebPreferences.yaml	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/Shared/WebPreferences.yaml	2020-01-27 19:54:41 UTC (rev 255158)
@@ -488,6 +488,10 @@
   type: bool
   defaultValue: DEFAULT_HIDDEN_PAGE_CSS_ANIMATION_SUSPENSION_ENABLED
 
+RenderingUpdateThrottlingEnabled:
+  type: bool
+  defaultValue: true
+
 LowPowerVideoAudioBufferSizeEnabled:
   type: bool
   defaultValue: true

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp (255157 => 255158)


--- trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1309,6 +1309,16 @@
     return toImpl(preferencesRef)->hiddenPageCSSAnimationSuspensionEnabled();
 }
 
+void WKPreferencesSetRenderingUpdateThrottlingEnabled(WKPreferencesRef preferencesRef, bool enabled)
+{
+    toImpl(preferencesRef)->setRenderingUpdateThrottlingEnabled(enabled);
+}
+
+bool WKPreferencesGetRenderingUpdateThrottlingEnabled(WKPreferencesRef preferencesRef)
+{
+    return toImpl(preferencesRef)->renderingUpdateThrottlingEnabled();
+}
+
 void WKPreferencesSetIncrementalRenderingSuppressionTimeout(WKPreferencesRef preferencesRef, double timeout)
 {
     toImpl(preferencesRef)->setIncrementalRenderingSuppressionTimeout(timeout);

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h (255157 => 255158)


--- trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -302,6 +302,10 @@
 WK_EXPORT void WKPreferencesSetHiddenPageCSSAnimationSuspensionEnabled(WKPreferencesRef preferences, bool enabled);
 WK_EXPORT bool WKPreferencesGetHiddenPageCSSAnimationSuspensionEnabled(WKPreferencesRef preferences);
 
+// Defaults to true.
+WK_EXPORT void WKPreferencesSetRenderingUpdateThrottlingEnabled(WKPreferencesRef preferences, bool enabled);
+WK_EXPORT bool WKPreferencesGetRenderingUpdateThrottlingEnabled(WKPreferencesRef preferences);
+
 // Defaults to false
 WK_EXPORT void WKPreferencesSetSnapshotAllPlugIns(WKPreferencesRef preferencesRef, bool enabled);
 WK_EXPORT bool WKPreferencesGetSnapshotAllPlugIns(WKPreferencesRef preferencesRef);

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h (255157 => 255158)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -28,6 +28,7 @@
 #include "DrawingAreaProxy.h"
 #include "RemoteLayerTreeHost.h"
 #include "TransactionID.h"
+#include <WebCore/AnimationFrameRate.h>
 #include <WebCore/FloatPoint.h>
 #include <WebCore/IntPoint.h>
 #include <WebCore/IntSize.h>
@@ -97,6 +98,7 @@
     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
 
     // Message handlers
+    void setPreferredFramesPerSecond(WebCore::FramesPerSecond);
     void willCommitLayerTree(TransactionID);
     void commitLayerTree(const RemoteLayerTreeTransaction&, const RemoteScrollingCoordinatorTransaction&);
     

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in (255157 => 255158)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in	2020-01-27 19:54:41 UTC (rev 255158)
@@ -21,6 +21,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 messages -> RemoteLayerTreeDrawingAreaProxy : DrawingAreaProxy NotRefCounted {
+    void SetPreferredFramesPerSecond(unsigned preferredFramesPerSecond)
     void WillCommitLayerTree(WebKit::TransactionID transactionID)
     void CommitLayerTree(WebKit::RemoteLayerTreeTransaction layerTreeTransaction, WebKit::RemoteScrollingCoordinatorTransaction scrollingTreeTransaction)
 }

Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm (255157 => 255158)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -49,6 +49,7 @@
 }
 
 - (id)initWithDrawingAreaProxy:(WebKit::RemoteLayerTreeDrawingAreaProxy*)drawingAreaProxy;
+- (void)setPreferredFramesPerSecond:(NSInteger)preferredFramesPerSecond;
 - (void)displayLinkFired:(CADisplayLink *)sender;
 - (void)invalidate;
 - (void)schedule;
@@ -76,6 +77,11 @@
     [super dealloc];
 }
 
+- (void)setPreferredFramesPerSecond:(NSInteger)preferredFramesPerSecond
+{
+    _displayLink.preferredFramesPerSecond = preferredFramesPerSecond;
+}
+
 - (void)displayLinkFired:(CADisplayLink *)sender
 {
     ASSERT(isUIThread());
@@ -183,6 +189,15 @@
     m_isWaitingForDidUpdateGeometry = true;
 }
 
+void RemoteLayerTreeDrawingAreaProxy::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+{
+#if PLATFORM(IOS_FAMILY)
+    [displayLinkHandler() setPreferredFramesPerSecond:preferredFramesPerSecond];
+#else
+    UNUSED_PARAM(preferredFramesPerSecond);
+#endif
+}
+
 void RemoteLayerTreeDrawingAreaProxy::willCommitLayerTree(TransactionID transactionID)
 {
     m_pendingLayerTreeTransactionID = transactionID;

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


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -28,6 +28,7 @@
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
 #include "RemoteLayerTreeDrawingArea.h"
+#include <WebCore/AnimationFrameRate.h>
 #include <WebCore/DisplayRefreshMonitor.h>
 
 namespace WebKit {
@@ -41,6 +42,7 @@
     
     virtual ~RemoteLayerTreeDisplayRefreshMonitor();
 
+    void setPreferredFramesPerSecond(WebCore::FramesPerSecond) override;
     bool requestRefreshCallback() override;
 
     void didUpdateLayers();

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


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -43,6 +43,12 @@
         m_drawingArea->willDestroyDisplayRefreshMonitor(this);
 }
 
+void RemoteLayerTreeDisplayRefreshMonitor::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+{
+    if (m_drawingArea)
+        m_drawingArea->setPreferredFramesPerSecond(preferredFramesPerSecond);
+}
+
 bool RemoteLayerTreeDisplayRefreshMonitor::requestRefreshCallback()
 {
     if (!m_drawingArea || !isActive())

Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h (255157 => 255158)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -29,6 +29,7 @@
 #include "DrawingArea.h"
 #include "GraphicsLayerCARemote.h"
 #include "RemoteLayerTreeTransaction.h"
+#include <WebCore/AnimationFrameRate.h>
 #include <WebCore/GraphicsLayerClient.h>
 #include <WebCore/Timer.h>
 #include <atomic>
@@ -73,6 +74,7 @@
 
     RefPtr<WebCore::DisplayRefreshMonitor> createDisplayRefreshMonitor(WebCore::PlatformDisplayID) override;
     void willDestroyDisplayRefreshMonitor(WebCore::DisplayRefreshMonitor*);
+    void setPreferredFramesPerSecond(WebCore::FramesPerSecond);
 
     bool shouldUseTiledBackingForFrameView(const WebCore::FrameView&) const override;
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm (255157 => 255158)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -123,6 +123,11 @@
     }
 }
 
+void RemoteLayerTreeDrawingArea::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+{
+    send(Messages::RemoteLayerTreeDrawingAreaProxy::SetPreferredFramesPerSecond(preferredFramesPerSecond));
+}
+
 void RemoteLayerTreeDrawingArea::updateRootLayers()
 {
     Vector<Ref<GraphicsLayer>> children;

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (255157 => 255158)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,3 +1,21 @@
+2020-01-27  Said Abou-Hallawa  <[email protected]>
+
+        Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
+        https://bugs.webkit.org/show_bug.cgi?id=204713
+
+        Reviewed by Simon Fraser.
+
+        Add a WKPreference key for RenderingUpdateThrottling.
+
+        * WebView/WebPreferenceKeysPrivate.h:
+        * WebView/WebPreferences.mm:
+        (+[WebPreferences initialize]):
+        (-[WebPreferences renderingUpdateThrottlingEnabled]):
+        (-[WebPreferences setRenderingUpdateThrottlingEnabled:]):
+        * WebView/WebPreferencesPrivate.h:
+        * WebView/WebView.mm:
+        (-[WebView _preferencesChanged:]):
+
 2020-01-27  Ryan Haddad  <[email protected]>
 
         Unreviewed, rolling out r255131.

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h (255157 => 255158)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -164,6 +164,7 @@
 #define WebKitPlugInSnapshottingEnabledPreferenceKey @"WebKitPlugInSnapshottingEnabled"
 #define WebKitHiddenPageDOMTimerThrottlingEnabledPreferenceKey @"WebKitHiddenPageDOMTimerThrottlingEnabled"
 #define WebKitHiddenPageCSSAnimationSuspensionEnabledPreferenceKey @"WebKitHiddenPageCSSAnimationSuspensionEnabled"
+#define WebKitRenderingUpdateThrottlingEnabledPreferenceKey @"WebKitRenderingUpdateThrottlingEnabled"
 #define WebKitLowPowerVideoAudioBufferSizeEnabledPreferenceKey @"WebKitLowPowerVideoAudioBufferSizeEnabled"
 #define WebKitUseLegacyTextAlignPositionedElementBehaviorPreferenceKey @"WebKitUseLegacyTextAlignPositionedElementBehavior"
 #define WebKitMediaSourceEnabledPreferenceKey @"WebKitMediaSourceEnabled"

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm (255157 => 255158)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -593,6 +593,7 @@
         [NSNumber numberWithLongLong:ApplicationCacheStorage::noQuota()], WebKitApplicationCacheDefaultOriginQuota,
         @NO, WebKitHiddenPageDOMTimerThrottlingEnabledPreferenceKey,
         @NO, WebKitHiddenPageCSSAnimationSuspensionEnabledPreferenceKey,
+        @YES, WebKitRenderingUpdateThrottlingEnabledPreferenceKey,
         @NO, WebKitLowPowerVideoAudioBufferSizeEnabledPreferenceKey,
         
         @NO, WebKitUseLegacyTextAlignPositionedElementBehaviorPreferenceKey,
@@ -2785,6 +2786,16 @@
     [self _setBoolValue:enabled forKey:WebKitHiddenPageCSSAnimationSuspensionEnabledPreferenceKey];
 }
 
+- (BOOL)renderingUpdateThrottlingEnabled
+{
+    return [self _boolValueForKey:WebKitRenderingUpdateThrottlingEnabledPreferenceKey];
+}
+
+- (void)setRenderingUpdateThrottlingEnabled:(BOOL)enabled
+{
+    [self _setBoolValue:enabled forKey:WebKitRenderingUpdateThrottlingEnabledPreferenceKey];
+}
+
 - (BOOL)lowPowerVideoAudioBufferSizeEnabled
 {
     return [self _boolValueForKey:WebKitLowPowerVideoAudioBufferSizeEnabledPreferenceKey];

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h (255157 => 255158)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -489,6 +489,9 @@
 - (BOOL)hiddenPageCSSAnimationSuspensionEnabled;
 - (void)setHiddenPageCSSAnimationSuspensionEnabled:(BOOL)flag;
 
+- (BOOL)renderingUpdateThrottlingEnabled;
+- (void)setRenderingUpdateThrottlingEnabled:(BOOL)flag;
+
 - (BOOL)lowPowerVideoAudioBufferSizeEnabled;
 - (void)setLowPowerVideoAudioBufferSizeEnabled:(BOOL)enabled;
 

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebView.mm (255157 => 255158)


--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -3133,8 +3133,8 @@
     RuntimeEnabledFeatures::sharedFeatures().setAdClickAttributionEnabled([preferences adClickAttributionEnabled]);
 
     settings.setHiddenPageDOMTimerThrottlingEnabled([preferences hiddenPageDOMTimerThrottlingEnabled]);
-
     settings.setHiddenPageCSSAnimationSuspensionEnabled([preferences hiddenPageCSSAnimationSuspensionEnabled]);
+    settings.setRenderingUpdateThrottlingEnabled([preferences renderingUpdateThrottlingEnabled]);
 
     WebCore::DeprecatedGlobalSettings::setResourceLoadStatisticsEnabled([preferences resourceLoadStatisticsEnabled]);
 

Modified: trunk/Source/WebKitLegacy/win/ChangeLog (255157 => 255158)


--- trunk/Source/WebKitLegacy/win/ChangeLog	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/win/ChangeLog	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,3 +1,22 @@
+2020-01-27  Said Abou-Hallawa  <[email protected]>
+
+        Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
+        https://bugs.webkit.org/show_bug.cgi?id=204713
+
+        Reviewed by Simon Fraser.
+
+        Add a WKPreference key for RenderingUpdateThrottling.
+
+        * Interfaces/IWebPreferencesPrivate.idl:
+        * WebPreferenceKeysPrivate.h:
+        * WebPreferences.cpp:
+        (WebPreferences::initializeDefaultSettings):
+        (WebPreferences::renderingUpdateThrottlingEnabled):
+        (WebPreferences::setRenderingUpdateThrottlingEnabled):
+        * WebPreferences.h:
+        * WebView.cpp:
+        (WebView::notifyPreferencesChanged):
+
 2020-01-27  Ryan Haddad  <[email protected]>
 
         Unreviewed, rolling out r255131.

Modified: trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl (255157 => 255158)


--- trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl	2020-01-27 19:54:41 UTC (rev 255158)
@@ -256,4 +256,6 @@
     HRESULT setAspectRatioOfImgFromWidthAndHeightEnabled([in] BOOL enabled);
     HRESULT setWebSQLEnabled([in] BOOL enabled);
     HRESULT webSQLEnabled([out, retval] BOOL* enabled);
+    HRESULT setRenderingUpdateThrottlingEnabled([in] BOOL enabled);
+    HRESULT renderingUpdateThrottlingEnabled([out, retval] BOOL* enabled);
 }

Modified: trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h (255157 => 255158)


--- trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -224,3 +224,5 @@
 #define WebKitAspectRatioOfImgFromWidthAndHeightEnabledPreferenceKey "WebKitAspectRatioOfImgFromWidthAndHeightEnabled"
 
 #define WebKitWebSQLEnabledPreferenceKey "WebKitWebSQLEnabled"
+
+#define WebKitRenderingUpdateThrottlingEnabledPreferenceKey "WebKitRenderingUpdateThrottlingEnabled"

Modified: trunk/Source/WebKitLegacy/win/WebPreferences.cpp (255157 => 255158)


--- trunk/Source/WebKitLegacy/win/WebPreferences.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/win/WebPreferences.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -351,6 +351,8 @@
 
     CFDictionaryAddValue(defaults, CFSTR(WebKitWebSQLEnabledPreferenceKey), kCFBooleanFalse);
 
+    CFDictionaryAddValue(defaults, CFSTR(WebKitRenderingUpdateThrottlingEnabledPreferenceKey), kCFBooleanTrue);
+
     defaultSettings = defaults;
 #endif
 }
@@ -2450,3 +2452,18 @@
     setBoolValue(WebKitWebSQLEnabledPreferenceKey, enabled);
     return S_OK;
 }
+
+HRESULT WebPreferences::renderingUpdateThrottlingEnabled(_Out_ BOOL* enabled)
+{
+    if (!enabled)
+        return E_POINTER;
+    *enabled = boolValueForKey(WebKitRenderingUpdateThrottlingEnabledPreferenceKey);
+    return S_OK;
+}
+
+HRESULT WebPreferences::setRenderingUpdateThrottlingEnabled(BOOL enabled)
+{
+    setBoolValue(WebKitRenderingUpdateThrottlingEnabledPreferenceKey, enabled);
+    return S_OK;
+}
+

Modified: trunk/Source/WebKitLegacy/win/WebPreferences.h (255157 => 255158)


--- trunk/Source/WebKitLegacy/win/WebPreferences.h	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/win/WebPreferences.h	2020-01-27 19:54:41 UTC (rev 255158)
@@ -301,6 +301,8 @@
     virtual HRESULT STDMETHODCALLTYPE setAspectRatioOfImgFromWidthAndHeightEnabled(BOOL);
     virtual HRESULT STDMETHODCALLTYPE webSQLEnabled(_Out_ BOOL*);
     virtual HRESULT STDMETHODCALLTYPE setWebSQLEnabled(BOOL);
+    virtual HRESULT STDMETHODCALLTYPE renderingUpdateThrottlingEnabled(_Out_ BOOL*);
+    virtual HRESULT STDMETHODCALLTYPE setRenderingUpdateThrottlingEnabled(BOOL);
 
     // WebPreferences
 

Modified: trunk/Source/WebKitLegacy/win/WebView.cpp (255157 => 255158)


--- trunk/Source/WebKitLegacy/win/WebView.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Source/WebKitLegacy/win/WebView.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -5604,6 +5604,11 @@
         return hr;
     settings.setRequestAnimationFrameEnabled(enabled);
 
+    hr = prefsPrivate->renderingUpdateThrottlingEnabled(&enabled);
+    if (FAILED(hr))
+        return hr;
+    settings.setRenderingUpdateThrottlingEnabled(enabled);
+
     hr = prefsPrivate->mockScrollbarsEnabled(&enabled);
     if (FAILED(hr))
         return hr;

Modified: trunk/Tools/ChangeLog (255157 => 255158)


--- trunk/Tools/ChangeLog	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Tools/ChangeLog	2020-01-27 19:54:41 UTC (rev 255158)
@@ -1,3 +1,21 @@
+2020-01-27  Said Abou-Hallawa  <[email protected]>
+
+        Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler
+        https://bugs.webkit.org/show_bug.cgi?id=204713
+
+        Reviewed by Simon Fraser.
+
+        RenderingUpdateThrottling is enabled by default. Turn it off for DRT and
+        WTR. In some cases, the page may not get visually active while it's
+        waiting for rAF. Throttling tests will have to explicitly turn it on.
+
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (resetWebPreferencesToConsistentValues):
+        * DumpRenderTree/win/DumpRenderTree.cpp:
+        (resetWebPreferencesToConsistentValues):
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::resetPreferencesToConsistentValues):
+
 2020-01-26  Aakash Jain  <[email protected]>
 
         [ews] Status bubble hover over message in case of success should indicate whether it built the patch or run tests

Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (255157 => 255158)


--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2020-01-27 19:54:41 UTC (rev 255158)
@@ -994,6 +994,7 @@
 
     [preferences setHiddenPageDOMTimerThrottlingEnabled:NO];
     [preferences setHiddenPageCSSAnimationSuspensionEnabled:NO];
+    [preferences setRenderingUpdateThrottlingEnabled:NO];
     [preferences setRemotePlaybackEnabled:YES];
 
     [preferences setMediaDevicesEnabled:YES];

Modified: trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp (255157 => 255158)


--- trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -800,6 +800,7 @@
     prefsPrivate->setWebAnimationsCompositeOperationsEnabled(TRUE);
     prefsPrivate->setServerTimingEnabled(TRUE);
     prefsPrivate->setAspectRatioOfImgFromWidthAndHeightEnabled(TRUE);
+    prefsPrivate->setRenderingUpdateThrottlingEnabled(FALSE);
     // FIXME: WebGL2
     // FIXME: WebRTC
 }

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (255157 => 255158)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2020-01-27 19:33:06 UTC (rev 255157)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2020-01-27 19:54:41 UTC (rev 255158)
@@ -907,6 +907,7 @@
 
     WKPreferencesSetHiddenPageDOMTimerThrottlingEnabled(preferences, false);
     WKPreferencesSetHiddenPageCSSAnimationSuspensionEnabled(preferences, false);
+    WKPreferencesSetRenderingUpdateThrottlingEnabled(preferences, false);
 
     WKPreferencesSetAcceleratedDrawingEnabled(preferences, m_shouldUseAcceleratedDrawing || options.useAcceleratedDrawing);
     // FIXME: We should be testing the default.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to