2016-01-15 20:57:37 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 Apple Inc. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2016-11-30 03:02:32 +00:00
|
|
|
#pragma once
|
2016-01-15 20:57:37 +00:00
|
|
|
|
2016-02-07 18:44:25 +00:00
|
|
|
#if USE(APPLE_INTERNAL_SDK)
|
2016-01-15 20:57:37 +00:00
|
|
|
#include <System/sys/kdebug.h>
|
|
|
|
#define HAVE_KDEBUG_H 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// No namespaces because this file has to be includable from C and Objective-C.
|
|
|
|
|
|
|
|
// Reserved component code. Do not change this.
|
|
|
|
#define WEBKIT_COMPONENT 47
|
|
|
|
|
|
|
|
// Trace point codes can be up to 14 bits (0-16383).
|
|
|
|
// When adding or changing these codes, update Tools/Tracing/SystemTracePoints.plist to match.
|
|
|
|
enum TracePointCode {
|
|
|
|
WTFRange = 0,
|
|
|
|
|
|
|
|
JavaScriptRange = 2500,
|
2016-12-13 20:44:17 +00:00
|
|
|
VMEntryScopeStart,
|
|
|
|
VMEntryScopeEnd,
|
2017-03-17 00:47:16 +00:00
|
|
|
WebAssemblyCompileStart,
|
|
|
|
WebAssemblyCompileEnd,
|
|
|
|
WebAssemblyExecuteStart,
|
|
|
|
WebAssemblyExecuteEnd,
|
2019-05-18 07:12:17 +00:00
|
|
|
DumpJITMemoryStart,
|
|
|
|
DumpJITMemoryStop,
|
2021-05-18 02:35:39 +00:00
|
|
|
FromJSStart,
|
|
|
|
FromJSStop,
|
2016-01-15 20:57:37 +00:00
|
|
|
|
|
|
|
WebCoreRange = 5000,
|
2017-03-17 00:47:16 +00:00
|
|
|
MainResourceLoadDidStartProvisional,
|
|
|
|
MainResourceLoadDidEnd,
|
|
|
|
SubresourceLoadWillStart,
|
|
|
|
SubresourceLoadDidEnd,
|
|
|
|
FetchCookiesStart,
|
|
|
|
FetchCookiesEnd,
|
2016-01-15 20:57:37 +00:00
|
|
|
StyleRecalcStart,
|
|
|
|
StyleRecalcEnd,
|
2017-03-17 00:47:16 +00:00
|
|
|
RenderTreeBuildStart,
|
|
|
|
RenderTreeBuildEnd,
|
2016-01-15 20:57:37 +00:00
|
|
|
LayoutStart,
|
|
|
|
LayoutEnd,
|
|
|
|
PaintLayerStart,
|
|
|
|
PaintLayerEnd,
|
2017-03-17 00:47:16 +00:00
|
|
|
AsyncImageDecodeStart,
|
|
|
|
AsyncImageDecodeEnd,
|
2016-06-21 22:29:57 +00:00
|
|
|
RAFCallbackStart,
|
|
|
|
RAFCallbackEnd,
|
2017-03-21 02:04:59 +00:00
|
|
|
MemoryPressureHandlerStart,
|
|
|
|
MemoryPressureHandlerEnd,
|
2017-04-29 01:55:10 +00:00
|
|
|
UpdateTouchRegionsStart,
|
|
|
|
UpdateTouchRegionsEnd,
|
2017-11-02 03:08:53 +00:00
|
|
|
DisplayListRecordStart,
|
|
|
|
DisplayListRecordEnd,
|
2017-12-05 01:13:27 +00:00
|
|
|
DisplayRefreshDispatchingToMainThread,
|
2019-03-02 00:23:56 +00:00
|
|
|
ComputeEventRegionsStart,
|
|
|
|
ComputeEventRegionsEnd,
|
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
|
|
|
ScheduleRenderingUpdate,
|
|
|
|
TriggerRenderingUpdate,
|
|
|
|
RenderingUpdateStart,
|
|
|
|
RenderingUpdateEnd,
|
2019-08-30 18:23:29 +00:00
|
|
|
CompositingUpdateStart,
|
|
|
|
CompositingUpdateEnd,
|
|
|
|
DispatchTouchEventsStart,
|
|
|
|
DispatchTouchEventsEnd,
|
2020-03-03 05:18:04 +00:00
|
|
|
ParseHTMLStart,
|
|
|
|
ParseHTMLEnd,
|
2020-03-05 03:33:47 +00:00
|
|
|
DisplayListReplayStart,
|
|
|
|
DisplayListReplayEnd,
|
[macOS] Scrolling synchronization part 1: Have the scrolling thread wait half a frame for the main thread to complete the rendering update
https://bugs.webkit.org/show_bug.cgi?id=212168
Reviewed by Tim Horton.
Source/WebCore:
Currently the scrolling thread is a free-running thread that moves layers around in response
to wheel events, and asynchronously posts data about scrolled layers back to the main thread.
That results in an almost guaranteed lack of synchronization between the displayed layer
positions, and the web-exposed values for scroll position (element.scrollTop, window.pageYOffset etc).
This is a frequent source of stuttering or jumpy web content when scrolling.
The first step to fixing this is to synchronize the scrolling thread layer positions
and the main thread state for the case where the main thread is responsive enough to
render once per frame. This is achieved as follow:
- When the main thread is starting a rendering update, Page::updateRendering() informs
the scrolling tree via ScrollingCoordinatorMac::willStartRenderingUpdate(). This
atomically waits for the scrolling thread to take the m_treeMutex (via a BinarySemaphore)
and starts waiting on the m_stateCondition Condition. Now the main thread pulls the
state of the scrolling tree via synchronizeStateFromScrollingTree() and uses it for
the rendering update.
- If the rendering update finishes within half a frame (8ms), then m_stateCondition
is released, and the scrolling thread assumes that the main thread is going to
commit layers rapidly enough to preserve 60fps scrolling.
- If the rendering update takes too long, m_stateCondition times out, and the scrolling
thread applies layer positions, triggering a CA commit on that thread.
We no longer apply layer positions directly when handling wheel events.
synchronizeStateFromScrollingTree() has to only pull state from nodes that have moved on the scrolling thread,
so track that via ScrollingTreeScrollingNode::scrolledSinceLastCommit() and adjust the visitor function to
make it available during scrolling tree traversal.
* page/Page.cpp:
(WebCore::Page::updateRendering):
(WebCore::Page::finalizeRenderingUpdate):
* page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::synchronizeStateFromScrollingTree):
* page/scrolling/AsyncScrollingCoordinator.h:
* page/scrolling/ScrollingCoordinator.h:
(WebCore::ScrollingCoordinator::willStartRenderingUpdate):
(WebCore::ScrollingCoordinator::didCompleteRenderingUpdate):
(WebCore::ScrollingCoordinator::synchronizeStateFromScrollingTree): Deleted.
* page/scrolling/ScrollingTree.cpp:
(WebCore::ScrollingTree::handleWheelEvent):
(WebCore::ScrollingTree::traverseScrollingTreeRecursive):
(WebCore::ScrollingTree::commitTreeState):
(WebCore::ScrollingTree::updateTreeFromStateNodeRecursive):
(WebCore::ScrollingTree::applyLayerPositionsInternal):
(WebCore::ScrollingTree::nominalFramesPerSecond):
* page/scrolling/ScrollingTree.h:
* page/scrolling/ScrollingTreeNode.h:
(WebCore::ScrollingTreeNode::didCompleteCommitForNode):
* page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::didCompleteCommitForNode):
(WebCore::ScrollingTreeScrollingNode::currentScrollPositionChanged):
* page/scrolling/ScrollingTreeScrollingNode.h:
* page/scrolling/ThreadedScrollingTree.cpp:
(WebCore::ThreadedScrollingTree::willStartRenderingUpdate):
(WebCore::ThreadedScrollingTree::maxAllowableRenderingUpdateDurationForSynchronization):
(WebCore::ThreadedScrollingTree::waitForRenderingUpdateCompletionOrTimeout):
(WebCore::ThreadedScrollingTree::didCompleteRenderingUpdate):
(WebCore::ThreadedScrollingTree::displayDidRefreshOnScrollingThread):
* page/scrolling/ThreadedScrollingTree.h:
(WebCore::ThreadedScrollingTree::treeMutex):
* page/scrolling/mac/ScrollingCoordinatorMac.h:
* page/scrolling/mac/ScrollingCoordinatorMac.mm:
(WebCore::ScrollingCoordinatorMac::willStartRenderingUpdate):
(WebCore::ScrollingCoordinatorMac::didCompleteRenderingUpdate):
Source/WTF:
Some new trace points for scrolling thread activity.
* wtf/SystemTracing.h:
Tools:
Some new trace points for scrolling thread activity.
* Tracing/SystemTracePoints.plist:
Canonical link: https://commits.webkit.org/225057@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@261985 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-05-21 06:47:24 +00:00
|
|
|
ScrollingThreadRenderUpdateSyncStart,
|
|
|
|
ScrollingThreadRenderUpdateSyncEnd,
|
|
|
|
ScrollingThreadDisplayDidRefreshStart,
|
|
|
|
ScrollingThreadDisplayDidRefreshEnd,
|
2021-04-21 15:00:38 +00:00
|
|
|
ScrollingTreeDisplayDidRefresh,
|
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
|
|
|
|
2016-01-15 20:57:37 +00:00
|
|
|
WebKitRange = 10000,
|
2017-03-17 00:47:16 +00:00
|
|
|
WebHTMLViewPaintStart,
|
|
|
|
WebHTMLViewPaintEnd,
|
2016-06-21 22:29:57 +00:00
|
|
|
|
2017-03-17 00:47:16 +00:00
|
|
|
WebKit2Range = 12000,
|
|
|
|
BackingStoreFlushStart,
|
|
|
|
BackingStoreFlushEnd,
|
|
|
|
BuildTransactionStart,
|
|
|
|
BuildTransactionEnd,
|
|
|
|
SyncMessageStart,
|
|
|
|
SyncMessageEnd,
|
|
|
|
SyncTouchEventStart,
|
|
|
|
SyncTouchEventEnd,
|
2018-04-17 15:57:32 +00:00
|
|
|
InitializeWebProcessStart,
|
|
|
|
InitializeWebProcessEnd,
|
2020-02-18 17:24:30 +00:00
|
|
|
RenderingUpdateRunLoopObserverStart,
|
|
|
|
RenderingUpdateRunLoopObserverEnd,
|
2020-02-17 16:45:29 +00:00
|
|
|
LayerTreeFreezeStart,
|
|
|
|
LayerTreeFreezeEnd,
|
2020-10-17 04:55:32 +00:00
|
|
|
FlushRemoteImageBufferStart,
|
|
|
|
FlushRemoteImageBufferEnd,
|
2021-03-16 16:57:35 +00:00
|
|
|
CreateInjectedBundleStart,
|
|
|
|
CreateInjectedBundleEnd,
|
2021-04-22 22:33:20 +00:00
|
|
|
PaintSnapshotStart,
|
|
|
|
PaintSnapshotEnd,
|
|
|
|
RenderServerSnapshotStart,
|
|
|
|
RenderServerSnapshotEnd,
|
|
|
|
TakeSnapshotStart,
|
|
|
|
TakeSnapshotEnd,
|
2016-06-21 22:29:57 +00:00
|
|
|
|
|
|
|
UIProcessRange = 14000,
|
2017-03-17 00:47:16 +00:00
|
|
|
CommitLayerTreeStart,
|
|
|
|
CommitLayerTreeEnd,
|
2018-04-17 15:57:32 +00:00
|
|
|
ProcessLaunchStart,
|
|
|
|
ProcessLaunchEnd,
|
2018-08-16 03:34:01 +00:00
|
|
|
InitializeSandboxStart,
|
|
|
|
InitializeSandboxEnd,
|
2020-11-12 01:16:25 +00:00
|
|
|
|
|
|
|
GPUProcessRange = 16000,
|
|
|
|
WakeUpAndApplyDisplayListStart,
|
|
|
|
WakeUpAndApplyDisplayListEnd,
|
2016-01-15 20:57:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
|
|
|
namespace WTF {
|
|
|
|
|
2018-04-17 15:57:32 +00:00
|
|
|
inline void tracePoint(TracePointCode code, uint64_t data1 = 0, uint64_t data2 = 0, uint64_t data3 = 0, uint64_t data4 = 0)
|
2016-06-21 22:29:57 +00:00
|
|
|
{
|
|
|
|
#if HAVE(KDEBUG_H)
|
2016-11-30 03:02:32 +00:00
|
|
|
kdebug_trace(ARIADNEDBG_CODE(WEBKIT_COMPONENT, code), data1, data2, data3, data4);
|
2016-06-21 22:29:57 +00:00
|
|
|
#else
|
|
|
|
UNUSED_PARAM(code);
|
2016-11-30 03:02:32 +00:00
|
|
|
UNUSED_PARAM(data1);
|
|
|
|
UNUSED_PARAM(data2);
|
|
|
|
UNUSED_PARAM(data3);
|
|
|
|
UNUSED_PARAM(data4);
|
2016-06-21 22:29:57 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-01-15 20:57:37 +00:00
|
|
|
class TraceScope {
|
2019-08-12 20:57:15 +00:00
|
|
|
WTF_MAKE_FAST_ALLOCATED;
|
2016-01-15 20:57:37 +00:00
|
|
|
public:
|
|
|
|
|
2017-03-21 02:04:59 +00:00
|
|
|
TraceScope(TracePointCode entryCode, TracePointCode exitCode, uint64_t data1 = 0, uint64_t data2 = 0, uint64_t data3 = 0, uint64_t data4 = 0)
|
2016-01-15 20:57:37 +00:00
|
|
|
: m_exitCode(exitCode)
|
|
|
|
{
|
2018-04-17 15:57:32 +00:00
|
|
|
tracePoint(entryCode, data1, data2, data3, data4);
|
2016-01-15 20:57:37 +00:00
|
|
|
}
|
2016-06-21 22:29:57 +00:00
|
|
|
|
2016-01-15 20:57:37 +00:00
|
|
|
~TraceScope()
|
|
|
|
{
|
2018-04-17 15:57:32 +00:00
|
|
|
tracePoint(m_exitCode);
|
2016-01-15 20:57:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
TracePointCode m_exitCode;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace WTF
|
|
|
|
|
|
|
|
using WTF::TraceScope;
|
2018-04-17 15:57:32 +00:00
|
|
|
using WTF::tracePoint;
|
2016-01-15 20:57:37 +00:00
|
|
|
|
|
|
|
#endif // __cplusplus
|
2020-03-03 05:14:21 +00:00
|
|
|
|
|
|
|
#if HAVE(OS_SIGNPOST)
|
|
|
|
|
|
|
|
#import <os/signpost.h>
|
|
|
|
|
|
|
|
WTF_EXTERN_C_BEGIN
|
|
|
|
WTF_EXPORT_PRIVATE bool WTFSignpostsEnabled();
|
|
|
|
WTF_EXPORT_PRIVATE os_log_t WTFSignpostLogHandle();
|
|
|
|
WTF_EXTERN_C_END
|
|
|
|
|
|
|
|
#define WTFEmitSignpost(pointer, name, ...) \
|
|
|
|
WTFEmitSignpostWithFunction(os_signpost_event_emit, (pointer), name, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define WTFBeginSignpost(pointer, name, ...) \
|
|
|
|
WTFEmitSignpostWithFunction(os_signpost_interval_begin, (pointer), name, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define WTFEndSignpost(pointer, name, ...) \
|
|
|
|
WTFEmitSignpostWithFunction(os_signpost_interval_end, (pointer), name, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define WTFEmitSignpostWithFunction(emitFunc, pointer, name, ...) \
|
|
|
|
do { \
|
|
|
|
if (UNLIKELY(WTFSignpostsEnabled())) { \
|
|
|
|
os_log_t handle = WTFSignpostLogHandle(); \
|
|
|
|
os_signpost_id_t signpostID = os_signpost_id_make_with_pointer(handle, (pointer)); \
|
|
|
|
emitFunc(handle, signpostID, name, ##__VA_ARGS__); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#define WTFEmitSignpost(pointer, name, ...) do { } while (0)
|
|
|
|
#define WTFBeginSignpost(pointer, name, ...) do { } while (0)
|
|
|
|
#define WTFEndSignpost(pointer, name, ...) do { } while (0)
|
|
|
|
|
|
|
|
#endif
|