Title: [136277] trunk/Source/WebCore
Revision
136277
Author
simon.fra...@apple.com
Date
2012-11-30 14:30:59 -0800 (Fri, 30 Nov 2012)

Log Message

Late-loading stylesheets can cause composited layers to be blank
https://bugs.webkit.org/show_bug.cgi?id=103773

Reviewed by Tim Horton.

Early painting can be short-circuited in RenderBlock::paintContents() if we know a stylesheet
is pending, which is done to avoid a flash of unstyled content (FOUC). When the stylesheet
finally loaded, Document::styleResolverChanged() would try to repaint everything by calling
repaint() on the RenderView(). In a composited world, however, this repaint() doesn't repaint
composited layers.

This was particularly prevalent on this specific URL because it failed to load
a CSS file from typekit.com, so Document::styleResolverChanged()
just did the repaint and returned (rather than doing a recalc style as would
happen for correctly loaded stylesheets).

Fix by making a way to repaint all compositing layers, and calling it
from Document::styleResolverChanged().

No tests because this is timing-dependant.

* dom/Document.cpp:
(WebCore::Document::styleResolverChanged): Call repaintViewAndCompositedLayers().
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintContents): Fix the comment.
* rendering/RenderLayerCompositor.cpp: Convert repaintCompositedLayersAbsoluteRect()
and associated recursiveRepaintLayerRect() to allow the rect to be null, which indicates
that we should just repaint the entire layer, and improve their names.
(WebCore::RenderLayerCompositor::repaintCompositedLayers):
(WebCore::RenderLayerCompositor::recursiveRepaintLayer):
* rendering/RenderLayerCompositor.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::repaintRectangleInViewAndCompositedLayers): repaintCompositedLayersAbsoluteRect()
was renamed to repaintCompositedLayers().
(WebCore::RenderView::repaintViewAndCompositedLayers):
* rendering/RenderView.h:
(RenderView): repaintViewRectangle() and repaintRectangleInViewAndCompositedLayers() should not
be virtual. Add repaintViewAndCompositedLayers().

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (136276 => 136277)


--- trunk/Source/WebCore/ChangeLog	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/ChangeLog	2012-11-30 22:30:59 UTC (rev 136277)
@@ -1,3 +1,44 @@
+2012-11-30  Simon Fraser  <simon.fra...@apple.com>
+
+        Late-loading stylesheets can cause composited layers to be blank
+        https://bugs.webkit.org/show_bug.cgi?id=103773
+
+        Reviewed by Tim Horton.
+
+        Early painting can be short-circuited in RenderBlock::paintContents() if we know a stylesheet
+        is pending, which is done to avoid a flash of unstyled content (FOUC). When the stylesheet
+        finally loaded, Document::styleResolverChanged() would try to repaint everything by calling
+        repaint() on the RenderView(). In a composited world, however, this repaint() doesn't repaint
+        composited layers.
+        
+        This was particularly prevalent on this specific URL because it failed to load
+        a CSS file from typekit.com, so Document::styleResolverChanged()
+        just did the repaint and returned (rather than doing a recalc style as would
+        happen for correctly loaded stylesheets).
+        
+        Fix by making a way to repaint all compositing layers, and calling it
+        from Document::styleResolverChanged().
+
+        No tests because this is timing-dependant.
+
+        * dom/Document.cpp:
+        (WebCore::Document::styleResolverChanged): Call repaintViewAndCompositedLayers().
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paintContents): Fix the comment.
+        * rendering/RenderLayerCompositor.cpp: Convert repaintCompositedLayersAbsoluteRect()
+        and associated recursiveRepaintLayerRect() to allow the rect to be null, which indicates
+        that we should just repaint the entire layer, and improve their names.
+        (WebCore::RenderLayerCompositor::repaintCompositedLayers):
+        (WebCore::RenderLayerCompositor::recursiveRepaintLayer):
+        * rendering/RenderLayerCompositor.h:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::repaintRectangleInViewAndCompositedLayers): repaintCompositedLayersAbsoluteRect()
+        was renamed to repaintCompositedLayers().
+        (WebCore::RenderView::repaintViewAndCompositedLayers):
+        * rendering/RenderView.h:
+        (RenderView): repaintViewRectangle() and repaintRectangleInViewAndCompositedLayers() should not
+        be virtual. Add repaintViewAndCompositedLayers().
+
 2012-11-30  Sheriff Bot  <webkit.review....@gmail.com>
 
         Unreviewed, rolling out r136142.

Modified: trunk/Source/WebCore/dom/Document.cpp (136276 => 136277)


--- trunk/Source/WebCore/dom/Document.cpp	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/dom/Document.cpp	2012-11-30 22:30:59 UTC (rev 136277)
@@ -3179,7 +3179,7 @@
     if (didLayoutWithPendingStylesheets() && !m_styleSheetCollection->hasPendingSheets()) {
         m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
         if (renderer())
-            renderer()->repaint();
+            renderView()->repaintViewAndCompositedLayers();
     }
 
     if (!stylesheetChangeRequiresStyleRecalc)

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (136276 => 136277)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2012-11-30 22:30:59 UTC (rev 136277)
@@ -2928,8 +2928,8 @@
 void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
     // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
-    // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
-    // will do a full repaint().
+    // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document
+    // will do a full repaint.
     if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
         return;
 

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (136276 => 136277)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2012-11-30 22:30:59 UTC (rev 136277)
@@ -1340,16 +1340,20 @@
 }
 
 
-void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect)
+void RenderLayerCompositor::repaintCompositedLayers(const IntRect* absRect)
 {
-    recursiveRepaintLayerRect(rootRenderLayer(), absRect);
+    recursiveRepaintLayer(rootRenderLayer(), absRect);
 }
 
-void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect)
+void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer* layer, const IntRect* rect)
 {
     // FIXME: This method does not work correctly with transforms.
-    if (layer->isComposited() && !layer->backing()->paintsIntoCompositedAncestor())
-        layer->setBackingNeedsRepaintInRect(rect);
+    if (layer->isComposited() && !layer->backing()->paintsIntoCompositedAncestor()) {
+        if (rect)
+            layer->setBackingNeedsRepaintInRect(*rect);
+        else
+            layer->setBackingNeedsRepaint();
+    }
 
 #if !ASSERT_DISABLED
     LayerListMutationDetector mutationChecker(layer);
@@ -1360,9 +1364,12 @@
             size_t listSize = negZOrderList->size();
             for (size_t i = 0; i < listSize; ++i) {
                 RenderLayer* curLayer = negZOrderList->at(i);
-                IntRect childRect(rect);
-                curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
-                recursiveRepaintLayerRect(curLayer, childRect);
+                if (rect) {
+                    IntRect childRect(*rect);
+                    curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
+                    recursiveRepaintLayer(curLayer, &childRect);
+                } else
+                    recursiveRepaintLayer(curLayer);
             }
         }
 
@@ -1370,9 +1377,12 @@
             size_t listSize = posZOrderList->size();
             for (size_t i = 0; i < listSize; ++i) {
                 RenderLayer* curLayer = posZOrderList->at(i);
-                IntRect childRect(rect);
-                curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
-                recursiveRepaintLayerRect(curLayer, childRect);
+                if (rect) {
+                    IntRect childRect(*rect);
+                    curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
+                    recursiveRepaintLayer(curLayer, &childRect);
+                } else
+                    recursiveRepaintLayer(curLayer);
             }
         }
     }
@@ -1380,9 +1390,12 @@
         size_t listSize = normalFlowList->size();
         for (size_t i = 0; i < listSize; ++i) {
             RenderLayer* curLayer = normalFlowList->at(i);
-            IntRect childRect(rect);
-            curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
-            recursiveRepaintLayerRect(curLayer, childRect);
+            if (rect) {
+                IntRect childRect(*rect);
+                curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
+                recursiveRepaintLayer(curLayer, &childRect);
+            } else
+                recursiveRepaintLayer(curLayer);
         }
     }
 }

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (136276 => 136277)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h	2012-11-30 22:30:59 UTC (rev 136277)
@@ -144,8 +144,8 @@
     // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context
     RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const;
 
-    // Repaint parts of all composited layers that intersect the given absolute rectangle.
-    void repaintCompositedLayersAbsoluteRect(const IntRect&);
+    // Repaint parts of all composited layers that intersect the given absolute rectangle (or the entire layer if the pointer is null).
+    void repaintCompositedLayers(const IntRect* = 0);
 
     // Returns true if the given layer needs it own backing store.
     bool requiresOwnBackingStore(const RenderLayer*, const RenderLayer* compositingAncestorLayer) const;
@@ -257,7 +257,7 @@
     void clearBackingForLayerIncludingDescendants(RenderLayer*);
 
     // Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
-    void recursiveRepaintLayerRect(RenderLayer*, const IntRect&);
+    void recursiveRepaintLayer(RenderLayer*, const IntRect* = 0);
 
     void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
     void addToOverlapMapRecursive(OverlapMap&, RenderLayer*, RenderLayer* ancestorLayer = 0);

Modified: trunk/Source/WebCore/rendering/RenderView.cpp (136276 => 136277)


--- trunk/Source/WebCore/rendering/RenderView.cpp	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/rendering/RenderView.cpp	2012-11-30 22:30:59 UTC (rev 136277)
@@ -435,8 +435,20 @@
     repaintViewRectangle(ur, immediate);
     
 #if USE(ACCELERATED_COMPOSITING)
+    if (compositor()->inCompositingMode()) {
+        IntRect repaintRect = pixelSnappedIntRect(ur);
+        compositor()->repaintCompositedLayers(&repaintRect);
+    }
+#endif
+}
+
+void RenderView::repaintViewAndCompositedLayers()
+{
+    repaint();
+    
+#if USE(ACCELERATED_COMPOSITING)
     if (compositor()->inCompositingMode())
-        compositor()->repaintCompositedLayersAbsoluteRect(pixelSnappedIntRect(ur));
+        compositor()->repaintCompositedLayers();
 #endif
 }
 

Modified: trunk/Source/WebCore/rendering/RenderView.h (136276 => 136277)


--- trunk/Source/WebCore/rendering/RenderView.h	2012-11-30 21:56:24 UTC (rev 136276)
+++ trunk/Source/WebCore/rendering/RenderView.h	2012-11-30 22:30:59 UTC (rev 136277)
@@ -78,10 +78,11 @@
     FrameView* frameView() const { return m_frameView; }
 
     virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
-    virtual void repaintViewRectangle(const LayoutRect&, bool immediate = false) const;
+    void repaintViewRectangle(const LayoutRect&, bool immediate = false) const;
     // Repaint the view, and all composited layers that intersect the given absolute rectangle.
     // FIXME: ideally we'd never have to do this, if all repaints are container-relative.
-    virtual void repaintRectangleInViewAndCompositedLayers(const LayoutRect&, bool immediate = false);
+    void repaintRectangleInViewAndCompositedLayers(const LayoutRect&, bool immediate = false);
+    void repaintViewAndCompositedLayers();
 
     virtual void paint(PaintInfo&, const LayoutPoint&);
     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to