Changeset 136326 in webkit


Ignore:
Timestamp:
Dec 2, 2012, 2:55:24 AM (13 years ago)
Author:
junov@google.com
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.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r136324 r136326  
     12012-12-02  Justin Novosad  <junov@google.com>
     2
     3        Fix occlusion culling logic to handle css background layer clipping
     4        https://bugs.webkit.org/show_bug.cgi?id=103276
     5
     6        Reviewed by Simon Fraser.
     7
     8        New ref test that verifies the superposition of background layers with
     9        the layers having smaller clip regions than the layers beneath them.
     10        This test ensures the bottom layers are not removed by culling
     11        optimizations.
     12
     13        * fast/backgrounds/background-opaque-clipped-gradients-expected.html: Added.
     14        * fast/backgrounds/background-opaque-clipped-gradients.html: Added.
     15
    1162012-12-02  Tony Chang  <tony@chromium.org>
    217
  • trunk/Source/WebCore/ChangeLog

    r136324 r136326  
     12012-12-02  Justin Novosad  <junov@google.com>
     2
     3        Fix occlusion culling logic to handle css background layer clipping
     4        https://bugs.webkit.org/show_bug.cgi?id=103276
     5
     6        Reviewed by Simon Fraser.
     7
     8        Bug was introduced by r135629
     9        This patch fixes it by verifying layer clip.  A fill layer must
     10        not be treated as if it occludes the layers under it unless it has
     11        a larger or equal clip setting than the layers under it.
     12
     13        Test: fast/backgrounds/background-opaque-clipped-gradients.html
     14
     15        * rendering/RenderBox.cpp:
     16        (WebCore::RenderBox::paintFillLayers):
     17        * rendering/style/FillLayer.cpp:
     18        (WebCore::clipMax):
     19        (WebCore::FillLayer::computeClipMax):
     20        (WebCore::FillLayer::clipOccludesNextLayers):
     21        * rendering/style/FillLayer.h:
     22        (FillLayer):
     23
    1242012-12-02  Tony Chang  <tony@chromium.org>
    225
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r136253 r136326  
    10491049    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
    10501050{
    1051     if (!fillLayer)
    1052         return;
    1053 
    1054     // FIXME : It would be possible for the following occlusion culling test to be more aggressive
    1055     // on layers with no repeat by testing whether the image covers the layout rect.
    1056     // Testing that here would imply duplicating a lot of calculations that are currently done in
    1057     // RenderBoxModelOBject::paintFillLayerExtended. A more efficient solution might be to move
    1058     // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
    1059     // and pass it down.
    1060     if (fillLayer->next() && (!fillLayer->hasOpaqueImage(this) || !fillLayer->image()->canRender(this, style()->effectiveZoom()) || !fillLayer->hasRepeatXY()))
    1061         paintFillLayers(paintInfo, c, fillLayer->next(), rect, bleedAvoidance, op, backgroundObject);
    1062     paintFillLayer(paintInfo, c, fillLayer, rect, bleedAvoidance, op, backgroundObject);
     1051    Vector<const FillLayer*, 8> layers;
     1052    const FillLayer* curLayer = fillLayer;
     1053    while (curLayer) {
     1054        layers.append(curLayer);
     1055        // Stop traversal when an opaque layer is encountered.
     1056        // FIXME : It would be possible for the following occlusion culling test to be more aggressive
     1057        // on layers with no repeat by testing whether the image covers the layout rect.
     1058        // Testing that here would imply duplicating a lot of calculations that are currently done in
     1059        // RenderBoxModelOBject::paintFillLayerExtended. A more efficient solution might be to move
     1060        // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
     1061        // and pass it down.
     1062        if (curLayer->hasOpaqueImage(this) && curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->image()->canRender(this, style()->effectiveZoom()) && curLayer->hasRepeatXY())
     1063            break;
     1064        curLayer = curLayer->next();
     1065    }
     1066
     1067    Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
     1068    for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
     1069        paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject);
    10631070}
    10641071
  • trunk/Source/WebCore/rendering/style/FillLayer.cpp

    r135629 r136326  
    259259}
    260260
     261static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
     262{
     263    if (clipA == BorderFillBox || clipB == BorderFillBox)
     264        return BorderFillBox;
     265    if (clipA == PaddingFillBox || clipB == PaddingFillBox)
     266        return PaddingFillBox;
     267    if (clipA == ContentFillBox || clipB == ContentFillBox)
     268        return ContentFillBox;
     269    return TextFillBox;
     270}
     271
     272void FillLayer::computeClipMax() const
     273{
     274    if (m_next) {
     275        m_next->computeClipMax();
     276        m_clipMax = clipMax(clip(), m_next->clip());
     277    } else
     278        m_clipMax = m_clip;
     279}
     280
     281bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
     282{
     283    if (firstLayer)
     284        computeClipMax();
     285    return m_clip == m_clipMax;
     286}
     287
    261288bool FillLayer::containsImage(StyleImage* s) const
    262289{
  • trunk/Source/WebCore/rendering/style/FillLayer.h

    r135629 r136326  
    147147    bool hasOpaqueImage(const RenderObject*) const;
    148148    bool hasRepeatXY() const;
     149    bool clipOccludesNextLayers(bool firstLayer) const;
    149150
    150151    EFillLayerType type() const { return static_cast<EFillLayerType>(m_type); }
     
    169170    friend class RenderStyle;
    170171
     172    void computeClipMax() const;
     173
    171174    FillLayer() { }
    172175
     
    199202   
    200203    unsigned m_type : 1; // EFillLayerType
     204
     205    mutable unsigned m_clipMax : 2; // EFillBox, maximum m_clip value from this to bottom layer
    201206};
    202207
Note: See TracChangeset for help on using the changeset viewer.