Title: [156291] trunk/Source/WebCore
Revision
156291
Author
[email protected]
Date
2013-09-23 13:43:17 -0700 (Mon, 23 Sep 2013)

Log Message

Rapidly loading pages can result in !needsLayout() assertions in FrameView::paintContents() and RenderView::paint()
https://bugs.webkit.org/show_bug.cgi?id=121725
<rdar://problem/13982161> ASSERT(!needsLayout()) in WebCore::RenderView::paint (121196)

Reviewed by Dean Jackson.

Layout has to be up-to-date before we paint, and when composited we rely on a
CFRunLoopObserver owned by LayerFlushScheduler to enforce this. The contract is
that changes to GraphicsLayers accumulate in those layers, and are all pushed to
CALayers only inside of flushCompositingState(). CALayers must not be touched
directly outside of flushCompositingState(), since this may trigger a CA commit
and resultant painting without us having updated layout.

In addition, we rely on the CA commits only happening after our runloop observer
has fired in order for LayerFlushScheduler's suspend/resume to work (these are used
for freezing the layer tree during page transitions).

However, TileController was violating this contract. It called revalidateTiles()
at random times, and on a timer. This would result in CA commits happening when
layer flushing was suspended at the LayerFlushScheduler level, and thus before
we'd had a chance to do layout.

Fix by only ever revalidatingTiles inside of flushCompositingState(). Calls
that used to result in revalidateTiles() at other times now just set a bit
on GraphicsLayerCA to indicate that revalidation is required, and this triggers
a later flush like any other GraphicsLayerCA change.

There is one exception to the revalidate-inside-flush rule: when purging
files for background tabs on a timer, we are only dealing with an unparented
layer tree, so CALayer manipulation is safe at any time.

Very timing dependent, so hard to test.

* platform/graphics/TiledBacking.h: Expose revalidateTiles()
* platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp: Remove
platformCALayerDidCreateTiles() override.
* platform/graphics/ca/GraphicsLayerCA.h: Keep track of m_isCommittingChanges
so we can assert. Add TilingAreaChanged flag.
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::GraphicsLayerCA):
(WebCore::GraphicsLayerCA::recursiveCommitChanges): noteSublayersChanged() is
used inside of a commit in some cases to trigger a parent layer to update
children after the children have been processed. To avoid trying to pointlessly
schedule the flusher inside a flush, and for strong assertions, use a new flag
that indicates that flushing is not required in this situation.
Set the m_isCommittingChanges flag around committing state.
(WebCore::GraphicsLayerCA::platformCALayerSetNeedsToRevalidateTiles): We used
to use platformCALayerDidCreateTiles() to ensure that we would flush after adding
new tiles to avoid garbage flashes. Now that we only ever create tiles inside
a flush, this is no longer necessary.
The new platformCALayerSetNeedsToRevalidateTiles() function just sets the
TilingAreaChanged flag and triggers a flush.
(WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers): After updating
visible rect, we look for the TilingAreaChanged flag to tell us whether to
revalidate TiledBacking tiles.
(WebCore::GraphicsLayerCA::ensureStructuralLayer): Use DontScheduleFlush when
telling a parent layer that it needs to reconsider sublayers.
(WebCore::GraphicsLayerCA::updateTiles): The caller of revalidateTiles().
(WebCore::GraphicsLayerCA::updateContentsRects): DontScheduleFlush again.
(WebCore::GraphicsLayerCA::noteSublayersChanged): Pass scheduleFlush along.
(WebCore::GraphicsLayerCA::noteLayerPropertyChanged): Handle scheduleFlush.
* platform/graphics/ca/PlatformCALayerClient.h:
(WebCore::PlatformCALayerClient::platformCALayerSetNeedsToRevalidateTiles): Added
so that TileController can call back out to GraphicsLayerCA.
(WebCore::PlatformCALayerClient::isCommittingChanges):
* platform/graphics/ca/mac/TileController.h: Need to keep track of secondary
coverage rects in m_secondaryTileCoverageRects.
* platform/graphics/ca/mac/TileController.mm:
(WebCore::TileController::tileCacheLayerBoundsChanged): Just trigger a tile revalidate,
which will happen later in this same commit.
(WebCore::TileController::setScale): This is called inside the commit. Does an extra
revalidate, which is needed to prune tiles. This could be optimized in future.
(WebCore::TileController::setVisibleRect): Assert that we're inside a commit,
and trigger a revalidate.
(WebCore::TileController::setExposedRect): Trigger a revalidate.
(WebCore::TileController::setClipsToExposedRect): Ditto.
(WebCore::TileController::prepopulateRect): Save the rect and trigger a revalidate.
(WebCore::TileController::setIsInWindow): If we're in the window, trigger a revalidate
otherwise schedule the timer.
(WebCore::TileController::revalidateTiles): Wrapper for the real revalidateTiles().
(WebCore::TileController::tileRevalidationTimerFired): If we're in the window,
schedule a revalidate. Otherwise our layer tree is disconnected, and it's OK to call revalidateTiles().
(WebCore::TileController::setNeedsRevalidateTiles): Call through the client to GraphicsLayerCA
which will schedule a layer tree flush.
(WebCore::TileController::revalidateTiles):
(WebCore::TileController::ensureTilesForRect): Move code from prepopulateRect
into here; ensureTilesForRect() for each secondary rect, then clear the rects.
No need to call platformCALayerDidCreateTiles() at the end.
* platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp: Remove
platformCALayerDidCreateTiles() override.
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::scheduleLayerFlush): This should only be
called when we're not inside a flush, otherwise it will fail to schedule
another one.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (156290 => 156291)


--- trunk/Source/WebCore/ChangeLog	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/ChangeLog	2013-09-23 20:43:17 UTC (rev 156291)
@@ -1,3 +1,100 @@
+2013-09-23  Simon Fraser  <[email protected]>
+
+        Rapidly loading pages can result in !needsLayout() assertions in FrameView::paintContents() and RenderView::paint()
+        https://bugs.webkit.org/show_bug.cgi?id=121725
+        <rdar://problem/13982161> ASSERT(!needsLayout()) in WebCore::RenderView::paint (121196)
+
+        Reviewed by Dean Jackson.
+        
+        Layout has to be up-to-date before we paint, and when composited we rely on a
+        CFRunLoopObserver owned by LayerFlushScheduler to enforce this. The contract is
+        that changes to GraphicsLayers accumulate in those layers, and are all pushed to
+        CALayers only inside of flushCompositingState(). CALayers must not be touched
+        directly outside of flushCompositingState(), since this may trigger a CA commit
+        and resultant painting without us having updated layout.
+        
+        In addition, we rely on the CA commits only happening after our runloop observer
+        has fired in order for LayerFlushScheduler's suspend/resume to work (these are used
+        for freezing the layer tree during page transitions).
+        
+        However, TileController was violating this contract. It called revalidateTiles()
+        at random times, and on a timer. This would result in CA commits happening when
+        layer flushing was suspended at the LayerFlushScheduler level, and thus before
+        we'd had a chance to do layout.
+        
+        Fix by only ever revalidatingTiles inside of flushCompositingState(). Calls
+        that used to result in revalidateTiles() at other times now just set a bit
+        on GraphicsLayerCA to indicate that revalidation is required, and this triggers
+        a later flush like any other GraphicsLayerCA change.
+        
+        There is one exception to the revalidate-inside-flush rule: when purging
+        files for background tabs on a timer, we are only dealing with an unparented
+        layer tree, so CALayer manipulation is safe at any time.
+
+        Very timing dependent, so hard to test.
+
+        * platform/graphics/TiledBacking.h: Expose revalidateTiles()
+        * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp: Remove
+        platformCALayerDidCreateTiles() override.
+        * platform/graphics/ca/GraphicsLayerCA.h: Keep track of m_isCommittingChanges
+        so we can assert. Add TilingAreaChanged flag.
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::GraphicsLayerCA):
+        (WebCore::GraphicsLayerCA::recursiveCommitChanges): noteSublayersChanged() is
+        used inside of a commit in some cases to trigger a parent layer to update
+        children after the children have been processed. To avoid trying to pointlessly
+        schedule the flusher inside a flush, and for strong assertions, use a new flag
+        that indicates that flushing is not required in this situation.
+        Set the m_isCommittingChanges flag around committing state.
+        (WebCore::GraphicsLayerCA::platformCALayerSetNeedsToRevalidateTiles): We used
+        to use platformCALayerDidCreateTiles() to ensure that we would flush after adding
+        new tiles to avoid garbage flashes. Now that we only ever create tiles inside
+        a flush, this is no longer necessary.
+        The new platformCALayerSetNeedsToRevalidateTiles() function just sets the
+        TilingAreaChanged flag and triggers a flush.
+        (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers): After updating
+        visible rect, we look for the TilingAreaChanged flag to tell us whether to
+        revalidate TiledBacking tiles.
+        (WebCore::GraphicsLayerCA::ensureStructuralLayer): Use DontScheduleFlush when 
+        telling a parent layer that it needs to reconsider sublayers.
+        (WebCore::GraphicsLayerCA::updateTiles): The caller of revalidateTiles().
+        (WebCore::GraphicsLayerCA::updateContentsRects): DontScheduleFlush again.
+        (WebCore::GraphicsLayerCA::noteSublayersChanged): Pass scheduleFlush along.
+        (WebCore::GraphicsLayerCA::noteLayerPropertyChanged): Handle scheduleFlush.
+        * platform/graphics/ca/PlatformCALayerClient.h:
+        (WebCore::PlatformCALayerClient::platformCALayerSetNeedsToRevalidateTiles): Added
+        so that TileController can call back out to GraphicsLayerCA.
+        (WebCore::PlatformCALayerClient::isCommittingChanges):
+        * platform/graphics/ca/mac/TileController.h: Need to keep track of secondary
+        coverage rects in m_secondaryTileCoverageRects.
+        * platform/graphics/ca/mac/TileController.mm:
+        (WebCore::TileController::tileCacheLayerBoundsChanged): Just trigger a tile revalidate,
+        which will happen later in this same commit.
+        (WebCore::TileController::setScale): This is called inside the commit. Does an extra
+        revalidate, which is needed to prune tiles. This could be optimized in future.
+        (WebCore::TileController::setVisibleRect): Assert that we're inside a commit,
+        and trigger a revalidate.
+        (WebCore::TileController::setExposedRect): Trigger a revalidate.
+        (WebCore::TileController::setClipsToExposedRect): Ditto.
+        (WebCore::TileController::prepopulateRect): Save the rect and trigger a revalidate.
+        (WebCore::TileController::setIsInWindow): If we're in the window, trigger a revalidate
+        otherwise schedule the timer.
+        (WebCore::TileController::revalidateTiles): Wrapper for the real revalidateTiles().
+        (WebCore::TileController::tileRevalidationTimerFired): If we're in the window,
+        schedule a revalidate. Otherwise our layer tree is disconnected, and it's OK to call revalidateTiles().
+        (WebCore::TileController::setNeedsRevalidateTiles): Call through the client to GraphicsLayerCA
+        which will schedule a layer tree flush.
+        (WebCore::TileController::revalidateTiles):
+        (WebCore::TileController::ensureTilesForRect): Move code from prepopulateRect
+        into here; ensureTilesForRect() for each secondary rect, then clear the rects.
+        No need to call platformCALayerDidCreateTiles() at the end.
+        * platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp: Remove
+        platformCALayerDidCreateTiles() override.
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::scheduleLayerFlush): This should only be
+        called when we're not inside a flush, otherwise it will fail to schedule
+        another one.
+
 2013-09-23  Sam Weinig  <[email protected]>
 
         CTTE: htmlediting.h Element creation function should take a Document&

Modified: trunk/Source/WebCore/platform/graphics/TiledBacking.h (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/TiledBacking.h	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/TiledBacking.h	2013-09-23 20:43:17 UTC (rev 156291)
@@ -70,6 +70,7 @@
 
     virtual IntSize tileSize() const = 0;
 
+    virtual void revalidateTiles() = 0;
     virtual void forceRepaint() = 0;
 
     virtual void setScrollingPerformanceLoggingEnabled(bool) = 0;

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp	2013-09-23 20:43:17 UTC (rev 156291)
@@ -193,7 +193,6 @@
     virtual bool platformCALayerContentsOpaque() const { return false; }
     virtual bool platformCALayerDrawsContent() const { return false; }
     virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
-    virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>&) { }
     virtual float platformCALayerDeviceScaleFactor() { return 1; }
 
     AVFWrapper* m_parent;

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2013-09-23 20:43:17 UTC (rev 156291)
@@ -44,6 +44,7 @@
 #include <QuartzCore/CATransform3D.h>
 #include <limits.h>
 #include <wtf/CurrentTime.h>
+#include <wtf/TemporaryChange.h>
 #include <wtf/text/WTFString.h>
 
 #if PLATFORM(MAC)
@@ -287,6 +288,7 @@
     , m_isPageTiledBackingLayer(false)
     , m_rootRelativeScaleFactor(1)
     , m_uncommittedChanges(0)
+    , m_isCommittingChanges(false)
 {
     PlatformCALayer::LayerType layerType = PlatformCALayer::LayerTypeWebLayer;
     if (client && client->shouldUseTiledBacking(this)) {
@@ -1103,7 +1105,7 @@
         m_visibleTileWashLayer->setBorderColor(washBorderColor);
         m_visibleTileWashLayer->setBorderWidth(8);
         m_visibleTileWashLayer->setBackgroundColor(washFillColor);
-        noteSublayersChanged();
+        noteSublayersChanged(DontScheduleFlush);
     }
 
     if (m_visibleTileWashLayer)
@@ -1123,7 +1125,10 @@
         baseRelativePosition += m_position;
     
     TransformationMatrix transformFromRoot = rootRelativeTransformForScaling;
-    commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect, &transformFromRoot);
+    {
+        TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
+        commitLayerChangesBeforeSublayers(childCommitState, pageScaleFactor, baseRelativePosition, oldVisibleRect, &transformFromRoot);
+    }
 
     if (isRunningTransformAnimation()) {
         childCommitState.ancestorHasTransformAnimation = true;
@@ -1149,7 +1154,10 @@
     if (m_maskLayer)
         static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(childCommitState);
 
-    commitLayerChangesAfterSublayers(childCommitState);
+    {
+        TemporaryChange<bool> committingChangesChange(m_isCommittingChanges, true);
+        commitLayerChangesAfterSublayers(childCommitState);
+    }
 
     if (affectedByTransformAnimation && client() && m_layer->layerType() == PlatformCALayer::LayerTypeTiledBackingLayer)
         client()->notifyFlushBeforeDisplayRefresh(this);
@@ -1173,14 +1181,9 @@
     paintGraphicsLayerContents(context, clip);
 }
 
-void GraphicsLayerCA::platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects)
+void GraphicsLayerCA::platformCALayerSetNeedsToRevalidateTiles()
 {
-    ASSERT(m_layer->usesTiledBackingLayer());
-
-    for (size_t i = 0; i < dirtyRects.size(); ++i)
-        setNeedsDisplayInRect(dirtyRects[i]);
-
-    noteLayerPropertyChanged(TilesAdded);
+    noteLayerPropertyChanged(TilingAreaChanged, m_isCommittingChanges ? DontScheduleFlush : ScheduleFlush);
 }
 
 float GraphicsLayerCA::platformCALayerDeviceScaleFactor()
@@ -1272,6 +1275,9 @@
 
     if (m_uncommittedChanges & VisibleRectChanged)
         updateVisibleRect(oldVisibleRect);
+    
+    if (m_uncommittedChanges & TilingAreaChanged) // Needs to happen after VisibleRectChanged, ContentsScaleChanged
+        updateTiles();
 
     if (m_uncommittedChanges & DirtyRectsChanged)
         repaintLayerDirtyRects();
@@ -1620,7 +1626,7 @@
 
     // We've changed the layer that our parent added to its sublayer list, so tell it to update
     // sublayers again in its commitLayerChangesAfterSublayers().
-    static_cast<GraphicsLayerCA*>(parent())->noteSublayersChanged();
+    static_cast<GraphicsLayerCA*>(parent())->noteSublayersChanged(DontScheduleFlush);
 
     // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
     FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
@@ -1755,6 +1761,14 @@
     m_sizeAtLastVisibleRectUpdate = m_size;
 }
 
+void GraphicsLayerCA::updateTiles()
+{
+    if (!m_layer->usesTiledBackingLayer())
+        return;
+
+    tiledBacking()->revalidateTiles();
+}
+
 void GraphicsLayerCA::updateBackgroundColor()
 {
     m_layer->setBackgroundColor(m_backgroundColor);
@@ -1881,7 +1895,7 @@
     }
     
     if (gainedOrLostClippingLayer)
-        noteSublayersChanged();
+        noteSublayersChanged(DontScheduleFlush);
 
     m_contentsLayer->setPosition(contentOrigin);
     m_contentsLayer->setBounds(contentBounds);
@@ -3264,9 +3278,9 @@
     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * pageScaleFactor);
 }
 
-void GraphicsLayerCA::noteSublayersChanged()
+void GraphicsLayerCA::noteSublayersChanged(ScheduleFlushOrNot scheduleFlush)
 {
-    noteLayerPropertyChanged(ChildrenChanged);
+    noteLayerPropertyChanged(ChildrenChanged, scheduleFlush);
     propagateLayerChangeToReplicas();
 }
 
@@ -3276,16 +3290,18 @@
     return !(m_uncommittedChanges & TilesAdded);
 }
 
-void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
+void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags, ScheduleFlushOrNot scheduleFlush)
 {
     bool hadUncommittedChanges = !!m_uncommittedChanges;
     bool oldCanThrottleLayerFlush = canThrottleLayerFlush();
 
     m_uncommittedChanges |= flags;
 
-    bool needsFlush = !hadUncommittedChanges || oldCanThrottleLayerFlush != canThrottleLayerFlush();
-    if (needsFlush && m_client)
-        m_client->notifyFlushRequired(this);
+    if (scheduleFlush == ScheduleFlush) {
+        bool needsFlush = !hadUncommittedChanges || oldCanThrottleLayerFlush != canThrottleLayerFlush();
+        if (needsFlush && m_client)
+            m_client->notifyFlushRequired(this);
+    }
 }
 
 double GraphicsLayerCA::backingStoreMemoryEstimate() const

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2013-09-23 20:43:17 UTC (rev 156291)
@@ -172,8 +172,9 @@
     virtual bool platformCALayerContentsOpaque() const { return contentsOpaque(); }
     virtual bool platformCALayerDrawsContent() const { return drawsContent(); }
     virtual void platformCALayerLayerDidDisplay(PlatformLayer* layer) { return layerDidDisplay(layer); }
-    virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) OVERRIDE;
+    virtual void platformCALayerSetNeedsToRevalidateTiles() OVERRIDE;
     virtual float platformCALayerDeviceScaleFactor() OVERRIDE;
+    virtual bool isCommittingChanges() const OVERRIDE { return m_isCommittingChanges; }
 
     virtual double backingStoreMemoryEstimate() const;
 
@@ -355,6 +356,7 @@
     void updateAcceleratesDrawing();
     void updateDebugBorder();
     void updateVisibleRect(const FloatRect& oldVisibleRect);
+    void updateTiles();
     void updateContentsScale(float pageScaleFactor);
     
     enum StructuralLayerPurpose {
@@ -410,12 +412,14 @@
         ContentsVisibilityChanged = 1 << 25,
         VisibleRectChanged = 1 << 26,
         FiltersChanged = 1 << 27,
-        TilesAdded = 1 < 28,
-        DebugIndicatorsChanged = 1 << 29
+        TilingAreaChanged = 1 << 28,
+        TilesAdded = 1 < 29,
+        DebugIndicatorsChanged = 1 << 30
     };
     typedef unsigned LayerChangeFlags;
-    void noteLayerPropertyChanged(LayerChangeFlags flags);
-    void noteSublayersChanged();
+    enum ScheduleFlushOrNot { ScheduleFlush, DontScheduleFlush };
+    void noteLayerPropertyChanged(LayerChangeFlags, ScheduleFlushOrNot = ScheduleFlush);
+    void noteSublayersChanged(ScheduleFlushOrNot = ScheduleFlush);
     void noteChangesForScaleSensitiveProperties();
 
     void repaintLayerDirtyRects();
@@ -505,6 +509,7 @@
     FloatSize m_pixelAlignmentOffset;
     
     LayerChangeFlags m_uncommittedChanges;
+    bool m_isCommittingChanges;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h	2013-09-23 20:43:17 UTC (rev 156291)
@@ -59,9 +59,11 @@
     virtual bool platformCALayerDrawsContent() const = 0;
     virtual void platformCALayerLayerDidDisplay(PlatformLayer*) = 0;
 
-    virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) = 0;
+    virtual void platformCALayerSetNeedsToRevalidateTiles() { }
     virtual float platformCALayerDeviceScaleFactor() = 0;
 
+    virtual bool isCommittingChanges() const { return false; }
+
 protected:
     virtual ~PlatformCALayerClient() {}
 };

Modified: trunk/Source/WebCore/platform/graphics/ca/mac/TileController.h (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/ca/mac/TileController.h	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/TileController.h	2013-09-23 20:43:17 UTC (rev 156291)
@@ -115,6 +115,7 @@
     virtual void setIsInWindow(bool) OVERRIDE;
     virtual void setTileCoverage(TileCoverage) OVERRIDE;
     virtual TileCoverage tileCoverage() const OVERRIDE { return m_tileCoverage; }
+    virtual void revalidateTiles() OVERRIDE;
     virtual void forceRepaint() OVERRIDE;
     virtual IntSize tileSize() const OVERRIDE { return m_tileSize; }
     virtual IntRect tileGridExtent() const OVERRIDE;
@@ -145,7 +146,8 @@
     
     typedef unsigned TileValidationPolicyFlags;
 
-    void revalidateTiles(TileValidationPolicyFlags foregroundValidationPolicy = 0, TileValidationPolicyFlags backgroundValidationPolicy = 0);
+    void setNeedsRevalidateTiles();
+    void revalidateTiles(TileValidationPolicyFlags foregroundValidationPolicy, TileValidationPolicyFlags backgroundValidationPolicy);
     enum class CoverageType { PrimaryTiles, SecondaryTiles };
 
     // Returns the bounds of the covered tiles.
@@ -179,6 +181,8 @@
     FloatRect m_visibleRectAtLastRevalidate;
     FloatRect m_exposedRect; // The exposed area of containing platform views.
     IntRect m_boundsAtLastRevalidate;
+    
+    Vector<FloatRect> m_secondaryTileCoverageRects;
 
     typedef HashMap<TileIndex, TileInfo> TileMap;
     TileMap m_tiles;

Modified: trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/ca/mac/TileController.mm	2013-09-23 20:43:17 UTC (rev 156291)
@@ -135,14 +135,8 @@
 
 void TileController::tileCacheLayerBoundsChanged()
 {
-    if (m_tiles.isEmpty()) {
-        // We must revalidate immediately instead of using a timer when there are
-        // no tiles to avoid a flash when transitioning from one page to another.
-        revalidateTiles();
-        return;
-    }
-
-    scheduleTileRevalidation(0);
+    ASSERT(PlatformCALayer::platformCALayer(m_tileCacheLayer)->owner()->isCommittingChanges());
+    setNeedsRevalidateTiles();
 }
 
 void TileController::setNeedsDisplay()
@@ -232,6 +226,8 @@
 void TileController::setScale(CGFloat scale)
 {
     PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
+    ASSERT(platformLayer->owner()->isCommittingChanges());
+
     float deviceScaleFactor = platformLayer->owner()->platformCALayerDeviceScaleFactor();
 
     // The scale we get is the produce of the page scale factor and device scale factor.
@@ -247,6 +243,7 @@
     m_scale = scale;
     [m_tileContainerLayer.get() setTransform:CATransform3DMakeScale(1 / m_scale, 1 / m_scale, 1)];
 
+    // FIXME: we may revalidateTiles twice in this commit.
     revalidateTiles(PruneSecondaryTiles, PruneSecondaryTiles);
 
     for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
@@ -259,8 +256,6 @@
         scaledTileRect.scale(1 / m_scale);
         dirtyRects.append(scaledTileRect);
     }
-
-    platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects);
 }
 
 void TileController::setAcceleratesDrawing(bool acceleratesDrawing)
@@ -291,11 +286,12 @@
 
 void TileController::setVisibleRect(const FloatRect& visibleRect)
 {
+    ASSERT(PlatformCALayer::platformCALayer(m_tileCacheLayer)->owner()->isCommittingChanges());
     if (m_visibleRect == visibleRect)
         return;
 
     m_visibleRect = visibleRect;
-    revalidateTiles();
+    setNeedsRevalidateTiles();
 }
 
 bool TileController::tilesWouldChangeForVisibleRect(const FloatRect& newVisibleRect) const
@@ -333,7 +329,7 @@
         return;
 
     m_exposedRect = exposedRect;
-    revalidateTiles();
+    setNeedsRevalidateTiles();
 }
 
 void TileController::setClipsToExposedRect(bool clipsToExposedRect)
@@ -345,7 +341,7 @@
 
     // Going from not clipping to clipping, we don't need to revalidate right away.
     if (clipsToExposedRect)
-        revalidateTiles();
+        setNeedsRevalidateTiles();
 }
 
 void TileController::prepopulateRect(const FloatRect& rect)
@@ -356,11 +352,9 @@
 
     if (m_primaryTileCoverageRect.contains(rectInTileCoords))
         return;
-
-    ensureTilesForRect(rect, CoverageType::SecondaryTiles);
-
-    if (m_tiledScrollingIndicatorLayer)
-        updateTileCoverageMap();
+    
+    m_secondaryTileCoverageRects.append(rect);
+    setNeedsRevalidateTiles();
 }
 
 void TileController::setIsInWindow(bool isInWindow)
@@ -371,7 +365,7 @@
     m_isInWindow = isInWindow;
 
     if (m_isInWindow)
-        revalidateTiles();
+        setNeedsRevalidateTiles();
     else {
         const double tileRevalidationTimeout = 4;
         scheduleTileRevalidation(tileRevalidationTimeout);
@@ -384,9 +378,15 @@
         return;
 
     m_tileCoverage = coverage;
-    scheduleTileRevalidation(0);
+    setNeedsRevalidateTiles();
 }
 
+void TileController::revalidateTiles()
+{
+    ASSERT(PlatformCALayer::platformCALayer(m_tileCacheLayer)->owner()->isCommittingChanges());
+    revalidateTiles(0, 0);
+}
+
 void TileController::forceRepaint()
 {
     setNeedsDisplay();
@@ -510,6 +510,11 @@
 
 void TileController::tileRevalidationTimerFired(Timer<TileController>*)
 {
+    if (m_isInWindow) {
+        setNeedsRevalidateTiles();
+        return;
+    }
+
     TileValidationPolicyFlags foregroundValidationPolicy = m_aggressivelyRetainsTiles ? 0 : PruneSecondaryTiles;
     TileValidationPolicyFlags backgroundValidationPolicy = foregroundValidationPolicy | UnparentAllTiles;
 
@@ -604,6 +609,12 @@
     }
 }
 
+void TileController::setNeedsRevalidateTiles()
+{
+    PlatformCALayer* platformLayer = PlatformCALayer::platformCALayer(m_tileCacheLayer);
+    platformLayer->owner()->platformCALayerSetNeedsToRevalidateTiles();
+}
+
 void TileController::revalidateTiles(TileValidationPolicyFlags foregroundValidationPolicy, TileValidationPolicyFlags backgroundValidationPolicy)
 {
     // If the underlying PlatformLayer has been destroyed, but the WebTiledBackingLayer hasn't
@@ -671,13 +682,17 @@
         if (!m_aggressivelyRetainsTiles)
             scheduleCohortRemoval();
     }
-    
+
     // Ensure primary tile coverage tiles.
     m_primaryTileCoverageRect = ensureTilesForRect(tileCoverageRect, CoverageType::PrimaryTiles);
 
     if (validationPolicy & PruneSecondaryTiles) {
         removeAllSecondaryTiles();
         m_cohortList.clear();
+    } else {
+        for (size_t i = 0; i < m_secondaryTileCoverageRects.size(); ++i)
+            ensureTilesForRect(m_secondaryTileCoverageRects[i], CoverageType::SecondaryTiles);
+        m_secondaryTileCoverageRects.clear();
     }
 
     if (m_unparentsOffscreenTiles && (validationPolicy & UnparentAllTiles)) {
@@ -834,10 +849,6 @@
     if (tilesInCohort)
         startedNewCohort(currCohort);
 
-    // This will ensure we flush compositing state and do layout in this run loop iteration.
-    if (!dirtyRects.isEmpty())
-        platformLayer->owner()->platformCALayerDidCreateTiles(dirtyRects);
-
     return coverageRect;
 }
 

Modified: trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp (156290 => 156291)


--- trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp	2013-09-23 20:43:17 UTC (rev 156291)
@@ -108,7 +108,6 @@
     virtual bool platformCALayerContentsOpaque() const { return false; }
     virtual bool platformCALayerDrawsContent() const { return false; }
     virtual void platformCALayerLayerDidDisplay(PlatformLayer*) { }
-    virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>&) { }
     virtual float platformCALayerDeviceScaleFactor() { return 1; }
 
     MediaPlayerPrivateQuickTimeVisualContext* m_parent;

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (156290 => 156291)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2013-09-23 20:38:36 UTC (rev 156290)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2013-09-23 20:43:17 UTC (rev 156291)
@@ -355,6 +355,8 @@
 
 void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
 {
+    ASSERT(!m_flushingLayers);
+
     if (canThrottle && isThrottlingLayerFlushes()) {
         m_hasPendingLayerFlush = true;
         return;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to