Changeset 183998 in webkit


Ignore:
Timestamp:
May 8, 2015 11:15:57 AM (9 years ago)
Author:
Chris Dumez
Message:

Throttle RequestAnimationFrame in subframes that are outside the viewport
https://bugs.webkit.org/show_bug.cgi?id=144718
<rdar://problem/20688782>

Reviewed by Simon Fraser.

Source/WebCore:

Throttle RequestAnimationFrame in subframes that are outside the
viewport or have "display: none" for performance and power.

Tests: fast/animation/request-animation-frame-throttle-subframe-display-none.html

fast/animation/request-animation-frame-throttle-subframe.html

  • dom/Document.h:

(WebCore::Document::scriptedAnimationController):

  • dom/ScriptedAnimationController.cpp:

(WebCore::ScriptedAnimationController::setThrottled):
(WebCore::ScriptedAnimationController::isThrottled):

  • dom/ScriptedAnimationController.h:
  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::open):
Call FrameView::setFrameRect() only *after* the view has been
set on the Frame. Otherwise, setFrameRect() ends up calling
viewportContentsChanged() and we hit the
ASSERT(frame().view() == this) assertion in windowClipRect()
because the Frame still has its old FrameView. This is covered
by loader/go-back-to-different-window-size.html layout test.

  • page/FrameView.cpp:

(WebCore::FrameView::viewportContentsChanged):
(WebCore::FrameView::applyRecursivelyWithVisibleRect):
(WebCore::FrameView::resumeVisibleImageAnimations):
(WebCore::FrameView::updateScriptedAnimationsThrottlingState):
(WebCore::FrameView::resumeVisibleImageAnimationsIncludingSubframes):
(WebCore::FrameView::updateThrottledDOMTimersState):
(WebCore::FrameView::scrollPositionChanged): Deleted.
(WebCore::FrameView::sendResizeEventIfNeeded): Deleted.

  • page/FrameView.h:
  • testing/Internals.cpp:

(WebCore::Internals::isRequestAnimationFrameThrottled):
(WebCore::Internals::isTimerThrottled): Deleted.

  • testing/Internals.h:
  • testing/Internals.idl:

LayoutTests:

  • fast/animation/request-animation-frame-throttle-subframe-display-none-expected.txt: Added.
  • fast/animation/request-animation-frame-throttle-subframe-display-none.html: Added.

Add layout test to test that RequestAnimationFrame is properly throttled
in "display: none" subframes.

  • fast/animation/request-animation-frame-throttle-subframe-expected.txt: Added.
  • fast/animation/request-animation-frame-throttle-subframe.html: Added.

Add layout test to test that RequestAnimationFrame is properly throttled
in frames that are outside the viewport.

  • fast/animation/resources/requestAnimationFrame-frame-2.html: Added.
  • fast/animation/resources/requestAnimationFrame-frame.html: Added.
  • platform/win/TestExpectations:

Skip the 2 new tests on Windows as requestAnimationFrame throttling is
only supported on Cocoa.

Location:
trunk
Files:
7 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r183995 r183998  
     12015-05-08  Chris Dumez  <cdumez@apple.com>
     2
     3        Throttle RequestAnimationFrame in subframes that are outside the viewport
     4        https://bugs.webkit.org/show_bug.cgi?id=144718
     5        <rdar://problem/20688782>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/animation/request-animation-frame-throttle-subframe-display-none-expected.txt: Added.
     10        * fast/animation/request-animation-frame-throttle-subframe-display-none.html: Added.
     11        Add layout test to test that RequestAnimationFrame is properly throttled
     12        in "display: none" subframes.
     13
     14        * fast/animation/request-animation-frame-throttle-subframe-expected.txt: Added.
     15        * fast/animation/request-animation-frame-throttle-subframe.html: Added.
     16        Add layout test to test that RequestAnimationFrame is properly throttled
     17        in frames that are outside the viewport.
     18
     19        * fast/animation/resources/requestAnimationFrame-frame-2.html: Added.
     20        * fast/animation/resources/requestAnimationFrame-frame.html: Added.
     21
     22        * platform/win/TestExpectations:
     23        Skip the 2 new tests on Windows as requestAnimationFrame throttling is
     24        only supported on Cocoa.
     25
    1262015-05-08  Carlos Garcia Campos  <cgarcia@igalia.com>
    227
  • trunk/LayoutTests/platform/win/TestExpectations

    r183994 r183998  
    24962496webkit.org/b/138676 imported/w3c/canvas/2d.line.join.parallel.html [ Failure ]
    24972497webkit.org/b/138676 imported/w3c/canvas/2d.strokeRect.zero.5.html [ Failure ]
     2498
     2499# requestAnimationFrame throttling does not work on Windows because USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) is disabled.
     2500webkit.org/b/144718 fast/animation/request-animation-frame-throttle-subframe-display-none.html [ Skip ]
     2501webkit.org/b/144718 fast/animation/request-animation-frame-throttle-subframe.html [ Skip ]
    24982502
    24992503################################################################################
  • trunk/Source/WebCore/ChangeLog

    r183997 r183998  
     12015-05-08  Chris Dumez  <cdumez@apple.com>
     2
     3        Throttle RequestAnimationFrame in subframes that are outside the viewport
     4        https://bugs.webkit.org/show_bug.cgi?id=144718
     5        <rdar://problem/20688782>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Throttle RequestAnimationFrame in subframes that are outside the
     10        viewport or have "display: none" for performance and power.
     11
     12        Tests: fast/animation/request-animation-frame-throttle-subframe-display-none.html
     13               fast/animation/request-animation-frame-throttle-subframe.html
     14
     15        * dom/Document.h:
     16        (WebCore::Document::scriptedAnimationController):
     17        * dom/ScriptedAnimationController.cpp:
     18        (WebCore::ScriptedAnimationController::setThrottled):
     19        (WebCore::ScriptedAnimationController::isThrottled):
     20        * dom/ScriptedAnimationController.h:
     21        * loader/FrameLoader.cpp:
     22        (WebCore::FrameLoader::open):
     23        Call FrameView::setFrameRect() only *after* the view has been
     24        set on the Frame. Otherwise, setFrameRect() ends up calling
     25        viewportContentsChanged() and we hit the
     26        ASSERT(frame().view() == this) assertion in windowClipRect()
     27        because the Frame still has its old FrameView. This is covered
     28        by loader/go-back-to-different-window-size.html layout test.
     29
     30        * page/FrameView.cpp:
     31        (WebCore::FrameView::viewportContentsChanged):
     32        (WebCore::FrameView::applyRecursivelyWithVisibleRect):
     33        (WebCore::FrameView::resumeVisibleImageAnimations):
     34        (WebCore::FrameView::updateScriptedAnimationsThrottlingState):
     35        (WebCore::FrameView::resumeVisibleImageAnimationsIncludingSubframes):
     36        (WebCore::FrameView::updateThrottledDOMTimersState):
     37        (WebCore::FrameView::scrollPositionChanged): Deleted.
     38        (WebCore::FrameView::sendResizeEventIfNeeded): Deleted.
     39        * page/FrameView.h:
     40        * testing/Internals.cpp:
     41        (WebCore::Internals::isRequestAnimationFrameThrottled):
     42        (WebCore::Internals::isTimerThrottled): Deleted.
     43        * testing/Internals.h:
     44        * testing/Internals.idl:
     45
    1462015-05-08  Daniel Bates  <dabates@apple.com>
    247
  • trunk/Source/WebCore/dom/Document.h

    r183990 r183998  
    949949    virtual void postTask(Task) override final; // Executes the task on context's thread asynchronously.
    950950
     951#if ENABLE(REQUEST_ANIMATION_FRAME)
     952    ScriptedAnimationController* scriptedAnimationController() { return m_scriptedAnimationController.get(); }
     953#endif
    951954    void suspendScriptedAnimationControllerCallbacks();
    952955    void resumeScriptedAnimationControllerCallbacks();
  • trunk/Source/WebCore/dom/ScriptedAnimationController.cpp

    r183990 r183998  
    3535#include "FrameView.h"
    3636#include "InspectorInstrumentation.h"
     37#include "Logging.h"
     38#include "MainFrame.h"
    3739#include "RequestAnimationFrameCallback.h"
    3840#include "Settings.h"
     
    8587        return;
    8688
     89    LOG(Animations, "%p - Setting RequestAnimationFrame throttling state to %d in frame %p (isMainFrame: %d)", this, isThrottled, m_document->frame(), m_document->frame() ? m_document->frame()->isMainFrame() : 0);
     90
    8791    m_isThrottled = isThrottled;
    8892    if (m_animationTimer.isActive()) {
     
    9296#else
    9397    UNUSED_PARAM(isThrottled);
     98#endif
     99}
     100
     101bool ScriptedAnimationController::isThrottled() const
     102{
     103#if USE(REQUEST_ANIMATION_FRAME_TIMER) && USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     104    return m_isThrottled;
     105#else
     106    return false;
    94107#endif
    95108}
  • trunk/Source/WebCore/dom/ScriptedAnimationController.h

    r183990 r183998  
    6969    void resume();
    7070    void setThrottled(bool);
     71    WEBCORE_EXPORT bool isThrottled() const;
    7172
    7273    void windowScreenDidChange(PlatformDisplayID);
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r183781 r183998  
    20692069    view->setWasScrolledByUser(false);
    20702070
    2071     // Use the current ScrollView's frame rect.
    2072     if (m_frame.view())
    2073         view->setFrameRect(m_frame.view()->frameRect());
     2071    Optional<IntRect> previousViewFrameRect = m_frame.view() ?  m_frame.view()->frameRect() : Optional<IntRect>(Nullopt);
    20742072    m_frame.setView(view);
     2073
     2074    // Use the previous ScrollView's frame rect.
     2075    if (previousViewFrameRect)
     2076        view->setFrameRect(previousViewFrameRect.value());
    20752077   
    20762078    m_frame.setDocument(document);
  • trunk/Source/WebCore/page/FrameView.cpp

    r183990 r183998  
    8181#include "SVGDocument.h"
    8282#include "SVGSVGElement.h"
     83#include "ScriptedAnimationController.h"
    8384#include "ScrollAnimator.h"
    8485#include "ScrollingCoordinator.h"
     
    17561757void FrameView::viewportContentsChanged()
    17571758{
     1759    if (!frame().view()) {
     1760        // The frame is being destroyed.
     1761        return;
     1762    }
     1763
    17581764    // When the viewport contents changes (scroll, resize, style recalc, layout, ...),
    17591765    // check if we should resume animated images or unthrottle DOM timers.
    1760     resumeVisibleImageAnimationsIncludingSubframes();
    1761     updateThrottledDOMTimersState();
     1766    applyRecursivelyWithVisibleRect([] (FrameView& frameView, const IntRect& visibleRect) {
     1767        frameView.resumeVisibleImageAnimations(visibleRect);
     1768        frameView.updateThrottledDOMTimersState(visibleRect);
     1769        frameView.updateScriptedAnimationsThrottlingState(visibleRect);
     1770    });
    17621771}
    17631772
     
    20962105}
    20972106
    2098 void FrameView::resumeVisibleImageAnimationsIncludingSubframes()
    2099 {
    2100     auto* renderView = frame().contentRenderer();
    2101     if (!renderView)
    2102         return;
    2103 
     2107void FrameView::applyRecursivelyWithVisibleRect(const std::function<void (FrameView& frameView, const IntRect& visibleRect)>& apply)
     2108{
    21042109    IntRect windowClipRect = this->windowClipRect();
    21052110    auto visibleRect = windowToContents(windowClipRect);
    2106     if (visibleRect.isEmpty())
    2107         return;
    2108 
    2109     // Resume paused image animations in this frame.
    2110     renderView->resumePausedImageAnimationsIfNeeded(visibleRect);
     2111    apply(*this, visibleRect);
    21112112
    21122113    // Recursive call for subframes. We cache the current FrameView's windowClipRect to avoid recomputing it for every subframe.
     
    21142115    for (Frame* childFrame = frame().tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) {
    21152116        if (auto* childView = childFrame->view())
    2116             childView->resumeVisibleImageAnimationsIncludingSubframes();
    2117     }
     2117            childView->applyRecursivelyWithVisibleRect(apply);
     2118    }
     2119}
     2120
     2121void FrameView::resumeVisibleImageAnimations(const IntRect& visibleRect)
     2122{
     2123    if (visibleRect.isEmpty())
     2124        return;
     2125
     2126    if (auto* renderView = frame().contentRenderer())
     2127        renderView->resumePausedImageAnimationsIfNeeded(visibleRect);
     2128}
     2129
     2130void FrameView::updateScriptedAnimationsThrottlingState(const IntRect& visibleRect)
     2131{
     2132#if ENABLE(REQUEST_ANIMATION_FRAME)
     2133    if (frame().isMainFrame())
     2134        return;
     2135
     2136    auto* document = frame().document();
     2137    if (!document)
     2138        return;
     2139
     2140    auto* scriptedAnimationController = document->scriptedAnimationController();
     2141    if (!scriptedAnimationController)
     2142        return;
     2143
     2144    // FIXME: This doesn't work for subframes of a "display: none" frame because
     2145    // they have a non-null ownerRenderer.
     2146    bool shouldThrottle = !frame().ownerRenderer() || visibleRect.isEmpty();
     2147    scriptedAnimationController->setThrottled(shouldThrottle);
     2148#else
     2149    UNUSED_PARAM(visibleRect);
     2150#endif
     2151}
     2152
     2153
     2154void FrameView::resumeVisibleImageAnimationsIncludingSubframes()
     2155{
     2156    applyRecursivelyWithVisibleRect([] (FrameView& frameView, const IntRect& visibleRect) {
     2157        frameView.resumeVisibleImageAnimations(visibleRect);
     2158    });
    21182159}
    21192160
     
    30603101}
    30613102
    3062 void FrameView::updateThrottledDOMTimersState()
     3103void FrameView::updateThrottledDOMTimersState(const IntRect& visibleRect)
    30633104{
    30643105    if (m_throttledTimers.isEmpty())
    30653106        return;
    3066 
    3067     IntRect visibleRect = windowToContents(windowClipRect());
    30683107
    30693108    // Do not iterate over the HashSet because calling DOMTimer::updateThrottlingStateAfterViewportChange()
  • trunk/Source/WebCore/page/FrameView.h

    r183990 r183998  
    597597    void performPostLayoutTasks();
    598598    void autoSizeIfEnabled();
    599     void updateThrottledDOMTimersState();
     599
     600    void applyRecursivelyWithVisibleRect(const std::function<void (FrameView& frameView, const IntRect& visibleRect)>&);
     601    void updateThrottledDOMTimersState(const IntRect& visibleRect);
     602    void resumeVisibleImageAnimations(const IntRect& visibleRect);
     603    void updateScriptedAnimationsThrottlingState(const IntRect& visibleRect);
    600604
    601605    void updateLayerFlushThrottling();
  • trunk/Source/WebCore/testing/Internals.cpp

    r183990 r183998  
    9999#include "RuntimeEnabledFeatures.h"
    100100#include "SchemeRegistry.h"
     101#include "ScriptedAnimationController.h"
    101102#include "ScrollingCoordinator.h"
    102103#include "SerializedScriptValue.h"
     
    765766    }
    766767    return timer->m_throttleState == DOMTimer::ShouldThrottle;
     768}
     769
     770bool Internals::isRequestAnimationFrameThrottled() const
     771{
     772#if ENABLE(REQUEST_ANIMATION_FRAME)
     773    auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
     774    if (!scriptedAnimationController)
     775        return false;
     776    return scriptedAnimationController->isThrottled();
     777#else
     778    return false;
     779#endif
    767780}
    768781
  • trunk/Source/WebCore/testing/Internals.h

    r183990 r183998  
    114114    // DOMTimers throttling testing.
    115115    bool isTimerThrottled(int timeoutId, ExceptionCode&);
     116    bool isRequestAnimationFrameThrottled() const;
    116117
    117118    // Spatial Navigation testing.
  • trunk/Source/WebCore/testing/Internals.idl

    r183990 r183998  
    280280    [RaisesException] boolean isTimerThrottled(long timerHandle);
    281281
     282    boolean isRequestAnimationFrameThrottled();
     283
    282284    [RaisesException] void startTrackingStyleRecalcs();
    283285    [RaisesException] unsigned long styleRecalcCount();
Note: See TracChangeset for help on using the changeset viewer.