Diff
Modified: trunk/LayoutTests/ChangeLog (136325 => 136326)
--- trunk/LayoutTests/ChangeLog 2012-12-02 10:42:17 UTC (rev 136325)
+++ trunk/LayoutTests/ChangeLog 2012-12-02 10:55:24 UTC (rev 136326)
@@ -1,3 +1,18 @@
+2012-12-02 Justin Novosad <ju...@google.com>
+
+ Fix occlusion culling logic to handle css background layer clipping
+ https://bugs.webkit.org/show_bug.cgi?id=103276
+
+ Reviewed by Simon Fraser.
+
+ New ref test that verifies the superposition of background layers with
+ the layers having smaller clip regions than the layers beneath them.
+ This test ensures the bottom layers are not removed by culling
+ optimizations.
+
+ * fast/backgrounds/background-opaque-clipped-gradients-expected.html: Added.
+ * fast/backgrounds/background-opaque-clipped-gradients.html: Added.
+
2012-12-02 Tony Chang <t...@chromium.org>
Avoid a second layout of flex items in layoutAndPlaceChildren()
Added: trunk/LayoutTests/fast/backgrounds/background-opaque-clipped-gradients-expected.html (0 => 136326)
--- trunk/LayoutTests/fast/backgrounds/background-opaque-clipped-gradients-expected.html (rev 0)
+++ trunk/LayoutTests/fast/backgrounds/background-opaque-clipped-gradients-expected.html 2012-12-02 10:55:24 UTC (rev 136326)
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+<head>
+<style type="text/css" media="screen">
+#div1
+{
+width: 150px;
+height: 150px;
+border:25px dotted;
+background-color: green;
+}
+#div2
+{
+width: 100px;
+height: 100px;
+padding: 25px;
+background-color: blue;
+}
+#div3
+{
+width: 100px;
+height: 100px;
+background-color: yellow;
+}
+</style>
+</head>
+<body>
+Test passes if the image below shows nested green, blue and yellow squares with a dotted black border.
+<div id="div1"><div id="div2"><div id="div3"></div></div></div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/backgrounds/background-opaque-clipped-gradients.html (0 => 136326)
--- trunk/LayoutTests/fast/backgrounds/background-opaque-clipped-gradients.html (rev 0)
+++ trunk/LayoutTests/fast/backgrounds/background-opaque-clipped-gradients.html 2012-12-02 10:55:24 UTC (rev 136326)
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+<head>
+<style type="text/css" media="screen">
+ #div1 {
+ width: 100px;
+ height: 100px;
+ padding: 25px;
+ border: 25px dotted;
+ background-image: -webkit-linear-gradient(top, yellow, yellow), -webkit-linear-gradient(top, blue, blue), -webkit-linear-gradient(top, green, green);
+ background-clip: content-box, padding-box, border-box;
+}
+</style>
+</head>
+<body>
+Test passes if the image below shows nested green, blue and yellow squares with a dotted black border.
+<div id="div1"></div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (136325 => 136326)
--- trunk/Source/WebCore/ChangeLog 2012-12-02 10:42:17 UTC (rev 136325)
+++ trunk/Source/WebCore/ChangeLog 2012-12-02 10:55:24 UTC (rev 136326)
@@ -1,3 +1,26 @@
+2012-12-02 Justin Novosad <ju...@google.com>
+
+ Fix occlusion culling logic to handle css background layer clipping
+ https://bugs.webkit.org/show_bug.cgi?id=103276
+
+ Reviewed by Simon Fraser.
+
+ Bug was introduced by r135629
+ This patch fixes it by verifying layer clip. A fill layer must
+ not be treated as if it occludes the layers under it unless it has
+ a larger or equal clip setting than the layers under it.
+
+ Test: fast/backgrounds/background-opaque-clipped-gradients.html
+
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::paintFillLayers):
+ * rendering/style/FillLayer.cpp:
+ (WebCore::clipMax):
+ (WebCore::FillLayer::computeClipMax):
+ (WebCore::FillLayer::clipOccludesNextLayers):
+ * rendering/style/FillLayer.h:
+ (FillLayer):
+
2012-12-02 Tony Chang <t...@chromium.org>
Avoid a second layout of flex items in layoutAndPlaceChildren()
Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (136325 => 136326)
--- trunk/Source/WebCore/rendering/RenderBox.cpp 2012-12-02 10:42:17 UTC (rev 136325)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp 2012-12-02 10:55:24 UTC (rev 136326)
@@ -1048,18 +1048,25 @@
void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
{
- if (!fillLayer)
- return;
+ Vector<const FillLayer*, 8> layers;
+ const FillLayer* curLayer = fillLayer;
+ while (curLayer) {
+ layers.append(curLayer);
+ // Stop traversal when an opaque layer is encountered.
+ // FIXME : It would be possible for the following occlusion culling test to be more aggressive
+ // on layers with no repeat by testing whether the image covers the layout rect.
+ // Testing that here would imply duplicating a lot of calculations that are currently done in
+ // RenderBoxModelOBject::paintFillLayerExtended. A more efficient solution might be to move
+ // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
+ // and pass it down.
+ if (curLayer->hasOpaqueImage(this) && curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->image()->canRender(this, style()->effectiveZoom()) && curLayer->hasRepeatXY())
+ break;
+ curLayer = curLayer->next();
+ }
- // FIXME : It would be possible for the following occlusion culling test to be more aggressive
- // on layers with no repeat by testing whether the image covers the layout rect.
- // Testing that here would imply duplicating a lot of calculations that are currently done in
- // RenderBoxModelOBject::paintFillLayerExtended. A more efficient solution might be to move
- // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
- // and pass it down.
- if (fillLayer->next() && (!fillLayer->hasOpaqueImage(this) || !fillLayer->image()->canRender(this, style()->effectiveZoom()) || !fillLayer->hasRepeatXY()))
- paintFillLayers(paintInfo, c, fillLayer->next(), rect, bleedAvoidance, op, backgroundObject);
- paintFillLayer(paintInfo, c, fillLayer, rect, bleedAvoidance, op, backgroundObject);
+ Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
+ for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
+ paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject);
}
void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
Modified: trunk/Source/WebCore/rendering/style/FillLayer.cpp (136325 => 136326)
--- trunk/Source/WebCore/rendering/style/FillLayer.cpp 2012-12-02 10:42:17 UTC (rev 136325)
+++ trunk/Source/WebCore/rendering/style/FillLayer.cpp 2012-12-02 10:55:24 UTC (rev 136326)
@@ -258,6 +258,33 @@
}
}
+static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
+{
+ if (clipA == BorderFillBox || clipB == BorderFillBox)
+ return BorderFillBox;
+ if (clipA == PaddingFillBox || clipB == PaddingFillBox)
+ return PaddingFillBox;
+ if (clipA == ContentFillBox || clipB == ContentFillBox)
+ return ContentFillBox;
+ return TextFillBox;
+}
+
+void FillLayer::computeClipMax() const
+{
+ if (m_next) {
+ m_next->computeClipMax();
+ m_clipMax = clipMax(clip(), m_next->clip());
+ } else
+ m_clipMax = m_clip;
+}
+
+bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
+{
+ if (firstLayer)
+ computeClipMax();
+ return m_clip == m_clipMax;
+}
+
bool FillLayer::containsImage(StyleImage* s) const
{
if (!s)
Modified: trunk/Source/WebCore/rendering/style/FillLayer.h (136325 => 136326)
--- trunk/Source/WebCore/rendering/style/FillLayer.h 2012-12-02 10:42:17 UTC (rev 136325)
+++ trunk/Source/WebCore/rendering/style/FillLayer.h 2012-12-02 10:55:24 UTC (rev 136326)
@@ -146,6 +146,7 @@
bool hasOpaqueImage(const RenderObject*) const;
bool hasRepeatXY() const;
+ bool clipOccludesNextLayers(bool firstLayer) const;
EFillLayerType type() const { return static_cast<EFillLayerType>(m_type); }
@@ -168,6 +169,8 @@
private:
friend class RenderStyle;
+ void computeClipMax() const;
+
FillLayer() { }
FillLayer* m_next;
@@ -198,6 +201,8 @@
unsigned m_compositeSet : 1;
unsigned m_type : 1; // EFillLayerType
+
+ mutable unsigned m_clipMax : 2; // EFillBox, maximum m_clip value from this to bottom layer
};
} // namespace WebCore