haikuwebkit/LayoutTests/fast/animation/request-animation-frame-thr...

32 lines
1.6 KiB
Plaintext
Raw Permalink Normal View History

[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
Test that requestAnimationFrame gets the right throttling in an iframe when inserted into a document.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS internals.requestAnimationFrameInterval is 0.015
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.015
internals.setLowPowerModeEnabled(true);
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS internals.requestAnimationFrameInterval is 0.030
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.030
frame.remove()
document.body.appendChild(frame)
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS internals.requestAnimationFrameInterval is 0.030
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "LowPowerMode"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.030
frame.remove()
internals.setLowPowerModeEnabled(false);
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS internals.requestAnimationFrameInterval is 0.015
document.body.appendChild(frame)
Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler https://bugs.webkit.org/show_bug.cgi?id=204713 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2020-05-04 Reviewed by Simon Fraser. Source/WebCore: 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. Source/WebKit: 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. LayoutTests: * 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(). Canonical link: https://commits.webkit.org/224287@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-04 21:24:49 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameThrottlingReasons() is "[Unthrottled]"
[iOS] Throttle requestAnimationFrame to 30fps in low power mode https://bugs.webkit.org/show_bug.cgi?id=168837 <rdar://problem/30700929> Reviewed by Simon Fraser. Source/WebCore: Throttle requestAnimationFrame to 30fps in low power mode on iOS to save battery. ScriptedAnimationController now maintains an OptionSet of throttling reasons. Throttling reasons for now are: OutsideViewport, VisuallyIdle, and LowPowerMode. The requestAnimationFrame interval is then determined based on those throttling reasons: - OutsideViewport or VisuallyIdle: 10 seconds (very aggressive throttling) - LowPowerMode: 30fps - No reasons: 60fps The Page now keeps track of low power mode state using a LowPowerModeNotifier. Whenever low power mode changes, it updates the throttling reasons in all the documents' ScriptedAnimationControllers in the frame tree. Tests: fast/animation/request-animation-frame-throttling-detached-iframe.html fast/animation/request-animation-frame-throttling-lowPowerMode.html * dom/Document.cpp: (WebCore::Document::requestAnimationFrame): * dom/Document.h: * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::ScriptedAnimationController): (WebCore::throttlingReasonToString): (WebCore::throttlingReasonsToString): (WebCore::ScriptedAnimationController::addThrottlingReason): (WebCore::ScriptedAnimationController::removeThrottlingReason): (WebCore::ScriptedAnimationController::isThrottled): (WebCore::ScriptedAnimationController::interval): (WebCore::ScriptedAnimationController::page): (WebCore::ScriptedAnimationController::scheduleAnimation): * dom/ScriptedAnimationController.h: (WebCore::ScriptedAnimationController::create): * page/FrameView.cpp: (WebCore::FrameView::updateScriptedAnimationsAndTimersThrottlingState): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::isLowPowerModeEnabled): (WebCore::Page::setLowPowerModeEnabledOverrideForTesting): (WebCore::updateScriptedAnimationsThrottlingReason): (WebCore::Page::setIsVisuallyIdleInternal): (WebCore::Page::handleLowModePowerChange): * page/Page.h: * testing/Internals.cpp: (WebCore::Internals::resetToConsistentState): (WebCore::Internals::requestAnimationFrameInterval): (WebCore::Internals::setLowPowerModeEnabled): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Add support for operator -= on WTF::OptionSet for convenience: set -= Enum::A; looks much better than: set = set - Enum::A; * wtf/OptionSet.h: (WTF::OptionSet::operator-=): Tools: Add unit test for -= operator on WTF::OptionSet. * TestWebKitAPI/Tests/WTF/OptionSet.cpp: (TestWebKitAPI::TEST): LayoutTests: Add layout test coverage. * fast/animation/request-animation-frame-throttling-detached-iframe-expected.txt: Added. * fast/animation/request-animation-frame-throttling-detached-iframe.html: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode-expected.txt: Added. * fast/animation/request-animation-frame-throttling-lowPowerMode.html: Added. * fast/animation/resources/frame-with-animation.html: Added. Canonical link: https://commits.webkit.org/185972@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213169 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-28 21:26:27 +00:00
PASS frame.contentWindow.internals.requestAnimationFrameInterval is 0.015
PASS successfullyParsed is true
TEST COMPLETE