- 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;