LayoutTests/ChangeLog

 12019-02-23 Said Abou-Hallawa <said@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 NOBODY (OOPS!).
 7
 8 * animations/animation-multiple-callbacks-timestamp.html:
 9 * fast/animation/request-animation-frame-in-two-pages.html:
 10 * legacy-animation-engine/animations/animation-multiple-callbacks-timestamp.html:
 11
1122019-02-20 Dean Jackson <dino@apple.com>
213
314 Rotation animations sometimes use the wrong origin (affects apple.com)

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/fast/animation/request-animation-frame-in-two-pages.html

@@function onload()
3030
3131 function raf()
3232 {
33  requestAnimationFrame(raf);
3433 if (c == 10) {
3534 src = "data:text/html, <script> c = 0; function raf() { requestAnimationFrame(raf); if (c++ == 10) window.close(); } requestAnimationFrame(raf); <\/script>";
3635 newWindow = window.open(src, "_blank");

@@function onload()
4039 }
4140 if (c == 20) {
4241 log("PASS");
43  if (window.testRunner)
 42 if (window.testRunner) {
4443 testRunner.notifyDone();
 44 return;
 45 }
4546 }
4647 c++;
 48 requestAnimationFrame(raf);
4749 }
4850 requestAnimationFrame(raf)
4951}

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

88 var currentFrame = 0;
99 var timestamp1 = 0;
1010 var failed = false;
 11 var doAnimation2CallbackId;
1112
1213 function finishTest()
1314 {

2324 timestamp1 = timestamp;
2425
2526 const MaxFrames = 25;
26  if (currentFrame == MaxFrames)
 27 if (currentFrame == MaxFrames) {
 28 cancelAnimationFrame(doAnimation2CallbackId);
2729 finishTest();
28  else {
 30 } else {
2931 requestAnimationFrame(doAnimation1);
30  requestAnimationFrame(doAnimation2);
 32 doAnimation2CallbackId = requestAnimationFrame(doAnimation2);
3133 }
3234 }
3335

Source/WTF/ChangeLog

 12019-02-23 Said Abou-Hallawa <said@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 NOBODY (OOPS!).
 7
 8 Add tracing signposts for requestAnimationFrame scheduling and flushing
 9 the layers interval.
 10
 11 * wtf/SystemTracing.h:
 12
1132019-02-20 Dean Jackson <dino@apple.com>
214
315 Rotation animations sometimes use the wrong origin (affects apple.com)

Source/WTF/wtf/SystemTracing.h

@@enum TracePointCode {
7575 DisplayListRecordEnd,
7676 DisplayRefreshDispatchingToMainThread,
7777
 78 ScheduleRenderingUpdate,
 79 TriggerRenderingUpdate,
 80 RenderingUpdateStart,
 81 RenderingUpdateEnd,
 82
7883 WebKitRange = 10000,
7984 WebHTMLViewPaintStart,
8085 WebHTMLViewPaintEnd,

Source/WebCore/ChangeLog

 12019-02-23 Said Abou-Hallawa <said@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 NOBODY (OOPS!).
 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 driven
 20 by a "RenderingScheduler", which only triggers paints once per 16.7ms frame.
 21
 22 Code that previously scheduled a compositing layer flush now schedules a
 23 "render", and that render is driven by a DisplayRefreshMonitor callback.
 24 When the render happens, we service requestAnimationFrame callbacks,
 25 intersection observations and Web Animations per the "Update the rendering"
 26 step of the HTML Event Loop specification
 27 <https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>.
 28
 29 In the future, more rendering steps will be added to this code.
 30
 31 * Sources.txt:
 32 * WebCore.xcodeproj/project.pbxproj:
 33 * animation/DocumentAnimationScheduler.cpp: Removed.
 34 * animation/DocumentTimeline.cpp:
 35 (WebCore::DocumentTimeline::DocumentTimeline):
 36 (WebCore::DocumentTimeline::detachFromDocument):
 37 (WebCore::DocumentTimeline::liveCurrentTime const):
 38 (WebCore::DocumentTimeline::currentTime):
 39 (WebCore::DocumentTimeline::scheduleAnimationResolution):
 40 (WebCore::DocumentTimeline::unscheduleAnimationResolution):
 41 (WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
 42 (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
 43 (WebCore::DocumentTimeline::animationResolutionTimerFired): Deleted.
 44 * animation/DocumentTimeline.h:
 45 * dom/Document.cpp:
 46 (WebCore::Document::resolveStyle):
 47 (WebCore::Document::prepareForDestruction):
 48 (WebCore::Document::updateAnimationsAndSendEvents):
 49 (WebCore::Document::serviceRequestAnimationFrameCallbacks):
 50 (WebCore::Document::windowScreenDidChange):
 51 (WebCore::Document::updateIntersectionObservations):
 52 (WebCore::Document::scheduleForcedIntersectionObservationUpdate): Deleted.
 53 (WebCore::Document::animationScheduler): Deleted.
 54 * dom/Document.h:
 55 (WebCore::Document::numberOfIntersectionObservers const):
 56 * dom/ScriptedAnimationController.cpp:
 57 (WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
 58 (WebCore::ScriptedAnimationController::scheduleAnimation):
 59 (WebCore::ScriptedAnimationController::animationTimerFired):
 60 (WebCore::ScriptedAnimationController::serviceScriptedAnimations): Deleted.
 61 (WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire): Deleted.
 62 * dom/ScriptedAnimationController.h:
 63 * page/FrameTree.cpp:
 64 * page/FrameView.cpp:
 65 (WebCore::FrameView::viewportContentsChanged):
 66 * page/IntersectionObserver.cpp:
 67 (WebCore::IntersectionObserver::observe):
 68 * page/Page.cpp:
 69 (WebCore::Page::Page):
 70 (WebCore::Page::layoutIfNeeded):
 71 (WebCore::Page::updateRendering):
 72 (WebCore::Page::renderingScheduler):
 73 (WebCore::Page::willDisplayPage): Deleted.
 74 (WebCore::Page::addDocumentNeedingIntersectionObservationUpdate): Deleted.
 75 (WebCore::Page::updateIntersectionObservations): Deleted.
 76 (WebCore::Page::scheduleForcedIntersectionObservationUpdate): Deleted.
 77 * page/Page.h:
 78 * page/PageOverlayController.cpp:
 79 (WebCore::PageOverlayController::didChangeViewExposedRect):
 80 (WebCore::PageOverlayController::notifyFlushRequired):
 81 * page/RenderingScheduler.cpp: Added.
 82 (WebCore::RenderingScheduler::RenderingScheduler):
 83 (WebCore::RenderingScheduler::scheduleRender):
 84 (WebCore::RenderingScheduler::startTimer):
 85 (WebCore::RenderingScheduler::clearTimer):
 86 (WebCore::RenderingScheduler::windowScreenDidChange):
 87 (WebCore::RenderingScheduler::createDisplayRefreshMonitor const):
 88 (WebCore::RenderingScheduler::displayRefreshFired):
 89 * page/RenderingScheduler.h: Renamed from Source/WebCore/animation/DocumentAnimationScheduler.h.
 90 (WebCore::RenderingScheduler::create):
 91 * page/mac/ServicesOverlayController.mm:
 92 (WebCore::ServicesOverlayController::Highlight::notifyFlushRequired):
 93 * rendering/RenderLayerCompositor.cpp:
 94 (WebCore::RenderLayerCompositor::scheduleLayerFlushNow):
 95
1962019-02-20 Dean Jackson <dino@apple.com>
297
398 Rotation animations sometimes use the wrong origin (affects apple.com)

Source/WebCore/Sources.txt

@@animation/AnimationTimeline.cpp
416416animation/CSSAnimation.cpp
417417animation/CSSTransition.cpp
418418animation/DeclarativeAnimation.cpp
419 animation/DocumentAnimationScheduler.cpp
420419animation/DocumentTimeline.cpp
421420animation/KeyframeEffect.cpp
422421animation/WebAnimation.cpp

@@page/ProcessWarming.cpp
15351534page/Quirks.cpp
15361535page/RemoteDOMWindow.cpp
15371536page/RemoteFrame.cpp
 1537page/RenderingScheduler.cpp
15381538page/ResourceUsageOverlay.cpp
15391539page/ResourceUsageThread.cpp
15401540page/RuntimeEnabledFeatures.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

17801780 5550CB421E955E3C00111AA0 /* ImageTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 5550CB411E955E3C00111AA0 /* ImageTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
17811781 555130011E7CCCCB00A69E38 /* DecodingOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 555130001E7CCCCA00A69E38 /* DecodingOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
17821782 555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
 1783 556C7C4B22123997009B06CA /* RenderingScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 556C7C4722123942009B06CA /* RenderingScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
17831784 5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 5576A5631D88A70800CCC04C /* ImageFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
17841785 55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
17851786 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 */; };

86448644 555130001E7CCCCA00A69E38 /* DecodingOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecodingOptions.h; sourceTree = "<group>"; };
86458645 555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
86468646 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
 8647 556C7C4722123942009B06CA /* RenderingScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderingScheduler.h; sourceTree = "<group>"; };
 8648 556C7C4922123943009B06CA /* RenderingScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderingScheduler.cpp; sourceTree = "<group>"; };
86478649 5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = "<group>"; };
86488650 5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = "<group>"; };
86498651 5597FCCB2076C06800D35BB0 /* GlyphDisplayListCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GlyphDisplayListCache.h; sourceTree = "<group>"; };

93679369 716C8DF21E48B269005BD0DA /* volume-up-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-support.js"; sourceTree = "<group>"; };
93689370 716C8DF31E48B284005BD0DA /* volume-down-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-down-button.js"; sourceTree = "<group>"; };
93699371 716C8DF41E48B284005BD0DA /* volume-up-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-button.js"; sourceTree = "<group>"; };
9370  716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentAnimationScheduler.h; sourceTree = "<group>"; };
9371  716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentAnimationScheduler.cpp; sourceTree = "<group>"; };
93729372 716FA0D81DB26591007323CC /* airplay-button.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "airplay-button.css"; sourceTree = "<group>"; };
93739373 716FA0D91DB26591007323CC /* airplay-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-button.js"; sourceTree = "<group>"; };
93749374 716FA0DA1DB26591007323CC /* airplay-placard.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-placard.js"; sourceTree = "<group>"; };

2049020490 46BCBBC3208500A700710638 /* RemoteDOMWindow.idl */,
2049120491 46B9518C207D632900A7D2DD /* RemoteFrame.cpp */,
2049220492 46B95192207D632E00A7D2DD /* RemoteFrame.h */,
 20493 556C7C4922123943009B06CA /* RenderingScheduler.cpp */,
 20494 556C7C4722123942009B06CA /* RenderingScheduler.h */,
2049320495 A5071E821C56D079009951BE /* ResourceUsageData.h */,
2049420496 ADBAD6EC1BCDD95000381325 /* ResourceUsageOverlay.cpp */,
2049520497 ADBAD6ED1BCDD95000381325 /* ResourceUsageOverlay.h */,

2064220644 7123C185204739B900789392 /* CSSTransition.idl */,
2064320645 715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */,
2064420646 715AD71D2050512400D592DC /* DeclarativeAnimation.h */,
20645  716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */,
20646  716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */,
2064720647 71025EC41F99F096004A250C /* DocumentTimeline.cpp */,
2064820648 71025EC51F99F096004A250C /* DocumentTimeline.h */,
2064920649 71025ECA1F99F096004A250C /* DocumentTimeline.idl */,

2905229052 B2F34FE60E82F81400F627CD /* DNS.h in Headers */,
2905329053 7EE6846F12D26E3800E73215 /* DNSResolveQueueCFNet.h in Headers */,
2905429054 A8185F4009765766005826D9 /* Document.h in Headers */,
29055  716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */,
2905629055 A3BB59F41457A40D00AC56FE /* DocumentEventQueue.h in Headers */,
2905729056 A8185F3D09765766005826D9 /* DocumentFragment.h in Headers */,
2905829057 46E1666E1FCC86A200C9710B /* DocumentIdentifier.h in Headers */,

3125331252 BCEA4876097D93020094C9E4 /* RenderImage.h in Headers */,
3125431253 08F2F00A1213E61700DCEC48 /* RenderImageResource.h in Headers */,
3125531254 08641D4812142F7D008DE9F6 /* RenderImageResourceStyleImage.h in Headers */,
 31255 556C7C4B22123997009B06CA /* RenderingScheduler.h in Headers */,
3125631256 BCEA4878097D93020094C9E4 /* RenderInline.h in Headers */,
3125731257 B595FF471824CEE300FF51CD /* RenderIterator.h in Headers */,
3125831258 BCEA487A097D93020094C9E4 /* RenderLayer.h in Headers */,

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/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
6763 , m_tickScheduleTimer(*this, &DocumentTimeline::scheduleAnimationResolutionIfNeeded)
6864 , m_document(&document)
6965 , m_originTime(originTime)

@@void DocumentTimeline::detachFromDocument()
8581
8682 unscheduleAnimationResolution();
8783 m_document = nullptr;
 84 m_timestamp = WTF::nullopt;
8885}
8986
9087static inline bool compareDeclarativeAnimationOwningElementPositionsInDocumentTreeOrder(Element* lhsOwningElement, Element* rhsOwningElement)

@@unsigned DocumentTimeline::numberOfActiveAnimationsForTesting() const
254251
255252Seconds DocumentTimeline::liveCurrentTime() const
256253{
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
 254 return Seconds(m_timestamp.valueOr(m_document->domWindow()->nowTimestamp()));
262255}
263256
264257Optional<Seconds> DocumentTimeline::currentTime()

@@Optional<Seconds> DocumentTimeline::currentTime()
273266 return WTF::nullopt;
274267 }
275268 }
 269
 270 if (!m_cachedCurrentTime)
 271 cacheCurrentTime(liveCurrentTime());
276272
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  }
301273 return m_cachedCurrentTime.value() - m_originTime;
302274}
303275

@@void DocumentTimeline::removeAnimation(WebAnimation& animation)
348320
349321void DocumentTimeline::scheduleAnimationResolution()
350322{
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
 323 if (m_document && m_document->page())
 324 m_document->page()->renderingScheduler().scheduleRender();
358325}
359326
360327void DocumentTimeline::unscheduleAnimationResolution()
361328{
362329 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();
 330}
 331
 332void DocumentTimeline::updateAnimationsAndSendEvents(double timestamp)
 333{
 334 m_timestamp = timestamp;
 335 internalUpdateAnimationsAndSendEvents();
379336 applyPendingAcceleratedAnimations();
380337 scheduleNextTick();
381338}
382339
383 void DocumentTimeline::updateAnimationsAndSendEvents()
 340void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
384341{
385342 m_numberOfAnimationTimelineInvalidationsForTesting++;
386343

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(double timestamp);
7876
7977 void updateThrottlingState();
8078 WEBCORE_EXPORT Seconds animationInterval() const;

@@private:
9694 void animationScheduleTimerFired();
9795 void scheduleAnimationResolution();
9896 void unscheduleAnimationResolution();
99  void updateAnimationsAndSendEvents();
 97 void internalUpdateAnimationsAndSendEvents();
10098 void performEventDispatchTask();
10199 void maybeClearCachedCurrentTime();
102100 void updateListOfElementsWithRunningAcceleratedAnimationsForElement(Element&);
103101 void transitionDidComplete(RefPtr<CSSTransition>);
104102 void scheduleNextTick();
105103
106 #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
107  void animationResolutionTimerFired();
108  Timer m_animationResolutionTimer;
109 #endif
110 
111104 Timer m_tickScheduleTimer;
112105 GenericTaskQueue<Timer> m_currentTimeClearingTaskQueue;
113106 HashSet<RefPtr<WebAnimation>> m_acceleratedAnimationsPendingRunningStateChange;

@@private:
116109 RefPtr<Document> m_document;
117110 Markable<Seconds, Seconds::MarkableTraits> m_cachedCurrentTime;
118111 Seconds m_originTime;
 112 Optional<double> m_timestamp;
119113 unsigned m_numberOfAnimationTimelineInvalidationsForTesting { 0 };
120114 bool m_isSuspended { false };
121115 bool m_waitingOnVMIdle { false };

Source/WebCore/dom/Document.cpp

5656#include "DOMWindow.h"
5757#include "DateComponents.h"
5858#include "DebugPageOverlays.h"
59 #include "DocumentAnimationScheduler.h"
6059#include "DocumentLoader.h"
6160#include "DocumentMarkerController.h"
6261#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()
25782574 m_timeline = nullptr;
25792575 }
25802576
2581 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
2582  if (m_animationScheduler) {
2583  m_animationScheduler->detachFromDocument();
2584  m_animationScheduler = nullptr;
2585  }
2586 #endif
2587 
25882577#if ENABLE(CSS_PAINTING_API)
25892578 for (auto& scope : m_paintWorkletGlobalScopes.values())
25902579 scope->prepareForDestruction();

@@void Document::resumeScriptedAnimationControllerCallbacks()
62936282 m_scriptedAnimationController->resume();
62946283}
62956284
6296 void Document::windowScreenDidChange(PlatformDisplayID displayID)
 6285void Document::updateAnimationsAndSendEvents(double timestamp)
62976286{
6298 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
6299  if (m_animationScheduler)
6300  m_animationScheduler->windowScreenDidChange(displayID);
6301 #endif
 6287 if (m_timeline)
 6288 m_timeline->updateAnimationsAndSendEvents(timestamp);
 6289}
 6290
 6291void Document::serviceRequestAnimationFrameCallbacks(double timestamp)
 6292{
 6293 if (m_scriptedAnimationController)
 6294 m_scriptedAnimationController->serviceRequestAnimationFrameCallbacks(timestamp);
 6295}
63026296
 6297void Document::windowScreenDidChange(PlatformDisplayID displayID)
 6298{
63036299 if (RenderView* view = renderView()) {
63046300 if (view->usesCompositing())
63056301 view->compositor().windowScreenDidChange(displayID);

@@void Document::updateIntersectionObservations()
79617957 if (needsLayout || hasPendingStyleRecalc())
79627958 return;
79637959
7964  m_needsForcedIntersectionObservationUpdate = false;
7965 
79667960 for (const auto& observer : m_intersectionObservers) {
79677961 bool needNotify = false;
79687962 DOMHighResTimeStamp timestamp;

@@void Document::updateIntersectionObservations()
80398033 m_intersectionObserversNotifyTimer.startOneShot(0_s);
80408034}
80418035
8042 void Document::scheduleForcedIntersectionObservationUpdate()
8043 {
8044  ASSERT(!m_intersectionObservers.isEmpty());
8045  if (m_needsForcedIntersectionObservationUpdate)
8046  return;
8047 
8048  m_needsForcedIntersectionObservationUpdate = true;
8049  if (auto* page = this->page())
8050  page->scheduleForcedIntersectionObservationUpdate(*this);
8051 }
8052 
80538036void Document::notifyIntersectionObserversTimerFired()
80548037{
80558038 for (const auto& observer : m_intersectionObserversWithPendingNotifications) {

@@void Document::setConsoleMessageListener(RefPtr<StringCallback>&& listener)
84838466 m_consoleMessageListener = listener;
84848467}
84858468
8486 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
8487 DocumentAnimationScheduler& Document::animationScheduler()
8488 {
8489  if (!m_animationScheduler)
8490  m_animationScheduler = DocumentAnimationScheduler::create(*this, page() ? page()->chrome().displayID() : 0);
8491 
8492  return *m_animationScheduler;
8493 }
8494 #endif
8495 
84968469DocumentTimeline& Document::timeline()
84978470{
84988471 if (!m_timeline)

Source/WebCore/dom/Document.h

@@class DOMWrapperWorld;
105105class Database;
106106class DatabaseThread;
107107class DeferredPromise;
108 class DocumentAnimationScheduler;
109108class DocumentFragment;
110109class DocumentLoader;
111110class DocumentMarkerController;

@@public:
10671066 ScriptedAnimationController* scriptedAnimationController() { return m_scriptedAnimationController.get(); }
10681067 void suspendScriptedAnimationControllerCallbacks();
10691068 void resumeScriptedAnimationControllerCallbacks();
1070 
 1069
 1070 void updateAnimationsAndSendEvents(double timestamp);
 1071 void serviceRequestAnimationFrameCallbacks(double timestamp);
 1072
10711073 void windowScreenDidChange(PlatformDisplayID);
10721074
10731075 void finishedParsing();

@@public:
14181420 void addIntersectionObserver(IntersectionObserver&);
14191421 void removeIntersectionObserver(IntersectionObserver&);
14201422 unsigned numberOfIntersectionObservers() const { return m_intersectionObservers.size(); }
1421  void scheduleForcedIntersectionObservationUpdate();
14221423 void updateIntersectionObservations();
14231424#endif
14241425

@@public:
14911492
14921493 WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
14931494
1494 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
1495  DocumentAnimationScheduler& animationScheduler();
1496 #endif
1497 
14981495 WEBCORE_EXPORT DocumentTimeline& timeline();
14991496 DocumentTimeline* existingTimeline() const { return m_timeline.get(); }
15001497 Vector<RefPtr<WebAnimation>> getAnimations();

@@private:
20542051 bool m_isTelephoneNumberParsingAllowed { true };
20552052#endif
20562053
2057 #if ENABLE(INTERSECTION_OBSERVER)
2058  bool m_needsForcedIntersectionObservationUpdate { false };
2059 #endif
2060 
20612054#if ENABLE(MEDIA_STREAM)
20622055 HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements;
20632056 String m_idHashSalt;

@@private:
20772070
20782071 bool m_grantStorageAccessOverride { false };
20792072
2080 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
2081  RefPtr<DocumentAnimationScheduler> m_animationScheduler;
2082 #endif
20832073 RefPtr<DocumentTimeline> m_timeline;
20842074 DocumentIdentifier m_identifier;
20852075

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(double timestamp)
193192{
194193 if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
195194 return;

@@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->renderingScheduler().scheduleRender();
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(double 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/FrameTree.cpp

2323
2424#include "Document.h"
2525#include "Frame.h"
 26#include "FrameLoader.h"
2627#include "FrameView.h"
2728#include "HTMLFrameOwnerElement.h"
2829#include "Page.h"

Source/WebCore/page/FrameView.cpp

@@void FrameView::viewportContentsChanged()
19591959 if (auto* renderView = frameView.frame().contentRenderer())
19601960 renderView->updateVisibleViewportRect(visibleRect);
19611961 });
1962 
1963 #if ENABLE(INTERSECTION_OBSERVER)
1964  if (auto* document = frame().document()) {
1965  if (auto* page = frame().page()) {
1966  if (document->numberOfIntersectionObservers())
1967  page->addDocumentNeedingIntersectionObservationUpdate(*document);
1968  if (!frame().isMainFrame()) {
1969  if (auto* mainDocument = frame().mainFrame().document()) {
1970  if (mainDocument->numberOfIntersectionObservers())
1971  page->addDocumentNeedingIntersectionObservationUpdate(*mainDocument);
1972  }
1973  }
1974  }
1975  }
1976 #endif
19771962}
19781963
19791964IntRect 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)
251251 , m_storageNamespaceProvider(*WTFMove(pageConfiguration.storageNamespaceProvider))
252252 , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
253253 , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
254 #if ENABLE(INTERSECTION_OBSERVER)
255  , m_intersectionObservationUpdateTimer(*this, &Page::updateIntersectionObservations)
256 #endif
257254 , m_sessionID(PAL::SessionID::defaultSessionID())
258255#if ENABLE(VIDEO)
259256 , m_playbackControlsManagerUpdateTimer(*this, &Page::playbackControlsManagerUpdateTimerFired)

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

@@void Page::removeActivityStateChangeObserver(ActivityStateChangeObserver& observ
12601250 m_activityStateChangeObservers.remove(&observer);
12611251}
12621252
1263 #if ENABLE(INTERSECTION_OBSERVER)
1264 void Page::addDocumentNeedingIntersectionObservationUpdate(Document& document)
 1253void Page::layoutIfNeeded()
12651254{
1266  if (m_documentsNeedingIntersectionObservationUpdate.find(&document) == notFound)
1267  m_documentsNeedingIntersectionObservationUpdate.append(makeWeakPtr(document));
 1255 if (FrameView* view = m_mainFrame->view())
 1256 view->updateLayoutAndStyleIfNeededRecursive();
12681257}
12691258
1270 void Page::updateIntersectionObservations()
 1259void Page::updateRendering()
12711260{
1272  m_intersectionObservationUpdateTimer.stop();
1273  for (const auto& document : m_documentsNeedingIntersectionObservationUpdate) {
1274  if (document)
1275  document->updateIntersectionObservations();
 1261 // This function is not reentrant, e.g. a rAF callback may force repaint.
 1262 if (m_inUpdateRendering)
 1263 return;
 1264
 1265 SetForScope<bool> change(m_inUpdateRendering, true);
 1266
 1267 Vector<RefPtr<Document>> documents;
 1268
 1269 // The requestAnimationFrame callbacks may change the frame hierarchy of the page
 1270 forEachDocument([&documents] (Document& document) {
 1271 documents.append(&document);
 1272 });
 1273
 1274 for (auto& document : documents) {
 1275 double timestamp = document->domWindow()->nowTimestamp();
 1276 document->updateAnimationsAndSendEvents(timestamp);
 1277 document->serviceRequestAnimationFrameCallbacks(timestamp);
12761278 }
1277  m_documentsNeedingIntersectionObservationUpdate.clear();
1278 }
12791279
1280 void Page::scheduleForcedIntersectionObservationUpdate(Document& document)
1281 {
1282  addDocumentNeedingIntersectionObservationUpdate(document);
1283  if (m_intersectionObservationUpdateTimer.isActive())
1284  return;
1285  m_intersectionObservationUpdateTimer.startOneShot(0_s);
1286 }
 1280 layoutIfNeeded();
 1281
 1282 for (auto& document : documents) {
 1283#if ENABLE(INTERSECTION_OBSERVER)
 1284 document->updateIntersectionObservations();
12871285#endif
 1286 }
 1287}
12881288
12891289void Page::suspendScriptedAnimations()
12901290{

@@void Page::didChangeMainDocument()
28152815#endif
28162816}
28172817
 2818RenderingScheduler& Page::renderingScheduler()
 2819{
 2820 if (!m_renderingScheduler)
 2821 m_renderingScheduler = RenderingScheduler::create(*this);
 2822 return *m_renderingScheduler;
 2823}
 2824
28182825void Page::forEachDocument(const Function<void(Document&)>& functor)
28192826{
28202827 for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {

Source/WebCore/page/Page.h

3232#include "Pagination.h"
3333#include "RTCController.h"
3434#include "Region.h"
 35#include "RenderingScheduler.h"
3536#include "ScrollTypes.h"
3637#include "Supplementable.h"
3738#include "Timer.h"

@@public:
261262
262263 PerformanceMonitor* performanceMonitor() { return m_performanceMonitor.get(); }
263264
 265 RenderingScheduler& renderingScheduler();
 266
264267 ValidationMessageClient* validationMessageClient() const { return m_validationMessageClient.get(); }
265268 void updateValidationBubbleStateIfNeeded();
266269

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

@@public:
464465 WEBCORE_EXPORT void addActivityStateChangeObserver(ActivityStateChangeObserver&);
465466 WEBCORE_EXPORT void removeActivityStateChangeObserver(ActivityStateChangeObserver&);
466467
467 #if ENABLE(INTERSECTION_OBSERVER)
468  void addDocumentNeedingIntersectionObservationUpdate(Document&);
469  void scheduleForcedIntersectionObservationUpdate(Document&);
470  void updateIntersectionObservations();
471 #endif
 468 WEBCORE_EXPORT void updateRendering();
472469
473470 WEBCORE_EXPORT void suspendScriptedAnimations();
474471 WEBCORE_EXPORT void resumeScriptedAnimations();

@@private:
739736 void updateTimerThrottlingState();
740737 void updateDOMTimerAlignmentInterval();
741738 void domTimerAlignmentIntervalIncreaseTimerFired();
 739
 740 void layoutIfNeeded();
742741
743742 const std::unique_ptr<Chrome> m_chrome;
744743 const std::unique_ptr<DragCaretController> m_dragCaretController;

@@private:
860859 int m_headerHeight { 0 };
861860 int m_footerHeight { 0 };
862861
 862 std::unique_ptr<RenderingScheduler> m_renderingScheduler;
 863
863864 HashSet<RenderObject*> m_relevantUnpaintedRenderObjects;
864865 Region m_topRelevantPaintedRegion;
865866 Region m_bottomRelevantPaintedRegion;

@@private:
900901
901902 HashSet<ActivityStateChangeObserver*> m_activityStateChangeObservers;
902903
903 #if ENABLE(INTERSECTION_OBSERVER)
904  Vector<WeakPtr<Document>> m_documentsNeedingIntersectionObservationUpdate;
905 
906  // FIXME: Schedule intersection observation updates in a way that fits into the HTML
907  // EventLoop. See https://bugs.webkit.org/show_bug.cgi?id=160711.
908  Timer m_intersectionObservationUpdateTimer;
909 #endif
910 
911904#if ENABLE(RESOURCE_USAGE)
912905 std::unique_ptr<ResourceUsageOverlay> m_resourceUsageOverlay;
913906#endif

@@private:
967960
968961 bool m_shouldEnableICECandidateFilteringByDefault { true };
969962 bool m_mediaPlaybackIsSuspended { false };
 963 bool m_inUpdateRendering { false };
970964};
971965
972966inline PageGroup& Page::group()

Source/WebCore/page/PageOverlayController.cpp

@@void PageOverlayController::didChangeDeviceScaleFactor()
317317
318318void PageOverlayController::didChangeViewExposedRect()
319319{
320  m_page.chrome().client().scheduleCompositingLayerFlush();
 320 m_page.renderingScheduler().scheduleRender();
321321}
322322
323323void PageOverlayController::didScrollFrame(Frame& frame)

@@float PageOverlayController::deviceScaleFactor() const
411411
412412void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
413413{
414  m_page.chrome().client().scheduleCompositingLayerFlush();
 414 m_page.renderingScheduler().scheduleRender();
415415}
416416
417417void PageOverlayController::didChangeOverlayFrame(PageOverlay& overlay)

Source/WebCore/page/RenderingScheduler.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 "RenderingScheduler.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
 37RenderingScheduler::RenderingScheduler(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 RenderingScheduler::scheduleRender()
 46{
 47 if (m_scheduled)
 48 return;
 49
 50 tracePoint(ScheduleRenderingUpdate);
 51
 52#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 53 if (!DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(*this))
 54#endif
 55 startTimer(Seconds(1.0 / 60));
 56
 57 m_scheduled = true;
 58}
 59
 60void RenderingScheduler::startTimer(Seconds delay)
 61{
 62 ASSERT(!m_refreshTimer);
 63 m_refreshTimer = std::make_unique<Timer>(*this, &RenderingScheduler::displayRefreshFired);
 64 m_refreshTimer->startOneShot(delay);
 65}
 66
 67void RenderingScheduler::clearTimer()
 68{
 69 m_refreshTimer = nullptr;
 70}
 71
 72#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 73void RenderingScheduler::windowScreenDidChange(PlatformDisplayID displayID)
 74{
 75 DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, *this);
 76}
 77
 78RefPtr<DisplayRefreshMonitor> RenderingScheduler::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
 79{
 80 if (auto monitor = m_page.chrome().client().createDisplayRefreshMonitor(displayID))
 81 return monitor;
 82
 83 return DisplayRefreshMonitor::createDefaultDisplayRefreshMonitor(displayID);
 84}
 85#endif
 86
 87void RenderingScheduler::displayRefreshFired()
 88{
 89 tracePoint(TriggerRenderingUpdate);
 90
 91 m_page.chrome().client().scheduleCompositingLayerFlush();
 92 clearTimer();
 93 m_scheduled = false;
 94}
 95
 96}

Source/WebCore/page/RenderingScheduler.h

was renamed from

Source/WebCore/animation/DocumentAnimationScheduler.h

11/*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

2525
2626#pragma once
2727
28 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
29 
3028#include "DisplayRefreshMonitorClient.h"
31 #include "PlatformScreen.h"
32 #include <wtf/Ref.h>
33 #include <wtf/RefCounted.h>
34 #include <wtf/RefPtr.h>
3529#include <wtf/Seconds.h>
3630
3731namespace WebCore {
3832
39 class Document;
 33class Page;
 34class Timer;
4035
41 class DocumentAnimationScheduler : public RefCounted<DocumentAnimationScheduler>
42  , public DisplayRefreshMonitorClient {
 36class RenderingScheduler
 37#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 38 : public DisplayRefreshMonitorClient
 39#endif
 40{
 41 WTF_MAKE_FAST_ALLOCATED;
4342public:
44  static Ref<DocumentAnimationScheduler> create(Document&, PlatformDisplayID);
45  ~DocumentAnimationScheduler();
46 
47  void detachFromDocument();
48  void windowScreenDidChange(PlatformDisplayID);
 43 static std::unique_ptr<RenderingScheduler> create(Page& page)
 44 {
 45 return std::make_unique<RenderingScheduler>(page);
 46 }
4947
50  bool scheduleWebAnimationsResolution();
51  void unscheduleWebAnimationsResolution();
52  bool scheduleScriptedAnimationResolution();
 48 RenderingScheduler(Page&);
 49 void scheduleRender();
5350
54  Seconds lastTimestamp() { return m_lastTimestamp; }
55  bool isFiring() const { return m_isFiring; }
 51#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 52 void windowScreenDidChange(PlatformDisplayID);
 53#endif
5654
5755private:
58  DocumentAnimationScheduler(Document&, PlatformDisplayID);
 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
5962
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 };
 63 void startTimer(Seconds);
 64 void clearTimer();
6565
66  void displayRefreshFired() override;
67  RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
 66 Page& m_page;
 67 std::unique_ptr<Timer> m_refreshTimer;
 68 bool m_scheduled { false };
6869};
6970
70 } // namespace WebCore
71 
72 #endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 71}

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().renderingScheduler().scheduleRender();
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)
430430void RenderLayerCompositor::scheduleLayerFlushNow()
431431{
432432 m_hasPendingLayerFlush = false;
433  page().chrome().client().scheduleCompositingLayerFlush();
 433 page().renderingScheduler().scheduleRender();
434434}
435435
436436void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)

Source/WebKit/ChangeLog

 12019-02-23 Said Abou-Hallawa <said@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 NOBODY (OOPS!).
 7
 8 Handle the page-level rendering actions through two phases: one before
 9 running the layout and the second is before committing the drawing.
 10
 11 * WebProcess/WebPage/AcceleratedDrawingArea.cpp:
 12 (WebKit::AcceleratedDrawingArea::updateBackingStoreState):
 13 * WebProcess/WebPage/CoordinatedGraphics/CoordinatedLayerTreeHost.cpp:
 14 (WebKit::CoordinatedLayerTreeHost::layerFlushTimerFired):
 15 * WebProcess/WebPage/DrawingAreaImpl.cpp:
 16 (WebKit::DrawingAreaImpl::display):
 17 * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
 18 (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
 19 * WebProcess/WebPage/WebPage.cpp:
 20 (WebKit::WebPage::updateRendering):
 21 (WebKit::WebPage::willDisplayPage): Deleted.
 22 * WebProcess/WebPage/WebPage.h:
 23 * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
 24 (WebKit::TiledCoreAnimationDrawingArea::flushLayers):
 25
1262019-02-20 Chris Dumez <cdumez@apple.com>
227
328 Unreviewed build fix after r241823.

Source/WebKit/WebProcess/WebPage/AcceleratedDrawingArea.cpp

@@void AcceleratedDrawingArea::updateBackingStoreState(uint64_t stateID, bool resp
253253
254254 m_webPage.setDeviceScaleFactor(deviceScaleFactor);
255255 m_webPage.setSize(size);
 256 m_webPage.processPreLayoutActions();
256257 m_webPage.layoutIfNeeded();
257258 m_webPage.flushPendingEditorStateUpdate();
258259 m_webPage.scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
259  m_webPage.willDisplayPage();
 260 m_webPage.processPreRenderActions();
260261
261262 if (m_layerTreeHost)
262263 m_layerTreeHost->sizeDidChange(m_webPage.size());

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

@@void CoordinatedLayerTreeHost::layerFlushTimerFired()
189189
190190 m_coordinator.syncDisplayState();
191191 m_webPage.flushPendingEditorStateUpdate();
192  m_webPage.willDisplayPage();
 192 m_webPage.processPreRenderActions();
193193
194194 if (!m_isValid || !m_coordinator.rootCompositingLayer())
195195 return;

Source/WebKit/WebProcess/WebPage/DrawingAreaImpl.cpp

@@void DrawingAreaImpl::display(UpdateInfo& updateInfo)
398398 ASSERT(!m_layerTreeHost);
399399 ASSERT(!m_webPage.size().isEmpty());
400400
 401 m_webPage.processPreLayoutActions();
401402 m_webPage.layoutIfNeeded();
402403 m_webPage.flushPendingEditorStateUpdate();
403404

@@void DrawingAreaImpl::display(UpdateInfo& updateInfo)
406407 if (m_layerTreeHost)
407408 return;
408409
409  m_webPage.willDisplayPage();
 410 m_webPage.processPreRenderActions();
410411 updateInfo.viewSize = m_webPage.size();
411412 updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
412413

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

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

Source/WebKit/WebProcess/WebPage/WebPage.cpp

@@void WebPage::didFlushLayerTreeAtTime(MonotonicTime timestamp)
35753575}
35763576#endif
35773577
3578 void WebPage::willDisplayPage()
 3578void WebPage::updateRendering()
35793579{
3580  m_page->willDisplayPage();
 3580 m_page->updateRendering();
35813581}
35823582
35833583WebInspector* WebPage::inspector(LazyCreationPolicy behavior)

Source/WebKit/WebProcess/WebPage/WebPage.h

@@public:
300300 void didFlushLayerTreeAtTime(MonotonicTime);
301301#endif
302302
303  void willDisplayPage();
 303 void updateRendering();
304304
305305 enum class LazyCreationPolicy { UseExistingOnly, CreateIfNeeded };
306306

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.updateRendering();
466469 m_webPage.flushPendingEditorStateUpdate();
467  m_webPage.willDisplayPage();
468470
469471 updateIntrinsicContentSizeIfNeeded();
470472

Source/WebKitLegacy/mac/ChangeLog

 12019-02-23 Said Abou-Hallawa <said@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 NOBODY (OOPS!).
 7
 8 * WebView/WebView.mm:
 9 (-[WebView _viewWillDrawInternal]):
 10
1112019-02-18 Wenson Hsieh <wenson_hsieh@apple.com>
212
313 [iOS] Support pasting item-provider-backed data on the pasteboard as attachment elements

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->updateRendering();
16261625}
16271626
16281627+ (NSArray *)_supportedMIMETypes

Tools/ChangeLog

 12019-02-23 Said Abou-Hallawa <said@apple.com>
 2
 3 requestAnimationFrame should execute before the next frame
 4 https://bugs.webkit.org/show_bug.cgi?id=177484
 5
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * Tracing/SystemTracePoints.plist:
 10
1112019-02-20 Chris Dumez <cdumez@apple.com>
212
313 Regression(PSON) "Reload without content extensions" does not work when the main resource is blocked

Tools/Tracing/SystemTracePoints.plist

202202 <key>Component</key>
203203 <string>47</string>
204204 <key>Code</key>
 205 <string>5025</string>
 206 </dict>
 207 <dict>
 208 <key>Name</key>
 209 <string>Schedule display refresh</string>
 210 <key>Type</key>
 211 <string>Impulse</string>
 212 <key>Component</key>
 213 <string>47</string>
 214 <key>Code</key>
205215 <string>5026</string>
206216 </dict>
 217 <dict>
 218 <key>Name</key>
 219 <string>Trigger display refresh</string>
 220 <key>Type</key>
 221 <string>Impulse</string>
 222 <key>Component</key>
 223 <string>47</string>
 224 <key>Code</key>
 225 <string>5027</string>
 226 </dict>
 227 <dict>
 228 <key>Name</key>
 229 <string>Update rendering</string>
 230 <key>Type</key>
 231 <string>Interval</string>
 232 <key>Component</key>
 233 <string>47</string>
 234 <key>CodeBegin</key>
 235 <string>5028</string>
 236 <key>CodeEnd</key>
 237 <string>5029</string>
 238 </dict>
207239 <dict>
208240 <key>Name</key>
209241 <string>Paint WebHTMLView</string>