Title: [136326] trunk
Revision
136326
Author
ju...@google.com
Date
2012-12-02 02:55:24 -0800 (Sun, 02 Dec 2012)

Log Message

Fix occlusion culling logic to handle css background layer clipping
https://bugs.webkit.org/show_bug.cgi?id=103276

Reviewed by Simon Fraser.

Source/WebCore:

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):

LayoutTests:

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.

Modified Paths

Added Paths

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
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to