haikuwebkit/LayoutTests/animations/no-style-recalc-during-acce...

3 lines
82 B
Plaintext
Raw Permalink Normal View History

[Web Animations] Don't schedule animation frames or update style while an accelerated animation is running https://bugs.webkit.org/show_bug.cgi?id=191542 <rdar://problem/45356027> Reviewed by Simon Fraser. Source/WebCore: Test: animations/no-style-recalc-during-accelerated-animation.html In order to be more power-efficient, we stop scheduling calls to updateAnimationsAndSendEvents() when running only accelerated animations. To do that, we prevent scheduling further animation resolution if we're in the process of updating animations, and when we are done, call the new DocumentTimeline::scheduleNextTick() method that will check whether we have only accelerated animations running, and in that case check which of those animations needs an update the soonest and starts a timer scheduled for that time when we'll schedule animation resolution. By default, animations compute the time until their natural completion but in the case of CSS Animations, we want to make sure we also update animations in-flight to dispatch "animationiteration" events. * animation/AnimationEffect.h: Make the simpleIterationProgress() public so it can be called by WebAnimation::timeToNextTick(). * animation/DocumentTimeline.cpp: (WebCore::DocumentTimeline::DocumentTimeline): Create the m_tickScheduleTimer and set it up to call scheduleAnimationResolutionIfNeeded(). (WebCore::DocumentTimeline::suspendAnimations): If we don't already have a cached current time, cache the current time. (WebCore::DocumentTimeline::resumeAnimations): Reset the cached current time to ensure we'll get a fresh one when updating animations next. (WebCore::DocumentTimeline::liveCurrentTime const): Factor the code to compute the current time out of currentTime() so that we can cache the current time in suspendAnimations() without also automatically clearing the current time. (WebCore::DocumentTimeline::currentTime): Use liveCurrentTime() and cacheCurrentTime() since much of the code from this function has been factored out into those. Additionally, we were failing to clear the current time if called inside an animation frame, which we now do correctly by virtue of using cacheCurrentTime(). This fixes some flakiness. (WebCore::DocumentTimeline::cacheCurrentTime): Factor the code to cache the current time out of currentTime(). (WebCore::DocumentTimeline::maybeClearCachedCurrentTime): No need to clear the current time if we get suspended. (WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded): Prevent scheduling an animation update if we're in the middle of one already, scheduleNextTick() will be called after animations are updated to see if we should schedule an animation update instead. (WebCore::DocumentTimeline::unscheduleAnimationResolution): Cancel the m_tickScheduleTimer if we need to unschedule animation resolution. (WebCore::DocumentTimeline::animationResolutionTimerFired): Factor the call to applyPendingAcceleratedAnimations() out of updateAnimationsAndSendEvents() and call scheduleNextTick(). (WebCore::DocumentTimeline::updateAnimationsAndSendEvents): Set the new m_isUpdatingAnimations member variable to true while this function is running. (WebCore::DocumentTimeline::scheduleNextTick): Schedule an animation update immediately if we have any relevant animation that is not accelerated. Otherwise, iterate through all animations to figure out the earliest moment at which we need to update animations. (WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement): Use the new WebAnimation::isRunningAccelerated() function. * animation/DocumentTimeline.h: * animation/WebAnimation.cpp: (WebCore::WebAnimation::isRunningAccelerated const): Since we end up checking if an animation is running with an accelerated effect, we introduce a new function to get that information directly through the WebAnimation object without bothering about its effect. (WebCore::WebAnimation::resolve): We should only call updateFinishedState() here since timingDidChange() would also notify the timeline about a potential change in relevance, which is not necessary and which would schedule an animation frame even for animations that are accelerated. (WebCore::WebAnimation::timeToNextTick const): Compute the time until our animation completion or, in the case of CSS animations, the next iteration. * animation/WebAnimation.h: LayoutTests: Add a test that checks that we make only minimal style updates and still dispatch events while an accelerated animation is running. * animations/no-style-recalc-during-accelerated-animation-expected.txt: Added. * animations/no-style-recalc-during-accelerated-animation.html: Added. * fast/layers/no-clipping-overflow-hidden-added-after-transform-expected.html: * fast/layers/no-clipping-overflow-hidden-added-after-transform.html: Change the colors to avoid a tiny ImageOnlyFailure. * platform/win/TestExpectations: Mark some regressions tracked by webkit.org/b/191584. Canonical link: https://commits.webkit.org/206337@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238128 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-11-13 10:22:56 +00:00
Got iteration event.
requestAnimationFrame should execute before the next frame https://bugs.webkit.org/show_bug.cgi?id=177484 Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2019-04-10 Reviewed by Simon Fraser. LayoutTests/imported/w3c: Add trace points for the page RenderingUpdate. * web-platform-tests/resize-observer/resources/resizeTestHelper.js: Change ResizeTestHelper.TIMEOUT to be 1 second instead of 100 ms which is too short for layout tests. Source/WebCore: This change fixes these issues with animation timing: 1. Calling the requestAnimationFrame callbacks would have happened when the DisplayLink fires. This may have happened even if the frame is missed and no display is committed. 2. Style changes and layout triggered by script could trigger painting at more than 60fps. CoreAnimation commits could happen at more than 60fps, although WindowServer will throttle those, and only some will be shown on the screen. This change introduces a new paint scheduling model where painting is driven by a "RenderingUpdateScheduler", which only triggers paints once per 16.7ms frame. Code that previously scheduled a compositing layer flush now schedules a "RenderingUpdate", and that update is driven by a DisplayRefreshMonitor callback. When the render happens, we service requestAnimationFrame callbacks, Web Animations, intersection observations and resize observations per the "Update the rendering" step of the HTML Event Loop specification: <https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>. In the future, more rendering steps will be added to this code. * Sources.txt: * WebCore.xcodeproj/project.pbxproj: * accessibility/mac/AXObjectCacheMac.mm: (WebCore::AXObjectCache::platformHandleFocusedUIElementChanged): Fix layout tests by adding null check. * animation/DocumentAnimationScheduler.cpp: Removed. * animation/DocumentAnimationScheduler.h: Removed. * animation/DocumentTimeline.cpp: (WebCore::DocumentTimeline::DocumentTimeline): (WebCore::DocumentTimeline::updateThrottlingState): (WebCore::DocumentTimeline::suspendAnimations): (WebCore::DocumentTimeline::resumeAnimations): (WebCore::DocumentTimeline::liveCurrentTime const): (WebCore::DocumentTimeline::currentTime): (WebCore::DocumentTimeline::cacheCurrentTime): (WebCore::DocumentTimeline::animationTimingDidChange): (WebCore::DocumentTimeline::scheduleAnimationResolution): (WebCore::DocumentTimeline::unscheduleAnimationResolution): (WebCore::DocumentTimeline::updateAnimationsAndSendEvents): (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents): (WebCore::DocumentTimeline::scheduleNextTick): (WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement): Simplify this function by handling the case of no-animations separately. (WebCore::DocumentTimeline::resolveAnimationsForElement): Simplify the loop and delete hasPendingAcceleratedAnimations because it is initialized to true and is not changed inside the loop. (WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded): Deleted. (WebCore::DocumentTimeline::animationResolutionTimerFired): Deleted. * animation/DocumentTimeline.h: * dom/Document.cpp: (WebCore::Document::resolveStyle): There is no need to force update in resolveStyle(). notifyFlushRequired() will be called eventually which will scheduleRenderingUpdate(). (WebCore::Document::prepareForDestruction): (WebCore::Document::updateAnimationsAndSendEvents): (WebCore::Document::serviceRequestAnimationFrameCallbacks): (WebCore::Document::windowScreenDidChange): (WebCore::Document::scheduleRenderingUpdate): (WebCore::Document::updateIntersectionObservations): (WebCore::Document::addResizeObserver): (WebCore::Document::updateResizeObservations): (WebCore::Document::scheduleForcedIntersectionObservationUpdate): Deleted. (WebCore::Document::scheduleResizeObservations): Deleted. (WebCore::Document::animationScheduler): Deleted. No need to schedule web-animations, intersection observations and resize observations updates separately. All of them will be updated through the "Update the rendering" step, i.e. Page::updateRendering(). * dom/Document.h: (WebCore::Document::numberOfIntersectionObservers const): * dom/ScriptedAnimationController.cpp: (WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks): (WebCore::ScriptedAnimationController::scheduleAnimation): (WebCore::ScriptedAnimationController::animationTimerFired): (WebCore::ScriptedAnimationController::serviceScriptedAnimations): Deleted. (WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire): Deleted. * dom/ScriptedAnimationController.h: * page/FrameView.cpp: (WebCore::FrameView::didLayout): (WebCore::FrameView::viewportContentsChanged): * page/FrameViewLayoutContext.cpp: (WebCore::FrameViewLayoutContext::layoutTimerFired): * page/IntersectionObserver.cpp: (WebCore::IntersectionObserver::observe): * page/Page.cpp: (WebCore::Page::Page): (WebCore::Page::layoutIfNeeded): (WebCore::Page::updateRendering): (WebCore::Page::renderingUpdateScheduler): (WebCore::Page::willDisplayPage): Deleted. (WebCore::Page::addDocumentNeedingIntersectionObservationUpdate): Deleted. (WebCore::Page::updateIntersectionObservations): Deleted. (WebCore::Page::scheduleForcedIntersectionObservationUpdate): Deleted. (WebCore::Page::hasResizeObservers const): Deleted. (WebCore::Page::gatherDocumentsNeedingResizeObservationCheck): Deleted. (WebCore::Page::checkResizeObservations): Deleted. (WebCore::Page::scheduleResizeObservations): Deleted. (WebCore::Page::notifyResizeObservers): Deleted. * page/Page.h: (WebCore::Page::setNeedsCheckResizeObservations): Deleted. (WebCore::Page::needsCheckResizeObservations const): Deleted. The IntersectionObserver and the ResizeObserver do not need to schedule their own timers. The RenderingUpdateScheduler will schedule the "Update the rendering" step in which these obverses will be served. * page/PageOverlayController.cpp: (WebCore::PageOverlayController::didChangeViewExposedRect): (WebCore::PageOverlayController::notifyFlushRequired): Force committing the layers to be 60 fps at maximum. * page/RenderingUpdateScheduler.cpp: Added. (WebCore::RenderingUpdateScheduler::RenderingUpdateScheduler): (WebCore::RenderingUpdateScheduler::scheduleRenderingUpdate): (WebCore::RenderingUpdateScheduler::isScheduled const): (WebCore::RenderingUpdateScheduler::startTimer): (WebCore::RenderingUpdateScheduler::clearScheduled): (WebCore::RenderingUpdateScheduler::createDisplayRefreshMonitor const): (WebCore::RenderingUpdateScheduler::windowScreenDidChange): (WebCore::RenderingUpdateScheduler::displayRefreshFired): (WebCore::RenderingUpdateScheduler::scheduleCompositingLayerFlush): * page/RenderingUpdateScheduler.h: Added. (WebCore::RenderingUpdateScheduler::create): * page/ResizeObserver.cpp: (WebCore::ResizeObserver::observe): (WebCore::ResizeObserver::scheduleObservations): Deleted. * page/ResizeObserver.h: (WebCore::ResizeObserver::hasActiveObservations const): * page/ios/ContentChangeObserver.h: * page/mac/ServicesOverlayController.mm: (WebCore::ServicesOverlayController::Highlight::notifyFlushRequired): * page/scrolling/ScrollingStateTree.cpp: * rendering/RenderLayerCompositor.cpp: (WebCore::RenderLayerCompositor::scheduleLayerFlushNow): (WebCore::RenderLayerCompositor::layerTreeAsText): Source/WebKit: Replace the calls to Page::layoutIfNeeded() and willDisplayPage() by a single call to Page::updateRendering(). This new function implements "Update the rendering" step of the HTML Event Loop specification <https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>. * WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp: (WebKit::DrawingAreaCoordinatedGraphics::scheduleCompositingLayerFlush): (WebKit::DrawingAreaCoordinatedGraphics::updateBackingStoreState): (WebKit::DrawingAreaCoordinatedGraphics::display): * WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp: (WebKit::LayerTreeHost::layerFlushTimerFired): * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm: (WebKit::RemoteLayerTreeDrawingArea::flushLayers): -- Call Page::updateRendering() to make sure that "Update the rendering" happens immediately before updating the page. -- Move the call to RemoteLayerBackingStoreCollection::willFlushLayers() to be exactly before flushing the layers. This fixes the assertion ASSERT(m_inLayerFlush) which was firing when running a layout test. RemoteLayerTreeDrawingArea::flushLayers() now can call itself through TestRunner::notifyDone(). flushLayers() was calling willFlushLayers() twice before calling didFlushLayers(). * WebProcess/WebPage/WebPage.cpp: (WebKit::WebPage::layoutIfNeeded): (WebKit::WebPage::updateRendering): (WebKit::WebPage::willDisplayPage): Deleted. * WebProcess/WebPage/WebPage.h: * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm: (WebKit::TiledCoreAnimationDrawingArea::flushLayers): Source/WebKitLegacy/mac: * WebView/WebView.mm: (-[WebView _viewWillDrawInternal]): (-[WebView _flushCompositingChanges]): Call Page::updateRendering() which implements "Update the rendering" step of the HTML Event Loop specification. Source/WebKitLegacy/win: * WebView.cpp: (WebView::updateBackingStore): (WebView::flushPendingGraphicsLayerChangesSoon): (WebView::flushPendingGraphicsLayerChanges): Call Page::updateRendering() which implements "Update the rendering" step of the HTML Event Loop specification. Source/WTF: Add trace points for the page RenderingUpdate. * wtf/SystemTracing.h: Tools: Add trace points for the page RenderingUpdate. * Tracing/SystemTracePoints.plist: LayoutTests: * TestExpectations: There is a slight difference between the actual DRT and the expected DRT due to animation timing change. But these two tests are not animating correctly if they are opened in Safari with web animation turned on. * accessibility/mac/selection-notification-focus-change-expected.txt: * accessibility/mac/selection-notification-focus-change.html: Remove the debug statements form notificationCallback() since the number of times this function is called back and the order of notifications are not defined. This test has been flaky and some trials were made to make it more reliable. With this change it became flaky again. * animations/animation-multiple-callbacks-timestamp.html: Fix variable names used by an error message. * animations/no-style-recalc-during-accelerated-animation-expected.txt: * animations/no-style-recalc-during-accelerated-animation.html: One extra styleReclc was incurred due to the document styleRecalcTimer. I think this timer is not needed anymore. I will look at removing it in a separate patch. * animations/resources/animation-test-helpers.js: (waitForAnimationToStart): The expectation that animation will start at the beginning of the next event loop is not true anymore. The animation will start at the time the requestAnimationFrame fires. * compositing/video/video-clip-change-src.html: This test loads a video data and pushes it to the encoder. Originally it used to wait 150 ms after receiving the second canplaythrough. I had to change this timing to 250 ms. * css3/filters/composited-during-animation.html: Ditto. setTimeout({...}, 0) versus requestAnimationFrame. * media/media-controls-accessibility.html: Updating the accessibility button happens asynchronously, see [WebAccessibilityObjectWrapper accessibilityPerformPressAction]. Due to changing the page update timing, this test became flaky. Originally it used to setTimeout({...}, 10) to ensure the stringValue of the mutate button was changed after it was pressed. The fix is to loop using rAF till the stringValue changes. * platform/mac-wk2/accessibility/mac/selection-notification-focus-change-expected.txt: Removed. The number of time notificationCallback() is called and the order of notifications are not defined. And this is why we have two expected files: one for WK1 and the other for WK2. Since the test is now simplified, we can get rid of this duplication. We will test the minimum reliable thing we can test. Canonical link: https://commits.webkit.org/211093@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244182 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-04-11 05:44:13 +00:00
PASS: saw three or fewer style recalcs during the animation.