⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 244182 in webkit


Ignore:
Timestamp:
Apr 10, 2019, 10:44:13 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

requestAnimationFrame should execute before the next frame
https://bugs.webkit.org/show_bug.cgi?id=177484

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2019-04-10
Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

Add trace points for the page RenderingUpdate.

  • web-platform-tests/resize-observer/resources/resizeTestHelper.js:

Change ResizeTestHelper.TIMEOUT to be 1 second instead of 100 ms which
is too short for layout tests.

Source/WebCore:

This change fixes these issues with animation timing:

  1. Calling the requestAnimationFrame callbacks would have happened when the DisplayLink fires. This may have happened even if the frame is missed and no display is committed.
  1. Style changes and layout triggered by script could trigger painting at more than 60fps. CoreAnimation commits could happen at more than 60fps, although WindowServer will throttle those, and only some will be shown on the screen.

This change introduces a new paint scheduling model where painting is
driven by a "RenderingUpdateScheduler", which only triggers paints once
per 16.7ms frame.

Code that previously scheduled a compositing layer flush now schedules a
"RenderingUpdate", and that update is driven by a DisplayRefreshMonitor
callback. When the render happens, we service requestAnimationFrame callbacks,
Web Animations, intersection observations and resize observations per the
"Update the rendering" step of the HTML Event Loop specification:
<https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>.

In the future, more rendering steps will be added to this code.

  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • accessibility/mac/AXObjectCacheMac.mm:

(WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
Fix layout tests by adding null check.

  • animation/DocumentAnimationScheduler.cpp: Removed.
  • animation/DocumentAnimationScheduler.h: Removed.
  • animation/DocumentTimeline.cpp:

(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::updateThrottlingState):
(WebCore::DocumentTimeline::suspendAnimations):
(WebCore::DocumentTimeline::resumeAnimations):
(WebCore::DocumentTimeline::liveCurrentTime const):
(WebCore::DocumentTimeline::currentTime):
(WebCore::DocumentTimeline::cacheCurrentTime):
(WebCore::DocumentTimeline::animationTimingDidChange):
(WebCore::DocumentTimeline::scheduleAnimationResolution):
(WebCore::DocumentTimeline::unscheduleAnimationResolution):
(WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
(WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
(WebCore::DocumentTimeline::scheduleNextTick):
(WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement):
Simplify this function by handling the case of no-animations separately.

(WebCore::DocumentTimeline::resolveAnimationsForElement):
Simplify the loop and delete hasPendingAcceleratedAnimations because it
is initialized to true and is not changed inside the loop.

(WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded): Deleted.
(WebCore::DocumentTimeline::animationResolutionTimerFired): Deleted.

  • animation/DocumentTimeline.h:
  • dom/Document.cpp:

(WebCore::Document::resolveStyle):
There is no need to force update in resolveStyle(). notifyFlushRequired()
will be called eventually which will scheduleRenderingUpdate().

(WebCore::Document::prepareForDestruction):
(WebCore::Document::updateAnimationsAndSendEvents):
(WebCore::Document::serviceRequestAnimationFrameCallbacks):
(WebCore::Document::windowScreenDidChange):
(WebCore::Document::scheduleRenderingUpdate):
(WebCore::Document::updateIntersectionObservations):
(WebCore::Document::addResizeObserver):
(WebCore::Document::updateResizeObservations):
(WebCore::Document::scheduleForcedIntersectionObservationUpdate): Deleted.
(WebCore::Document::scheduleResizeObservations): Deleted.
(WebCore::Document::animationScheduler): Deleted.
No need to schedule web-animations, intersection observations and resize
observations updates separately. All of them will be updated through the
"Update the rendering" step, i.e. Page::updateRendering().

  • dom/Document.h:

(WebCore::Document::numberOfIntersectionObservers const):

  • dom/ScriptedAnimationController.cpp:

(WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
(WebCore::ScriptedAnimationController::scheduleAnimation):
(WebCore::ScriptedAnimationController::animationTimerFired):
(WebCore::ScriptedAnimationController::serviceScriptedAnimations): Deleted.
(WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire): Deleted.

  • dom/ScriptedAnimationController.h:
  • page/FrameView.cpp:

(WebCore::FrameView::didLayout):
(WebCore::FrameView::viewportContentsChanged):

  • page/FrameViewLayoutContext.cpp:

(WebCore::FrameViewLayoutContext::layoutTimerFired):

  • page/IntersectionObserver.cpp:

(WebCore::IntersectionObserver::observe):

  • page/Page.cpp:

(WebCore::Page::Page):
(WebCore::Page::layoutIfNeeded):
(WebCore::Page::updateRendering):
(WebCore::Page::renderingUpdateScheduler):
(WebCore::Page::willDisplayPage): Deleted.
(WebCore::Page::addDocumentNeedingIntersectionObservationUpdate): Deleted.
(WebCore::Page::updateIntersectionObservations): Deleted.
(WebCore::Page::scheduleForcedIntersectionObservationUpdate): Deleted.
(WebCore::Page::hasResizeObservers const): Deleted.
(WebCore::Page::gatherDocumentsNeedingResizeObservationCheck): Deleted.
(WebCore::Page::checkResizeObservations): Deleted.
(WebCore::Page::scheduleResizeObservations): Deleted.
(WebCore::Page::notifyResizeObservers): Deleted.

  • page/Page.h:

(WebCore::Page::setNeedsCheckResizeObservations): Deleted.
(WebCore::Page::needsCheckResizeObservations const): Deleted.
The IntersectionObserver and the ResizeObserver do not need to schedule
their own timers. The RenderingUpdateScheduler will schedule the "Update
the rendering" step in which these obverses will be served.

  • page/PageOverlayController.cpp:

(WebCore::PageOverlayController::didChangeViewExposedRect):
(WebCore::PageOverlayController::notifyFlushRequired):
Force committing the layers to be 60 fps at maximum.

  • page/RenderingUpdateScheduler.cpp: Added.

(WebCore::RenderingUpdateScheduler::RenderingUpdateScheduler):
(WebCore::RenderingUpdateScheduler::scheduleRenderingUpdate):
(WebCore::RenderingUpdateScheduler::isScheduled const):
(WebCore::RenderingUpdateScheduler::startTimer):
(WebCore::RenderingUpdateScheduler::clearScheduled):
(WebCore::RenderingUpdateScheduler::createDisplayRefreshMonitor const):
(WebCore::RenderingUpdateScheduler::windowScreenDidChange):
(WebCore::RenderingUpdateScheduler::displayRefreshFired):
(WebCore::RenderingUpdateScheduler::scheduleCompositingLayerFlush):

  • page/RenderingUpdateScheduler.h: Added.

(WebCore::RenderingUpdateScheduler::create):

  • page/ResizeObserver.cpp:

(WebCore::ResizeObserver::observe):
(WebCore::ResizeObserver::scheduleObservations): Deleted.

  • page/ResizeObserver.h:

(WebCore::ResizeObserver::hasActiveObservations const):

  • page/ios/ContentChangeObserver.h:
  • page/mac/ServicesOverlayController.mm:

(WebCore::ServicesOverlayController::Highlight::notifyFlushRequired):

  • page/scrolling/ScrollingStateTree.cpp:
  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::scheduleLayerFlushNow):
(WebCore::RenderLayerCompositor::layerTreeAsText):

Source/WebKit:

Replace the calls to Page::layoutIfNeeded() and willDisplayPage() by
a single call to Page::updateRendering(). This new function implements
"Update the rendering" step of the HTML Event Loop specification
<https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering>.

  • WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:

(WebKit::DrawingAreaCoordinatedGraphics::scheduleCompositingLayerFlush):
(WebKit::DrawingAreaCoordinatedGraphics::updateBackingStoreState):
(WebKit::DrawingAreaCoordinatedGraphics::display):

  • WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:

(WebKit::LayerTreeHost::layerFlushTimerFired):

  • WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:

(WebKit::RemoteLayerTreeDrawingArea::flushLayers):
-- Call Page::updateRendering() to make sure that "Update the rendering"

happens immediately before updating the page.

-- Move the call to RemoteLayerBackingStoreCollection::willFlushLayers()

to be exactly before flushing the layers. This fixes the assertion
ASSERT(m_inLayerFlush) which was firing when running a layout test.
RemoteLayerTreeDrawingArea::flushLayers() now can call itself through
TestRunner::notifyDone(). flushLayers() was calling willFlushLayers()
twice before calling didFlushLayers().

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::layoutIfNeeded):
(WebKit::WebPage::updateRendering):
(WebKit::WebPage::willDisplayPage): Deleted.

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:

(WebKit::TiledCoreAnimationDrawingArea::flushLayers):

Source/WebKitLegacy/mac:

  • WebView/WebView.mm:

(-[WebView _viewWillDrawInternal]):
(-[WebView _flushCompositingChanges]):
Call Page::updateRendering() which implements "Update the rendering"
step of the HTML Event Loop specification.

Source/WebKitLegacy/win:

  • WebView.cpp:

(WebView::updateBackingStore):
(WebView::flushPendingGraphicsLayerChangesSoon):
(WebView::flushPendingGraphicsLayerChanges):
Call Page::updateRendering() which implements "Update the rendering"
step of the HTML Event Loop specification.

Source/WTF:

Add trace points for the page RenderingUpdate.

  • wtf/SystemTracing.h:

Tools:

Add trace points for the page RenderingUpdate.

  • Tracing/SystemTracePoints.plist:

LayoutTests:

There is a slight difference between the actual DRT and the expected DRT
due to animation timing change. But these two tests are not animating
correctly if they are opened in Safari with web animation turned on.

  • accessibility/mac/selection-notification-focus-change-expected.txt:
  • accessibility/mac/selection-notification-focus-change.html:

Remove the debug statements form notificationCallback() since the number
of times this function is called back and the order of notifications are
not defined. This test has been flaky and some trials were made to make
it more reliable. With this change it became flaky again.

  • animations/animation-multiple-callbacks-timestamp.html:

Fix variable names used by an error message.

  • animations/no-style-recalc-during-accelerated-animation-expected.txt:
  • animations/no-style-recalc-during-accelerated-animation.html:

One extra styleReclc was incurred due to the document styleRecalcTimer.
I think this timer is not needed anymore. I will look at removing it in
a separate patch.

  • animations/resources/animation-test-helpers.js:

(waitForAnimationToStart):
The expectation that animation will start at the beginning of the next
event loop is not true anymore. The animation will start at the time the
requestAnimationFrame fires.

  • compositing/video/video-clip-change-src.html:

This test loads a video data and pushes it to the encoder. Originally it
used to wait 150 ms after receiving the second canplaythrough. I had to
change this timing to 250 ms.

  • css3/filters/composited-during-animation.html:

Ditto. setTimeout({...}, 0) versus requestAnimationFrame.

  • media/media-controls-accessibility.html:

Updating the accessibility button happens asynchronously, see
[WebAccessibilityObjectWrapper accessibilityPerformPressAction]. Due to
changing the page update timing, this test became flaky. Originally it used
to setTimeout({...}, 10) to ensure the stringValue of the mutate button
was changed after it was pressed. The fix is to loop using rAF till the
stringValue changes.

  • platform/mac-wk2/accessibility/mac/selection-notification-focus-change-expected.txt: Removed.

The number of time notificationCallback() is called and the order of
notifications are not defined. And this is why we have two expected files:
one for WK1 and the other for WK2. Since the test is now simplified, we
can get rid of this duplication. We will test the minimum reliable thing
we can test.

Location:
trunk
Files:
1 added
2 deleted
50 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r244181 r244182  
     12019-04-10  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        * accessibility/mac/selection-notification-focus-change-expected.txt:
     14        * accessibility/mac/selection-notification-focus-change.html:
     15        Remove the debug statements form notificationCallback() since the number
     16        of times this function is called back and the order of notifications are
     17        not defined. This test has been flaky and some trials were made to make
     18        it more reliable. With this change it became flaky again.
     19
     20        * animations/animation-multiple-callbacks-timestamp.html:
     21        Fix variable names used by an error message.
     22
     23        * animations/no-style-recalc-during-accelerated-animation-expected.txt:
     24        * animations/no-style-recalc-during-accelerated-animation.html:
     25        One extra styleReclc was incurred due to the document styleRecalcTimer.
     26        I think this timer is not needed anymore. I will look at removing it in
     27        a separate patch.
     28
     29        * animations/resources/animation-test-helpers.js:
     30        (waitForAnimationToStart):
     31        The expectation that animation will start at the beginning of the next
     32        event loop is not true anymore. The animation will start at the time the
     33        requestAnimationFrame fires.
     34
     35        * compositing/video/video-clip-change-src.html:
     36        This test loads a video data and pushes it to the encoder. Originally it
     37        used to wait 150 ms after receiving the second canplaythrough. I had to
     38        change this timing to 250 ms.
     39
     40        * css3/filters/composited-during-animation.html:
     41        Ditto. setTimeout({...}, 0) versus requestAnimationFrame.
     42
     43        * media/media-controls-accessibility.html:
     44        Updating the accessibility button happens asynchronously, see
     45        [WebAccessibilityObjectWrapper accessibilityPerformPressAction]. Due to
     46        changing the page update timing, this test became flaky. Originally it used
     47        to setTimeout({...}, 10) to ensure the stringValue of the mutate button
     48        was changed after it was pressed. The fix is to loop using rAF till the
     49        stringValue changes.
     50
     51        * platform/mac-wk2/accessibility/mac/selection-notification-focus-change-expected.txt: Removed.
     52        The number of time notificationCallback() is called and the order of
     53        notifications are not defined. And this is why we have two expected files:
     54        one for WK1 and the other for WK2. Since the test is now simplified, we
     55        can get rid of this duplication. We will test the minimum reliable thing
     56        we can test.
     57
    1582019-04-10  Ryosuke Niwa  <rniwa@webkit.org>
    259
  • trunk/LayoutTests/TestExpectations

    r244112 r244182  
    30283028# This is fallout from turning Web Animations on.
    30293029webkit.org/b/190032 animations/animation-playstate-paused-style-resolution.html [ Failure ]
     3030webkit.org/b/190032 animations/missing-values-first-keyframe.html [ Failure ]
     3031webkit.org/b/190032 animations/missing-values-last-keyframe.html [ Failure ]
    30303032webkit.org/b/190032 compositing/backing/backing-store-attachment-fill-forwards-animation.html [ Failure ]
    30313033webkit.org/b/190032 compositing/backing/transform-transition-from-outside-view.html [ Failure ]
  • trunk/LayoutTests/accessibility/mac/selection-notification-focus-change-expected.txt

    r228417 r244182  
    1 This tests that selection changes as a result of advancing focus include AXTextSelectionChangedFocus flag.
     1This tests that selection changes as a result of advancing focus.
    22
    33On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
     
    66PASS webArea.addNotificationListener(notificationCallback) is true
    77eventSender.keyDown(tabCharacter);
    8 Received AXSelectedTextChanged
    9 PASS userInfo["AXTextSelectionChangedFocus"] is true
    10 Received AXFocusChanged
    11 Received AXSelectedTextChanged
    12 PASS userInfo["AXTextSelectionChangedFocus"] is true
    138
    149PASS accessibilityController.accessibleElementById("1").isFocusable is true
    1510accessibilityController.accessibleElementById("1").takeFocus()
    16 Received AXFocusChanged
    1711
    1812eventSender.keyDown(tabCharacter)
    19 Received AXSelectedTextChanged
    20 PASS userInfo["AXTextSelectionChangedFocus"] is true
    21 Received AXFocusChanged
    22 Received AXSelectedTextChanged
    23 PASS userInfo["AXTextSelectionChangedFocus"] is true
    2413PASS successfullyParsed is true
    2514
  • trunk/LayoutTests/accessibility/mac/selection-notification-focus-change.html

    r227713 r244182  
    1616        </fieldset>
    1717        <script>
    18             description("This tests that selection changes as a result of advancing focus include AXTextSelectionChangedFocus flag.");
     18            description("This tests that selection changes as a result of advancing focus.");
    1919            jsTestIsAsync = true;
    2020
    2121            var webArea = 0;
    22             var axTextFocusChangeOne = 0;
    23             var axTextFocusChangeTwo = 0;
    24             var axTextFocusChangeThree = 0;
    25             var axTextFocusChangeFour = 0;
    2622            var tabCharacter = "\t";
    2723
    2824            function notificationCallback(notification, userInfo) {
    29                 if (notification == "AXSelectedTextChanged") {
    30                     debug("Received AXSelectedTextChanged");
    31                     window.userInfo = userInfo;
    32                     shouldBeTrue("userInfo[\"AXTextSelectionChangedFocus\"]");
    33                 } else if (notification == "AXFocusChanged")
    34                     debug("Received AXFocusChanged");
     25                if (notification == "AXSelectedTextChanged" || notification == "AXFocusChanged")
     26                    window.promise.resolve();
    3527            }
    3628
    3729            function runTest() {
    38                 if (window.accessibilityController) {
    39                     testRunner.overridePreference("WebKitTabToLinksPreferenceKey", 1);
    40 
    41                     accessibilityController.enableEnhancedAccessibility(true);
    42                     webArea = accessibilityController.rootElement.childAtIndex(0);
    43                     webArea.setBoolAttributeValue("AXCaretBrowsingEnabled", true)
    44 
    45                     shouldBeTrue("webArea.addNotificationListener(notificationCallback)");
    46                     evalAndLog("eventSender.keyDown(tabCharacter);");
    47                     setTimeout(runTakeFocusTest, 0);
    48                 } else {
     30                if (!window.accessibilityController) {
    4931                    debug("window.accessibilityController is not present");
    5032                    finishJSTest();
     33                    return;
    5134                }
     35
     36                runFirstTabMoveTest();
     37            }
     38
     39            function runFirstTabMoveTest() {
     40                testRunner.overridePreference("WebKitTabToLinksPreferenceKey", 1);
     41
     42                accessibilityController.enableEnhancedAccessibility(true);
     43                webArea = accessibilityController.rootElement.childAtIndex(0);
     44                webArea.setBoolAttributeValue("AXCaretBrowsingEnabled", true)
     45
     46                shouldBeTrue("webArea.addNotificationListener(notificationCallback)");
     47                evalAndLog("eventSender.keyDown(tabCharacter);");
     48
     49                window.promise = new Promise(function(resolve, reject) {
     50                    setTimeout(() => {
     51                        runTakeFocusTest();
     52                    }, 0);
     53                });
    5254            }
    5355
     
    5658                shouldBeTrue("accessibilityController.accessibleElementById(\"1\").isFocusable");
    5759                evalAndLog("accessibilityController.accessibleElementById(\"1\").takeFocus()");
    58                 setTimeout(runSecondTabMoveTest, 0);
     60
     61                window.promise = new Promise(function(resolve, reject) {
     62                    setTimeout(() => {
     63                        runSecondTabMoveTest();
     64                    }, 0);
     65                });
    5966            }
    6067
     
    6269                debug('');
    6370                evalAndLog("eventSender.keyDown(tabCharacter)");
    64                 setTimeout(() => {
    65                     webArea.removeNotificationListener();
    66                     finishJSTest();
    67                 }, 0);
     71
     72                window.promise = new Promise(function(resolve, reject) {
     73                    setTimeout(() => {
     74                        webArea.removeNotificationListener();
     75                        finishJSTest();
     76                    }, 0);
     77                });
    6878            }
    6979
  • trunk/LayoutTests/animations/animation-multiple-callbacks-timestamp.html

    r242714 r244182  
    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            }
  • trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation-expected.txt

    r242714 r244182  
    11Got iteration event.
    2 PASS: saw two or fewer style recalcs during the animation.
     2PASS: saw three or fewer style recalcs during the animation.
  • trunk/LayoutTests/animations/no-style-recalc-during-accelerated-animation.html

    r242714 r244182  
    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)
  • trunk/LayoutTests/animations/resources/animation-test-helpers.js

    r232559 r244182  
    596596{
    597597    element.addEventListener('webkitAnimationStart', function() {
    598         window.setTimeout(callback, 0); // delay to give hardware animations a chance to start
     598        requestAnimationFrame(callback); // delay to give hardware animations a chance to start
    599599    }, false);
    600600}
  • trunk/LayoutTests/compositing/video/video-clip-change-src.html

    r238090 r244182  
    3838    function endTest() {
    3939        if (window.testRunner)
    40             setTimeout(function() { testRunner.notifyDone(); }, 150);
     40            setTimeout(function() { testRunner.notifyDone(); }, 250);
    4141    }
    4242    </script>
  • trunk/LayoutTests/css3/filters/composited-during-animation.html

    r236541 r244182  
    150150
    151151        // Completed the pre-animation tests. Now start the animation.
    152         setTimeout(function () {
     152        requestAnimationFrame(function () {
    153153            document.body.className = "animating";
    154154            runAnimationTest(expectedValues);
    155         }, 0);
     155        });
    156156    }
    157157
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r244094 r244182  
     12019-04-10  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        * web-platform-tests/resize-observer/resources/resizeTestHelper.js:
     11        Change ResizeTestHelper.TIMEOUT to be 1 second instead of 100 ms which
     12        is too short for layout tests.
     13
    1142019-04-09  Youenn Fablet  <youenn@apple.com>
    215
  • trunk/LayoutTests/imported/w3c/web-platform-tests/resize-observer/resources/resizeTestHelper.js

    r240655 r244182  
    5353}
    5454
    55 ResizeTestHelper.TIMEOUT = 100;
     55ResizeTestHelper.TIMEOUT = 1000;
    5656
    5757ResizeTestHelper.prototype = {
  • trunk/LayoutTests/media/media-controls-accessibility.html

    r219906 r244182  
    3333        // Mute button should be a checkbox with on/off state.
    3434        muteButton = videoElement.childAtIndex(0).childAtIndex(9);
     35        muteButtonStringValue = muteButton.stringValue;
    3536        debug("muteButton.description: " + muteButton.description);
    3637        debug("muteButton.role: " + muteButton.role);
    37         debug("muteButton.stringValue: " + muteButton.stringValue);
     38        debug("muteButton.stringValue: " + muteButtonStringValue);
    3839        debug("press muteButton");
    3940        muteButton.press();
    40         setTimeout(function() {
     41
     42        function checkMuteButton() {
     43            if (muteButtonStringValue == muteButton.stringValue) {
     44                requestAnimationFrame(checkMuteButton);
     45                return;
     46            }
     47
    4148            debug("muteButton.stringValue: " + muteButton.stringValue + "\n");
    42              
    4349            // Left/Right arrow key should have 0.5 second step on timeline.
    4450            checkTimeLineValue(rightArrow);
    45         }, 10);
     51        }
     52
     53        requestAnimationFrame(checkMuteButton);
    4654    });
    4755   
  • trunk/Source/WTF/ChangeLog

    r244135 r244182  
     12019-04-10  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-04-10  Claudio Saavedra  <csaavedra@igalia.com>
    213
  • trunk/Source/WTF/wtf/SystemTracing.h

    r242714 r244182  
    7878    ComputeEventRegionsEnd,
    7979
     80    ScheduleRenderingUpdate,
     81    TriggerRenderingUpdate,
     82    RenderingUpdateStart,
     83    RenderingUpdateEnd,
     84
    8085    WebKitRange = 10000,
    8186    WebHTMLViewPaintStart,
  • trunk/Source/WebCore/ChangeLog

    r244181 r244182  
     12019-04-10  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 these 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, intersection observations and resize observations per the
     27        "Update the rendering" 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        (WebCore::AXObjectCache::platformHandleFocusedUIElementChanged):
     36        Fix layout tests by adding null check.
     37
     38        * animation/DocumentAnimationScheduler.cpp: Removed.
     39        * animation/DocumentAnimationScheduler.h: Removed.
     40        * animation/DocumentTimeline.cpp:
     41        (WebCore::DocumentTimeline::DocumentTimeline):
     42        (WebCore::DocumentTimeline::updateThrottlingState):
     43        (WebCore::DocumentTimeline::suspendAnimations):
     44        (WebCore::DocumentTimeline::resumeAnimations):
     45        (WebCore::DocumentTimeline::liveCurrentTime const):
     46        (WebCore::DocumentTimeline::currentTime):
     47        (WebCore::DocumentTimeline::cacheCurrentTime):
     48        (WebCore::DocumentTimeline::animationTimingDidChange):
     49        (WebCore::DocumentTimeline::scheduleAnimationResolution):
     50        (WebCore::DocumentTimeline::unscheduleAnimationResolution):
     51        (WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
     52        (WebCore::DocumentTimeline::internalUpdateAnimationsAndSendEvents):
     53        (WebCore::DocumentTimeline::scheduleNextTick):
     54        (WebCore::DocumentTimeline::updateListOfElementsWithRunningAcceleratedAnimationsForElement):
     55        Simplify this function by handling the case of no-animations separately.
     56
     57        (WebCore::DocumentTimeline::resolveAnimationsForElement):
     58        Simplify the loop and delete hasPendingAcceleratedAnimations because it
     59        is initialized to true and is not changed inside the loop.
     60
     61        (WebCore::DocumentTimeline::scheduleAnimationResolutionIfNeeded): Deleted.
     62        (WebCore::DocumentTimeline::animationResolutionTimerFired): Deleted.
     63        * animation/DocumentTimeline.h:
     64        * dom/Document.cpp:
     65        (WebCore::Document::resolveStyle):
     66        There is no need to force update in resolveStyle(). notifyFlushRequired()
     67        will be called eventually which will scheduleRenderingUpdate().
     68
     69        (WebCore::Document::prepareForDestruction):
     70        (WebCore::Document::updateAnimationsAndSendEvents):
     71        (WebCore::Document::serviceRequestAnimationFrameCallbacks):
     72        (WebCore::Document::windowScreenDidChange):
     73        (WebCore::Document::scheduleRenderingUpdate):
     74        (WebCore::Document::updateIntersectionObservations):
     75        (WebCore::Document::addResizeObserver):
     76        (WebCore::Document::updateResizeObservations):
     77        (WebCore::Document::scheduleForcedIntersectionObservationUpdate): Deleted.
     78        (WebCore::Document::scheduleResizeObservations): Deleted.
     79        (WebCore::Document::animationScheduler): Deleted.
     80        No need to schedule web-animations, intersection observations and resize
     81        observations updates separately. All of them will be updated through the
     82        "Update the rendering" step, i.e. Page::updateRendering().       
     83
     84        * dom/Document.h:
     85        (WebCore::Document::numberOfIntersectionObservers const):
     86        * dom/ScriptedAnimationController.cpp:
     87        (WebCore::ScriptedAnimationController::serviceRequestAnimationFrameCallbacks):
     88        (WebCore::ScriptedAnimationController::scheduleAnimation):
     89        (WebCore::ScriptedAnimationController::animationTimerFired):
     90        (WebCore::ScriptedAnimationController::serviceScriptedAnimations): Deleted.
     91        (WebCore::ScriptedAnimationController::documentAnimationSchedulerDidFire): Deleted.
     92        * dom/ScriptedAnimationController.h:
     93        * page/FrameView.cpp:
     94        (WebCore::FrameView::didLayout):
     95        (WebCore::FrameView::viewportContentsChanged):
     96        * page/FrameViewLayoutContext.cpp:
     97        (WebCore::FrameViewLayoutContext::layoutTimerFired):
     98        * page/IntersectionObserver.cpp:
     99        (WebCore::IntersectionObserver::observe):
     100        * page/Page.cpp:
     101        (WebCore::Page::Page):
     102        (WebCore::Page::layoutIfNeeded):
     103        (WebCore::Page::updateRendering):
     104        (WebCore::Page::renderingUpdateScheduler):
     105        (WebCore::Page::willDisplayPage): Deleted.
     106        (WebCore::Page::addDocumentNeedingIntersectionObservationUpdate): Deleted.
     107        (WebCore::Page::updateIntersectionObservations): Deleted.
     108        (WebCore::Page::scheduleForcedIntersectionObservationUpdate): Deleted.
     109        (WebCore::Page::hasResizeObservers const): Deleted.
     110        (WebCore::Page::gatherDocumentsNeedingResizeObservationCheck): Deleted.
     111        (WebCore::Page::checkResizeObservations): Deleted.
     112        (WebCore::Page::scheduleResizeObservations): Deleted.
     113        (WebCore::Page::notifyResizeObservers): Deleted.
     114        * page/Page.h:
     115        (WebCore::Page::setNeedsCheckResizeObservations): Deleted.
     116        (WebCore::Page::needsCheckResizeObservations const): Deleted.
     117        The IntersectionObserver and the ResizeObserver do not need to schedule
     118        their own timers. The RenderingUpdateScheduler will schedule the "Update
     119        the rendering" step in which these obverses will be served.
     120
     121        * page/PageOverlayController.cpp:
     122        (WebCore::PageOverlayController::didChangeViewExposedRect):
     123        (WebCore::PageOverlayController::notifyFlushRequired):
     124        Force committing the layers to be 60 fps at maximum.
     125
     126        * page/RenderingUpdateScheduler.cpp: Added.
     127        (WebCore::RenderingUpdateScheduler::RenderingUpdateScheduler):
     128        (WebCore::RenderingUpdateScheduler::scheduleRenderingUpdate):
     129        (WebCore::RenderingUpdateScheduler::isScheduled const):
     130        (WebCore::RenderingUpdateScheduler::startTimer):
     131        (WebCore::RenderingUpdateScheduler::clearScheduled):
     132        (WebCore::RenderingUpdateScheduler::createDisplayRefreshMonitor const):
     133        (WebCore::RenderingUpdateScheduler::windowScreenDidChange):
     134        (WebCore::RenderingUpdateScheduler::displayRefreshFired):
     135        (WebCore::RenderingUpdateScheduler::scheduleCompositingLayerFlush):
     136        * page/RenderingUpdateScheduler.h: Added.
     137        (WebCore::RenderingUpdateScheduler::create):
     138        * page/ResizeObserver.cpp:
     139        (WebCore::ResizeObserver::observe):
     140        (WebCore::ResizeObserver::scheduleObservations): Deleted.
     141        * page/ResizeObserver.h:
     142        (WebCore::ResizeObserver::hasActiveObservations const):
     143        * page/ios/ContentChangeObserver.h:
     144        * page/mac/ServicesOverlayController.mm:
     145        (WebCore::ServicesOverlayController::Highlight::notifyFlushRequired):
     146        * page/scrolling/ScrollingStateTree.cpp:
     147        * rendering/RenderLayerCompositor.cpp:
     148        (WebCore::RenderLayerCompositor::scheduleLayerFlushNow):
     149        (WebCore::RenderLayerCompositor::layerTreeAsText):
     150
    11512019-04-10  Ryosuke Niwa  <rniwa@webkit.org>
    2152
  • trunk/Source/WebCore/Sources.txt

    r244078 r244182  
    427427animation/CSSTransition.cpp
    428428animation/DeclarativeAnimation.cpp
    429 animation/DocumentAnimationScheduler.cpp
    430429animation/DocumentTimeline.cpp
    431430animation/KeyframeEffect.cpp
     
    15331532page/RemoteDOMWindow.cpp
    15341533page/RemoteFrame.cpp
     1534page/RenderingUpdateScheduler.cpp
    15351535page/ResizeObservation.cpp
    15361536page/ResizeObserver.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r244078 r244182  
    17321732                555130011E7CCCCB00A69E38 /* DecodingOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 555130001E7CCCCA00A69E38 /* DecodingOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17331733                555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
     1734                556C7C4B22123997009B06CA /* RenderingUpdateScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17341735                5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 5576A5631D88A70800CCC04C /* ImageFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
    17351736                55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    20762077                715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AD71D2050512400D592DC /* DeclarativeAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20772078                715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; };
    2078                 716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20792079                71729F7B20F3BA4900801CE6 /* DocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20802080                71729F7E20F3BB4700801CE6 /* JSDocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */; };
     
    84858485                555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
    84868486                555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
     8487                556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderingUpdateScheduler.h; sourceTree = "<group>"; };
     8488                556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderingUpdateScheduler.cpp; sourceTree = "<group>"; };
    84878489                5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = "<group>"; };
    84888490                5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = "<group>"; };
     
    92559257                716C8DF31E48B284005BD0DA /* volume-down-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-down-button.js"; sourceTree = "<group>"; };
    92569258                716C8DF41E48B284005BD0DA /* volume-up-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-up-button.js"; sourceTree = "<group>"; };
    9257                 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentAnimationScheduler.h; sourceTree = "<group>"; };
    9258                 716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentAnimationScheduler.cpp; sourceTree = "<group>"; };
    92599259                716FA0D81DB26591007323CC /* airplay-button.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "airplay-button.css"; sourceTree = "<group>"; };
    92609260                716FA0D91DB26591007323CC /* airplay-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "airplay-button.js"; sourceTree = "<group>"; };
     
    2021620216                                46B9518C207D632900A7D2DD /* RemoteFrame.cpp */,
    2021720217                                46B95192207D632E00A7D2DD /* RemoteFrame.h */,
     20218                                556C7C4922123943009B06CA /* RenderingUpdateScheduler.cpp */,
     20219                                556C7C4722123942009B06CA /* RenderingUpdateScheduler.h */,
    2021820220                                58B2F9F22232D43F00938D63 /* ResizeObservation.cpp */,
    2021920221                                58B2F9F32232D43F00938D63 /* ResizeObservation.h */,
     
    2037820380                                715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */,
    2037920381                                715AD71D2050512400D592DC /* DeclarativeAnimation.h */,
    20380                                 716E55AF20DBABDD00F0CF29 /* DocumentAnimationScheduler.cpp */,
    20381                                 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */,
    2038220382                                71025EC41F99F096004A250C /* DocumentTimeline.cpp */,
    2038320383                                71025EC51F99F096004A250C /* DocumentTimeline.h */,
     
    2876828768                                7EE6846F12D26E3800E73215 /* DNSResolveQueueCFNet.h in Headers */,
    2876928769                                A8185F4009765766005826D9 /* Document.h in Headers */,
    28770                                 716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */,
    2877128770                                A3BB59F41457A40D00AC56FE /* DocumentEventQueue.h in Headers */,
    2877228771                                A8185F3D09765766005826D9 /* DocumentFragment.h in Headers */,
     
    3095830957                                08F2F00A1213E61700DCEC48 /* RenderImageResource.h in Headers */,
    3095930958                                08641D4812142F7D008DE9F6 /* RenderImageResourceStyleImage.h in Headers */,
     30959                                556C7C4B22123997009B06CA /* RenderingUpdateScheduler.h in Headers */,
    3096030960                                BCEA4878097D93020094C9E4 /* RenderInline.h in Headers */,
    3096130961                                B595FF471824CEE300FF51CD /* RenderIterator.h in Headers */,
  • trunk/Source/WebCore/accessibility/mac/AXObjectCacheMac.mm

    r244107 r244182  
    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
  • trunk/Source/WebCore/animation/DocumentTimeline.cpp

    r244032 r244182  
    3434#include "DeclarativeAnimation.h"
    3535#include "Document.h"
    36 #include "DocumentAnimationScheduler.h"
    3736#include "GraphicsLayer.h"
    3837#include "KeyframeEffect.h"
     
    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)
     
    195191void DocumentTimeline::updateThrottlingState()
    196192{
    197     scheduleAnimationResolutionIfNeeded();
     193    scheduleAnimationResolution();
    198194}
    199195
     
    211207
    212208    if (!m_cachedCurrentTime)
    213         m_cachedCurrentTime = liveCurrentTime();
     209        m_cachedCurrentTime = Seconds(liveCurrentTime());
    214210
    215211    for (const auto& animation : m_animations)
     
    235231        animation->setSuspended(false);
    236232
    237     scheduleAnimationResolutionIfNeeded();
     233    scheduleAnimationResolution();
    238234}
    239235
     
    253249}
    254250
    255 Seconds DocumentTimeline::liveCurrentTime() const
    256 {
    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
     251DOMHighResTimeStamp DocumentTimeline::liveCurrentTime() const
     252{
     253    return m_document->domWindow()->nowTimestamp();
    262254}
    263255
     
    274266    }
    275267
    276     auto currentTime = liveCurrentTime();
    277 
    278 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    279     // If we're in the middle of firing a frame, either due to a requestAnimationFrame callback
    280     // or scheduling an animation update, we want to ensure we use the same time we're using as
    281     // the timestamp for requestAnimationFrame() callbacks.
    282     if (m_document->animationScheduler().isFiring())
    283         cacheCurrentTime(currentTime);
    284 #endif
    285 
    286     if (!m_cachedCurrentTime) {
    287 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    288         // If we're not in the middle of firing a frame, let's make our best guess at what the currentTime should
    289         // be since the last time a frame fired by increment of our update interval. This way code using something
    290         // like setTimeout() or handling events will get a time that's only updating at around 60fps, or less if
    291         // we're throttled.
    292         auto lastAnimationSchedulerTimestamp = currentTime;
    293         auto delta = Seconds(m_document->domWindow()->nowTimestamp()) - lastAnimationSchedulerTimestamp;
    294         int frames = std::floor(delta.seconds() / animationInterval().seconds());
    295         cacheCurrentTime(lastAnimationSchedulerTimestamp + Seconds(frames * animationInterval().seconds()));
    296 #else
    297         cacheCurrentTime(currentTime);
    298 #endif
    299     }
     268    if (!m_cachedCurrentTime)
     269        cacheCurrentTime(liveCurrentTime());
     270   
    300271    return m_cachedCurrentTime.value() - m_originTime;
    301272}
    302273
    303 void DocumentTimeline::cacheCurrentTime(Seconds newCurrentTime)
    304 {
    305     m_cachedCurrentTime = newCurrentTime;
     274void DocumentTimeline::cacheCurrentTime(DOMHighResTimeStamp newCurrentTime)
     275{
     276    m_cachedCurrentTime = Seconds(newCurrentTime);
    306277    // We want to be sure to keep this time cached until we've both finished running JS and finished updating
    307278    // animations, so we schedule the invalidation task and register a whenIdle callback on the VM, which will
     
    326297}
    327298
    328 void DocumentTimeline::scheduleAnimationResolutionIfNeeded()
    329 {
    330     if (!m_isUpdatingAnimations && !m_isSuspended && !m_animations.isEmpty())
    331         scheduleAnimationResolution();
    332 }
    333 
    334299void DocumentTimeline::animationTimingDidChange(WebAnimation& animation)
    335300{
    336301    AnimationTimeline::animationTimingDidChange(animation);
    337     scheduleAnimationResolutionIfNeeded();
     302    scheduleAnimationResolution();
    338303}
    339304
     
    348313void DocumentTimeline::scheduleAnimationResolution()
    349314{
    350 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    351     m_document->animationScheduler().scheduleWebAnimationsResolution();
    352 #else
    353     // FIXME: We need to use the same logic as ScriptedAnimationController here,
    354     // which will be addressed by the refactor tracked by webkit.org/b/179293.
    355     m_animationResolutionTimer.startOneShot(animationInterval());
    356 #endif
     315    if (m_isSuspended || m_animations.isEmpty() || m_animationResolutionScheduled)
     316        return;
     317
     318    if (!m_document || !m_document->page())
     319        return;
     320   
     321    m_document->page()->renderingUpdateScheduler().scheduleRenderingUpdate();
     322    m_animationResolutionScheduled = true;
    357323}
    358324
     
    360326{
    361327    m_tickScheduleTimer.stop();
    362 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    363     m_document->animationScheduler().unscheduleWebAnimationsResolution();
    364 #else
    365     // FIXME: We need to use the same logic as ScriptedAnimationController here,
    366     // which will be addressed by the refactor tracked by webkit.org/b/179293.
    367     m_animationResolutionTimer.stop();
    368 #endif
    369 }
    370 
    371 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    372 void DocumentTimeline::documentAnimationSchedulerDidFire()
    373 #else
    374 void DocumentTimeline::animationResolutionTimerFired()
    375 #endif
    376 {
    377     updateAnimationsAndSendEvents();
     328    m_animationResolutionScheduled = false;
     329}
     330
     331void DocumentTimeline::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
     332{
     333    // We need to freeze the current time even if no animation is running.
     334    // document.timeline.currentTime may be called from a rAF callback and
     335    // it has to match the rAF timestamp.
     336    if (!m_isSuspended)
     337        cacheCurrentTime(timestamp);
     338
     339    if (m_isSuspended || m_animations.isEmpty() || !m_animationResolutionScheduled)
     340        return;
     341
     342    internalUpdateAnimationsAndSendEvents();
    378343    applyPendingAcceleratedAnimations();
     344
     345    m_animationResolutionScheduled = false;
    379346    scheduleNextTick();
    380347}
    381348
    382 void DocumentTimeline::updateAnimationsAndSendEvents()
     349void DocumentTimeline::internalUpdateAnimationsAndSendEvents()
    383350{
    384351    m_numberOfAnimationTimelineInvalidationsForTesting++;
    385 
    386     m_isUpdatingAnimations = true;
    387352
    388353    // https://drafts.csswg.org/web-animations/#update-animations-and-send-events
     
    448413    for (auto& completedTransition : completedTransitions)
    449414        transitionDidComplete(completedTransition);
    450 
    451     m_isUpdatingAnimations = false;
    452415}
    453416
     
    473436    for (const auto& animation : m_animations) {
    474437        if (!animation->isRunningAccelerated()) {
    475             scheduleAnimationResolutionIfNeeded();
     438            scheduleAnimationResolution();
    476439            return;
    477440        }
     
    483446        auto animationTimeToNextRequiredTick = animation->timeToNextTick();
    484447        if (animationTimeToNextRequiredTick < animationInterval()) {
    485             scheduleAnimationResolutionIfNeeded();
     448            scheduleAnimationResolution();
    486449            return;
    487450        }
     
    593556{
    594557    auto animations = animationsForElement(element);
    595     bool runningAnimationsForElementAreAllAccelerated = !animations.isEmpty();
     558
     559    if (animations.isEmpty()) {
     560        m_elementsWithRunningAcceleratedAnimations.remove(&element);
     561        return;
     562    }
     563
    596564    for (const auto& animation : animations) {
    597565        if (!animation->isRunningAccelerated()) {
    598             runningAnimationsForElementAreAllAccelerated = false;
    599             break;
    600         }
    601     }
    602 
    603     if (runningAnimationsForElementAreAllAccelerated)
    604         m_elementsWithRunningAcceleratedAnimations.add(&element);
    605     else
    606         m_elementsWithRunningAcceleratedAnimations.remove(&element);
     566            m_elementsWithRunningAcceleratedAnimations.remove(&element);
     567            return;
     568        }
     569    }
     570
     571    m_elementsWithRunningAcceleratedAnimations.add(&element);
    607572}
    608573
     
    625590bool DocumentTimeline::resolveAnimationsForElement(Element& element, RenderStyle& targetStyle)
    626591{
    627     bool hasNonAcceleratedAnimations = false;
    628     bool hasPendingAcceleratedAnimations = true;
     592    bool hasNonAcceleratedAnimationProperty = false;
     593
    629594    for (const auto& animation : animationsForElement(element)) {
    630595        animation->resolve(targetStyle);
    631         if (!hasNonAcceleratedAnimations) {
    632             if (auto* effect = animation->effect()) {
    633                 if (is<KeyframeEffect>(effect)) {
    634                     auto* keyframeEffect = downcast<KeyframeEffect>(effect);
    635                     for (auto cssPropertyId : keyframeEffect->animatedProperties()) {
    636                         if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
    637                             hasNonAcceleratedAnimations = true;
    638                             continue;
    639                         }
    640                         if (!hasPendingAcceleratedAnimations)
    641                             hasPendingAcceleratedAnimations = keyframeEffect->hasPendingAcceleratedAction();
    642                     }
    643                 }
     596
     597        if (hasNonAcceleratedAnimationProperty)
     598            continue;
     599
     600        auto* effect = animation->effect();
     601        if (!effect || !is<KeyframeEffect>(effect))
     602            continue;
     603
     604        auto* keyframeEffect = downcast<KeyframeEffect>(effect);
     605        for (auto cssPropertyId : keyframeEffect->animatedProperties()) {
     606            if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) {
     607                hasNonAcceleratedAnimationProperty = true;
     608                break;
    644609            }
    645610        }
    646611    }
    647612
    648     // If there are no non-accelerated animations and we've encountered at least one pending
    649     // accelerated animation, we should recomposite this element's layer for animation purposes.
    650     return !hasNonAcceleratedAnimations && hasPendingAcceleratedAnimations;
     613    return !hasNonAcceleratedAnimationProperty;
    651614}
    652615
  • trunk/Source/WebCore/animation/DocumentTimeline.h

    r242714 r244182  
    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();
     
    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();
    105 
    106 #if !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    107     void animationResolutionTimerFired();
    108     Timer m_animationResolutionTimer;
    109 #endif
    110101
    111102    Timer m_tickScheduleTimer;
     
    120111    bool m_isSuspended { false };
    121112    bool m_waitingOnVMIdle { false };
    122     bool m_isUpdatingAnimations { false };
     113    bool m_animationResolutionScheduled { false };
    123114};
    124115
  • trunk/Source/WebCore/dom/Document.cpp

    r244151 r244182  
    5858#include "DateComponents.h"
    5959#include "DebugPageOverlays.h"
    60 #include "DocumentAnimationScheduler.h"
    6160#include "DocumentLoader.h"
    6261#include "DocumentMarkerController.h"
     
    19421941
    19431942        // Usually this is handled by post-layout.
    1944         if (!frameView.needsLayout()) {
     1943        if (!frameView.needsLayout())
    19451944            frameView.frame().selection().scheduleAppearanceUpdateAfterStyleChange();
    1946             if (m_needsForcedIntersectionObservationUpdate)
    1947                 page()->scheduleForcedIntersectionObservationUpdate(*this);
    1948         }
    19491945
    19501946        // As a result of the style recalculation, the currently hovered element might have been
     
    25422538    }
    25432539
    2544 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    2545     if (m_animationScheduler) {
    2546         m_animationScheduler->detachFromDocument();
    2547         m_animationScheduler = nullptr;
    2548     }
    2549 #endif
    2550 
    25512540#if ENABLE(CSS_PAINTING_API)
    25522541    for (auto& scope : m_paintWorkletGlobalScopes.values())
     
    62666255}
    62676256
     6257void Document::updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp)
     6258{
     6259    if (m_timeline)
     6260        m_timeline->updateAnimationsAndSendEvents(timestamp);
     6261}
     6262
     6263void Document::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
     6264{
     6265    if (m_scriptedAnimationController)
     6266        m_scriptedAnimationController->serviceRequestAnimationFrameCallbacks(timestamp);
     6267}
     6268
    62686269void Document::windowScreenDidChange(PlatformDisplayID displayID)
    62696270{
    6270 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    6271     if (m_animationScheduler)
    6272         m_animationScheduler->windowScreenDidChange(displayID);
    6273 #endif
    6274 
    62756271    if (RenderView* view = renderView()) {
    62766272        if (view->usesCompositing())
     
    78117807}
    78127808
     7809void Document::scheduleRenderingUpdate()
     7810{
     7811    if (auto page = this->page())
     7812        page->renderingUpdateScheduler().scheduleRenderingUpdate();
     7813}
     7814
    78137815#if ENABLE(INTERSECTION_OBSERVER)
    78147816void Document::addIntersectionObserver(IntersectionObserver& observer)
     
    79417943    if (needsLayout || hasPendingStyleRecalc())
    79427944        return;
    7943 
    7944     m_needsForcedIntersectionObservationUpdate = false;
    79457945
    79467946    for (const auto& observer : m_intersectionObservers) {
     
    80208020}
    80218021
    8022 void Document::scheduleForcedIntersectionObservationUpdate()
    8023 {
    8024     ASSERT(!m_intersectionObservers.isEmpty());
    8025     if (m_needsForcedIntersectionObservationUpdate)
    8026         return;
    8027 
    8028     m_needsForcedIntersectionObservationUpdate = true;
    8029     if (auto* page = this->page())
    8030         page->scheduleForcedIntersectionObservationUpdate(*this);
    8031 }
    8032 
    80338022void Document::notifyIntersectionObserversTimerFired()
    80348023{
     
    80448033void Document::addResizeObserver(ResizeObserver& observer)
    80458034{
    8046     ASSERT(m_resizeObservers.find(&observer) == notFound);
    8047     m_resizeObservers.append(makeWeakPtr(&observer));
     8035    if (!m_resizeObservers.contains(&observer))
     8036        m_resizeObservers.append(makeWeakPtr(&observer));
    80488037}
    80498038
     
    80948083}
    80958084
    8096 void Document::scheduleResizeObservations()
    8097 {
    8098     if (!page())
    8099         return;
    8100     page()->scheduleResizeObservations();
     8085void Document::updateResizeObservations(Page& page)
     8086{
     8087    if (!hasResizeObservers())
     8088        return;
     8089
     8090    // We need layout the whole frame tree here. Because ResizeObserver could observe element in other frame,
     8091    // and it could change other frame in deliverResizeObservations().
     8092    page.layoutIfNeeded();
     8093
     8094    // Start check resize obervers;
     8095    for (size_t depth = gatherResizeObservations(0); depth != ResizeObserver::maxElementDepth(); depth = gatherResizeObservations(depth)) {
     8096        deliverResizeObservations();
     8097        page.layoutIfNeeded();
     8098    }
     8099
     8100    if (hasSkippedResizeObservations()) {
     8101        setHasSkippedResizeObservations(false);
     8102        String url;
     8103        unsigned line = 0;
     8104        unsigned column = 0;
     8105        getParserLocation(url, line, column);
     8106        reportException("ResizeObserver loop completed with undelivered notifications.", line, column, url, nullptr, nullptr);
     8107        // Starting a new schedule the next round of notify.
     8108        scheduleRenderingUpdate();
     8109    }
    81018110}
    81028111#endif
     
    85258534}
    85268535
    8527 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    8528 DocumentAnimationScheduler& Document::animationScheduler()
    8529 {
    8530     if (!m_animationScheduler)
    8531         m_animationScheduler = DocumentAnimationScheduler::create(*this, page() ? page()->chrome().displayID() : 0);
    8532 
    8533     return *m_animationScheduler;
    8534 }
    8535 #endif
    8536 
    85378536DocumentTimeline& Document::timeline()
    85388537{
  • trunk/Source/WebCore/dom/Document.h

    r244151 r244182  
    109109class DatabaseThread;
    110110class DeferredPromise;
    111 class DocumentAnimationScheduler;
    112111class DocumentFragment;
    113112class DocumentLoader;
     
    10571056    void suspendScriptedAnimationControllerCallbacks();
    10581057    void resumeScriptedAnimationControllerCallbacks();
    1059    
     1058
     1059    void updateAnimationsAndSendEvents(DOMHighResTimeStamp timestamp);
     1060    void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
     1061
    10601062    void windowScreenDidChange(PlatformDisplayID);
    10611063
     
    14121414    void removeAppearanceDependentPicture(HTMLPictureElement&);
    14131415
     1416    void scheduleRenderingUpdate();
     1417
    14141418#if ENABLE(INTERSECTION_OBSERVER)
    14151419    void addIntersectionObserver(IntersectionObserver&);
    14161420    void removeIntersectionObserver(IntersectionObserver&);
    14171421    unsigned numberOfIntersectionObservers() const { return m_intersectionObservers.size(); }
    1418     void scheduleForcedIntersectionObservationUpdate();
    14191422    void updateIntersectionObservations();
    14201423#endif
     
    14291432    bool hasSkippedResizeObservations() const;
    14301433    void setHasSkippedResizeObservations(bool);
    1431     void scheduleResizeObservations();
     1434    void updateResizeObservations(Page&);
    14321435#endif
    14331436
     
    15011504    WEBCORE_EXPORT void setConsoleMessageListener(RefPtr<StringCallback>&&); // For testing.
    15021505
    1503 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    1504     DocumentAnimationScheduler& animationScheduler();
    1505 #endif
    1506 
    15071506    WEBCORE_EXPORT DocumentTimeline& timeline();
    15081507    DocumentTimeline* existingTimeline() const { return m_timeline.get(); }
     
    20722071#endif
    20732072
    2074 #if ENABLE(INTERSECTION_OBSERVER)
    2075     bool m_needsForcedIntersectionObservationUpdate { false };
    2076 #endif
    2077 
    20782073#if ENABLE(MEDIA_STREAM)
    20792074    HashSet<HTMLMediaElement*> m_mediaStreamStateChangeElements;
     
    20952090    bool m_grantStorageAccessOverride { false };
    20962091
    2097 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    2098     RefPtr<DocumentAnimationScheduler> m_animationScheduler;
    2099 #endif
    21002092    RefPtr<DocumentTimeline> m_timeline;
    21012093    DocumentIdentifier m_identifier;
  • trunk/Source/WebCore/dom/ScriptedAnimationController.cpp

    r243810 r244182  
    3131#include "DOMWindow.h"
    3232#include "Document.h"
    33 #include "DocumentAnimationScheduler.h"
    3433#include "DocumentLoader.h"
    3534#include "Frame.h"
     
    190189}
    191190
    192 void ScriptedAnimationController::serviceScriptedAnimations(double timestamp)
     191void ScriptedAnimationController::serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp)
    193192{
    194193    if (!m_callbacks.size() || m_suspendCount || !requestAnimationFrameEnabled())
     
    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);
     199    DOMHighResTimeStamp highResNowMs = std::round(1000 * timestamp);
    201200
    202201    // First, generate a list of callbacks to consider.  Callbacks registered from this point
     
    210209
    211210    for (auto& callback : callbacks) {
    212         if (!callback->m_firedOrCancelled) {
    213             callback->m_firedOrCancelled = true;
    214             InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(protectedDocument, callback->m_id);
    215             callback->handleEvent(highResNowMs);
    216             InspectorInstrumentation::didFireAnimationFrame(cookie);
    217         }
     211        if (callback->m_firedOrCancelled)
     212            continue;
     213        callback->m_firedOrCancelled = true;
     214        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(protectedDocument, callback->m_id);
     215        callback->handleEvent(highResNowMs);
     216        InspectorInstrumentation::didFireAnimationFrame(cookie);
    218217    }
    219218
    220219    // Remove any callbacks we fired from the list of pending callbacks.
    221     for (size_t i = 0; i < m_callbacks.size();) {
    222         if (m_callbacks[i]->m_firedOrCancelled)
    223             m_callbacks.remove(i);
    224         else
    225             ++i;
    226     }
     220    m_callbacks.removeAllMatching([](auto& callback) {
     221        return callback->m_firedOrCancelled;
     222    });
    227223
    228224    if (m_callbacks.size())
     
    259255#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    260256    if (!m_isUsingTimer && !isThrottled()) {
    261         if (m_document->animationScheduler().scheduleScriptedAnimationResolution())
     257        if (auto* page = this->page()) {
     258            page->renderingUpdateScheduler().scheduleRenderingUpdate();
    262259            return;
     260        }
    263261
    264262        m_isUsingTimer = true;
     
    289287{
    290288    m_lastAnimationFrameTimestamp = m_document->domWindow()->nowTimestamp();
    291     serviceScriptedAnimations(m_lastAnimationFrameTimestamp);
    292 }
    293 
    294 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    295 void ScriptedAnimationController::documentAnimationSchedulerDidFire()
    296 {
    297     // We obtain the time from the animation scheduler so that we use the same timestamp as the DocumentTimeline.
    298     serviceScriptedAnimations(m_document->animationScheduler().lastTimestamp().seconds());
    299 }
    300 #endif
    301 
    302 }
     289    serviceRequestAnimationFrameCallbacks(m_lastAnimationFrameTimestamp);
     290}
     291
     292}
  • trunk/Source/WebCore/dom/ScriptedAnimationController.h

    r243459 r244182  
    5353    CallbackId registerCallback(Ref<RequestAnimationFrameCallback>&&);
    5454    void cancelCallback(CallbackId);
    55     void serviceScriptedAnimations(double timestamp);
     55    void serviceRequestAnimationFrameCallbacks(DOMHighResTimeStamp timestamp);
    5656
    5757    void suspend();
     
    6969    WEBCORE_EXPORT bool isThrottled() const;
    7070    WEBCORE_EXPORT Seconds interval() const;
    71 
    72 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
    73     void documentAnimationSchedulerDidFire();
    74 #endif
    7571
    7672private:
  • trunk/Source/WebCore/page/FrameView.cpp

    r244141 r244182  
    12681268void FrameView::didLayout(WeakPtr<RenderElement> layoutRoot)
    12691269{
    1270 #if ENABLE(RESIZE_OBSERVER)
    1271     auto page = frame().page();
    1272     if (page && page->hasResizeObservers())
    1273         page->setNeedsCheckResizeObservations(true);
    1274 #endif
    12751270    renderView()->releaseProtectedRenderWidgets();
    12761271    auto* layoutRootEnclosingLayer = layoutRoot->enclosingLayer();
     
    19771972            renderView->updateVisibleViewportRect(visibleRect);
    19781973    });
    1979 
    1980 #if ENABLE(INTERSECTION_OBSERVER)
    1981     if (auto* document = frame().document()) {
    1982         if (auto* page = frame().page()) {
    1983             if (document->numberOfIntersectionObservers())
    1984                 page->addDocumentNeedingIntersectionObservationUpdate(*document);
    1985             if (!frame().isMainFrame()) {
    1986                 if (auto* mainDocument = frame().mainFrame().document()) {
    1987                     if (mainDocument->numberOfIntersectionObservers())
    1988                         page->addDocumentNeedingIntersectionObservationUpdate(*mainDocument);
    1989                 }
    1990             }
    1991         }
    1992     }
    1993 #endif
    19941974}
    19951975
  • trunk/Source/WebCore/page/FrameViewLayoutContext.cpp

    r243919 r244182  
    457457#endif
    458458    layout();
    459 
    460 #if ENABLE(RESIZE_OBSERVER)
    461     // After this layout, it might not trigger display timer. E.g.: Running layout test for WK1.
    462     // So scheduleResizeObservations() here to make sure ResizeObserver could be fired properly.
    463     auto page = frame().page();
    464     if (page && page->needsCheckResizeObservations())
    465         page->scheduleResizeObservations();
    466 #endif
    467459}
    468460
  • trunk/Source/WebCore/page/IntersectionObserver.cpp

    r244115 r244182  
    159159    if (!hadObservationTargets)
    160160        document->addIntersectionObserver(*this);
    161     document->scheduleForcedIntersectionObservationUpdate();
    162161}
    163162
  • trunk/Source/WebCore/page/Page.cpp

    r243762 r244182  
    123123#include "WheelEventDeltaFilter.h"
    124124#include "Widget.h"
    125 #if ENABLE(RESIZE_OBSERVER)
    126 #include <JavaScriptCore/ScriptCallStack.h>
    127 #endif
    128125#include <wtf/FileSystem.h>
    129126#include <wtf/RefCountedLeakCounter.h>
    130127#include <wtf/StdLibExtras.h>
     128#include <wtf/SystemTracing.h>
    131129#include <wtf/text/Base64.h>
    132130#include <wtf/text/StringHash.h>
     
    258256    , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
    259257    , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
    260 #if ENABLE(INTERSECTION_OBSERVER)
    261     , m_intersectionObservationUpdateTimer(*this, &Page::updateIntersectionObservations)
    262 #endif
    263258    , m_sessionID(PAL::SessionID::defaultSessionID())
    264259#if ENABLE(VIDEO)
    265260    , m_playbackControlsManagerUpdateTimer(*this, &Page::playbackControlsManagerUpdateTimerFired)
    266 #endif
    267 #if ENABLE(RESIZE_OBSERVER)
    268     , m_resizeObserverTimer(*this, &Page::checkResizeObservations)
    269261#endif
    270262    , m_isUtilityPage(isUtilityPageChromeClient(chrome().client()))
     
    11221114}
    11231115
    1124 void Page::willDisplayPage()
    1125 {
    1126 #if ENABLE(RESIZE_OBSERVER)
    1127     checkResizeObservations();
    1128 #endif
    1129 
    1130 #if ENABLE(INTERSECTION_OBSERVER)
    1131     updateIntersectionObservations();
    1132 #endif
    1133 }
    1134 
    11351116bool Page::isOnlyNonUtilityPage() const
    11361117{
     
    12741255}
    12751256
     1257void Page::layoutIfNeeded()
     1258{
     1259    if (FrameView* view = m_mainFrame->view())
     1260        view->updateLayoutAndStyleIfNeededRecursive();
     1261}
     1262
     1263void Page::updateRendering()
     1264{
     1265    // This function is not reentrant, e.g. a rAF callback may force repaint.
     1266    if (m_inUpdateRendering) {
     1267        layoutIfNeeded();
     1268        return;
     1269    }
     1270
     1271    TraceScope traceScope(RenderingUpdateStart, RenderingUpdateEnd);
     1272
     1273    SetForScope<bool> change(m_inUpdateRendering, true);
     1274
     1275    Vector<RefPtr<Document>> documents;
     1276
     1277    // The requestAnimationFrame callbacks may change the frame hierarchy of the page
     1278    forEachDocument([&documents] (Document& document) {
     1279        documents.append(&document);
     1280    });
     1281
     1282    for (auto& document : documents) {
     1283        DOMHighResTimeStamp timestamp = document->domWindow()->nowTimestamp();
     1284        document->updateAnimationsAndSendEvents(timestamp);
     1285        document->serviceRequestAnimationFrameCallbacks(timestamp);
     1286    }
     1287
     1288    layoutIfNeeded();
     1289
    12761290#if ENABLE(INTERSECTION_OBSERVER)
    1277 void Page::addDocumentNeedingIntersectionObservationUpdate(Document& document)
    1278 {
    1279     if (m_documentsNeedingIntersectionObservationUpdate.find(&document) == notFound)
    1280         m_documentsNeedingIntersectionObservationUpdate.append(makeWeakPtr(document));
    1281 }
    1282 
    1283 void Page::updateIntersectionObservations()
    1284 {
    1285     m_intersectionObservationUpdateTimer.stop();
    1286     for (const auto& document : m_documentsNeedingIntersectionObservationUpdate) {
    1287         if (document)
    1288             document->updateIntersectionObservations();
    1289     }
    1290     m_documentsNeedingIntersectionObservationUpdate.clear();
    1291 }
    1292 
    1293 void Page::scheduleForcedIntersectionObservationUpdate(Document& document)
    1294 {
    1295     addDocumentNeedingIntersectionObservationUpdate(document);
    1296     if (m_intersectionObservationUpdateTimer.isActive())
    1297         return;
    1298     m_intersectionObservationUpdateTimer.startOneShot(0_s);
    1299 }
    1300 #endif
    1301 
     1291    for (auto& document : documents)
     1292        document->updateIntersectionObservations();
     1293#endif
    13021294#if ENABLE(RESIZE_OBSERVER)
    1303 bool Page::hasResizeObservers() const
    1304 {
    1305     for (const Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
    1306         auto doc = frame->document();
    1307         if (doc && doc->hasResizeObservers())
    1308             return true;
    1309     }
    1310     return false;
    1311 }
    1312 
    1313 void Page::gatherDocumentsNeedingResizeObservationCheck(Vector<WeakPtr<Document>>& documentsNeedingResizeObservationCheck)
    1314 {
    1315     forEachDocument([&] (Document& document) {
    1316         if (document.hasResizeObservers())
    1317             documentsNeedingResizeObservationCheck.append(makeWeakPtr(document));
    1318     });
    1319 }
    1320 
    1321 void Page::checkResizeObservations()
    1322 {
    1323     if (!needsCheckResizeObservations())
    1324         return;
    1325     setNeedsCheckResizeObservations(false);
    1326     m_resizeObserverTimer.stop();
    1327 
    1328     Vector<WeakPtr<Document>> documentsNeedingResizeObservationCheck;
    1329     gatherDocumentsNeedingResizeObservationCheck(documentsNeedingResizeObservationCheck);
    1330     for (const auto& document : documentsNeedingResizeObservationCheck)
    1331         notifyResizeObservers(document);
    1332     documentsNeedingResizeObservationCheck.clear();
    1333 }
    1334 
    1335 void Page::scheduleResizeObservations()
    1336 {
    1337     setNeedsCheckResizeObservations(true);
    1338     if (m_resizeObserverTimer.isActive())
    1339         return;
    1340     m_resizeObserverTimer.startOneShot(0_s);
    1341 }
    1342 
    1343 void Page::notifyResizeObservers(WeakPtr<Document> document)
    1344 {
    1345     if (!document)
    1346         return;
    1347 
    1348     // We need layout the whole frame tree here. Because ResizeObserver could observe element in other frame,
    1349     // and it could change other frame in deliverResizeObservations().
    1350     if (mainFrame().view())
    1351         mainFrame().view()->updateLayoutAndStyleIfNeededRecursive();
    1352 
    1353     // Start check resize obervers;
    1354     for (size_t depth = document->gatherResizeObservations(0); depth != ResizeObserver::maxElementDepth(); depth = document->gatherResizeObservations(depth)) {
    1355         document->deliverResizeObservations();
    1356         if (!document)
    1357             return;
    1358         if (mainFrame().view())
    1359             mainFrame().view()->updateLayoutAndStyleIfNeededRecursive();
    1360     }
    1361 
    1362     if (document->hasSkippedResizeObservations()) {
    1363         document->setHasSkippedResizeObservations(false);
    1364         String url;
    1365         unsigned line = 0;
    1366         unsigned column = 0;
    1367         document->getParserLocation(url, line, column);
    1368         document->reportException("ResizeObserver loop completed with undelivered notifications.", line, column, url, nullptr, nullptr);
    1369         // TODO: We are starting a timer to schedule the next round of notify.
    1370         // However, this should be in synchrony with the next requestAnimationFrame.
    1371         scheduleResizeObservations();
    1372     }
    1373 }
    1374 #endif
     1295    for (auto& document : documents)
     1296        document->updateResizeObservations(*this);
     1297#endif
     1298
     1299    layoutIfNeeded();
     1300}
    13751301
    13761302void Page::suspendScriptedAnimations()
     
    29122838}
    29132839
     2840RenderingUpdateScheduler& Page::renderingUpdateScheduler()
     2841{
     2842    if (!m_renderingUpdateScheduler)
     2843        m_renderingUpdateScheduler = RenderingUpdateScheduler::create(*this);
     2844    return *m_renderingUpdateScheduler;
     2845}
     2846
    29142847void Page::forEachDocument(const Function<void(Document&)>& functor)
    29152848{
  • trunk/Source/WebCore/page/Page.h

    r243899 r244182  
    3434#include "Region.h"
    3535#include "RegistrableDomain.h"
     36#include "RenderingUpdateScheduler.h"
    3637#include "ScrollTypes.h"
    3738#include "Supplementable.h"
     
    265266    PerformanceMonitor* performanceMonitor() { return m_performanceMonitor.get(); }
    266267
     268    RenderingUpdateScheduler& renderingUpdateScheduler();
     269
    267270    ValidationMessageClient* validationMessageClient() const { return m_validationMessageClient.get(); }
    268271    void updateValidationBubbleStateIfNeeded();
     
    340343    void didFinishLoad(); // Called when the load has been committed in the main frame.
    341344
    342     WEBCORE_EXPORT void willDisplayPage();
    343 
    344345    // The view scale factor is multiplied into the page scale factor by all
    345346    // callers of setPageScaleFactor.
     
    469470    WEBCORE_EXPORT void removeActivityStateChangeObserver(ActivityStateChangeObserver&);
    470471
    471 #if ENABLE(INTERSECTION_OBSERVER)
    472     void addDocumentNeedingIntersectionObservationUpdate(Document&);
    473     void scheduleForcedIntersectionObservationUpdate(Document&);
    474     void updateIntersectionObservations();
    475 #endif
    476 
    477 #if ENABLE(RESIZE_OBSERVER)
    478     WEBCORE_EXPORT void checkResizeObservations();
    479     bool hasResizeObservers() const;
    480     void gatherDocumentsNeedingResizeObservationCheck(Vector<WeakPtr<Document>>&);
    481     void scheduleResizeObservations();
    482     void notifyResizeObservers(WeakPtr<Document>);
    483     void setNeedsCheckResizeObservations(bool check) { m_needsCheckResizeObservations = check; }
    484     bool needsCheckResizeObservations() const { return m_needsCheckResizeObservations; }
    485 
    486 #endif
     472    WEBCORE_EXPORT void layoutIfNeeded();
     473    WEBCORE_EXPORT void updateRendering();
    487474
    488475    WEBCORE_EXPORT void suspendScriptedAnimations();
     
    888875    int m_headerHeight { 0 };
    889876    int m_footerHeight { 0 };
     877
     878    std::unique_ptr<RenderingUpdateScheduler> m_renderingUpdateScheduler;
    890879
    891880    HashSet<RenderObject*> m_relevantUnpaintedRenderObjects;
     
    929918    HashSet<ActivityStateChangeObserver*> m_activityStateChangeObservers;
    930919
    931 #if ENABLE(INTERSECTION_OBSERVER)
    932     Vector<WeakPtr<Document>> m_documentsNeedingIntersectionObservationUpdate;
    933 
    934     // FIXME: Schedule intersection observation updates in a way that fits into the HTML
    935     // EventLoop. See https://bugs.webkit.org/show_bug.cgi?id=160711.
    936     Timer m_intersectionObservationUpdateTimer;
    937 #endif
    938 
    939920#if ENABLE(RESOURCE_USAGE)
    940921    std::unique_ptr<ResourceUsageOverlay> m_resourceUsageOverlay;
     
    950931#if ENABLE(VIDEO)
    951932    Timer m_playbackControlsManagerUpdateTimer;
    952 #endif
    953 
    954 #if ENABLE(RESIZE_OBSERVER)
    955     Timer m_resizeObserverTimer;
    956     bool m_needsCheckResizeObservations { false };
    957933#endif
    958934
     
    1002978    bool m_mediaPlaybackIsSuspended { false };
    1003979    bool m_mediaBufferingIsSuspended { false };
     980    bool m_inUpdateRendering { false };
    1004981};
    1005982
  • trunk/Source/WebCore/page/PageOverlayController.cpp

    r242714 r244182  
    319319void PageOverlayController::didChangeViewExposedRect()
    320320{
    321     m_page.chrome().client().scheduleCompositingLayerFlush();
     321    m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
    322322}
    323323
     
    413413void PageOverlayController::notifyFlushRequired(const WebCore::GraphicsLayer*)
    414414{
    415     m_page.chrome().client().scheduleCompositingLayerFlush();
     415    m_page.renderingUpdateScheduler().scheduleRenderingUpdate();
    416416}
    417417
  • trunk/Source/WebCore/page/RenderingUpdateScheduler.h

    r244181 r244182  
    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
     
    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 RenderingUpdateScheduler
     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();
     43    static std::unique_ptr<RenderingUpdateScheduler> create(Page& page)
     44    {
     45        return std::make_unique<RenderingUpdateScheduler>(page);
     46    }
    4647
    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; }
     48    RenderingUpdateScheduler(Page&);
     49    void scheduleRenderingUpdate();
     50    void scheduleCompositingLayerFlush();
    5651
    5752private:
    58     DocumentAnimationScheduler(Document&, PlatformDisplayID);
     53#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     54    RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const final;
     55    void windowScreenDidChange(PlatformDisplayID);
     56    void displayRefreshFired() final;
     57#else
     58    void displayRefreshFired();
     59#endif
    5960
    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 };
     61    bool isScheduled() const;
     62    void startTimer(Seconds);
     63    void clearScheduled();
    6564
    66     void displayRefreshFired() override;
    67     RefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
     65    Page& m_page;
     66    bool m_scheduled { false };
     67    std::unique_ptr<Timer> m_refreshTimer;
    6868};
    6969
    70 } // namespace WebCore
    71 
    72 #endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     70}
  • trunk/Source/WebCore/page/ResizeObserver.cpp

    r243643 r244182  
    5454}
    5555
    56 void ResizeObserver::scheduleObservations()
    57 {
    58     if (m_document)
    59         m_document->scheduleResizeObservations();
    60 }
    61 
    6256void ResizeObserver::observe(Element& target)
    6357{
     
    6559        return;
    6660
    67     for (auto& observation : m_observations) {
    68         if (observation->target() == &target)
    69             return;
    70     }
     61    auto position = m_observations.findMatching([&](auto& observation) {
     62        return observation->target() == &target;
     63    });
     64
     65    if (position != notFound)
     66        return;
    7167
    7268    auto& observerData = target.ensureResizeObserverData();
    7369    observerData.observers.append(makeWeakPtr(this));
    74     if (m_document && !hasObservations())
    75         m_document->addResizeObserver(*this);
     70
    7671    m_observations.append(ResizeObservation::create(&target));
    7772
    78     scheduleObservations();
     73    if (m_document) {
     74        m_document->addResizeObserver(*this);
     75        m_document->scheduleRenderingUpdate();
     76    }
    7977}
    8078
  • trunk/Source/WebCore/page/ResizeObserver.h

    r243643 r244182  
    5151    bool hasObservations() const { return m_observations.size(); }
    5252    bool hasActiveObservations() const { return m_activeObservations.size(); }
    53     void scheduleObservations();
    5453
    5554    void observe(Element&);
  • trunk/Source/WebCore/page/ios/ContentChangeObserver.h

    r243752 r244182  
    2929
    3030#include "CSSPropertyNames.h"
     31#include "Document.h"
    3132#include "PlatformEvent.h"
     33#include "RenderStyleConstants.h"
    3234#include "Timer.h"
    3335#include "WKContentObservation.h"
    3436#include <wtf/HashSet.h>
     37#include <wtf/Seconds.h>
    3538
    3639namespace WebCore {
     
    3841class Animation;
    3942class DOMTimer;
    40 class Document;
    4143class Element;
    4244
  • trunk/Source/WebCore/page/mac/ServicesOverlayController.mm

    r242714 r244182  
    122122        return;
    123123
    124     m_controller->page().chrome().client().scheduleCompositingLayerFlush();
     124    m_controller->page().renderingUpdateScheduler().scheduleRenderingUpdate();
    125125}
    126126
  • trunk/Source/WebCore/page/scrolling/ScrollingStateTree.cpp

    r243539 r244182  
    3535#include "ScrollingStateFrameScrollingNode.h"
    3636#include "ScrollingStateOverflowScrollingNode.h"
     37#include "ScrollingStatePositionedNode.h"
    3738#include "ScrollingStateStickyNode.h"
    3839#include <wtf/text/CString.h>
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r244068 r244182  
    451451{
    452452    m_hasPendingLayerFlush = false;
    453     page().chrome().client().scheduleCompositingLayerFlush();
     453    page().renderingUpdateScheduler().scheduleRenderingUpdate();
    454454}
    455455
     
    19241924
    19251925    flushPendingLayerChanges(true);
     1926    page().renderingUpdateScheduler().scheduleCompositingLayerFlush();
    19261927
    19271928    LayerTreeAsTextBehavior layerTreeBehavior = LayerTreeAsTextBehaviorNormal;
  • trunk/Source/WebKit/ChangeLog

    r244180 r244182  
     12019-04-10  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::updateRendering(). 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/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp:
     14        (WebKit::DrawingAreaCoordinatedGraphics::scheduleCompositingLayerFlush):
     15        (WebKit::DrawingAreaCoordinatedGraphics::updateBackingStoreState):
     16        (WebKit::DrawingAreaCoordinatedGraphics::display):
     17        * WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:
     18        (WebKit::LayerTreeHost::layerFlushTimerFired):
     19
     20        * WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm:
     21        (WebKit::RemoteLayerTreeDrawingArea::flushLayers):
     22        -- Call Page::updateRendering() to make sure that "Update the rendering"
     23           happens immediately before updating the page.
     24
     25        -- Move the call to RemoteLayerBackingStoreCollection::willFlushLayers()
     26           to be exactly before flushing the layers. This fixes the assertion
     27           ASSERT(m_inLayerFlush) which was firing when running a layout test.
     28           RemoteLayerTreeDrawingArea::flushLayers() now can call itself through
     29           TestRunner::notifyDone(). flushLayers() was calling willFlushLayers()
     30           twice before calling didFlushLayers().
     31
     32        * WebProcess/WebPage/WebPage.cpp:
     33        (WebKit::WebPage::layoutIfNeeded):
     34        (WebKit::WebPage::updateRendering):
     35        (WebKit::WebPage::willDisplayPage): Deleted.
     36        * WebProcess/WebPage/WebPage.h:
     37        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
     38        (WebKit::TiledCoreAnimationDrawingArea::flushLayers):
     39
    1402019-04-10  Devin Rousso  <drousso@apple.com>
    241
  • trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/DrawingAreaCoordinatedGraphics.cpp

    r243796 r244182  
    304304    if (m_layerTreeHost)
    305305        m_layerTreeHost->scheduleLayerFlush();
     306    else
     307        setNeedsDisplay();
    306308}
    307309
     
    382384        m_webPage.setDeviceScaleFactor(deviceScaleFactor);
    383385        m_webPage.setSize(size);
    384         m_webPage.layoutIfNeeded();
     386        m_webPage.updateRendering();
    385387        m_webPage.flushPendingEditorStateUpdate();
    386388        m_webPage.scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
    387         m_webPage.willDisplayPage();
    388389
    389390        if (m_layerTreeHost)
     
    707708    ASSERT(!m_webPage.size().isEmpty());
    708709
    709     m_webPage.layoutIfNeeded();
     710    m_webPage.updateRendering();
    710711    m_webPage.flushPendingEditorStateUpdate();
    711712
     
    715716        return;
    716717
    717     m_webPage.willDisplayPage();
    718718    updateInfo.viewSize = m_webPage.size();
    719719    updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
  • trunk/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp

    r243865 r244182  
    146146
    147147    m_coordinator.syncDisplayState();
     148    m_webPage.updateRendering();
    148149    m_webPage.flushPendingEditorStateUpdate();
    149     m_webPage.willDisplayPage();
    150150
    151151    if (!m_isValid || !m_coordinator.rootCompositingLayer())
  • trunk/Source/WebKit/WebProcess/WebPage/RemoteLayerTree/RemoteLayerTreeDrawingArea.mm

    r242714 r244182  
    345345    }
    346346
    347     RELEASE_ASSERT(!m_pendingBackingStoreFlusher || m_pendingBackingStoreFlusher->hasFlushed());
    348 
    349     RemoteLayerBackingStoreCollection& backingStoreCollection = m_remoteLayerTreeContext->backingStoreCollection();
    350     backingStoreCollection.willFlushLayers();
    351 
    352     m_webPage.layoutIfNeeded();
    353     m_webPage.willDisplayPage();
     347    m_webPage.updateRendering();
    354348
    355349    FloatRect visibleRect(FloatPoint(), m_viewSize);
     
    373367    if (m_viewOverlayRootLayer)
    374368        m_viewOverlayRootLayer->flushCompositingState(visibleRect);
     369
     370    RELEASE_ASSERT(!m_pendingBackingStoreFlusher || m_pendingBackingStoreFlusher->hasFlushed());
     371
     372    RemoteLayerBackingStoreCollection& backingStoreCollection = m_remoteLayerTreeContext->backingStoreCollection();
     373    backingStoreCollection.willFlushLayers();
    375374
    376375    m_rootLayer->flushCompositingStateForThisLayerOnly();
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r244151 r244182  
    16121612}
    16131613
    1614 void WebPage::layoutIfNeeded()
    1615 {
    1616     if (m_mainFrame->coreFrame()->view())
    1617         m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
    1618 }
    1619 
    16201614WebPage* WebPage::fromCorePage(Page* page)
    16211615{
     
    36533647#endif
    36543648
    3655 void WebPage::willDisplayPage()
    3656 {
    3657     m_page->willDisplayPage();
     3649void WebPage::layoutIfNeeded()
     3650{
     3651    m_page->layoutIfNeeded();
     3652}
     3653   
     3654void WebPage::updateRendering()
     3655{
     3656    m_page->updateRendering();
    36583657}
    36593658
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r244148 r244182  
    307307#endif
    308308
    309     void willDisplayPage();
     309    void layoutIfNeeded();
     310    void updateRendering();
    310311
    311312    enum class LazyCreationPolicy { UseExistingOnly, CreateIfNeeded };
     
    340341    // FIXME: We could genericize these into a DrawingArea client interface. Would that be beneficial?
    341342    void drawRect(WebCore::GraphicsContext&, const WebCore::IntRect&);
    342     void layoutIfNeeded();
    343343
    344344    // -- Called from WebCore clients.
  • trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

    r243469 r244182  
    460460        scaleViewToFitDocumentIfNeeded();
    461461
    462         m_webPage.layoutIfNeeded();
     462        m_webPage.updateRendering();
    463463        m_webPage.flushPendingEditorStateUpdate();
    464         m_webPage.willDisplayPage();
    465464
    466465        updateIntrinsicContentSizeIfNeeded();
  • trunk/Source/WebKitLegacy/mac/ChangeLog

    r244180 r244182  
     12019-04-10  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        (-[WebView _flushCompositingChanges]):
     11        Call Page::updateRendering() which implements "Update the rendering"
     12        step of the HTML Event Loop specification.
     13
    1142019-04-10  Devin Rousso  <drousso@apple.com>
    215
  • trunk/Source/WebKitLegacy/mac/WebView/WebView.mm

    r243666 r244182  
    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
     
    93899388- (BOOL)_flushCompositingChanges
    93909389{
    9391 #if ENABLE(RESIZE_OBSERVER)
    9392     if (_private->page)
    9393         _private->page->checkResizeObservations();
    9394 #endif
    9395 
    93969390    Frame* frame = [self _mainCoreFrame];
    93979391    if (frame && frame->view())
  • trunk/Source/WebKitLegacy/win/ChangeLog

    r244180 r244182  
     12019-04-10  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::updateRendering() which implements "Update the rendering"
     13        step of the HTML Event Loop specification.
     14
    1152019-04-10  Devin Rousso  <drousso@apple.com>
    216
  • trunk/Source/WebKitLegacy/win/WebView.cpp

    r243643 r244182  
    11721172    if (m_backingStoreBitmap && (m_backingStoreDirtyRegion || backingStoreCompletelyDirty)) {
    11731173        // Do a layout first so that everything we render to the backing store is always current.
    1174         if (Frame* coreFrame = core(m_mainFrame))
    1175             if (FrameView* view = coreFrame->view())
    1176                 view->updateLayoutAndStyleIfNeededRecursive();
     1174        m_page->updateRendering();
    11771175
    11781176        Vector<IntRect> paintRects;
     
    71617159{
    71627160#if USE(CA)
    7163     if (!m_layerTreeHost)
     7161    if (!m_layerTreeHost) {
     7162        m_page->updateRendering();
    71647163        return;
     7164    }
    71657165    m_layerTreeHost->flushPendingGraphicsLayerChangesSoon();
    71667166#elif USE(TEXTURE_MAPPER_GL)
     
    73907390        return;
    73917391
    7392     view->updateLayoutAndStyleIfNeededRecursive();
     7392    m_page->updateRendering();
    73937393
    73947394    // Updating layout might have taken us out of compositing mode.
  • trunk/Tools/ChangeLog

    r244171 r244182  
     12019-04-10  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-04-10  Fujii Hironori  <Hironori.Fujii@sony.com>
    213
  • trunk/Tools/Tracing/SystemTracePoints.plist

    r242714 r244182  
    219219             <dict>
    220220                 <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>
     251             <dict>
     252                 <key>Name</key>
     253                 <string>Schedule rendering update</string>
     254                 <key>Type</key>
     255                 <string>Impulse</string>
     256                 <key>Component</key>
     257                 <string>47</string>
     258                 <key>Code</key>
     259                 <string>5028</string>
     260             </dict>
     261             <dict>
     262                 <key>Name</key>
     263                 <string>Trigger rendering update</string>
     264                 <key>Type</key>
     265                 <string>Impulse</string>
     266                 <key>Component</key>
     267                 <string>47</string>
     268                 <key>Code</key>
     269                 <string>5029</string>
     270             </dict>
     271             <dict>
     272                 <key>Name</key>
     273                 <string>Rendering update</string>
     274                 <key>Type</key>
     275                 <string>Interval</string>
     276                 <key>Component</key>
     277                 <string>47</string>
     278                 <key>CodeBegin</key>
     279                 <string>5030</string>
     280                 <key>CodeEnd</key>
     281                 <string>5031</string>
     282             </dict>
     283             <dict>
     284                 <key>Name</key>
    221285                 <string>Paint WebHTMLView</string>
    222286                 <key>Type</key>
Note: See TracChangeset for help on using the changeset viewer.