Diff
Modified: trunk/LayoutTests/ChangeLog (261112 => 261113)
--- trunk/LayoutTests/ChangeLog 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/ChangeLog 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,3 +1,31 @@
+2020-05-04 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/request-animation-frame-throttle-inside-overflow-scroll-expected.txt:
+ * fast/animation/request-animation-frame-throttle-inside-overflow-scroll.html:
+ * fast/animation/request-animation-frame-throttle-subframe-display-none-expected.txt:
+ * fast/animation/request-animation-frame-throttle-subframe-display-none.html:
+ * fast/animation/request-animation-frame-throttle-subframe-expected.txt:
+ * fast/animation/request-animation-frame-throttle-subframe-zero-size-expected.txt:
+ * fast/animation/request-animation-frame-throttle-subframe-zero-size.html:
+ * fast/animation/request-animation-frame-throttle-subframe.html:
+ * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt:
+ * fast/animation/request-animation-frame-throttling-detached-iframe.html:
+ Replace the call isRequestAnimationFrameThrottled() by requestAnimationFrameThrottlingReasons().
+
+ * 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.
+
+ * http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe-expected.txt:
+ * http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html:
+ * http/tests/frame-throttling/resources/requestAnimationFrame-frame.html:
+ Replace the call isRequestAnimationFrameThrottled() by requestAnimationFrameThrottlingReasons().
+
2020-05-04 Eric Carlson <[email protected]>
(r261004) platform/mac/media/media-source/media-source-change-source.html is a flaky timeout
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-inside-overflow-scroll-expected.txt (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-inside-overflow-scroll-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-inside-overflow-scroll-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -4,10 +4,10 @@
Frame is initially inside the viewport so requestAnimationFrame should not be throttled
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
Scrolling overflow.
requestAnimationFrame should still not be throttled
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-inside-overflow-scroll.html (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-inside-overflow-scroll.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-inside-overflow-scroll.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -14,7 +14,7 @@
container.scrollLeft = window.innerWidth + 10;
debug("requestAnimationFrame should still not be throttled");
- shouldBeFalse("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
finishJSTest();
}
@@ -23,7 +23,7 @@
{
testFrame = document.getElementById("testFrame");
debug("Frame is initially inside the viewport so requestAnimationFrame should not be throttled");
- shouldBeFalse("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
scrollOverflow();
}
</script>
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-display-none-expected.txt (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-display-none-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-display-none-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -3,7 +3,7 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-display-none.html (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-display-none.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-display-none.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -13,7 +13,7 @@
// Force layout.
document.body.offsetTop;
- shouldBeFalse("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
finishJSTest();
}
</script>
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-expected.txt (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -4,20 +4,20 @@
Frame is initially outside the viewport so requestAnimationFrame should be throttled
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() became true
-PASS internals.isRequestAnimationFrameThrottled() is false
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is true
-PASS grandChildFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is true
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() became "OutsideViewport"
+PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "OutsideViewport"
+PASS grandChildFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "OutsideViewport"
Scrolling frame into view.
RequestAnimationFrame should no longer be throttled
-PASS internals.isRequestAnimationFrameThrottled() is false
-PASS grandChildFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
+PASS grandChildFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
Scrolling frame out of view again.
-PASS internals.isRequestAnimationFrameThrottled() is false
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() became true
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is true
-PASS grandChildFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is true
+PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() became "OutsideViewport"
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "OutsideViewport"
+PASS grandChildFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "OutsideViewport"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-zero-size-expected.txt (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-zero-size-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-zero-size-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -3,7 +3,7 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS testFrame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-zero-size.html (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-zero-size.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe-zero-size.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -13,7 +13,7 @@
// Force layout.
document.body.offsetTop;
- shouldBeFalse("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
finishJSTest();
}
</script>
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttle-subframe.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -8,8 +8,8 @@
function checkSubframesThrottled()
{
- shouldBeTrue("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
- shouldBeTrue("grandChildFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "OutsideViewport");
+ shouldBeEqualToString("grandChildFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "OutsideViewport");
finishJSTest();
}
@@ -19,23 +19,23 @@
debug("Scrolling frame out of view again.");
window.scroll(0, 0);
- shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
- shouldBecomeEqual("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()", "true", checkSubframesThrottled);
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
+ shouldBecomeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "OutsideViewport", checkSubframesThrottled);
}
function scrollFrameIntoView()
{
- shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
- shouldBeTrue("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
- shouldBeTrue("grandChildFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "OutsideViewport");
+ shouldBeEqualToString("grandChildFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "OutsideViewport");
debug("Scrolling frame into view.");
window.internals.scrollElementToRect(testFrame, 0, 0, 300, 300);
debug("RequestAnimationFrame should no longer be throttled");
- shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
- shouldBeFalse("grandChildFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
- shouldBeFalse("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
+ shouldBeEqualToString("grandChildFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
+ shouldBeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
scrollFrameOutOfView();
}
@@ -45,7 +45,7 @@
testFrame = document.getElementById("testFrame");
grandChildFrame = testFrame.contentDocument.getElementById("grandChildFrame");
debug("Frame is initially outside the viewport so requestAnimationFrame should be throttled");
- shouldBecomeEqual("testFrame.contentWindow.internals.isRequestAnimationFrameThrottled()", "true", scrollFrameIntoView);
+ shouldBecomeEqualToString("testFrame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "OutsideViewport", scrollFrameIntoView);
}
var i = 0;
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -3,27 +3,27 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-PASS internals.isRequestAnimationFrameThrottled() is false
+PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS internals.requestAnimationFrameInterval is 0.015
-PASS frame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.015
internals.setLowPowerModeEnabled(true);
-PASS internals.isRequestAnimationFrameThrottled() is true
+PASS internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
PASS internals.requestAnimationFrameInterval is 0.030
-PASS frame.contentWindow.internals.isRequestAnimationFrameThrottled() is true
+PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.030
frame.remove()
document.body.appendChild(frame)
-PASS internals.isRequestAnimationFrameThrottled() is true
+PASS internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
PASS internals.requestAnimationFrameInterval is 0.030
-PASS frame.contentWindow.internals.isRequestAnimationFrameThrottled() is true
+PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.030
frame.remove()
internals.setLowPowerModeEnabled(false);
-PASS internals.isRequestAnimationFrameThrottled() is false
+PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS internals.requestAnimationFrameInterval is 0.015
document.body.appendChild(frame)
-PASS frame.contentWindow.internals.isRequestAnimationFrameThrottled() is false
+PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.015
PASS successfullyParsed is true
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-detached-iframe.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -18,33 +18,33 @@
const frame = document.createElement("iframe");
frame.src = ""
frame._onload_ = function() {
- shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
shouldBe("internals.requestAnimationFrameInterval", "0.015");
- shouldBeFalse("frame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("frame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
shouldBe("frame.contentWindow.internals.requestAnimationFrameInterval", "0.015");
evalAndLog("internals.setLowPowerModeEnabled(true);");
- shouldBeTrue("internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "LowPowerMode");
shouldBe("internals.requestAnimationFrameInterval", "0.030");
- shouldBeTrue("frame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("frame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "LowPowerMode");
shouldBe("frame.contentWindow.internals.requestAnimationFrameInterval", "0.030");
evalAndLog("frame.remove()");
evalAndLog("document.body.appendChild(frame)");
frame._onload_ = function() {
- shouldBeTrue("internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "LowPowerMode");
shouldBe("internals.requestAnimationFrameInterval", "0.030");
- shouldBeTrue("frame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("frame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "LowPowerMode");
shouldBe("frame.contentWindow.internals.requestAnimationFrameInterval", "0.030");
evalAndLog("frame.remove()");
evalAndLog("internals.setLowPowerModeEnabled(false);");
- shouldBeFalse("internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
shouldBe("internals.requestAnimationFrameInterval", "0.015");
evalAndLog("document.body.appendChild(frame)");
frame._onload_ = function() {
- shouldBeFalse("frame.contentWindow.internals.isRequestAnimationFrameThrottled()");
+ shouldBeEqualToString("frame.contentWindow.internals.requestAnimationFrameThrottlingReasons()", "[Unthrottled]");
shouldBe("frame.contentWindow.internals.requestAnimationFrameInterval", "0.015");
finishJSTest();
}
Modified: trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/fast/animation/request-animation-frame-throttling-lowPowerMode.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,36 +1,31 @@
<!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.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>
Modified: trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe-expected.txt (261112 => 261113)
--- trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe-expected.txt 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe-expected.txt 2020-05-04 21:24:49 UTC (rev 261113)
@@ -6,16 +6,16 @@
Received message: frameload
Received message: frameload
Checking that requestAnimationFrame is throttled in cross origin frame
-Received message: throttled[cross]: true
-Received message: throttled[same]: false
-PASS throttledState['cross'] is "true"
-PASS throttledState['same'] is "false"
+Received message: throttled[cross]: NonInteractiveCrossOriginFrame
+Received message: throttled[same]: [Unthrottled]
+PASS throttledState['cross'] is "NonInteractiveCrossOriginFrame"
+PASS throttledState['same'] is "[Unthrottled]"
Interacted with cross-origin frame
Interacted with same-origin frame
-Received message: throttled[cross]: false
-Received message: throttled[same]: false
-PASS throttledState['cross'] is "false"
-PASS throttledState['same'] is "false"
+Received message: throttled[cross]: [Unthrottled]
+Received message: throttled[same]: [Unthrottled]
+PASS throttledState['cross'] is "[Unthrottled]"
+PASS throttledState['same'] is "[Unthrottled]"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html (261112 => 261113)
--- trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/http/tests/frame-throttling/raf-throttle-in-cross-origin-subframe.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -54,15 +54,15 @@
function checkInitiallyThrottled()
{
- shouldBeEqualToString("throttledState['cross']", "true");
- shouldBeEqualToString("throttledState['same']", "false");
+ shouldBeEqualToString("throttledState['cross']", "NonInteractiveCrossOriginFrame");
+ shouldBeEqualToString("throttledState['same']", "[Unthrottled]");
interactWithSubframes();
}
function checkUnthrottledAfterInteraction()
{
- shouldBeEqualToString("throttledState['cross']", "false");
- shouldBeEqualToString("throttledState['same']", "false");
+ shouldBeEqualToString("throttledState['cross']", "[Unthrottled]");
+ shouldBeEqualToString("throttledState['same']", "[Unthrottled]");
finishJSTest();
}
@@ -75,7 +75,7 @@
return;
}
- var re = /throttled\[(\w+)\]: (true|false)/;
+ var re = /throttled\[(\w+)\]: ((\w+)(\|\w+)*|\[Unthrottled\])/;
var match = re.exec(message.data);
if (match) {
frameID = match[1];
Modified: trunk/LayoutTests/http/tests/frame-throttling/resources/requestAnimationFrame-frame.html (261112 => 261113)
--- trunk/LayoutTests/http/tests/frame-throttling/resources/requestAnimationFrame-frame.html 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/LayoutTests/http/tests/frame-throttling/resources/requestAnimationFrame-frame.html 2020-05-04 21:24:49 UTC (rev 261113)
@@ -18,7 +18,7 @@
if (match) {
var frameId = match[1];
if (window.internals)
- parent.window.postMessage("throttled[" + frameId + "]: " + internals.isRequestAnimationFrameThrottled(), "*");
+ parent.window.postMessage("throttled[" + frameId + "]: " + internals.requestAnimationFrameThrottlingReasons(), "*");
}
}
Modified: trunk/Source/WebCore/ChangeLog (261112 => 261113)
--- trunk/Source/WebCore/ChangeLog 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/ChangeLog 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,3 +1,162 @@
+2020-05-04 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.
+
+ rAF and Page rendering were managed by two different timers. Throttling
+ rAF was implemented by changing its timer. After r242624, RenderingUpdate
+ steps have been managed by RenderingUpdateScheduler. This means rAF is
+ now serviced by the preferredFramesPerSecond which is 60 fps regardless
+ it's throttled or not. Moreover the rAF throttling timer was mistakenly
+ kept and it has been running under the old assumption which is: rAF is
+ serviced by a timer only. This means rAF will be serviced by its timer
+ and by the RenderingUpdate steps at the same time when it is supposed to
+ throttle. This will make it fire more than 60 fps in cases which it is
+ supposed to run less than 60 fps.
+
+ The solution is to have two throttling types:
+
+ 1) Page throttling (or full throttling): This slows down all the steps
+ of RenderingUpdate for the main document and all the sub-documents.
+ Page throttling reasons are:
+ -- VisuallyIdle: Aggressive throttling.
+ -- LowPowerMode: Half speed throttling.
+ 2) Document throttling (or partial throttling): This only slows down the
+ rAF of a certain document. Document throttling reasons are:
+ -- OutsideViewport: Aggressive throttling.
+ -- NonInteractedCrossOriginFrame: Half speed throttling.
+
+ RenderingUpdate steps will still be managed by RenderingUpdateScheduler
+ which can be throttled. The assumption is none of these steps will need
+ to run faster than the Page preferredFramesPerSecond. If rAF wants to
+ run slower than the Page because of a Document throttling reason, no rAF
+ callbacks will be serviced before its preferredFrameInterval has elapsed.
+
+ In this patch, "Half speed throttling" is only implemented for the Page
+ and the Document throttling. The "Aggressive throttling" will be done in
+ following patches. Page rendering was never throttled before. We need to
+ make sure this is not going to affect PLT. Some tests need to be changed
+ and new tests need to be written. All of the throttling tests checks the
+ state of the code but none of them checks the real user's experience.
+
+ * 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
+ from the Document.
+
+ * dom/ScriptedAnimationController.cpp:
+ (WebCore::ScriptedAnimationController::ScriptedAnimationController):
+ (WebCore::ScriptedAnimationController::page const):
+ (WebCore::ScriptedAnimationController::interval const):
+ (WebCore::ScriptedAnimationController::preferredScriptedAnimationInterval const):
+ (WebCore::ScriptedAnimationController::throttlingReasons 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::isThrottled const): 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::m_loadsFromNetwork):
+ (WebCore::Page::setLowPowerModeEnabledOverrideForTesting):
+
+ (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::Page::isLowPowerModeEnabled const): Deleted.
+ (WebCore::updateScriptedAnimationsThrottlingReason): Deleted.
+ * page/Page.h:
+ (WebCore::Page::isLowPowerModeEnabled const):
+ (WebCore::Page::throttlingReasons const):
+ (WebCore::Page::canUpdateThrottlingReason const):
+
+ * page/RenderingUpdateScheduler.cpp:
+ (WebCore::RenderingUpdateScheduler::setPreferredFramesPerSecond):
+ (WebCore::RenderingUpdateScheduler::scheduleAnimation):
+ (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:
+ * platform/graphics/AnimationFrameRate.h: Added.
+ (WebCore::preferredFrameInterval):
+ (WebCore::preferredFramesPerSecond):
+ (WebCore::operator<<):
+ Push names of ThrottlingReasons to a TextStream.
+
+ * 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.
+
+ * testing/Internals.cpp:
+ (WebCore::Internals::requestAnimationFrameThrottlingReasons const):
+ (WebCore::Internals::isRequestAnimationFrameThrottled const): Deleted.
+ * testing/Internals.h:
+ * testing/Internals.idl:
+ Replace isRequestAnimationFrameThrottled() which returns a boolean by
+ requestAnimationFrameThrottlingReasons() which returns a string. The
+ string represents the throttling reasons.
+
2020-05-04 Darin Adler <[email protected]>
Remove unneeded USE(MEDIAREMOTE)
Modified: trunk/Source/WebCore/Headers.cmake (261112 => 261113)
--- trunk/Source/WebCore/Headers.cmake 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/Headers.cmake 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1072,6 +1072,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 (261112 => 261113)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-05-04 21:24:49 UTC (rev 261113)
@@ -2155,6 +2155,7 @@
727A7F3A24078B84004D2931 /* ImageBufferIOSurfaceBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 72BAC3AB23E1E544008D741C /* ImageBufferIOSurfaceBackend.h */; settings = {ATTRIBUTES = (Private, ); }; };
7299BC6723D6A53200CC6883 /* AlphaPremultiplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 7299BC6423D686A600CC6883 /* AlphaPremultiplication.h */; settings = {ATTRIBUTES = (Private, ); }; };
7299BC6823D6A53E00CC6883 /* RenderingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7299BC6623D686C600CC6883 /* RenderingMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 72A73BEF245A3F90001C9D03 /* AnimationFrameRate.h in Headers */ = {isa = PBXBuildFile; fileRef = 722A815C238FD50500C00583 /* AnimationFrameRate.h */; settings = {ATTRIBUTES = (Private, ); }; };
72BAC3AE23E1F0B0008D741C /* ImageBufferBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 72BAC3A523E17328008D741C /* ImageBufferBackend.h */; settings = {ATTRIBUTES = (Private, ); }; };
7553CFE8108F473F00EA281E /* TimelineRecordFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 7553CFE6108F473F00EA281E /* TimelineRecordFactory.h */; };
75793E840D0CE0B3007FC0AC /* MessageEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 75793E810D0CE0B3007FC0AC /* MessageEvent.h */; };
@@ -9713,6 +9714,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>"; };
@@ -25324,6 +25326,7 @@
7299BC6423D686A600CC6883 /* AlphaPremultiplication.h */,
490707E41219C04300D90E51 /* ANGLEWebKitBridge.cpp */,
490707E51219C04300D90E51 /* ANGLEWebKitBridge.h */,
+ 722A815C238FD50500C00583 /* AnimationFrameRate.h */,
BEF29EE91715DD0900C4B4C9 /* AudioTrackPrivate.h */,
A89943270B42338700D7C802 /* BitmapImage.cpp */,
A89943260B42338700D7C802 /* BitmapImage.h */,
@@ -29514,6 +29517,7 @@
71E2C42621C935280024F8C8 /* AnimationEffectPhase.h in Headers */,
319848011A1D817B00A13318 /* AnimationEvent.h in Headers */,
711AD126236D86E5006FF37C /* AnimationEventBase.h in Headers */,
+ 72A73BEF245A3F90001C9D03 /* 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 (261112 => 261113)
--- trunk/Source/WebCore/animation/DocumentTimeline.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -46,9 +46,6 @@
#include "Settings.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)
@@ -214,16 +211,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 (261112 => 261113)
--- trunk/Source/WebCore/animation/DocumentTimeline.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/animation/DocumentTimeline.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -80,7 +80,6 @@
AnimationEvents prepareForPendingAnimationEventsDispatch();
void documentDidUpdateAnimationsAndSendEvents();
- void updateThrottlingState();
WEBCORE_EXPORT Seconds animationInterval() const;
WEBCORE_EXPORT void suspendAnimations();
WEBCORE_EXPORT void resumeAnimations();
Modified: trunk/Source/WebCore/dom/Document.cpp (261112 => 261113)
--- trunk/Source/WebCore/dom/Document.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/dom/Document.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -6553,11 +6553,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));
@@ -6796,7 +6793,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 (261112 => 261113)
--- trunk/Source/WebCore/dom/ScriptedAnimationController.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2020 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,39 +27,18 @@
#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 "Performance.h"
#include "Quirks.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)
{
}
@@ -85,112 +65,70 @@
scheduleAnimation();
}
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) && !RELEASE_LOG_DISABLED
-
-static const char* throttlingReasonToString(ScriptedAnimationController::ThrottlingReason reason)
+Page* ScriptedAnimationController::page() 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";
- }
- RELEASE_ASSERT_NOT_REACHED();
- return "";
+ return m_document ? m_document->page() : nullptr;
}
-static String throttlingReasonsToString(OptionSet<ScriptedAnimationController::ThrottlingReason> reasons)
+Seconds ScriptedAnimationController::interval() 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 std::max(preferredScriptedAnimationInterval(), page->preferredRenderingUpdateInterval());
+ return FullSpeedAnimationInterval;
}
-#endif
-
-void ScriptedAnimationController::addThrottlingReason(ThrottlingReason reason)
+Seconds ScriptedAnimationController::preferredScriptedAnimationInterval() 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
+ if (auto* page = this->page())
+ return preferredFrameInterval(m_throttlingReasons);
+ return FullSpeedAnimationInterval;
}
-void ScriptedAnimationController::removeThrottlingReason(ThrottlingReason reason)
+OptionSet<ThrottlingReason> ScriptedAnimationController::throttlingReasons() const
{
-#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
+ if (auto* page = this->page())
+ return page->throttlingReasons() | m_throttlingReasons;
+ return { };
}
-bool ScriptedAnimationController::isThrottled() const
+bool ScriptedAnimationController::isThrottledRelativeToPage() const
{
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
- return !m_throttlingReasons.isEmpty();
-#else
+ if (auto* page = this->page())
+ return preferredScriptedAnimationInterval() > page->preferredRenderingUpdateInterval();
return false;
-#endif
}
+bool ScriptedAnimationController::shouldRescheduleRequestAnimationFrame(ReducedResolutionSeconds timestamp) const
+{
+ return isThrottledRelativeToPage() && (timestamp - m_lastAnimationFrameTimestamp < preferredScriptedAnimationInterval());
+}
+
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([callbackId](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(ReducedResolutionSeconds timestamp)
@@ -198,6 +136,11 @@
if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
return;
+ if (shouldRescheduleRequestAnimationFrame(timestamp)) {
+ scheduleAnimation();
+ return;
+ }
+
TraceScope tracingScope(RAFCallbackStart, RAFCallbackEnd);
auto highResNowMs = std::round(1000 * timestamp.seconds());
@@ -228,72 +171,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 - (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 (261112 => 261113)
--- trunk/Source/WebCore/dom/ScriptedAnimationController.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/dom/ScriptedAnimationController.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All Rights Reserved.
+ * Copyright (C) 2020 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,7 +26,7 @@
#pragma once
-#include "DOMHighResTimeStamp.h"
+#include "AnimationFrameRate.h"
#include "ReducedResolutionSeconds.h"
#include "Timer.h"
#include <wtf/OptionSet.h>
@@ -50,36 +51,30 @@
void clearDocumentPointer() { m_document = nullptr; }
bool requestAnimationFrameEnabled() const;
- typedef int CallbackId;
+ WEBCORE_EXPORT Seconds interval() const;
+ WEBCORE_EXPORT OptionSet<ThrottlingReason> throttlingReasons() const;
- CallbackId registerCallback(Ref<RequestAnimationFrameCallback>&&);
- void cancelCallback(CallbackId);
- void serviceRequestAnimationFrameCallbacks(ReducedResolutionSeconds);
-
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;
+ using CallbackId = int;
+ CallbackId registerCallback(Ref<RequestAnimationFrameCallback>&&);
+ void cancelCallback(CallbackId);
+ void serviceRequestAnimationFrameCallbacks(ReducedResolutionSeconds);
private:
ScriptedAnimationController(Document&);
+ Page* page() const;
+ Seconds preferredScriptedAnimationInterval() const;
+ bool isThrottledRelativeToPage() const;
+ bool shouldRescheduleRequestAnimationFrame(ReducedResolutionSeconds) const;
void scheduleAnimation();
- void animationTimerFired();
- Page* page() const;
-
- typedef Vector<RefPtr<RequestAnimationFrameCallback>> CallbackList;
+ using CallbackList = Vector<RefPtr<RequestAnimationFrameCallback>>;
CallbackList m_callbacks;
WeakPtr<Document> m_document;
@@ -86,13 +81,8 @@
CallbackId m_nextCallbackId { 0 };
int m_suspendCount { 0 };
- Timer m_animationTimer;
- ReducedResolutionSeconds m_lastAnimationFrameTimestamp { 0 };
-
-#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ ReducedResolutionSeconds m_lastAnimationFrameTimestamp;
OptionSet<ThrottlingReason> m_throttlingReasons;
- bool m_isUsingTimer { false };
-#endif
};
} // namespace WebCore
Modified: trunk/Source/WebCore/page/FrameView.cpp (261112 => 261113)
--- trunk/Source/WebCore/page/FrameView.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/page/FrameView.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -2530,9 +2530,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 (261112 => 261113)
--- trunk/Source/WebCore/page/Page.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/page/Page.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -22,6 +22,7 @@
#include "ActivityStateChangeObserver.h"
#include "AlternativeTextClient.h"
+#include "AnimationFrameRate.h"
#include "ApplicationCacheStorage.h"
#include "AuthenticatorCoordinator.h"
#include "BackForwardCache.h"
@@ -333,9 +334,12 @@
#if USE(LIBWEBRTC)
m_libWebRTCProvider->supportsH265(RuntimeEnabledFeatures::sharedFeatures().webRTCH265CodecEnabled());
#endif
-
+
if (!pageConfiguration.userScriptsShouldWaitUntilNotification)
m_hasBeenNotifiedToInjectUserScripts = true;
+
+ if (m_lowPowerModeNotifier->isLowPowerModeEnabled())
+ m_throttlingReasons.add(ThrottlingReason::LowPowerMode);
}
Page::~Page()
@@ -1170,18 +1174,20 @@
return !isUtilityPage() && nonUtilityPageCount == 1;
}
-bool Page::isLowPowerModeEnabled() const
+void Page::setLowPowerModeEnabledOverrideForTesting(Optional<bool> isEnabled)
{
- if (m_lowPowerModeEnabledOverrideForTesting)
- return m_lowPowerModeEnabledOverrideForTesting.value();
+ // Remove ThrottlingReason::LowPowerMode so handleLowModePowerChange() can do its work.
+ m_throttlingReasonsOverridenForTesting.remove(ThrottlingReason::LowPowerMode);
- return m_lowPowerModeNotifier->isLowPowerModeEnabled();
-}
+ // Use the current low power mode value of the device.
+ if (!isEnabled) {
+ handleLowModePowerChange(m_lowPowerModeNotifier->isLowPowerModeEnabled());
+ return;
+ }
-void Page::setLowPowerModeEnabledOverrideForTesting(Optional<bool> isEnabled)
-{
- m_lowPowerModeEnabledOverrideForTesting = isEnabled;
- handleLowModePowerChange(m_lowPowerModeEnabledOverrideForTesting.valueOr(false));
+ // Override the value and add ThrottlingReason::LowPowerMode so it override the device state.
+ handleLowModePowerChange(isEnabled.value());
+ m_throttlingReasonsOverridenForTesting.add(ThrottlingReason::LowPowerMode);
}
void Page::setTopContentInset(float contentInset)
@@ -1474,34 +1480,34 @@
});
}
-enum class ThrottlingReasonOperation { Add, Remove };
-static void updateScriptedAnimationsThrottlingReason(Page& page, ThrottlingReasonOperation operation, ScriptedAnimationController::ThrottlingReason reason)
+Seconds Page::preferredRenderingUpdateInterval() const
{
- page.forEachDocument([&] (Document& document) {
- if (auto* controller = document.scriptedAnimationController()) {
- if (operation == ThrottlingReasonOperation::Add)
- controller->addThrottlingReason(reason);
- else
- controller->removeThrottlingReason(reason);
- }
- });
+ return preferredFrameInterval(m_throttlingReasons);
}
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;
+ 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 (!canUpdateThrottlingReason(ThrottlingReason::LowPowerMode))
+ return;
+
+ if (isLowPowerModeEnabled == m_throttlingReasons.contains(ThrottlingReason::LowPowerMode))
+ return;
+
+ m_throttlingReasons = m_throttlingReasons ^ ThrottlingReason::LowPowerMode;
+ renderingUpdateScheduler().adjustRenderingUpdateFrequency();
+
+ if (!RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
mainFrame().legacyAnimation().updateThrottlingState();
+
updateDOMTimerAlignmentInterval();
}
Modified: trunk/Source/WebCore/page/Page.h (261112 => 261113)
--- trunk/Source/WebCore/page/Page.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/page/Page.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -21,6 +21,7 @@
#pragma once
#include "ActivityState.h"
+#include "AnimationFrameRate.h"
#include "DisabledAdaptations.h"
#include "Document.h"
#include "FindOptions.h"
@@ -720,9 +721,12 @@
bool loadsSubresources() const { return m_loadsSubresources; }
bool loadsFromNetwork() const { return m_loadsFromNetwork; }
- bool isLowPowerModeEnabled() const;
+ bool isLowPowerModeEnabled() const { return m_throttlingReasons.contains(ThrottlingReason::LowPowerMode); }
WEBCORE_EXPORT void setLowPowerModeEnabledOverrideForTesting(Optional<bool>);
+ OptionSet<ThrottlingReason> throttlingReasons() const { return m_throttlingReasons; }
+ Seconds preferredRenderingUpdateInterval() const;
+
WEBCORE_EXPORT void applicationWillResignActive();
WEBCORE_EXPORT void applicationDidEnterBackground();
WEBCORE_EXPORT void applicationWillEnterForeground();
@@ -790,6 +794,8 @@
void updateDOMTimerAlignmentInterval();
void domTimerAlignmentIntervalIncreaseTimerFired();
+ bool canUpdateThrottlingReason(ThrottlingReason reason) const { return !m_throttlingReasonsOverridenForTesting.contains(reason); }
+
void doAfterUpdateRendering();
WheelEventTestMonitor& ensureWheelEventTestMonitor();
@@ -1000,7 +1006,8 @@
std::unique_ptr<PerformanceMonitor> m_performanceMonitor;
std::unique_ptr<LowPowerModeNotifier> m_lowPowerModeNotifier;
- Optional<bool> m_lowPowerModeEnabledOverrideForTesting;
+ OptionSet<ThrottlingReason> m_throttlingReasons;
+ OptionSet<ThrottlingReason> m_throttlingReasonsOverridenForTesting;
Optional<Navigation> m_navigationToLogWhenVisible;
Modified: trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp (261112 => 261113)
--- trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,6 +42,45 @@
#endif
}
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+void RenderingUpdateScheduler::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+{
+ if (m_preferredFramesPerSecond == preferredFramesPerSecond)
+ return;
+
+ m_preferredFramesPerSecond = preferredFramesPerSecond;
+ DisplayRefreshMonitorManager::sharedManager().setPreferredFramesPerSecond(*this, m_preferredFramesPerSecond);
+}
+
+bool RenderingUpdateScheduler::scheduleAnimation(FramesPerSecond preferredFramesPerSecond)
+{
+#if !PLATFORM(IOS_FAMILY)
+ // PreferredFramesPerSecond can only be changed for iOS DisplayRefreshMonitor.
+ // The caller has to fall back to using the timer.
+ if (preferredFramesPerSecond != FullSpeedFramesPerSecond)
+ return false;
+#endif
+ setPreferredFramesPerSecond(preferredFramesPerSecond);
+ return DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
+}
+#endif
+
+void RenderingUpdateScheduler::adjustRenderingUpdateFrequency()
+{
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ Seconds interval = m_page.preferredRenderingUpdateInterval();
+
+ // PreferredFramesPerSecond is an integer and should be > 0.
+ if (interval <= 1_s)
+ setPreferredFramesPerSecond(preferredFramesPerSecond(interval));
+#endif
+ if (isScheduled()) {
+ clearScheduled();
+ scheduleTimedRenderingUpdate();
+ }
+}
+
void RenderingUpdateScheduler::scheduleTimedRenderingUpdate()
{
if (isScheduled())
@@ -55,12 +94,16 @@
tracePoint(ScheduleRenderingUpdate);
+ Seconds interval = m_page.preferredRenderingUpdateInterval();
+
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
- if (!DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this))
+ // PreferredFramesPerSecond is an integer and should be > 0.
+ if (interval <= 1_s)
+ m_scheduled = scheduleAnimation(preferredFramesPerSecond(interval));
#endif
- startTimer(Seconds(1.0 / 60));
- m_scheduled = true;
+ if (!isScheduled())
+ startTimer(interval);
}
bool RenderingUpdateScheduler::isScheduled() const
@@ -74,6 +117,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 (261112 => 261113)
--- trunk/Source/WebCore/page/RenderingUpdateScheduler.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/page/RenderingUpdateScheduler.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2019-2020 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,6 +25,7 @@
#pragma once
+#include "AnimationFrameRate.h"
#include "DisplayRefreshMonitorClient.h"
#include <wtf/Seconds.h>
@@ -46,6 +47,8 @@
}
RenderingUpdateScheduler(Page&);
+
+ void adjustRenderingUpdateFrequency();
void scheduleTimedRenderingUpdate();
void scheduleImmediateRenderingUpdate();
void scheduleRenderingUpdate();
@@ -56,6 +59,8 @@
private:
#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ void setPreferredFramesPerSecond(FramesPerSecond);
+ bool scheduleAnimation(FramesPerSecond);
RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const final;
void displayRefreshFired() final;
#else
@@ -69,6 +74,9 @@
Page& m_page;
bool m_scheduled { false };
std::unique_ptr<Timer> m_refreshTimer;
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+ FramesPerSecond m_preferredFramesPerSecond { FullSpeedFramesPerSecond };
+#endif
};
}
Added: trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h (0 => 261113)
--- trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h (rev 0)
+++ trunk/Source/WebCore/platform/graphics/AnimationFrameRate.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 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>
+#include <wtf/text/TextStream.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>& reasons)
+{
+ // FIXME: handle ThrottlingReason::VisuallyIdle, ThrottlingReason::OutsideViewport
+ if (reasons.containsAny({ ThrottlingReason::LowPowerMode, ThrottlingReason::NonInteractedCrossOriginFrame }))
+ return HalfSpeedThrottlingAnimationInterval;
+
+ return FullSpeedAnimationInterval;
+}
+
+inline FramesPerSecond preferredFramesPerSecond(Seconds preferredFrameInterval)
+{
+ if (preferredFrameInterval == FullSpeedAnimationInterval)
+ return FullSpeedFramesPerSecond;
+
+ if (preferredFrameInterval == HalfSpeedThrottlingAnimationInterval)
+ return HalfSpeedThrottlingFramesPerSecond;
+
+ ASSERT_NOT_REACHED();
+ return ZeroFramesPerSecond;
+}
+
+inline TextStream& operator<<(TextStream& ts, const OptionSet<ThrottlingReason>& reasons)
+{
+ StringBuilder builder;
+ for (auto reason : reasons) {
+ if (!builder.isEmpty())
+ ts << "|";
+
+ switch (reason) {
+ case ThrottlingReason::VisuallyIdle:
+ ts << "VisuallyIdle";
+ break;
+ case ThrottlingReason::OutsideViewport:
+ ts << "OutsideViewport";
+ break;
+ case ThrottlingReason::LowPowerMode:
+ ts << "LowPowerMode";
+ break;
+ case ThrottlingReason::NonInteractedCrossOriginFrame:
+ ts << "NonInteractiveCrossOriginFrame";
+ break;
+ }
+ }
+ if (reasons.isEmpty())
+ ts << "[Unthrottled]";
+ return ts;
+}
+
+}
Modified: trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h (261112 => 261113)
--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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/testing/Internals.cpp (261112 => 261113)
--- trunk/Source/WebCore/testing/Internals.cpp 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/testing/Internals.cpp 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1387,12 +1387,15 @@
return !!timer->alignedFireTime(MonotonicTime { });
}
-bool Internals::isRequestAnimationFrameThrottled() const
+String Internals::requestAnimationFrameThrottlingReasons() const
{
auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
if (!scriptedAnimationController)
- return false;
- return scriptedAnimationController->isThrottled();
+ return String();
+
+ TextStream ts;
+ ts << scriptedAnimationController->throttlingReasons();
+ return ts.release();
}
double Internals::requestAnimationFrameInterval() const
Modified: trunk/Source/WebCore/testing/Internals.h (261112 => 261113)
--- trunk/Source/WebCore/testing/Internals.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/testing/Internals.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -205,7 +205,7 @@
// DOMTimers throttling testing.
ExceptionOr<bool> isTimerThrottled(int timeoutId);
- bool isRequestAnimationFrameThrottled() const;
+ String requestAnimationFrameThrottlingReasons() const;
double requestAnimationFrameInterval() const;
bool scriptedAnimationsAreSuspended() const;
bool areTimersThrottled() const;
Modified: trunk/Source/WebCore/testing/Internals.idl (261112 => 261113)
--- trunk/Source/WebCore/testing/Internals.idl 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebCore/testing/Internals.idl 2020-05-04 21:24:49 UTC (rev 261113)
@@ -557,7 +557,7 @@
// Query if a timer is currently throttled, to debug timer throttling.
[MayThrowException] boolean isTimerThrottled(long timerHandle);
- boolean isRequestAnimationFrameThrottled();
+ DOMString requestAnimationFrameThrottlingReasons();
boolean areTimersThrottled();
[MayThrowException] void setLowPowerModeEnabled(boolean enabled);
Modified: trunk/Source/WebKit/ChangeLog (261112 => 261113)
--- trunk/Source/WebKit/ChangeLog 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/ChangeLog 2020-05-04 21:24:49 UTC (rev 261113)
@@ -1,3 +1,31 @@
+2020-05-04 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.
+
+ * 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):
+ Forward 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-05-04 Alex Christensen <[email protected]>
TestWebKitAPI.WebKit.CustomDisplayName is a flaky timeout
Modified: trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h (261112 => 261113)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.messages.in 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDisplayRefreshMonitor.mm 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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 (261112 => 261113)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.h 2020-05-04 21:24:49 UTC (rev 261113)
@@ -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>
@@ -72,6 +73,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 (261112 => 261113)
--- trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm 2020-05-04 21:04:23 UTC (rev 261112)
+++ trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm 2020-05-04 21:24:49 UTC (rev 261113)
@@ -126,6 +126,11 @@
}
}
+void RemoteLayerTreeDrawingArea::setPreferredFramesPerSecond(FramesPerSecond preferredFramesPerSecond)
+{
+ send(Messages::RemoteLayerTreeDrawingAreaProxy::SetPreferredFramesPerSecond(preferredFramesPerSecond));
+}
+
void RemoteLayerTreeDrawingArea::updateRootLayers()
{
Vector<Ref<GraphicsLayer>> children;