Source/WTF/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 Add trace points for the page RenderingUpdate.
 9
 10 * wtf/SystemTracing.h:
 11
1122019-02-28 Ryosuke Niwa <rniwa@webkit.org>
213
314 Add WeakHashSet

Source/WebCore/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 This change fixes two issues with animation timing:
 9
 10 1. Calling the requestAnimationFrame callbacks would have happened when
 11 the DisplayLink fires. This may have happened even if the frame is
 12 missed and no display is committed.
 13
 14 2. Style changes and layout triggered by script could trigger painting
 15 at more than 60fps. CoreAnimation commits could happen at more than
 16 60fps, although WindowServer will throttle those, and only some will
 17 be shown on the screen.
 18
 19 This change introduces a new paint scheduling model where painting is
 20 driven by a "RenderingUpdateScheduler", which only triggers paints once
 21 per 16.7ms frame.
 22
 23 Code that previously scheduled a compositing layer flush now schedules a
 24 "RenderingUpdate", and that update is driven by a DisplayRefreshMonitor
 25 callback. When the render happens, we service requestAnimationFrame callbacks,
 26 Web Animations and intersection observations per the "Update the rendering"
 27 step of the HTML Event Loop specification
 28 <https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>.
 29
 30 In the future, more rendering steps will be added to this code.
 31
 32 * Sources.txt:
 33 * WebCore.xcodeproj/project.pbxproj:
 34 * accessibility/mac/AXObjectCacheMac.mm:
 35 Fix layout tests by adding null check.
 36
 37 * animation/DocumentAnimationScheduler.cpp: Removed.
 38 * animation/DocumentAnimationScheduler.h: Removed.
 39 * animation/DocumentTimeline.cpp:
 40 (WebCore::DocumentTimeline::DocumentTimeline):
 41 (WebCore::DocumentTimeline::updateThrottlingState):
 42 (WebCore::DocumentTimeline::resumeAnimations):
 43 (WebCore::DocumentTimeline::liveCurrentTime const):
 44 (WebCore::DocumentTimeline::currentTime):
 45 (WebCore::DocumentTimeline::animationTimingDidChange):
 46 (WebCore::DocumentTimeline::scheduleAnimationResolution):
 47 (WebCore::DocumentTimeline::unscheduleAnimationResolution):
 48 (WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
 49 (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
 50 (WebCore::DocumentTimeline::scheduleNextTick):
 51 (WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement):
 52 Simplify this function by handling the case of no-animations separately.
 53
 54 (WebCore::DocumentTimeline::resolveAnimationsForElement):
 55 Simplify the loop and delete hasPendingAcceleratedAnimations because it
 56 is initialized to true and is not changed inside the loop.
 57
 58 (WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded): Deleted.
 59 (WebCore::DocumentTimeline::animationResolutionTimerFired): Deleted.
 60 * animation/DocumentTimeline.h:
 61 * dom/Document.cpp:
 62 (WebCore::Document::resolveStyle):
 63 There is no need to force update in resolveStyle(). notifyFlushRequired()
 64 will be called eventually which will scheduleRenderingUpdate().
 65
 66 (WebCore::Document::prepareForDestruction):
 67 (WebCore::Document::updateAnimationsAndSendEvents):
 68 (WebCore::Document::serviceRequestAnimationFrameCallbacks):
 69 (WebCore::Document::windowScreenDidChange):
 70 (WebCore::Document::updateIntersectionObservations):
 71 (WebCore::Document::scheduleForcedIntersectionObservationUpdate): Deleted.
 72 (WebCore::Document::animationScheduler): Deleted.
 73 * dom/Document.h:
 74 (WebCore::Document::numberOfIntersectionObservers const):
 75 * dom/ScriptedAnimationController.cpp:
 76 (WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
 77 (WebCore::ScriptedAnimationController::scheduleAnimation):
 78 (WebCore::ScriptedAnimationController::animationTimerFired):
 79 (WebCore::ScriptedAnimationController::serviceScriptedAnimations): Deleted.
 80 (WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire): Deleted.
 81 * dom/ScriptedAnimationController.h:
 82 * page/FrameView.cpp:
 83 (WebCore::FrameView::viewportContentsChanged):
 84 * page/IntersectionObserver.cpp:
 85 (WebCore::IntersectionObserver::observe):
 86 * page/Page.cpp:
 87 (WebCore::Page::Page):
 88 (WebCore::Page::layoutIfNeeded):
 89 (WebCore::Page::renderingUpdate):
 90 (WebCore::Page::renderingUpdateScheduler):
 91 (WebCore::Page::willDisplayPage): Deleted.
 92 (WebCore::Page::addDocumentNeedingIntersectionObservationUpdate): Deleted.
 93 (WebCore::Page::updateIntersectionObservations): Deleted.
 94 (WebCore::Page::scheduleForcedIntersectionObservationUpdate): Deleted.
 95 * page/Page.h:
 96 * page/PageOverlayController.cpp:
 97 (WebCore::PageOverlayController::didChangeViewExposedRect):
 98 (WebCore::PageOverlayController::notifyFlushRequired):
 99 * page/ResourceUsageData.h:
 100 Include header files that become missing because of adding
 101 RenderingUpdateScheduler.cpp.
 102
 103 * page/RenderingUpdateScheduler.cpp: Added.
 104 (WebCore::RenderingUpdateScheduler::RenderingUpdateScheduler):
 105 (WebCore::RenderingUpdateScheduler::scheduleRenderingUpdate):
 106 (WebCore::RenderingUpdateScheduler::startTimer):
 107 (WebCore::RenderingUpdateScheduler::clearTimer):
 108 (WebCore::RenderingUpdateScheduler::windowScreenDidChange):
 109 (WebCore::RenderingUpdateScheduler::createDisplayRefreshMonitor const):
 110 (WebCore::RenderingUpdateScheduler::displayRefreshFired):
 111 * page/RenderingUpdateScheduler.h: Added.
 112 (WebCore::RenderingUpdateScheduler::create):
 113 * page/ios/ContentChangeObserver.h:
 114 Include header files that become missing because of adding
 115 RenderingUpdateScheduler.cpp.
 116
 117 * page/mac/ServicesOverlayController.mm:
 118 (WebCore::ServicesOverlayController::Highlight::notifyFlushRequired):
 119 * rendering/RenderLayerCompositor.cpp:
 120 (WebCore::RenderLayerCompositor::scheduleLayerFlushNow):
 121
11222019-03-06 Devin Rousso <drousso@apple.com>
2123
3124 Web Inspector: DOM Debugger: event breakpoints still fire when breakpoints are disabled

Source/WebKit/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 Replace the calls to Page::layoutIfNeeded() and willDisplayPage() by
 9 a single call to Page::renderingUpdate(). This new function implements
 10 "Update the rendering" step of the HTML Event Loop specification
 11 <https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>.
 12
 13 * WebProcess/WebPage/AcceleratedDrawingArea.cpp:
 14 (WebKit::AcceleratedDrawingArea::updateBackingStoreState):
 15 * WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:
 16 (WebKit::LayerTreeHost::layerFlushTimerFired):
 17 * WebProcess/WebPage/DrawingAreaImpl.cpp:
 18 (WebKit::DrawingAreaImpl::display):
 19 * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
 20 (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
 21 * WebProcess/WebPage/WebPage.cpp:
 22 (WebKit::WebPage::layoutIfNeeded):
 23 (WebKit::WebPage::renderingUpdate):
 24 (WebKit::WebPage::willDisplayPage): Deleted.
 25 * WebProcess/WebPage/WebPage.h:
 26 * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
 27 (WebKit::TiledCoreAnimationDrawingArea::flushLayers):
 28
1292019-03-06 Wenson Hsieh <wenson_hsieh@apple.com>
230
331 Crash when attempting to change input type while dismissing datalist suggestions

Source/WebKitLegacy/mac/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 * WebView/WebView.mm:
 9 (-[WebView _viewWillDrawInternal]):
 10 Call Page::renderingUpdate() which implements "Update the rendering"
 11 step of the HTML Event Loop specification.
 12
1132019-03-06 Sam Weinig <sam@webkit.org>
214
315 WebKitLegacy does not need to generate an export file for i386 anymore

Source/WebKitLegacy/win/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 * WebView.cpp:
 9 (WebView::updateBackingStore):
 10 (WebView::flushPendingGraphicsLayerChangesSoon):
 11 (WebView::flushPendingGraphicsLayerChanges):
 12 Call Page::renderingUpdate() which implements "Update the rendering"
 13 step of the HTML Event Loop specification.
 14
1152019-03-02 Wenson Hsieh <wenson_hsieh@apple.com>
216
317 [iOS] Programmatic paste access should be granted when copying and pasting within the same origin

Source/WTF/wtf/SystemTracing.h

@@enum TracePointCode {
7777 ComputeEventRegionsStart,
7878 ComputeEventRegionsEnd,
7979
 80 ScheduleRenderingUpdate,
 81 TriggerRenderingUpdate,
 82 RenderingUpdateStart,
 83 RenderingUpdateEnd,
 84
8085 WebKitRange = 10000,
8186 WebHTMLViewPaintStart,
8287 WebHTMLViewPaintEnd,

Source/WebCore/Sources.txt

@@animation/AnimationTimeline.cpp
419419animation/CSSAnimation.cpp
420420animation/CSSTransition.cpp
421421animation/DeclarativeAnimation.cpp
422 animation/DocumentAnimationScheduler.cpp
423422animation/DocumentTimeline.cpp
424423animation/KeyframeEffect.cpp
425424animation/WebAnimation.cpp

@@page/ProcessWarming.cpp
15381537page/Quirks.cpp
15391538page/RemoteDOMWindow.cpp
15401539page/RemoteFrame.cpp
 1540page/RenderingUpdateScheduler.cpp
15411541page/ResourceUsageOverlay.cpp
15421542page/ResourceUsageThread.cpp
15431543page/RuntimeEnabledFeatures.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

17781778 5550CB421E955E3C00111AA0 /* ImageTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5550CB411E955E3C00111AA0 /* ImageTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
17791779 555130011E7CCCCB00A69E38 /* DecodingOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 555130001E7CCCCA00A69E38 /* DecodingOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
17801780 555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
 1781 556C7C4B22123997009B06CA /* RenderingUpdateScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
17811782 5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 5576A5631D88A70800CCC04C /* ImageFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
17821783 55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
17831784 55AF14E61EAAC59B0026EEAA /* UTIRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 55AF14E41EAAC59B0026EEAA /* UTIRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };

21152116 7156BCA121CA350F00534397 /* BasicEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 7156BC9F21CA350600534397 /* BasicEffectTiming.h */; };
21162117 715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AD71D2050512400D592DC /* DeclarativeAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; };
21172118 715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; };
2118  716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
21192119 71729F7B20F3BA4900801CE6 /* DocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
21202120 71729F7E20F3BB4700801CE6 /* JSDocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */; };
21212121 71A1B6081DEE5AD70073BCFB /* modern-media-controls-localized-strings.js in Resources */ = {isa = PBXBuildFile; fileRef = 71A1B6061DEE5A820073BCFB /* modern-media-controls-localized-strings.js */; };

86388638 555130001E7CCCCA00A69E38 /* DecodingOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecodingOptions.h; sourceTree = "<group>"; };
86398639 555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
86408640 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
 8641 556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderingUpdateScheduler.h; sourceTree = "<group>"; };
 8642 556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderingUpdateScheduler.cpp; sourceTree = "<group>"; };
86418643 5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = "<group>"; };
86428644 5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = "<group>"; };
86438645 5597FCCB2076C06800D35BB0 /* GlyphDisplayListCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlyphDisplayListCache.h; sourceTree = "<group>"; };

93649366 716C8DF21E48B269005BD0DA /* volume-up-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-support.js"; sourceTree = "<group>"; };
93659367 716C8DF31E48B284005BD0DA /* volume-down-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-down-button.js"; sourceTree = "<group>"; };
93669368 716C8DF41E48B284005BD0DA /* volume-up-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-button.js"; sourceTree = "<group>"; };
9367  716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentAnimationScheduler.h; sourceTree = "<group>"; };
9368  716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentAnimationScheduler.cpp; sourceTree = "<group>"; };
93699369 716FA0D81DB26591007323CC /* airplay-button.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "airplay-button.css"; sourceTree = "<group>"; };
93709370 716FA0D91DB26591007323CC /* airplay-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-button.js"; sourceTree = "<group>"; };
93719371 716FA0DA1DB26591007323CC /* airplay-placard.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-placard.js"; sourceTree = "<group>"; };

2047820478 46BCBBC3208500A700710638 /* RemoteDOMWindow.idl */,
2047920479 46B9518C207D632900A7D2DD /* RemoteFrame.cpp */,
2048020480 46B95192207D632E00A7D2DD /* RemoteFrame.h */,
 20481 556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */,
 20482 556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */,
2048120483 A5071E821C56D079009951BE /* ResourceUsageData.h */,
2048220484 ADBAD6EC1BCDD95000381325 /* ResourceUsageOverlay.cpp */,
2048320485 ADBAD6ED1BCDD95000381325 /* ResourceUsageOverlay.h */,

2063020632 7123C185204739B900789392 /* CSSTransition.idl */,
2063120633 715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */,
2063220634 715AD71D2050512400D592DC /* DeclarativeAnimation.h */,
20633  716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */,
20634  716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */,
2063520635 71025EC41F99F096004A250C /* DocumentTimeline.cpp */,
2063620636 71025EC51F99F096004A250C /* DocumentTimeline.h */,
2063720637 71025ECA1F99F096004A250C /* DocumentTimeline.idl */,

2904929049 B2F34FE60E82F81400F627CD /* DNS.h in Headers */,
2905029050 7EE6846F12D26E3800E73215 /* DNSResolveQueueCFNet.h in Headers */,
2905129051 A8185F4009765766005826D9 /* Document.h in Headers */,
29052  716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */,
2905329052 A3BB59F41457A40D00AC56FE /* DocumentEventQueue.h in Headers */,
2905429053 A8185F3D09765766005826D9 /* DocumentFragment.h in Headers */,
2905529054 46E1666E1FCC86A200C9710B /* DocumentIdentifier.h in Headers */,

3125131250 BCEA4876097D93020094C9E4 /* RenderImage.h in Headers */,
3125231251 08F2F00A1213E61700DCEC48 /* RenderImageResource.h in Headers */,
3125331252 08641D4812142F7D008DE9F6 /* RenderImageResourceStyleImage.h in Headers */,
 31253 556C7C4B22123997009B06CA /* RenderingUpdateScheduler.h in Headers */,
3125431254 BCEA4878097D93020094C9E4 /* RenderInline.h in Headers */,
3125531255 B595FF471824CEE300FF51CD /* RenderIterator.h in Headers */,
3125631256 BCEA487A097D93020094C9E4 /* RenderLayer.h in Headers */,

Source/WebCore/accessibility/mac/AXObjectCacheMac.mm

@@void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node*)
539539{
540540 NSAccessibilityHandleFocusChanged();
541541 // AXFocusChanged is a test specific notification name and not something a real AT will be listening for
542  if (UNLIKELY(axShouldRepostNotificationsForTests))
543  [rootWebArea()->wrapper() accessibilityPostedNotification:@"AXFocusChanged" userInfo:nil];
 542 if (UNLIKELY(!axShouldRepostNotificationsForTests))
 543 return;
 544
 545 auto* rootWebArea = this->rootWebArea();
 546 if (!rootWebArea)
 547 return;
 548
 549 [rootWebArea->wrapper() accessibilityPostedNotification:@"AXFocusChanged" userInfo:nil];
544550}
545551
546552void AXObjectCache::handleScrolledToAnchor(const Node*)

Source/WebCore/animation/DocumentAnimationScheduler.cpp

1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "DocumentAnimationScheduler.h"
28 
29 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
30 
31 #include "Chrome.h"
32 #include "ChromeClient.h"
33 #include "DOMWindow.h"
34 #include "DisplayRefreshMonitor.h"
35 #include "DisplayRefreshMonitorManager.h"
36 #include "Document.h"
37 #include "DocumentTimeline.h"
38 #include "Page.h"
39 #include "ScriptedAnimationController.h"
40 
41 namespace WebCore {
42 
43 Ref<DocumentAnimationScheduler> DocumentAnimationScheduler::create(Document& document, PlatformDisplayID displayID)
44 {
45  return adoptRef(*new DocumentAnimationScheduler(document, displayID));
46 }
47 
48 DocumentAnimationScheduler::DocumentAnimationScheduler(Document& document, PlatformDisplayID displayID)
49  : m_document(&document)
50 {
51  windowScreenDidChange(displayID);
52 }
53 
54 DocumentAnimationScheduler::~DocumentAnimationScheduler() = default;
55 
56 void DocumentAnimationScheduler::detachFromDocument()
57 {
58  m_document = nullptr;
59 }
60 
61 bool DocumentAnimationScheduler::scheduleWebAnimationsResolution()
62 {
63  m_scheduledWebAnimationsResolution = true;
64  return DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
65 }
66 
67 void DocumentAnimationScheduler::unscheduleWebAnimationsResolution()
68 {
69  m_scheduledWebAnimationsResolution = false;
70 
71  if (!m_scheduledScriptedAnimationResolution)
72  DisplayRefreshMonitorManager::sharedManager().unregisterClient(*this);
73 }
74 
75 bool DocumentAnimationScheduler::scheduleScriptedAnimationResolution()
76 {
77  m_scheduledScriptedAnimationResolution = true;
78  return DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this);
79 }
80 
81 void DocumentAnimationScheduler::displayRefreshFired()
82 {
83  if (!m_document || !m_document->domWindow())
84  return;
85 
86  // This object could be deleted after scripts in the the requestAnimationFrame callbacks are executed.
87  auto protectedThis = makeRef(*this);
88 
89  m_isFiring = true;
90  m_lastTimestamp = Seconds(m_document->domWindow()->nowTimestamp());
91 
92  if (m_scheduledWebAnimationsResolution) {
93  m_scheduledWebAnimationsResolution = false;
94  m_document->timeline().documentAnimationSchedulerDidFire();
95  }
96 
97  if (m_scheduledScriptedAnimationResolution) {
98  m_scheduledScriptedAnimationResolution = false;
99  if (auto* scriptedAnimationController = m_document->scriptedAnimationController())
100  scriptedAnimationController->documentAnimationSchedulerDidFire();
101  }
102 
103  m_isFiring = false;
104 }
105 
106 void DocumentAnimationScheduler::windowScreenDidChange(PlatformDisplayID displayID)
107 {
108  DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, *this);
109 }
110 
111 RefPtr<DisplayRefreshMonitor> DocumentAnimationScheduler::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
112 {
113  if (!m_document || !m_document->page())
114  return nullptr;
115 
116  if (auto monitor = m_document->page()->chrome().client().createDisplayRefreshMonitor(displayID))
117  return monitor;
118 
119  return DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(displayID);
120 }
121 
122 } // namespace WebCore
123 
124 #endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)

Source/WebCore/animation/DocumentAnimationScheduler.h

1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #pragma once
27 
28 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
29 
30 #include "DisplayRefreshMonitorClient.h"
31 #include "PlatformScreen.h"
32 #include <wtf/Ref.h>
33 #include <wtf/RefCounted.h>
34 #include <wtf/RefPtr.h>
35 #include <wtf/Seconds.h>
36 
37 namespace WebCore {
38 
39 class Document;
40 
41 class DocumentAnimationScheduler : public RefCounted<DocumentAnimationScheduler>
42  , public DisplayRefreshMonitorClient {
43 public:
44  static Ref<DocumentAnimationScheduler> create(Document&, PlatformDisplayID);
45  ~DocumentAnimationScheduler();
46 
47  void detachFromDocument();
48  void windowScreenDidChange(PlatformDisplayID);
49 
50  bool scheduleWebAnimationsResolution();
51  void unscheduleWebAnimationsResolution();
52  bool scheduleScriptedAnimationResolution();
53 
54  Seconds lastTimestamp() { return m_lastTimestamp; }
55  bool isFiring() const { return m_isFiring; }
56 
57 private:
58  DocumentAnimationScheduler(Document&, PlatformDisplayID);
59 
60  RefPtr<Document> m_document;
61  bool m_scheduledWebAnimationsResolution { false };
62  bool m_scheduledScriptedAnimationResolution { false };
63  bool m_isFiring { false };
64  Seconds m_lastTimestamp { 0_s };
65 
66  void displayRefreshFired() override;
67  RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
68 };
69 
70 } // namespace WebCore
71 
72 #endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)

Source/WebCore/animation/DocumentTimeline.cpp

3333#include "DOMWindow.h"
3434#include "DeclarativeAnimation.h"
3535#include "Document.h"
36 #include "DocumentAnimationScheduler.h"
3736#include "GraphicsLayer.h"
3837#include "KeyframeEffect.h"
3938#include "Microtasks.h"

@@Ref<DocumentTimeline> DocumentTimeline::create(Document& document, DocumentTimel
6160
6261DocumentTimeline::DocumentTimeline(Document& document, Seconds originTime)
6362 : AnimationTimeline()
64 #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
65  , m_animationResolutionTimer(*this, &DocumentTimeline::animationResolutionTimerFired)
66 #endif
67  , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolutionIfNeeded)
 63 , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolution)
6864 , m_document(&document)
6965 , m_originTime(originTime)
7066{

@@Vector<RefPtr<WebAnimation>> DocumentTimeline::getAnimations() const
194190
195191void DocumentTimeline::updateThrottlingState()
196192{
197  scheduleAnimationResolutionIfNeeded();
 193 scheduleAnimationResolution();
198194}
199195
200196Seconds DocumentTimeline::animationInterval() const

@@void DocumentTimeline::suspendAnimations()
210206 return;
211207
212208 if (!m_cachedCurrentTime)
213  m_cachedCurrentTime = liveCurrentTime();
 209 m_cachedCurrentTime = Seconds(liveCurrentTime());
214210
215211 for (const auto& animation : m_animations)
216212 animation->setSuspended(true);

@@void DocumentTimeline::resumeAnimations()
234230 for (const auto& animation : m_animations)
235231 animation->setSuspended(false);
236232
237  scheduleAnimationResolutionIfNeeded();
 233 scheduleAnimationResolution();
238234}
239235
240236bool DocumentTimeline::animationsAreSuspended()

@@unsigned DocumentTimeline::numberOfActiveAnimationsForTesting() const
252248 return count;
253249}
254250
255 Seconds DocumentTimeline::liveCurrentTime() const
 251DOMHighResTimeStamp DocumentTimeline::liveCurrentTime() const
256252{
257 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
258  return m_document->animationScheduler().lastTimestamp();
259 #else
260  return Seconds(m_document->domWindow()->nowTimestamp());
261 #endif
 253 return m_document->domWindow()->nowTimestamp();
262254}
263255
264256Optional<Seconds> DocumentTimeline::currentTime()

@@Optional<Seconds> DocumentTimeline::currentTime()
274266 }
275267 }
276268
277  auto currentTime = liveCurrentTime();
278 
279 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
280  // If we're in the middle of firing a frame, either due to a requestAnimationFrame callback
281  // or scheduling an animation update, we want to ensure we use the same time we're using as
282  // the timestamp for requestAnimationFrame() callbacks.
283  if (m_document->animationScheduler().isFiring())
284  cacheCurrentTime(currentTime);
285 #endif
286 
287  if (!m_cachedCurrentTime) {
288 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
289  // If we're not in the middle of firing a frame, let's make our best guess at what the currentTime should
290  // be since the last time a frame fired by increment of our update interval. This way code using something
291  // like setTimeout() or handling events will get a time that's only updating at around 60fps, or less if
292  // we're throttled.
293  auto lastAnimationSchedulerTimestamp = currentTime;
294  auto delta = Seconds(m_document->domWindow()->nowTimestamp()) - lastAnimationSchedulerTimestamp;
295  int frames = std::floor(delta.seconds() / animationInterval().seconds());
296  cacheCurrentTime(lastAnimationSchedulerTimestamp + Seconds(frames * animationInterval().seconds()));
297 #else
298  cacheCurrentTime(currentTime);
299 #endif
300  }
 269 if (!m_cachedCurrentTime)
 270 cacheCurrentTime(liveCurrentTime());
 271
301272 return m_cachedCurrentTime.value() - m_originTime;
302273}
303274
304 void DocumentTimeline::cacheCurrentTime(Seconds newCurrentTime)
 275void DocumentTimeline::cacheCurrentTime(DOMHighResTimeStamp newCurrentTime)
305276{
306  m_cachedCurrentTime = newCurrentTime;
 277 m_cachedCurrentTime = Seconds(newCurrentTime);
307278 // We want to be sure to keep this time cached until we've both finished running JS and finished updating
308279 // animations, so we schedule the invalidation task and register a whenIdle callback on the VM, which will
309280 // fire syncronously if no JS is running.

@@void DocumentTimeline::maybeClearCachedCurrentTime()
326297 m_cachedCurrentTime = WTF::nullopt;
327298}
328299
329 void DocumentTimeline::scheduleAnimationResolutionIfNeeded()
330 {
331  if (!m_isUpdatingAnimations && !m_isSuspended && !m_animations.isEmpty())
332  scheduleAnimationResolution();
333 }
334 
335300void DocumentTimeline::animationTimingDidChange(WebAnimation& animation)
336301{
337302 AnimationTimeline::animationTimingDidChange(animation);
338  scheduleAnimationResolutionIfNeeded();
 303 scheduleAnimationResolution();
339304}
340305
341306void DocumentTimeline::removeAnimation(WebAnimation& animation)

@@void DocumentTimeline::removeAnimation(WebAnimation& animation)
348313
349314void DocumentTimeline::scheduleAnimationResolution()
350315{
351 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
352  m_document->animationScheduler().scheduleWebAnimationsResolution();
353 #else
354  // FIXME: We need to use the same logic as ScriptedAnimationController here,
355  // which will be addressed by the refactor tracked by webkit.org/b/179293.
356  m_animationResolutionTimer.startOneShot(animationInterval());
357 #endif
 316 if (m_isSuspended || m_animations.isEmpty() || m_animationResolutionScheduled)
 317 return;
 318
 319 if (!m_document || !m_document->page())
 320 return;
 321
 322 m_document->page()->renderingUpdateScheduler().scheduleRenderingUpdate();
 323 m_animationResolutionScheduled = true;
358324}
359325
360326void DocumentTimeline::unscheduleAnimationResolution()
361327{
362328 m_tickScheduleTimer.stop();
363 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
364  m_document->animationScheduler().unscheduleWebAnimationsResolution();
365 #else
366  // FIXME: We need to use the same logic as ScriptedAnimationController here,
367  // which will be addressed by the refactor tracked by webkit.org/b/179293.
368  m_animationResolutionTimer.stop();
369 #endif
370 }
371 
372 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
373 void DocumentTimeline::documentAnimationSchedulerDidFire()
374 #else
375 void DocumentTimeline::animationResolutionTimerFired()
376 #endif
377 {
378  updateAnimationsAndSendEvents();
 329 m_animationResolutionScheduled = false;
 330}
 331
 332void DocumentTimeline::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
 333{
 334 // We need to freeze the current time even if no animation is running.
 335 // document.timeline.currentTime may be called from a rAF callback and
 336 // it has to match the rAF timestamp.
 337 if (!m_isSuspended)
 338 cacheCurrentTime(timestamp);
 339
 340 if (m_isSuspended || m_animations.isEmpty() || !m_animationResolutionScheduled)
 341 return;
 342
 343 internalUpdateAnimationsAndSendEvents();
379344 applyPendingAcceleratedAnimations();
 345
 346 m_animationResolutionScheduled = false;
380347 scheduleNextTick();
381348}
382349
383 void DocumentTimeline::updateAnimationsAndSendEvents()
 350void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
384351{
385352 m_numberOfAnimationTimelineInvalidationsForTesting++;
386353
387  m_isUpdatingAnimations = true;
388 
389354 // https://drafts.csswg.org/web-animations/#update-animations-and-send-events
390355
391356 // 1. Update the current time of all timelines associated with doc passing now as the timestamp.

@@void DocumentTimeline::updateAnimationsAndSendEvents()
448413 // removed from the list of completed transitions otherwise.
449414 for (auto& completedTransition : completedTransitions)
450415 transitionDidComplete(completedTransition);
451 
452  m_isUpdatingAnimations = false;
453416}
454417
455418void DocumentTimeline::transitionDidComplete(RefPtr<CSSTransition> transition)

@@void DocumentTimeline::scheduleNextTick()
473436
474437 for (const auto& animation : m_animations) {
475438 if (!animation->isRunningAccelerated()) {
476  scheduleAnimationResolutionIfNeeded();
 439 scheduleAnimationResolution();
477440 return;
478441 }
479442 }

@@void DocumentTimeline::scheduleNextTick()
483446 for (const auto& animation : m_animations) {
484447 auto animationTimeToNextRequiredTick = animation->timeToNextTick();
485448 if (animationTimeToNextRequiredTick < animationInterval()) {
486  scheduleAnimationResolutionIfNeeded();
 449 scheduleAnimationResolution();
487450 return;
488451 }
489452 scheduleDelay = std::min(scheduleDelay, animationTimeToNextRequiredTick);

@@void DocumentTimeline::animationAcceleratedRunningStateDidChange(WebAnimation& a
593556void DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement(Element& element)
594557{
595558 auto animations = animationsForElement(element);
596  bool runningAnimationsForElementAreAllAccelerated = !animations.isEmpty();
 559
 560 if (animations.isEmpty()) {
 561 m_elementsWithRunningAcceleratedAnimations.remove(&element);
 562 return;
 563 }
 564
597565 for (const auto& animation : animations) {
598566 if (!animation->isRunningAccelerated()) {
599  runningAnimationsForElementAreAllAccelerated = false;
600  break;
 567 m_elementsWithRunningAcceleratedAnimations.remove(&element);
 568 return;
601569 }
602570 }
603571
604  if (runningAnimationsForElementAreAllAccelerated)
605  m_elementsWithRunningAcceleratedAnimations.add(&element);
606  else
607  m_elementsWithRunningAcceleratedAnimations.remove(&element);
 572 m_elementsWithRunningAcceleratedAnimations.add(&element);
608573}
609574
610575void DocumentTimeline::applyPendingAcceleratedAnimations()

@@void DocumentTimeline::applyPendingAcceleratedAnimations()
625590
626591bool DocumentTimeline::resolveAnimationsForElement(Element& element, RenderStyle& targetStyle)
627592{
628  bool hasNonAcceleratedAnimations = false;
629  bool hasPendingAcceleratedAnimations = true;
 593 bool hasNonAcceleratedAnimationProperty = false;
 594
630595 for (const auto& animation : animationsForElement(element)) {
631596 animation->resolve(targetStyle);
632  if (!hasNonAcceleratedAnimations) {
633  if (auto* effect = animation->effect()) {
634  if (is<KeyframeEffect>(effect)) {
635  auto* keyframeEffect = downcast<KeyframeEffect>(effect);
636  for (auto cssPropertyId : keyframeEffect->animatedProperties()) {
637  if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
638  hasNonAcceleratedAnimations = true;
639  continue;
640  }
641  if (!hasPendingAcceleratedAnimations)
642  hasPendingAcceleratedAnimations = keyframeEffect->hasPendingAcceleratedAction();
643  }
644  }
 597
 598 if (hasNonAcceleratedAnimationProperty)
 599 continue;
 600
 601 auto* effect = animation->effect();
 602 if (!effect || !is<KeyframeEffect>(effect))
 603 continue;
 604
 605 auto* keyframeEffect = downcast<KeyframeEffect>(effect);
 606 for (auto cssPropertyId : keyframeEffect->animatedProperties()) {
 607 if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
 608 hasNonAcceleratedAnimationProperty = true;
 609 break;
645610 }
646611 }
647612 }
648613
649  // If there are no non-accelerated animations and we've encountered at least one pending
650  // accelerated animation, we should recomposite this element's layer for animation purposes.
651  return !hasNonAcceleratedAnimations && hasPendingAcceleratedAnimations;
 614 return !hasNonAcceleratedAnimationProperty;
652615}
653616
654617bool DocumentTimeline::runningAnimationsForElementAreAllAccelerated(Element& element) const

Source/WebCore/animation/DocumentTimeline.h

@@public:
7171 void detachFromDocument();
7272
7373 void enqueueAnimationPlaybackEvent(AnimationPlaybackEvent&);
74 
75 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
76  void documentAnimationSchedulerDidFire();
77 #endif
 74
 75 void updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp);
7876
7977 void updateThrottlingState();
8078 WEBCORE_EXPORT Seconds animationInterval() const;

@@public:
8886private:
8987 DocumentTimeline(Document&, Seconds);
9088
91  Seconds liveCurrentTime() const;
92  void cacheCurrentTime(Seconds);
93  void scheduleAnimationResolutionIfNeeded();
 89 DOMHighResTimeStamp liveCurrentTime() const;
 90 void cacheCurrentTime(DOMHighResTimeStamp);
 91 void maybeClearCachedCurrentTime();
9492 void scheduleInvalidationTaskIfNeeded();
9593 void performInvalidationTask();
96  void animationScheduleTimerFired();
9794 void scheduleAnimationResolution();
9895 void unscheduleAnimationResolution();
99  void updateAnimationsAndSendEvents();
 96 void internalUpdateAnimationsAndSendEvents();
10097 void performEventDispatchTask();
101  void maybeClearCachedCurrentTime();
10298 void updateListOfElementsWithRunningAcceleratedAnimationsForElement(Element&);
10399 void transitionDidComplete(RefPtr<CSSTransition>);
104100 void scheduleNextTick();
105101
106 #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
107  void animationResolutionTimerFired();
108  Timer m_animationResolutionTimer;
109 #endif
110 
111102 Timer m_tickScheduleTimer;
112103 GenericTaskQueue<Timer> m_currentTimeClearingTaskQueue;
113104 HashSet<RefPtr<WebAnimation>> m_acceleratedAnimationsPendingRunningStateChange;

@@private:
119110 unsigned m_numberOfAnimationTimelineInvalidationsForTesting { 0 };
120111 bool m_isSuspended { false };
121112 bool m_waitingOnVMIdle { false };
122  bool m_isUpdatingAnimations { false };
 113 bool m_animationResolutionScheduled { false };
123114};
124115
125116} // namespace WebCore

Source/WebCore/dom/Document.cpp

5757#include "DOMWindow.h"
5858#include "DateComponents.h"
5959#include "DebugPageOverlays.h"
60 #include "DocumentAnimationScheduler.h"
6160#include "DocumentLoader.h"
6261#include "DocumentMarkerController.h"
6362#include "DocumentSharedObjectPool.h"

@@void Document::resolveStyle(ResolveStyleType type)
19571956 frameView.layoutContext().scheduleLayout();
19581957
19591958 // Usually this is handled by post-layout.
1960  if (!frameView.needsLayout()) {
 1959 if (!frameView.needsLayout())
19611960 frameView.frame().selection().scheduleAppearanceUpdateAfterStyleChange();
1962  if (m_needsForcedIntersectionObservationUpdate)
1963  page()->scheduleForcedIntersectionObservationUpdate(*this);
1964  }
19651961
19661962 // As a result of the style recalculation, the currently hovered element might have been
19671963 // detached (for example, by setting display:none in the :hover style), schedule another mouseMove event

@@void Document::prepareForDestruction()
25582554 m_timeline = nullptr;
25592555 }
25602556
2561 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
2562  if (m_animationScheduler) {
2563  m_animationScheduler->detachFromDocument();
2564  m_animationScheduler = nullptr;
2565  }
2566 #endif
2567 
25682557#if ENABLE(CSS_PAINTING_API)
25692558 for (auto& scope : m_paintWorkletGlobalScopes.values())
25702559 scope->prepareForDestruction();

@@void Document::resumeScriptedAnimationControllerCallbacks()
62616250 m_scriptedAnimationController->resume();
62626251}
62636252
6264 void Document::windowScreenDidChange(PlatformDisplayID displayID)
 6253void Document::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
62656254{
6266 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
6267  if (m_animationScheduler)
6268  m_animationScheduler->windowScreenDidChange(displayID);
6269 #endif
 6255 if (m_timeline)
 6256 m_timeline->updateAnimationsAndSendEvents(timestamp);
 6257}
 6258
 6259void Document::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
 6260{
 6261 if (m_scriptedAnimationController)
 6262 m_scriptedAnimationController->serviceRequestAnimationFrameCallbacks(timestamp);
 6263}
62706264
 6265void Document::windowScreenDidChange(PlatformDisplayID displayID)
 6266{
62716267 if (RenderView* view = renderView()) {
62726268 if (view->usesCompositing())
62736269 view->compositor().windowScreenDidChange(displayID);

@@void Document::updateIntersectionObservations()
79297925 if (needsLayout || hasPendingStyleRecalc())
79307926 return;
79317927
7932  m_needsForcedIntersectionObservationUpdate = false;
7933 
79347928 for (const auto& observer : m_intersectionObservers) {
79357929 bool needNotify = false;
79367930 DOMHighResTimeStamp timestamp;

@@void Document::updateIntersectionObservations()
80078001 m_intersectionObserversNotifyTimer.startOneShot(0_s);
80088002}
80098003
8010 void Document::scheduleForcedIntersectionObservationUpdate()
8011 {
8012  ASSERT(!m_intersectionObservers.isEmpty());
8013  if (m_needsForcedIntersectionObservationUpdate)
8014  return;
8015 
8016  m_needsForcedIntersectionObservationUpdate = true;
8017  if (auto* page = this->page())
8018  page->scheduleForcedIntersectionObservationUpdate(*this);
8019 }
8020 
80218004void Document::notifyIntersectionObserversTimerFired()
80228005{
80238006 for (const auto& observer : m_intersectionObserversWithPendingNotifications) {

@@void Document::setConsoleMessageListener(RefPtr<StringCallback>&& listener)
84518434 m_consoleMessageListener = listener;
84528435}
84538436
8454 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
8455 DocumentAnimationScheduler& Document::animationScheduler()
8456 {
8457  if (!m_animationScheduler)
8458  m_animationScheduler = DocumentAnimationScheduler::create(*this, page() ? page()->chrome().displayID() : 0);
8459 
8460  return *m_animationScheduler;
8461 }
8462 #endif
8463 
84648437DocumentTimeline& Document::timeline()
84658438{
84668439 if (!m_timeline)

Source/WebCore/dom/Document.h

@@class DOMWrapperWorld;
107107class Database;
108108class DatabaseThread;
109109class DeferredPromise;
110 class DocumentAnimationScheduler;
111110class DocumentFragment;
112111class DocumentLoader;
113112class DocumentMarkerController;

@@public:
10451044 ScriptedAnimationController* scriptedAnimationController() { return m_scriptedAnimationController.get(); }
10461045 void suspendScriptedAnimationControllerCallbacks();
10471046 void resumeScriptedAnimationControllerCallbacks();
1048 
 1047
 1048 void updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp);
 1049 void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
 1050
10491051 void windowScreenDidChange(PlatformDisplayID);
10501052
10511053 void finishedParsing();

@@public:
13981400 void addIntersectionObserver(IntersectionObserver&);
13991401 void removeIntersectionObserver(IntersectionObserver&);
14001402 unsigned numberOfIntersectionObservers() const { return m_intersectionObservers.size(); }
1401  void scheduleForcedIntersectionObservationUpdate();
14021403 void updateIntersectionObservations();
14031404#endif
14041405

@@public:
14711472
14721473 WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
14731474
1474 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
1475  DocumentAnimationScheduler& animationScheduler();
1476 #endif
1477 
14781475 WEBCORE_EXPORT DocumentTimeline& timeline();
14791476 DocumentTimeline* existingTimeline() const { return m_timeline.get(); }
14801477 Vector<RefPtr<WebAnimation>> getAnimations();

@@private:
20292026 bool m_isTelephoneNumberParsingAllowed { true };
20302027#endif
20312028
2032 #if ENABLE(INTERSECTION_OBSERVER)
2033  bool m_needsForcedIntersectionObservationUpdate { false };
2034 #endif
2035 
20362029#if ENABLE(MEDIA_STREAM)
20372030 HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements;
20382031 String m_idHashSalt;

@@private:
20522045
20532046 bool m_grantStorageAccessOverride { false };
20542047
2055 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
2056  RefPtr<DocumentAnimationScheduler> m_animationScheduler;
2057 #endif
20582048 RefPtr<DocumentTimeline> m_timeline;
20592049 DocumentIdentifier m_identifier;
20602050

Source/WebCore/dom/ScriptedAnimationController.cpp

3030#include "ChromeClient.h"
3131#include "DOMWindow.h"
3232#include "Document.h"
33 #include "DocumentAnimationScheduler.h"
3433#include "DocumentLoader.h"
3534#include "Frame.h"
3635#include "FrameView.h"

@@void ScriptedAnimationController::cancelCallback(CallbackId id)
189188 }
190189}
191190
192 void ScriptedAnimationController::serviceScriptedAnimations(double timestamp)
 191void ScriptedAnimationController::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
193192{
194193 if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
195194 return;

@@void ScriptedAnimationController::serviceScriptedAnimations(double timestamp)
197196 TraceScope tracingScope(RAFCallbackStart, RAFCallbackEnd);
198197
199198 // We round this to the nearest microsecond so that we can return a time that matches what is returned by document.timeline.currentTime.
200  double highResNowMs = std::round(1000 * timestamp);
201  double legacyHighResNowMs = 1000 * (timestamp + m_document->loader()->timing().referenceWallTime().secondsSinceEpoch().seconds());
 199 DOMHighResTimeStamp highResNowMs = std::round(1000 * timestamp);
 200 DOMHighResTimeStamp legacyHighResNowMs = 1000 * (timestamp + m_document->loader()->timing().referenceWallTime().secondsSinceEpoch().seconds());
202201
203202 // First, generate a list of callbacks to consider. Callbacks registered from this point
204203 // on are considered only for the "next" frame, not this one.

@@void ScriptedAnimationController::serviceScriptedAnimations(double timestamp)
210209 Ref<Document> protectedDocument(*m_document);
211210
212211 for (auto& callback : callbacks) {
213  if (!callback->m_firedOrCancelled) {
214  callback->m_firedOrCancelled = true;
215  InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(protectedDocument, callback->m_id);
216  if (callback->m_useLegacyTimeBase)
217  callback->handleEvent(legacyHighResNowMs);
218  else
219  callback->handleEvent(highResNowMs);
220  InspectorInstrumentation::didFireAnimationFrame(cookie);
221  }
 212 if (callback->m_firedOrCancelled)
 213 continue;
 214 callback->m_firedOrCancelled = true;
 215 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(protectedDocument, callback->m_id);
 216 if (callback->m_useLegacyTimeBase)
 217 callback->handleEvent(legacyHighResNowMs);
 218 else
 219 callback->handleEvent(highResNowMs);
 220 InspectorInstrumentation::didFireAnimationFrame(cookie);
222221 }
223222
224223 // Remove any callbacks we fired from the list of pending callbacks.
225  for (size_t i = 0; i < m_callbacks.size();) {
226  if (m_callbacks[i]->m_firedOrCancelled)
227  m_callbacks.remove(i);
228  else
229  ++i;
230  }
 224 m_callbacks.removeAllMatching([](auto& callback) {
 225 return callback->m_firedOrCancelled;
 226 });
231227
232228 if (m_callbacks.size())
233229 scheduleAnimation();

@@void ScriptedAnimationController::scheduleAnimation()
262258
263259#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
264260 if (!m_isUsingTimer && !isThrottled()) {
265  if (m_document->animationScheduler().scheduleScriptedAnimationResolution())
 261 if (auto* page = this->page()) {
 262 page->renderingUpdateScheduler().scheduleRenderingUpdate();
266263 return;
 264 }
267265
268266 m_isUsingTimer = true;
269267 }

@@void ScriptedAnimationController::scheduleAnimation()
292290void ScriptedAnimationController::animationTimerFired()
293291{
294292 m_lastAnimationFrameTimestamp = m_document->domWindow()->nowTimestamp();
295  serviceScriptedAnimations(m_lastAnimationFrameTimestamp);
 293 serviceRequestAnimationFrameCallbacks(m_lastAnimationFrameTimestamp);
296294}
297295
298 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
299 void ScriptedAnimationController::documentAnimationSchedulerDidFire()
300 {
301  // We obtain the time from the animation scheduler so that we use the same timestamp as the DocumentTimeline.
302  serviceScriptedAnimations(m_document->animationScheduler().lastTimestamp().seconds());
303 }
304 #endif
305 
306296}

Source/WebCore/dom/ScriptedAnimationController.h

@@public:
5252
5353 CallbackId registerCallback(Ref<RequestAnimationFrameCallback>&&);
5454 void cancelCallback(CallbackId);
55  void serviceScriptedAnimations(double timestamp);
 55 void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
5656
5757 void suspend();
5858 void resume();

@@public:
6969 WEBCORE_EXPORT bool isThrottled() const;
7070 WEBCORE_EXPORT Seconds interval() const;
7171
72 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
73  void documentAnimationSchedulerDidFire();
74 #endif
75 
7672private:
7773 ScriptedAnimationController(Document&);
7874

Source/WebCore/page/FrameView.cpp

@@void FrameView::viewportContentsChanged()
19621962 if (auto* renderView = frameView.frame().contentRenderer())
19631963 renderView->updateVisibleViewportRect(visibleRect);
19641964 });
1965 
1966 #if ENABLE(INTERSECTION_OBSERVER)
1967  if (auto* document = frame().document()) {
1968  if (auto* page = frame().page()) {
1969  if (document->numberOfIntersectionObservers())
1970  page->addDocumentNeedingIntersectionObservationUpdate(*document);
1971  if (!frame().isMainFrame()) {
1972  if (auto* mainDocument = frame().mainFrame().document()) {
1973  if (mainDocument->numberOfIntersectionObservers())
1974  page->addDocumentNeedingIntersectionObservationUpdate(*mainDocument);
1975  }
1976  }
1977  }
1978  }
1979 #endif
19801965}
19811966
19821967IntRect FrameView::unobscuredContentRectExpandedByContentInsets() const

Source/WebCore/page/IntersectionObserver.cpp

@@void IntersectionObserver::observe(Element& target)
157157 auto* document = trackingDocument();
158158 if (!hadObservationTargets)
159159 document->addIntersectionObserver(*this);
160  document->scheduleForcedIntersectionObservationUpdate();
161160}
162161
163162void IntersectionObserver::unobserve(Element& target)

Source/WebCore/page/Page.cpp

@@Page::Page(PageConfiguration&& pageConfiguration)
250250 , m_storageNamespaceProvider(*WTFMove(pageConfiguration.storageNamespaceProvider))
251251 , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
252252 , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
253 #if ENABLE(INTERSECTION_OBSERVER)
254  , m_intersectionObservationUpdateTimer(*this, &Page::updateIntersectionObservations)
255 #endif
256253 , m_sessionID(PAL::SessionID::defaultSessionID())
257254#if ENABLE(VIDEO)
258255 , m_playbackControlsManagerUpdateTimer(*this, &Page::playbackControlsManagerUpdateTimerFired)

@@void Page::didFinishLoad()
11111108 m_performanceMonitor->didFinishLoad();
11121109}
11131110
1114 void Page::willDisplayPage()
1115 {
1116 #if ENABLE(INTERSECTION_OBSERVER)
1117  updateIntersectionObservations();
1118 #endif
1119 }
1120 
11211111bool Page::isOnlyNonUtilityPage() const
11221112{
11231113 return !isUtilityPage() && nonUtilityPageCount == 1;

@@void Page::removeActivityStateChangeObserver(ActivityStateChangeObserver& observ
12591249 m_activityStateChangeObservers.remove(&observer);
12601250}
12611251
1262 #if ENABLE(INTERSECTION_OBSERVER)
1263 void Page::addDocumentNeedingIntersectionObservationUpdate(Document& document)
 1252void Page::layoutIfNeeded()
12641253{
1265  if (m_documentsNeedingIntersectionObservationUpdate.find(&document) == notFound)
1266  m_documentsNeedingIntersectionObservationUpdate.append(makeWeakPtr(document));
 1254 if (FrameView* view = m_mainFrame->view())
 1255 view->updateLayoutAndStyleIfNeededRecursive();
12671256}
12681257
1269 void Page::updateIntersectionObservations()
 1258void Page::renderingUpdate()
12701259{
1271  m_intersectionObservationUpdateTimer.stop();
1272  for (const auto& document : m_documentsNeedingIntersectionObservationUpdate) {
1273  if (document)
1274  document->updateIntersectionObservations();
 1260 // This function is not reentrant, e.g. a rAF callback may force repaint.
 1261 if (m_inRenderingUpdate) {
 1262 layoutIfNeeded();
 1263 return;
12751264 }
1276  m_documentsNeedingIntersectionObservationUpdate.clear();
1277 }
12781265
1279 void Page::scheduleForcedIntersectionObservationUpdate(Document& document)
1280 {
1281  addDocumentNeedingIntersectionObservationUpdate(document);
1282  if (m_intersectionObservationUpdateTimer.isActive())
1283  return;
1284  m_intersectionObservationUpdateTimer.startOneShot(0_s);
1285 }
 1266 SetForScope<bool> change(m_inRenderingUpdate, true);
 1267
 1268 Vector<RefPtr<Document>> documents;
 1269
 1270 // The requestAnimationFrame callbacks may change the frame hierarchy of the page
 1271 forEachDocument([&documents] (Document& document) {
 1272 documents.append(&document);
 1273 });
 1274
 1275 for (auto& document : documents) {
 1276 DOMHighResTimeStamp timestamp = document->domWindow()->nowTimestamp();
 1277 document->updateAnimationsAndSendEvents(timestamp);
 1278 document->serviceRequestAnimationFrameCallbacks(timestamp);
 1279 }
 1280
 1281 layoutIfNeeded();
 1282
 1283 for (auto& document : documents) {
 1284#if ENABLE(INTERSECTION_OBSERVER)
 1285 document->updateIntersectionObservations();
12861286#endif
 1287 }
 1288}
12871289
12881290void Page::suspendScriptedAnimations()
12891291{

@@void Page::didChangeMainDocument()
28232825#endif
28242826}
28252827
 2828RenderingUpdateScheduler& Page::renderingUpdateScheduler()
 2829{
 2830 if (!m_renderingUpdateScheduler)
 2831 m_renderingUpdateScheduler = RenderingUpdateScheduler::create(*this);
 2832 return *m_renderingUpdateScheduler;
 2833}
 2834
28262835void Page::forEachDocument(const Function<void(Document&)>& functor)
28272836{
28282837 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {

Source/WebCore/page/Page.h

3333#include "RTCController.h"
3434#include "Region.h"
3535#include "RegistrableDomain.h"
 36#include "RenderingUpdateScheduler.h"
3637#include "ScrollTypes.h"
3738#include "Supplementable.h"
3839#include "Timer.h"

@@public:
262263
263264 PerformanceMonitor* performanceMonitor() { return m_performanceMonitor.get(); }
264265
 266 RenderingUpdateScheduler& renderingUpdateScheduler();
 267
265268 ValidationMessageClient* validationMessageClient() const { return m_validationMessageClient.get(); }
266269 void updateValidationBubbleStateIfNeeded();
267270

@@public:
334337 void didStartProvisionalLoad();
335338 void didFinishLoad(); // Called when the load has been committed in the main frame.
336339
337  WEBCORE_EXPORT void willDisplayPage();
338 
339340 // The view scale factor is multiplied into the page scale factor by all
340341 // callers of setPageScaleFactor.
341342 WEBCORE_EXPORT void setViewScaleFactor(float);

@@public:
463464 WEBCORE_EXPORT void addActivityStateChangeObserver(ActivityStateChangeObserver&);
464465 WEBCORE_EXPORT void removeActivityStateChangeObserver(ActivityStateChangeObserver&);
465466
466 #if ENABLE(INTERSECTION_OBSERVER)
467  void addDocumentNeedingIntersectionObservationUpdate(Document&);
468  void scheduleForcedIntersectionObservationUpdate(Document&);
469  void updateIntersectionObservations();
470 #endif
 467 WEBCORE_EXPORT void layoutIfNeeded();
 468 WEBCORE_EXPORT void renderingUpdate();
471469
472470 WEBCORE_EXPORT void suspendScriptedAnimations();
473471 WEBCORE_EXPORT void resumeScriptedAnimations();

@@private:
862860 int m_headerHeight { 0 };
863861 int m_footerHeight { 0 };
864862
 863 std::unique_ptr<RenderingUpdateScheduler> m_renderingUpdateScheduler;
 864
865865 HashSet<RenderObject*> m_relevantUnpaintedRenderObjects;
866866 Region m_topRelevantPaintedRegion;
867867 Region m_bottomRelevantPaintedRegion;

@@private:
902902
903903 HashSet<ActivityStateChangeObserver*> m_activityStateChangeObservers;
904904
905 #if ENABLE(INTERSECTION_OBSERVER)
906  Vector<WeakPtr<Document>> m_documentsNeedingIntersectionObservationUpdate;
907 
908  // FIXME: Schedule intersection observation updates in a way that fits into the HTML
909  // EventLoop. See https://bugs.webkit.org/show_bug.cgi?id=160711.
910  Timer m_intersectionObservationUpdateTimer;
911 #endif
912 
913905#if ENABLE(RESOURCE_USAGE)
914906 std::unique_ptr<ResourceUsageOverlay> m_resourceUsageOverlay;
915907#endif

@@private:
970962 bool m_shouldEnableICECandidateFilteringByDefault { true };
971963 bool m_mediaPlaybackIsSuspended { false };
972964 bool m_mediaBufferingIsSuspended { false };
 965 bool m_inRenderingUpdate { false };
973966};
974967
975968inline PageGroup& Page::group()

Source/WebCore/page/PageOverlayController.cpp

@@void PageOverlayController::didChangeDeviceScaleFactor()
318318
319319void PageOverlayController::didChangeViewExposedRect()
320320{
321  m_page.chrome().client().scheduleCompositingLayerFlush();
 321 m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
322322}
323323
324324void PageOverlayController::didScrollFrame(Frame& frame)

@@float PageOverlayController::deviceScaleFactor() const
412412
413413void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
414414{
415  m_page.chrome().client().scheduleCompositingLayerFlush();
 415 m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
416416}
417417
418418void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)

Source/WebCore/page/RenderingUpdateScheduler.cpp

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "RenderingUpdateScheduler.h"
 28
 29#include "Chrome.h"
 30#include "ChromeClient.h"
 31#include "DisplayRefreshMonitorManager.h"
 32#include "Page.h"
 33#include <wtf/SystemTracing.h>
 34
 35namespace WebCore {
 36
 37RenderingUpdateScheduler::RenderingUpdateScheduler(Page& page)
 38 : m_page(page)
 39{
 40#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 41 windowScreenDidChange(page.chrome().displayID());
 42#endif
 43}
 44
 45void RenderingUpdateScheduler::scheduleRenderingUpdate()
 46{
 47 if (isScheduled())
 48 return;
 49
 50 tracePoint(ScheduleRenderingUpdate);
 51
 52#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 53 if (DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this))
 54 m_scheduled = true;
 55 else
 56#endif
 57 startTimer(Seconds(1.0 / 60));
 58}
 59
 60bool RenderingUpdateScheduler::isScheduled() const
 61{
 62#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 63 if (m_scheduled)
 64 return true;
 65#endif
 66 return m_refreshTimer.get();
 67}
 68
 69void RenderingUpdateScheduler::startTimer(Seconds delay)
 70{
 71 ASSERT(!isScheduled());
 72 m_refreshTimer = std::make_unique<Timer>(*this, &RenderingUpdateScheduler::displayRefreshFired);
 73 m_refreshTimer->startOneShot(delay);
 74}
 75
 76void RenderingUpdateScheduler::clearScheduled()
 77{
 78#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 79 m_scheduled = false;
 80#endif
 81 m_refreshTimer = nullptr;
 82}
 83
 84#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 85void RenderingUpdateScheduler::windowScreenDidChange(PlatformDisplayID displayID)
 86{
 87 DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, *this);
 88}
 89
 90RefPtr<DisplayRefreshMonitor> RenderingUpdateScheduler::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
 91{
 92 if (auto monitor = m_page.chrome().client().createDisplayRefreshMonitor(displayID))
 93 return monitor;
 94
 95 return DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(displayID);
 96}
 97#endif
 98
 99void RenderingUpdateScheduler::displayRefreshFired()
 100{
 101 tracePoint(TriggerRenderingUpdate);
 102
 103 clearScheduled();
 104 m_page.chrome().client().scheduleCompositingLayerFlush();
 105}
 106
 107}

Source/WebCore/page/RenderingUpdateScheduler.h

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#include "DisplayRefreshMonitorClient.h"
 29#include <wtf/Seconds.h>
 30
 31namespace WebCore {
 32
 33class Page;
 34class Timer;
 35
 36class RenderingUpdateScheduler
 37#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 38 : public DisplayRefreshMonitorClient
 39#endif
 40{
 41 WTF_MAKE_FAST_ALLOCATED;
 42public:
 43 static std::unique_ptr<RenderingUpdateScheduler> create(Page& page)
 44 {
 45 return std::make_unique<RenderingUpdateScheduler>(page);
 46 }
 47
 48 RenderingUpdateScheduler(Page&);
 49 void scheduleRenderingUpdate();
 50
 51#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 52 void windowScreenDidChange(PlatformDisplayID);
 53#endif
 54
 55private:
 56#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 57 RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const final;
 58 void displayRefreshFired() final;
 59#else
 60 void displayRefreshFired();
 61#endif
 62
 63 bool isScheduled() const;
 64 void startTimer(Seconds);
 65 void clearScheduled();
 66
 67 Page& m_page;
 68#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 69 bool m_scheduled { false };
 70#endif
 71 std::unique_ptr<Timer> m_refreshTimer;
 72};
 73
 74}

Source/WebCore/page/ios/ContentChangeObserver.h

2727
2828#if PLATFORM(IOS_FAMILY)
2929
 30#include "Document.h"
 31#include "RenderStyleConstants.h"
3032#include "WKContentObservation.h"
 33#include <wtf/HashSet.h>
 34#include <wtf/Seconds.h>
3135
3236namespace WebCore {
3337
3438class DOMTimer;
35 class Document;
 39class Element;
3640
3741class ContentChangeObserver {
3842public:

Source/WebCore/page/mac/ServicesOverlayController.mm

@@void ServicesOverlayController::Highlight::notifyFlushRequired(const GraphicsLay
121121 if (!m_controller)
122122 return;
123123
124  m_controller->page().chrome().client().scheduleCompositingLayerFlush();
 124 m_controller->page().renderingUpdateScheduler().scheduleRenderingUpdate();
125125}
126126
127127void ServicesOverlayController::Highlight::paintContents(const GraphicsLayer*, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const FloatRect&, GraphicsLayerPaintBehavior)

Source/WebCore/rendering/RenderLayerCompositor.cpp

@@void RenderLayerCompositor::notifyFlushRequired(const GraphicsLayer* layer)
431431void RenderLayerCompositor::scheduleLayerFlushNow()
432432{
433433 m_hasPendingLayerFlush = false;
434  page().chrome().client().scheduleCompositingLayerFlush();
 434 page().renderingUpdateScheduler().scheduleRenderingUpdate();
435435}
436436
437437void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)

Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp

@@void DrawingAreaCoordinatedGraphics::updateBackingStoreState(uint64_t stateID, b
381381
382382 m_webPage.setDeviceScaleFactor(deviceScaleFactor);
383383 m_webPage.setSize(size);
384  m_webPage.layoutIfNeeded();
 384 m_webPage.renderingUpdate();
385385 m_webPage.flushPendingEditorStateUpdate();
386386 m_webPage.scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
387  m_webPage.willDisplayPage();
388387
389388 if (m_layerTreeHost)
390389 m_layerTreeHost->sizeDidChange(m_webPage.size());

@@void DrawingAreaCoordinatedGraphics::display(UpdateInfo& updateInfo)
703702 ASSERT(!m_layerTreeHost);
704703 ASSERT(!m_webPage.size().isEmpty());
705704
706  m_webPage.layoutIfNeeded();
 705 m_webPage.renderingUpdate();
707706 m_webPage.flushPendingEditorStateUpdate();
708707
709708 // The layout may have put the page into accelerated compositing mode. If the LayerTreeHost is

@@void DrawingAreaCoordinatedGraphics::display(UpdateInfo& updateInfo)
711710 if (m_layerTreeHost)
712711 return;
713712
714  m_webPage.willDisplayPage();
715713 updateInfo.viewSize = m_webPage.size();
716714 updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
717715

Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp

@@void LayerTreeHost::layerFlushTimerFired()
145145 return;
146146
147147 m_coordinator.syncDisplayState();
 148 m_webPage.renderingUpdate();
148149 m_webPage.flushPendingEditorStateUpdate();
149  m_webPage.willDisplayPage();
150150
151151 if (!m_isValid || !m_coordinator.rootCompositingLayer())
152152 return;

Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm

@@void RemoteLayerTreeDrawingArea::flushLayers()
349349 RemoteLayerBackingStoreCollection& backingStoreCollection = m_remoteLayerTreeContext->backingStoreCollection();
350350 backingStoreCollection.willFlushLayers();
351351
352  m_webPage.layoutIfNeeded();
353  m_webPage.willDisplayPage();
 352 m_webPage.renderingUpdate();
354353
355354 FloatRect visibleRect(FloatPoint(), m_viewSize);
356355 if (m_scrolledViewExposedRect)

Source/WebKit/WebProcess/WebPage/WebPage.cpp

@@void WebPage::tryRestoreScrollPosition()
15541554 m_page->mainFrame().loader().history().restoreScrollPositionAndViewState();
15551555}
15561556
1557 void WebPage::layoutIfNeeded()
1558 {
1559  if (m_mainFrame->coreFrame()->view())
1560  m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
1561 }
1562 
15631557WebPage* WebPage::fromCorePage(Page* page)
15641558{
15651559 return &static_cast<WebChromeClient&>(page->chrome().client()).page();

@@void WebPage::didFlushLayerTreeAtTime(MonotonicTime timestamp)
35873581}
35883582#endif
35893583
3590 void WebPage::willDisplayPage()
 3584void WebPage::layoutIfNeeded()
 3585{
 3586 m_page->layoutIfNeeded();
 3587}
 3588
 3589void WebPage::renderingUpdate()
35913590{
3592  m_page->willDisplayPage();
 3591 m_page->renderingUpdate();
35933592}
35943593
35953594WebInspector* WebPage::inspector(LazyCreationPolicy behavior)

Source/WebKit/WebProcess/WebPage/WebPage.h

@@public:
301301 void didFlushLayerTreeAtTime(MonotonicTime);
302302#endif
303303
304  void willDisplayPage();
 304 void layoutIfNeeded();
 305 void renderingUpdate();
305306
306307 enum class LazyCreationPolicy { UseExistingOnly, CreateIfNeeded };
307308

@@public:
334335 // -- Called by the DrawingArea.
335336 // FIXME: We could genericize these into a DrawingArea client interface. Would that be beneficial?
336337 void drawRect(WebCore::GraphicsContext&, const WebCore::IntRect&);
337  void layoutIfNeeded();
338338
339339 // -- Called from WebCore clients.
340340 bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*);

Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

5959#import <pal/spi/cocoa/QuartzCoreSPI.h>
6060#import <wtf/MachSendRight.h>
6161#import <wtf/MainThread.h>
 62#import <wtf/SystemTracing.h>
6263
6364#if ENABLE(ASYNC_SCROLLING)
6465#import <WebCore/AsyncScrollingCoordinator.h>

@@void TiledCoreAnimationDrawingArea::flushLayers()
459460 if (layerTreeStateIsFrozen())
460461 return;
461462
 463 TraceScope traceScope(RenderingUpdateStart, RenderingUpdateEnd);
 464
462465 @autoreleasepool {
463466 scaleViewToFitDocumentIfNeeded();
464467
465  m_webPage.layoutIfNeeded();
 468 m_webPage.renderingUpdate();
466469 m_webPage.flushPendingEditorStateUpdate();
467  m_webPage.willDisplayPage();
468470
469471 updateIntrinsicContentSizeIfNeeded();
470472

Source/WebKitLegacy/mac/WebView/WebView.mm

@@static void WebKitInitializeGamepadProviderIfNecessary()
16201620
16211621- (void)_viewWillDrawInternal
16221622{
1623  Frame* frame = [self _mainCoreFrame];
1624  if (frame && frame->view())
1625  frame->view()->updateLayoutAndStyleIfNeededRecursive();
 1623 if (_private->page)
 1624 _private->page->renderingUpdate();
16261625}
16271626
16281627+ (NSArray *)_supportedMIMETypes

Source/WebKitLegacy/win/WebView.cpp

@@void WebView::updateBackingStore(FrameView* frameView, HDC dc, bool backingStore
11731173
11741174 if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
11751175 // Do a layout first so that everything we render to the backing store is always current.
1176  if (Frame* coreFrame = core(m_mainFrame))
1177  if (FrameView* view = coreFrame->view())
1178  view->updateLayoutAndStyleIfNeededRecursive();
 1176 m_page->renderingUpdate();
11791177
11801178 Vector<IntRect> paintRects;
11811179 if (!backingStoreCompletelyDirty && m_backingStoreDirtyRegion) {

@@void WebView::setRootChildLayer(GraphicsLayer* layer)
71597157void WebView::flushPendingGraphicsLayerChangesSoon()
71607158{
71617159#if USE(CA)
7162  if (!m_layerTreeHost)
 7160 if (!m_layerTreeHost) {
 7161 m_page->renderingUpdate();
71637162 return;
 7163 }
71647164 m_layerTreeHost->flushPendingGraphicsLayerChangesSoon();
71657165#elif USE(TEXTURE_MAPPER_GL)
71667166 if (!m_acceleratedCompositingContext)

@@void WebView::flushPendingGraphicsLayerChanges()
73887388 if (!isAcceleratedCompositing())
73897389 return;
73907390
7391  view->updateLayoutAndStyleIfNeededRecursive();
 7391 m_page->renderingUpdate();
73927392
73937393 // Updating layout might have taken us out of compositing mode.
73947394 if (m_backingLayer)

Tools/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 Add trace points for the page RenderingUpdate.
 9
 10 * Tracing/SystemTracePoints.plist:
 11
1122019-03-06 Rob Buis <rbuis@igalia.com>
213
314 Consider supporting the `referrerpolicy` attribute.

Tools/Tracing/SystemTracePoints.plist

216216 <key>CodeEnd</key>
217217 <string>5027</string>
218218 </dict>
 219 <dict>
 220 <key>Name</key>
 221 <string>Schedule rendering update</string>
 222 <key>Type</key>
 223 <string>Impulse</string>
 224 <key>Component</key>
 225 <string>47</string>
 226 <key>Code</key>
 227 <string>5028</string>
 228 </dict>
 229 <dict>
 230 <key>Name</key>
 231 <string>Trigger rendering update</string>
 232 <key>Type</key>
 233 <string>Impulse</string>
 234 <key>Component</key>
 235 <string>47</string>
 236 <key>Code</key>
 237 <string>5029</string>
 238 </dict>
 239 <dict>
 240 <key>Name</key>
 241 <string>Rendering update</string>
 242 <key>Type</key>
 243 <string>Interval</string>
 244 <key>Component</key>
 245 <string>47</string>
 246 <key>CodeBegin</key>
 247 <string>5030</string>
 248 <key>CodeEnd</key>
 249 <string>5031</string>
 250 </dict>
219251 <dict>
220252 <key>Name</key>
221253 <string>Paint WebHTMLView</string>

LayoutTests/ChangeLog

 12019-03-06 Said Abou-Hallawa <sabouhallawa@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6 Reviewed by Simon Fraser.
 7
 8 * TestExpectations:
 9 There is a slight difference between the actual DRT and the expected DRT
 10 due to animation timing change. But these two tests are not animating
 11 correctly if they are opened in Safari with web animation turned on.
 12
 13 * animations/animation-multiple-callbacks-timestamp.html:
 14 Fix variable names used by an error message.
 15 * animations/no-style-recalc-during-accelerated-animation-expected.txt:
 16 * animations/no-style-recalc-during-accelerated-animation.html:
 17 One extra styleReclc was incurred due to the document styleRecalcTimer.
 18 I think this timer is not needed anymore. I will look at removing it in
 19 a separate patch.
 20
1212019-03-06 Devin Rousso <drousso@apple.com>
222
323 Web Inspector: DOM Debugger: event breakpoints still fire when breakpoints are disabled

LayoutTests/TestExpectations

@@webkit.org/b/187773 http/tests/webAPIStatistics [ Skip ]
30093009
30103010# This is fallout from turning Web Animations on.
30113011webkit.org/b/190032 animations/animation-playstate-paused-style-resolution.html [ Failure ]
 3012webkit.org/b/190032 animations/missing-values-first-keyframe.html [ Failure ]
 3013webkit.org/b/190032 animations/missing-values-last-keyframe.html [ Failure ]
30123014webkit.org/b/190032 compositing/backing/backing-store-attachment-fill-forwards-animation.html [ Failure ]
30133015webkit.org/b/190032 compositing/backing/transform-transition-from-outside-view.html [ Failure ]
30143016webkit.org/b/190032 compositing/layer-creation/mismatched-rotated-transform-transition-overlap.html [ Failure ]

LayoutTests/animations/animation-multiple-callbacks-timestamp.html

3535 {
3636 const WarmupFrames = 5;
3737 if (++currentFrame > WarmupFrames && timestamp != timestamp1) {
38  testFailed("timestamp1 = " + timestamp1 + ", timestamp2 = " + timestamp2 + ", window.performance.now() = " + window.performance.now());
 38 testFailed("timestamp = " + timestamp + ", timestamp1 = " + timestamp1 + ", window.performance.now() = " + window.performance.now());
3939 failed = true;
4040 }
4141 }

LayoutTests/animations/no-style-recalc-during-accelerated-animation-expected.txt

11Got iteration event.
2 PASS: saw two or fewer style recalcs during the animation.
 2PASS: saw three or fewer style recalcs during the animation.

LayoutTests/animations/no-style-recalc-during-accelerated-animation.html

3535 box.addEventListener("animationiteration", () => result.innerText = "Got iteration event.\n");
3636 box.addEventListener("animationend", () => {
3737 const numRecalcs = internals.styleRecalcCount();
38  if (numRecalcs > 2)
39  result.innerText += "FAIL: saw " + numRecalcs + " style recalcs during the animation, should only see two."
 38 if (numRecalcs > 3)
 39 result.innerText += "FAIL: saw " + numRecalcs + " style recalcs during the animation, should only see three."
4040 else
41  result.innerText += "PASS: saw two or fewer style recalcs during the animation."
 41 result.innerText += "PASS: saw three or fewer style recalcs during the animation."
4242
4343 if (window.testRunner)
4444 testRunner.notifyDone();