Title: [163928] trunk
Revision
163928
Author
[email protected]
Date
2014-02-11 18:55:22 -0800 (Tue, 11 Feb 2014)

Log Message

GIF animations should be suspended when outside of viewport
https://bugs.webkit.org/show_bug.cgi?id=128632

Source/WebCore: 

Reviewed by Andreas Kling.
        
Animations are driven by the paint cycle. Speculative tiles keep animations outside the actual viewport going.
        
Pause animations when they are outside the viewport by not painting them.

Test: fast/repaint/no-animation-outside-viewport.html

* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::animationAdvanced):
        
    Call animation specific newImageAnimationFrameAvailable instead of the generic notifyObservers.

* loader/cache/CachedImage.h:
        
    Removed now unnecessary resumeAnimatingImagesForLoader mechanism.
    Remove unnecessary shouldPauseAnimation. Pausing is now always done when by avoiding repaint.

* loader/cache/CachedImageClient.h:
(WebCore::CachedImageClient::newImageAnimationFrameAvailable):
* page/FrameView.cpp:
(WebCore::FrameView::scrollPositionChanged):
        
    Check if we have image animations to resume when scroll position changes.

* page/Page.cpp:
(WebCore::Page::resumeAnimatingImages):
        
    Use the same mechanism when resuming background tabs etc.

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::internalAdvanceAnimation):
        
    Remove the shouldPauseAnimation test, always rely on pausing on invalidation.

* platform/graphics/ImageObserver.h:
* rendering/RenderBoxModelObject.cpp:
* rendering/RenderElement.cpp:
(WebCore::RenderElement::RenderElement):
(WebCore::RenderElement::~RenderElement):
(WebCore::shouldRepaintForImageAnimation):
        
    Factor the pausing conditions to a function. Test that the animation is withing the
    visible rect.

(WebCore::RenderElement::newImageAnimationFrameAvailable):
        
    Add renderer to the paused animation set if we don't continue the animation.

(WebCore::RenderElement::repaintForPausedImageAnimationsIfNeeded):
        
    Resume the paused animations by triggering repaint.

* rendering/RenderElement.h:
(WebCore::RenderElement::setHasPausedImageAnimations):
(WebCore::RenderElement::hasPausedImageAnimations):
* rendering/RenderObject.cpp:
* rendering/RenderObject.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::addRendererWithPausedImageAnimations):
(WebCore::RenderView::removeRendererWithPausedImageAnimations):
(WebCore::RenderView::resumePausedImageAnimationsIfNeeded):
* rendering/RenderView.h:

LayoutTests: 

Reviewed by Andreas Kling.

* fast/repaint/no-animation-outside-viewport-expected.txt: Added.
* fast/repaint/no-animation-outside-viewport.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (163927 => 163928)


--- trunk/LayoutTests/ChangeLog	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/LayoutTests/ChangeLog	2014-02-12 02:55:22 UTC (rev 163928)
@@ -1,3 +1,13 @@
+2014-02-11  Antti Koivisto  <[email protected]>
+
+        GIF animations should be suspended when outside of viewport
+        https://bugs.webkit.org/show_bug.cgi?id=128632
+
+        Reviewed by Andreas Kling.
+
+        * fast/repaint/no-animation-outside-viewport-expected.txt: Added.
+        * fast/repaint/no-animation-outside-viewport.html: Added.
+
 2014-02-11  Ryosuke Niwa  <[email protected]>
 
         Add failing test expectations to asynchronous spellchecking tests.

Added: trunk/LayoutTests/fast/repaint/no-animation-outside-viewport-expected.txt (0 => 163928)


--- trunk/LayoutTests/fast/repaint/no-animation-outside-viewport-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/repaint/no-animation-outside-viewport-expected.txt	2014-02-12 02:55:22 UTC (rev 163928)
@@ -0,0 +1,10 @@
+Test that animated gif outside viewport does not trigger repaint.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS repaintRects is ""
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/repaint/no-animation-outside-viewport.html (0 => 163928)


--- trunk/LayoutTests/fast/repaint/no-animation-outside-viewport.html	                        (rev 0)
+++ trunk/LayoutTests/fast/repaint/no-animation-outside-viewport.html	2014-02-12 02:55:22 UTC (rev 163928)
@@ -0,0 +1,39 @@
+<html>
+<head>
+<script>jsTestIsAsync = true;</script>
+<script src=""
+<script>
+    description("Test that animated gif outside viewport does not trigger repaint.");
+    function startTrackingRepaints()
+    {
+        document.body.offsetTop;
+        window.internals.startTrackingRepaints();
+        testRunner.display();
+        setTimeout(logRepaints, 200);
+    }
+
+    function logRepaints()
+    {
+        repaintRects = window.internals.repaintRectsAsText();
+        window.internals.stopTrackingRepaints();
+
+        shouldBeEqualToString("repaintRects", "");
+
+        finishJSTest();
+    }
+
+    function start() {
+        if (!window.testRunner || !window.internals)
+            return;
+
+        var img = new Image();
+        img._onload_ = startTrackingRepaints;
+        img.src = ""
+    }
+</script>
+</head>
+<body _onload_="start()">
+<div style="height:600px"></div>
+<img src=""
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (163927 => 163928)


--- trunk/Source/WebCore/ChangeLog	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/ChangeLog	2014-02-12 02:55:22 UTC (rev 163928)
@@ -1,3 +1,72 @@
+2014-02-11  Antti Koivisto  <[email protected]>
+
+        GIF animations should be suspended when outside of viewport
+        https://bugs.webkit.org/show_bug.cgi?id=128632
+
+        Reviewed by Andreas Kling.
+        
+        Animations are driven by the paint cycle. Speculative tiles keep animations outside the actual viewport going.
+        
+        Pause animations when they are outside the viewport by not painting them.
+
+        Test: fast/repaint/no-animation-outside-viewport.html
+
+        * loader/cache/CachedImage.cpp:
+        (WebCore::CachedImage::animationAdvanced):
+        
+            Call animation specific newImageAnimationFrameAvailable instead of the generic notifyObservers.
+
+        * loader/cache/CachedImage.h:
+        
+            Removed now unnecessary resumeAnimatingImagesForLoader mechanism.
+            Remove unnecessary shouldPauseAnimation. Pausing is now always done when by avoiding repaint.
+
+        * loader/cache/CachedImageClient.h:
+        (WebCore::CachedImageClient::newImageAnimationFrameAvailable):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::scrollPositionChanged):
+        
+            Check if we have image animations to resume when scroll position changes.
+
+        * page/Page.cpp:
+        (WebCore::Page::resumeAnimatingImages):
+        
+            Use the same mechanism when resuming background tabs etc.
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::internalAdvanceAnimation):
+        
+            Remove the shouldPauseAnimation test, always rely on pausing on invalidation.
+
+        * platform/graphics/ImageObserver.h:
+        * rendering/RenderBoxModelObject.cpp:
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::RenderElement):
+        (WebCore::RenderElement::~RenderElement):
+        (WebCore::shouldRepaintForImageAnimation):
+        
+            Factor the pausing conditions to a function. Test that the animation is withing the
+            visible rect.
+
+        (WebCore::RenderElement::newImageAnimationFrameAvailable):
+        
+            Add renderer to the paused animation set if we don't continue the animation.
+
+        (WebCore::RenderElement::repaintForPausedImageAnimationsIfNeeded):
+        
+            Resume the paused animations by triggering repaint.
+
+        * rendering/RenderElement.h:
+        (WebCore::RenderElement::setHasPausedImageAnimations):
+        (WebCore::RenderElement::hasPausedImageAnimations):
+        * rendering/RenderObject.cpp:
+        * rendering/RenderObject.h:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::addRendererWithPausedImageAnimations):
+        (WebCore::RenderView::removeRendererWithPausedImageAnimations):
+        (WebCore::RenderView::resumePausedImageAnimationsIfNeeded):
+        * rendering/RenderView.h:
+
 2014-02-11  Andreas Kling  <[email protected]>
 
         Remove unused RenderNamedFlowThread::previousRendererForNode().

Modified: trunk/Source/WebCore/loader/cache/CachedImage.cpp (163927 => 163928)


--- trunk/Source/WebCore/loader/cache/CachedImage.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/loader/cache/CachedImage.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -499,25 +499,13 @@
     CachedResource::didAccessDecodedData(timeStamp);
 }
 
-bool CachedImage::shouldPauseAnimation(const Image* image)
-{
-    if (!image || image != m_image)
-        return false;
-    
-    CachedResourceClientWalker<CachedImageClient> w(m_clients);
-    while (CachedImageClient* c = w.next()) {
-        if (c->willRenderImage(this))
-            return false;
-    }
-
-    return true;
-}
-
 void CachedImage::animationAdvanced(const Image* image)
 {
     if (!image || image != m_image)
         return;
-    notifyObservers();
+    CachedResourceClientWalker<CachedImageClient> clientWalker(m_clients);
+    while (CachedImageClient* client = clientWalker.next())
+        client->newImageAnimationFrameAvailable(*this);
 }
 
 void CachedImage::changedInRect(const Image* image, const IntRect& rect)
@@ -527,27 +515,6 @@
     notifyObservers(&rect);
 }
 
-void CachedImage::resumeAnimatingImagesForLoader(CachedResourceLoader* loader)
-{
-    const CachedResourceLoader::DocumentResourceMap& resources = loader->allCachedResources();
-
-    for (CachedResourceLoader::DocumentResourceMap::const_iterator it = resources.begin(), end = resources.end(); it != end; ++it) {
-        const CachedResourceHandle<CachedResource>& resource = it->value;
-        if (!resource || !resource->isImage())
-            continue;
-        CachedImage* cachedImage = toCachedImage(resource.get());
-        if (!cachedImage->hasImage())
-            continue;
-        Image* image = cachedImage->image();
-        if (!image->isBitmapImage())
-            continue;
-        BitmapImage* bitmapImage = toBitmapImage(image);
-        if (!bitmapImage->canAnimate())
-            continue;
-        cachedImage->animationAdvanced(bitmapImage);
-    }
-}
-
 bool CachedImage::currentFrameKnownToBeOpaque(const RenderElement* renderer)
 {
     Image* image = imageForRenderer(renderer);

Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (163927 => 163928)


--- trunk/Source/WebCore/loader/cache/CachedImage.h	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/loader/cache/CachedImage.h	2014-02-12 02:55:22 UTC (rev 163928)
@@ -84,8 +84,6 @@
     bool isManuallyCached() const { return m_isManuallyCached; }
     virtual bool mustRevalidateDueToCacheHeaders(CachePolicy) const;
 
-    static void resumeAnimatingImagesForLoader(CachedResourceLoader*);
-
 #if ENABLE(DISK_IMAGE_CACHE)
     virtual bool canUseDiskImageCache() const override;
     virtual void useDiskImageCache() override;
@@ -128,7 +126,6 @@
     virtual void decodedSizeChanged(const Image*, int delta) override;
     virtual void didDraw(const Image*) override;
 
-    virtual bool shouldPauseAnimation(const Image*) override;
     virtual void animationAdvanced(const Image*) override;
     virtual void changedInRect(const Image*, const IntRect&) override;
 

Modified: trunk/Source/WebCore/loader/cache/CachedImageClient.h (163927 => 163928)


--- trunk/Source/WebCore/loader/cache/CachedImageClient.h	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/loader/cache/CachedImageClient.h	2014-02-12 02:55:22 UTC (rev 163928)
@@ -36,15 +36,12 @@
     static CachedResourceClientType expectedType() { return ImageType; }
     virtual CachedResourceClientType resourceClientType() const override { return expectedType(); }
 
-    // Called whenever a frame of an image changes, either because we got more data from the network or
-    // because we are animating. If not null, the IntRect is the changed rect of the image.
+    // Called whenever a frame of an image changes because we got more data from the network.
+    // If not null, the IntRect is the changed rect of the image.
     virtual void imageChanged(CachedImage*, const IntRect* = 0) { }
 
-    // Called to find out if this client wants to actually display the image. Used to tell when we
-    // can halt animation. Content nodes that hold image refs for example would not render the image,
-    // but RenderImages would (assuming they have visibility: visible and their render tree isn't hidden
-    // e.g., in the b/f cache or in a background tab).
-    virtual bool willRenderImage(CachedImage*) { return false; }
+    // Called when GIF animation progresses.
+    virtual void newImageAnimationFrameAvailable(CachedImage& image) { imageChanged(&image); }
 };
 
 }

Modified: trunk/Source/WebCore/page/FrameView.cpp (163927 => 163928)


--- trunk/Source/WebCore/page/FrameView.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/page/FrameView.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -1947,6 +1947,7 @@
     sendWillRevealEdgeEventsIfNeeded(oldPosition, newPosition);
 
     if (RenderView* renderView = this->renderView()) {
+        renderView->resumePausedImageAnimationsIfNeeded();
         if (renderView->usesCompositing())
             renderView->compositor().frameViewDidScroll();
     }

Modified: trunk/Source/WebCore/page/Page.cpp (163927 => 163928)


--- trunk/Source/WebCore/page/Page.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/page/Page.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -1144,8 +1144,10 @@
     // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
     // require that we repaint animated images to kickstart the animation loop.
 
-    for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
-        CachedImage::resumeAnimatingImagesForLoader(frame->document()->cachedResourceLoader());
+    for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
+        if (auto* renderView = frame->contentRenderer())
+            renderView->resumePausedImageAnimationsIfNeeded();
+    }
 }
 
 void Page::setViewState(ViewState::Flags viewState)

Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (163927 => 163928)


--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -709,13 +709,6 @@
     // Stop the animation.
     stopAnimation();
     
-#if !PLATFORM(IOS)
-    // See if anyone is still paying attention to this animation.  If not, we don't
-    // advance and will remain suspended at the current frame until the animation is resumed.
-    if (!skippingFrames && imageObserver()->shouldPauseAnimation(this))
-        return false;
-#endif
-
     ++m_currentFrame;
     bool advancedAnimation = true;
     bool destroyAll = false;

Modified: trunk/Source/WebCore/platform/graphics/ImageObserver.h (163927 => 163928)


--- trunk/Source/WebCore/platform/graphics/ImageObserver.h	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/platform/graphics/ImageObserver.h	2014-02-12 02:55:22 UTC (rev 163928)
@@ -40,7 +40,6 @@
     virtual void decodedSizeChanged(const Image*, int delta) = 0;
     virtual void didDraw(const Image*) = 0;
 
-    virtual bool shouldPauseAnimation(const Image*) = 0;
     virtual void animationAdvanced(const Image*) = 0;
 
     virtual void changedInRect(const Image*, const IntRect&) = 0;

Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -27,6 +27,7 @@
 #include "RenderBoxModelObject.h"
 
 #include "Frame.h"
+#include "FrameView.h"
 #include "GraphicsContext.h"
 #include "HTMLFrameOwnerElement.h"
 #include "HTMLNames.h"

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -69,6 +69,7 @@
     , m_ancestorLineBoxDirty(false)
     , m_hasInitializedStyle(false)
     , m_renderInlineAlwaysCreatesLineBoxes(false)
+    , m_hasPausedImageAnimations(false)
     , m_firstChild(nullptr)
     , m_lastChild(nullptr)
     , m_style(std::move(style))
@@ -81,6 +82,7 @@
     , m_ancestorLineBoxDirty(false)
     , m_hasInitializedStyle(false)
     , m_renderInlineAlwaysCreatesLineBoxes(false)
+    , m_hasPausedImageAnimations(false)
     , m_firstChild(nullptr)
     , m_lastChild(nullptr)
     , m_style(std::move(style))
@@ -119,6 +121,8 @@
         }
 #endif
     }
+    if (m_hasPausedImageAnimations)
+        view().removeRendererWithPausedImageAnimations(*this);
 }
 
 RenderPtr<RenderElement> RenderElement::createFor(Element& element, PassRef<RenderStyle> style)
@@ -1275,6 +1279,47 @@
     return borderImage && borderImage->canRender(this, style().effectiveZoom()) && borderImage->isLoaded();
 }
 
+static bool shouldRepaintForImageAnimation(const RenderElement& renderer, const IntRect& visibleRect)
+{
+    const Document& document = renderer.document();
+    if (document.inPageCache())
+        return false;
+    auto& frameView = renderer.view().frameView();
+    if (frameView.isOffscreen())
+        return false;
+#if PLATFORM(IOS)
+    if (frameView.timersPaused())
+        return false;
+#endif
+    if (document.activeDOMObjectsAreSuspended())
+        return false;
+    if (renderer.style().visibility() != VISIBLE)
+        return false;
+    if (!visibleRect.intersects(renderer.absoluteBoundingBoxRect()))
+        return false;
+
+    return true;
+}
+
+void RenderElement::newImageAnimationFrameAvailable(CachedImage& image)
+{
+    auto visibleRect = view().frameView().visibleContentRect();
+    if (!shouldRepaintForImageAnimation(*this, visibleRect)) {
+        view().addRendererWithPausedImageAnimations(*this);
+        return;
+    }
+    imageChanged(&image);
+}
+
+bool RenderElement::repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect)
+{
+    ASSERT(m_hasPausedImageAnimations);
+    if (!shouldRepaintForImageAnimation(*this, visibleRect))
+        return false;
+    repaint();
+    return true;
+}
+
 RenderNamedFlowThread* RenderElement::renderNamedFlowThreadWrapper()
 {
     auto renderer = this;

Modified: trunk/Source/WebCore/rendering/RenderElement.h (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderElement.h	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderElement.h	2014-02-12 02:55:22 UTC (rev 163928)
@@ -141,6 +141,10 @@
     bool hasBlendMode() const { return false; }
 #endif
 
+    bool repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect);
+    bool hasPausedImageAnimations() const { return m_hasPausedImageAnimations; }
+    void setHasPausedImageAnimations(bool b) { m_hasPausedImageAnimations = b; }
+
     RenderNamedFlowThread* renderNamedFlowThreadWrapper();
 
 protected:
@@ -200,12 +204,14 @@
     StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
     RenderStyle* cachedFirstLineStyle() const;
 
+    virtual void newImageAnimationFrameAvailable(CachedImage&) final override;
+
     unsigned m_baseTypeFlags : 6;
     bool m_ancestorLineBoxDirty : 1;
     bool m_hasInitializedStyle : 1;
 
-    // Specific to RenderInline.
     bool m_renderInlineAlwaysCreatesLineBoxes : 1;
+    bool m_hasPausedImageAnimations : 1;
 
     RenderObject* m_firstChild;
     RenderObject* m_lastChild;

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -2203,26 +2203,6 @@
 }
 #endif
 
-bool RenderObject::willRenderImage(CachedImage*)
-{
-    // Without visibility we won't render (and therefore don't care about animation).
-    if (style().visibility() != VISIBLE)
-        return false;
-
-#if PLATFORM(IOS)
-    if (document().frame()->timersPaused())
-        return false;
-#else
-    // We will not render a new image when Active DOM is suspended
-    if (document().activeDOMObjectsAreSuspended())
-        return false;
-#endif
-
-    // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
-    // then we don't want to render either.
-    return !document().inPageCache() && !document().view()->isOffscreen();
-}
-
 int RenderObject::maximalOutlineSize(PaintPhase p) const
 {
     if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)

Modified: trunk/Source/WebCore/rendering/RenderObject.h (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderObject.h	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderObject.h	2014-02-12 02:55:22 UTC (rev 163928)
@@ -847,7 +847,6 @@
 
     virtual void imageChanged(CachedImage*, const IntRect* = 0) override;
     virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) { }
-    virtual bool willRenderImage(CachedImage*) override;
 
     void selectionStartEnd(int& spos, int& epos) const;
     

Modified: trunk/Source/WebCore/rendering/RenderView.cpp (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderView.cpp	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderView.cpp	2014-02-12 02:55:22 UTC (rev 163928)
@@ -1178,6 +1178,37 @@
     return *m_imageQualityController;
 }
 
+void RenderView::addRendererWithPausedImageAnimations(RenderElement& renderer)
+{
+    if (renderer.hasPausedImageAnimations()) {
+        ASSERT(m_renderersWithPausedImageAnimation.contains(&renderer));
+        return;
+    }
+    renderer.setHasPausedImageAnimations(true);
+    m_renderersWithPausedImageAnimation.add(&renderer);
+}
+
+void RenderView::removeRendererWithPausedImageAnimations(RenderElement& renderer)
+{
+    ASSERT(renderer.hasPausedImageAnimations());
+    ASSERT(m_renderersWithPausedImageAnimation.contains(&renderer));
+
+    renderer.setHasPausedImageAnimations(false);
+    m_renderersWithPausedImageAnimation.remove(&renderer);
+}
+
+void RenderView::resumePausedImageAnimationsIfNeeded()
+{
+    auto visibleRect = frameView().visibleContentRect();
+    Vector<RenderElement*, 10> toRemove;
+    for (auto* renderer : m_renderersWithPausedImageAnimation) {
+        if (renderer->repaintForPausedImageAnimationsIfNeeded(visibleRect))
+            toRemove.append(renderer);
+    }
+    for (auto& renderer : toRemove)
+        removeRendererWithPausedImageAnimations(*renderer);
+}
+
 RenderView::RepaintRegionAccumulator::RepaintRegionAccumulator(RenderView* view)
     : m_rootView(view ? view->document().topDocument().renderView() : nullptr)
 {

Modified: trunk/Source/WebCore/rendering/RenderView.h (163927 => 163928)


--- trunk/Source/WebCore/rendering/RenderView.h	2014-02-12 02:52:19 UTC (rev 163927)
+++ trunk/Source/WebCore/rendering/RenderView.h	2014-02-12 02:55:22 UTC (rev 163928)
@@ -27,6 +27,7 @@
 #include "PODFreeListArena.h"
 #include "Region.h"
 #include "RenderBlockFlow.h"
+#include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 
 namespace WebCore {
@@ -219,6 +220,10 @@
     void didCreateRenderer() { ++m_rendererCount; }
     void didDestroyRenderer() { --m_rendererCount; }
 
+    void resumePausedImageAnimationsIfNeeded();
+    void addRendererWithPausedImageAnimations(RenderElement&);
+    void removeRendererWithPausedImageAnimations(RenderElement&);
+
     class RepaintRegionAccumulator {
         WTF_MAKE_NONCOPYABLE(RepaintRegionAccumulator);
     public:
@@ -340,6 +345,8 @@
 #if ENABLE(CSS_FILTERS)
     bool m_hasSoftwareFilters;
 #endif
+
+    HashSet<RenderElement*> m_renderersWithPausedImageAnimation;
 };
 
 RENDER_OBJECT_TYPE_CASTS(RenderView, isRenderView())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to