Changeset 111480 in webkit


Ignore:
Timestamp:
Mar 20, 2012 6:19:23 PM (12 years ago)
Author:
morrita@google.com
Message:

Infinite repaint loop with SVGImageCache and deferred repaint timers
https://bugs.webkit.org/show_bug.cgi?id=78315
<rdar://problem/10651634>

Patch by Tim Horton <timothy_horton@apple.com> on 2012-03-18
Reviewed by Nikolas Zimmermann.

Only defer image redraw on a timer if we're in layout. This breaks
the repaint loop while still preventing us from drawing inside layout.

Completely disable repaint during relayout inside SVGImage::drawSVGToImageBuffer,
preventing deferred repaint timers from being started during that process.

No new tests, as the problem only occurs in a nonstandard configuration.

  • page/FrameView.cpp:

(WebCore::FrameView::FrameView):
(WebCore::FrameView::reset):
(WebCore::FrameView::repaintContentRectangle):
(WebCore::FrameView::endDeferredRepaints):
(WebCore::FrameView::startDeferredRepaintTimer):
(WebCore):
(WebCore::FrameView::doDeferredRepaints):
(WebCore::FrameView::deferredRepaintTimerFired):
(WebCore::FrameView::beginDisableRepaints):
(WebCore::FrameView::endDisableRepaints):

  • page/FrameView.h:

(FrameView):
(WebCore::FrameView::repaintsDisabled):

  • rendering/RenderView.cpp:

(WebCore::RenderView::shouldRepaint):

  • svg/graphics/SVGImage.cpp:

(WebCore::SVGImage::drawSVGToImageBuffer):
(WebCore::SVGImage::draw):
(WebCore::SVGImage::frameView):
(WebCore):

  • svg/graphics/SVGImage.h:

(WebCore):

  • svg/graphics/SVGImageCache.cpp:

(WebCore::SVGImageCache::imageContentChanged):
(WebCore::SVGImageCache::redraw):
(WebCore::SVGImageCache::redrawTimerFired):
(WebCore):

  • svg/graphics/SVGImageCache.h:

(SVGImageCache):

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r111478 r111480  
     12012-03-18  Tim Horton  <timothy_horton@apple.com>
     2
     3        Infinite repaint loop with SVGImageCache and deferred repaint timers
     4        https://bugs.webkit.org/show_bug.cgi?id=78315
     5        <rdar://problem/10651634>
     6
     7        Reviewed by Nikolas Zimmermann.
     8
     9        Only defer image redraw on a timer if we're in layout. This breaks
     10        the repaint loop while still preventing us from drawing inside layout.
     11
     12        Completely disable repaint during relayout inside SVGImage::drawSVGToImageBuffer,
     13        preventing deferred repaint timers from being started during that process.
     14
     15        No new tests, as the problem only occurs in a nonstandard configuration.
     16
     17        * page/FrameView.cpp:
     18        (WebCore::FrameView::FrameView):
     19        (WebCore::FrameView::reset):
     20        (WebCore::FrameView::repaintContentRectangle):
     21        (WebCore::FrameView::endDeferredRepaints):
     22        (WebCore::FrameView::startDeferredRepaintTimer):
     23        (WebCore):
     24        (WebCore::FrameView::doDeferredRepaints):
     25        (WebCore::FrameView::deferredRepaintTimerFired):
     26        (WebCore::FrameView::beginDisableRepaints):
     27        (WebCore::FrameView::endDisableRepaints):
     28        * page/FrameView.h:
     29        (FrameView):
     30        (WebCore::FrameView::repaintsDisabled):
     31        * rendering/RenderView.cpp:
     32        (WebCore::RenderView::shouldRepaint):
     33        * svg/graphics/SVGImage.cpp:
     34        (WebCore::SVGImage::drawSVGToImageBuffer):
     35        (WebCore::SVGImage::draw):
     36        (WebCore::SVGImage::frameView):
     37        (WebCore):
     38        * svg/graphics/SVGImage.h:
     39        (WebCore):
     40        * svg/graphics/SVGImageCache.cpp:
     41        (WebCore::SVGImageCache::imageContentChanged):
     42        (WebCore::SVGImageCache::redraw):
     43        (WebCore::SVGImageCache::redrawTimerFired):
     44        (WebCore):
     45        * svg/graphics/SVGImageCache.h:
     46        (SVGImageCache):
     47
    1482012-03-20  Adam Klein  <adamk@chromium.org>
    249
  • trunk/Source/WebCore/page/FrameView.cpp

    r111471 r111480  
    140140    , m_inProgrammaticScroll(false)
    141141    , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
     142    , m_disableRepaints(0)
    142143    , m_isTrackingRepaints(false)
    143144    , m_shouldUpdateWhileOffscreen(true)
     
    246247    m_firstVisuallyNonEmptyLayoutCallbackPending = true;
    247248    m_maintainScrollPositionAnchor = 0;
     249    m_disableRepaints = 0;
    248250}
    249251
     
    17821784{
    17831785    ASSERT(!m_frame->ownerElement());
    1784    
     1786
    17851787    if (m_isTrackingRepaints) {
    17861788        IntRect repaintRect = r;
     
    18081810            m_repaintRects[0].unite(paintRect);
    18091811        m_repaintCount++;
    1810    
    1811         if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
    1812              m_deferredRepaintTimer.startOneShot(delay);
     1812
     1813        if (!m_deferringRepaints)
     1814            startDeferredRepaintTimer(delay);
     1815
    18131816        return;
    18141817    }
     
    18631866}
    18641867
    1865 
    18661868void FrameView::endDeferredRepaints()
    18671869{
     
    18761878    if (--m_deferringRepaints)
    18771879        return;
    1878    
     1880
    18791881    if (m_deferredRepaintTimer.isActive())
    18801882        return;
    18811883
    18821884    if (double delay = adjustedDeferredRepaintDelay()) {
    1883         m_deferredRepaintTimer.startOneShot(delay);
     1885        startDeferredRepaintTimer(delay);
    18841886        return;
    18851887    }
    18861888   
    18871889    doDeferredRepaints();
     1890}
     1891
     1892void FrameView::startDeferredRepaintTimer(double delay)
     1893{
     1894    if (m_deferredRepaintTimer.isActive())
     1895        return;
     1896
     1897    if (m_disableRepaints)
     1898        return;
     1899
     1900    m_deferredRepaintTimer.startOneShot(delay);
    18881901}
    18891902
     
    19041917void FrameView::doDeferredRepaints()
    19051918{
     1919    if (m_disableRepaints)
     1920        return;
     1921
    19061922    ASSERT(!m_deferringRepaints);
    19071923    if (!shouldUpdate()) {
     
    19621978{
    19631979    doDeferredRepaints();
    1964 }   
     1980}
     1981
     1982void FrameView::beginDisableRepaints()
     1983{
     1984    m_disableRepaints++;
     1985}
     1986
     1987void FrameView::endDisableRepaints()
     1988{
     1989    ASSERT(m_disableRepaints > 0);
     1990    m_disableRepaints--;
     1991}
    19651992
    19661993void FrameView::layoutTimerFired(Timer<FrameView>*)
  • trunk/Source/WebCore/page/FrameView.h

    r111471 r111480  
    209209    void endDeferredRepaints();
    210210    void checkStopDelayingDeferredRepaints();
     211    void startDeferredRepaintTimer(double delay);
    211212    void resetDeferredRepaintDelay();
     213
     214    void beginDisableRepaints();
     215    void endDisableRepaints();
     216    bool repaintsDisabled() { return m_disableRepaints > 0; }
    212217
    213218#if ENABLE(DASHBOARD_SUPPORT)
     
    476481    double m_deferredRepaintDelay;
    477482    double m_lastPaintTime;
    478    
     483
     484    unsigned m_disableRepaints;
     485
    479486    bool m_isTrackingRepaints; // Used for testing.
    480487    Vector<IntRect> m_trackedRepaintRects;
  • trunk/Source/WebCore/rendering/RenderView.cpp

    r111279 r111480  
    302302    if (!m_frameView)
    303303        return false;
    304    
     304
     305    if (m_frameView->repaintsDisabled())
     306        return false;
     307
    305308    return true;
    306309}
  • trunk/Source/WebCore/svg/graphics/SVGImage.cpp

    r111126 r111480  
    178178    ASSERT(observer);
    179179
    180     // Temporarily reset image observer, we don't want to receive any changeInRect() calls due this relayout.
     180    // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout.
    181181    setImageObserver(0);
     182
     183    // Disable repainting; we don't want deferred repaints to schedule any timers due to this relayout.
     184    frame->view()->beginDisableRepaints();
     185
    182186    renderer->setContainerSize(size);
    183187    frame->view()->resize(this->size());
     188
    184189    if (zoom != 1)
    185190        frame->setPageZoomFactor(zoom);
     
    203208        frame->view()->layout();
    204209
    205     setImageObserver(observer);
     210    setImageObserver(observer);
     211
     212    frame->view()->endDisableRepaints();
    206213}
    207214
     
    211218        return;
    212219
    213     FrameView* view = m_page->mainFrame()->view();
     220    FrameView* view = frameView();
    214221
    215222    GraphicsContextStateSaver stateSaver(*context);
     
    254261        return 0;
    255262    return toRenderBox(rootElement->renderer());
     263}
     264
     265FrameView* SVGImage::frameView() const
     266{
     267    if (!m_page)
     268        return 0;
     269
     270    return m_page->mainFrame()->view();
    256271}
    257272
  • trunk/Source/WebCore/svg/graphics/SVGImage.h

    r110581 r111480  
    3535namespace WebCore {
    3636
     37class FrameView;
    3738class ImageBuffer;
    3839class Page;
     
    5455    void drawSVGToImageBuffer(ImageBuffer*, const IntSize&, float zoom, ShouldClearBuffer);
    5556    RenderBox* embeddedContentBox() const;
     57    FrameView* frameView() const;
    5658
    5759    virtual bool isSVGImage() const { return true; }
  • trunk/Source/WebCore/svg/graphics/SVGImageCache.cpp

    r110581 r111480  
    2222
    2323#if ENABLE(SVG)
     24#include "FrameView.h"
    2425#include "GraphicsContext.h"
    2526#include "ImageBuffer.h"
     
    8283        it->second.imageNeedsUpdate = true;
    8384
    84     // Start redrawing dirty images with a timer, as imageContentChanged() may be called
    85     // by the FrameView of the SVGImage which is currently in FrameView::layout().
    86     if (!m_redrawTimer.isActive())
    87         m_redrawTimer.startOneShot(0);
     85    // If we're in the middle of layout, start redrawing dirty
     86    // images on a timer; otherwise it's safe to draw immediately.
     87
     88    FrameView* frameView = m_svgImage->frameView();
     89    if (frameView && frameView->needsLayout()) {
     90        if (!m_redrawTimer.isActive())
     91            m_redrawTimer.startOneShot(0);
     92    } else
     93       redraw();
    8894}
    8995
    90 void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
     96void SVGImageCache::redraw()
    9197{
    9298    ImageDataMap::iterator end = m_imageDataMap.end();
     
    104110    ASSERT(m_svgImage->imageObserver());
    105111    m_svgImage->imageObserver()->animationAdvanced(m_svgImage);
     112}
     113
     114void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
     115{
     116    redraw();
    106117}
    107118
  • trunk/Source/WebCore/svg/graphics/SVGImageCache.h

    r110581 r111480  
    7171private:
    7272    SVGImageCache(SVGImage*);
     73    void redraw();
    7374    void redrawTimerFired(Timer<SVGImageCache>*);
    7475
Note: See TracChangeset for help on using the changeset viewer.