Title: [255131] trunk
Revision
255131
Author
[email protected]
Date
2020-01-26 13:35:32 -0800 (Sun, 26 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-26
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.

* platform/ios/LowPowerModeNotifierIOS.mm:
(-[WebLowPowerModeObserver initWithNotifier:]):
Set the initial state of the low power mode.

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 (255130 => 255131)


--- trunk/LayoutTests/ChangeLog	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/ChangeLog	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1,3 +1,27 @@
+2020-01-26  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-26  Eric Carlson  <[email protected]>
 
         media/modern-media-controls/media-controller/media-controller-auto-hide.html is flaky timing out

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


--- trunk/LayoutTests/fast/animation/css-animation-throttling-lowPowerMode.html	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/fast/animation/css-animation-throttling-lowPowerMode.html	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 => 255131)


--- 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-26 21:35:32 UTC (rev 255131)
@@ -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 => 255131)


--- 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-26 21:35:32 UTC (rev 255131)
@@ -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 => 255131)


--- trunk/LayoutTests/fast/animation/resources/frame-with-animation-2.html	                        (rev 0)
+++ trunk/LayoutTests/fast/animation/resources/frame-with-animation-2.html	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/ChangeLog	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/ChangeLog	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1,3 +1,134 @@
+2020-01-26  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.
+
+        * platform/ios/LowPowerModeNotifierIOS.mm:
+        (-[WebLowPowerModeObserver initWithNotifier:]):
+        Set the initial state of the low power mode.
+
 2020-01-26  Rob Buis  <[email protected]>
 
         Improve compatibility with hyperlink auditing spec

Modified: trunk/Source/WebCore/Headers.cmake (255130 => 255131)


--- trunk/Source/WebCore/Headers.cmake	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/Headers.cmake	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1034,6 +1034,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 (255130 => 255131)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-01-26 21:35:32 UTC (rev 255131)
@@ -2141,6 +2141,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, ); }; };
@@ -9631,6 +9632,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>"; };
@@ -25040,6 +25042,7 @@
 				7299BC6423D686A600CC6883 /* AlphaPremultiplication.h */,
 				490707E41219C04300D90E51 /* ANGLEWebKitBridge.cpp */,
 				490707E51219C04300D90E51 /* ANGLEWebKitBridge.h */,
+				722A815C238FD50500C00583 /* AnimationFrameRate.h */,
 				BEF29EE91715DD0900C4B4C9 /* AudioTrackPrivate.h */,
 				A89943270B42338700D7C802 /* BitmapImage.cpp */,
 				A89943260B42338700D7C802 /* BitmapImage.h */,
@@ -29086,6 +29089,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 (255130 => 255131)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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)
@@ -192,16 +189,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 (255130 => 255131)


--- trunk/Source/WebCore/animation/DocumentTimeline.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/animation/DocumentTimeline.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -73,7 +73,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 (255130 => 255131)


--- trunk/Source/WebCore/dom/Document.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/dom/Document.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -6499,11 +6499,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));
@@ -6742,7 +6739,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 (255130 => 255131)


--- trunk/Source/WebCore/dom/ScriptedAnimationController.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/dom/ScriptedAnimationController.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/FrameView.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/FrameView.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/Page.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/Page.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/Page.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/Page.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/RenderingUpdateScheduler.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/Settings.yaml	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/Settings.yaml	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/SettingsBase.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/SettingsBase.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/page/SettingsBase.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/page/SettingsBase.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 => 255131)


--- trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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/WebCore/platform/ios/LowPowerModeNotifierIOS.mm (255130 => 255131)


--- trunk/Source/WebCore/platform/ios/LowPowerModeNotifierIOS.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebCore/platform/ios/LowPowerModeNotifierIOS.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -48,8 +48,9 @@
         return nil;
 
     _notifier = &notifier;
-    _isLowPowerModeEnabled = [NSProcessInfo processInfo].lowPowerModeEnabled;
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didReceiveLowPowerModeChange) name:NSProcessInfoPowerStateDidChangeNotification object:nil];
+    // Set the initial state of the low power mode.
+    [self _didReceiveLowPowerModeChange];
     return self;
 }
 

Modified: trunk/Source/WebKit/ChangeLog (255130 => 255131)


--- trunk/Source/WebKit/ChangeLog	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/ChangeLog	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1,3 +1,39 @@
+2020-01-26  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-25  Brady Eidson  <[email protected]>
 
         Make ContentWorlds be identified by an ObjectIdentifier instead of a uint64_t

Modified: trunk/Source/WebKit/Shared/WebPreferences.yaml (255130 => 255131)


--- trunk/Source/WebKit/Shared/WebPreferences.yaml	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/Shared/WebPreferences.yaml	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferences.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPreferencesRefPrivate.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1,3 +1,21 @@
+2020-01-26  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-25  Antti Koivisto  <[email protected]>
 
         [LFC][Integration] Re-enable line layout integration

Modified: trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h (255130 => 255131)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/mac/WebView/WebView.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/win/ChangeLog	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/win/ChangeLog	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1,3 +1,22 @@
+2020-01-26  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-21  Sihui Liu  <[email protected]>
 
         Disable WebSQL everywhere by default except in tests

Modified: trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl (255130 => 255131)


--- trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -224,3 +224,5 @@
 #define WebKitAspectRatioOfImgFromWidthAndHeightEnabledPreferenceKey "WebKitAspectRatioOfImgFromWidthAndHeightEnabled"
 
 #define WebKitWebSQLEnabledPreferenceKey "WebKitWebSQLEnabled"
+
+#define WebKitRenderingUpdateThrottlingEnabledPreferenceKey "WebKitRenderingUpdateThrottlingEnabled"

Modified: trunk/Source/WebKitLegacy/win/WebPreferences.cpp (255130 => 255131)


--- trunk/Source/WebKitLegacy/win/WebPreferences.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/win/WebPreferences.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/win/WebPreferences.h	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/win/WebPreferences.h	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Source/WebKitLegacy/win/WebView.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Source/WebKitLegacy/win/WebView.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Tools/ChangeLog	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Tools/ChangeLog	2020-01-26 21:35:32 UTC (rev 255131)
@@ -1,3 +1,21 @@
+2020-01-26  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-25  Mark Lam  <[email protected]>
 
         Add some tests for dynamically allocated StaticStringImpls.

Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm (255130 => 255131)


--- trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Tools/DumpRenderTree/win/DumpRenderTree.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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 (255130 => 255131)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2020-01-26 21:11:08 UTC (rev 255130)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2020-01-26 21:35:32 UTC (rev 255131)
@@ -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