Changeset 245602 in webkit


Ignore:
Timestamp:
May 21, 2019, 5:12:49 PM (6 years ago)
Author:
Simon Fraser
Message:

Layer flashing and poor perf during scrolling of message list on gmail.com and hotmail.com - overlap testing needs to constrained to clipping scopes
https://bugs.webkit.org/show_bug.cgi?id=198091
<rdar://problem/49403082>

Reviewed by Antti Koivisto.
Source/WebCore:

When overflow:scroll is scrolled asynchronously, we need to have already created compositing layers where necessary
for clipped-out layers in the scrolled content so that we have something to reveal. We also have ensure
that layers inside the scroller (but scrolled out of view) don't trigger overlap with layers outside the scroller.
All this has to work when the containing block hierarchy (clipping/scrolling) doesn't match the paint order hierarchy (structure
of the z-order and compositing trees).

Overlap testing previously simply used a list of rectangles per compositing container (OverlapMapContainer). This is
a series of layer bounds, built up as we traver the layer tree in z-order. Layers contribute to container N-2, and test
against container N-1.

To handle overlap with non-stacking-context scrollers, introduce the concept of a ClippingScope, which encompasses
a set of layers sharing the same composited-scrolling containing-block ancestor. Within a ClippingScope, layer bounds
are computed unclipped. Between them, bounds are tested clipped.

Conceptually, each OverlapMapContainer has a tree of ClippingScopes (reflecting the containing-block order tree of
composited overflow scroll), and rects are added to the appropriate ClippingScope. This tree is currently always
root-relative; the root node is the RenderView's RenderLayer, and will accumulate the bounds of layers not inside
composited overflow scroll (just like the old code).

When a OverlapMapContainer is popped, the list of rectangles in its ClippingScope tree is merged with that of the previous
container.

Tests: compositing/layer-creation/clipping-scope/nested-scroller-overlap.html

compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller.html
compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller.html
compositing/layer-creation/clipping-scope/scroller-with-negative-z-children.html
compositing/layer-creation/clipping-scope/shared-layers-in-scroller.html

  • rendering/LayerOverlapMap.cpp:

(WebCore::operator<<):
(WebCore::OverlapMapContainer::OverlapMapContainer):
(WebCore::OverlapMapContainer::ClippingScope::ClippingScope):
(WebCore::OverlapMapContainer::ClippingScope::childWithLayer const):
(WebCore::OverlapMapContainer::ClippingScope::addChildWithLayerAndBounds):
(WebCore::OverlapMapContainer::ClippingScope::addChild):
(WebCore::OverlapMapContainer::ClippingScope::appendRect):
(WebCore::OverlapMapContainer::clippingScopeContainingLayerChildRecursive):
(WebCore::OverlapMapContainer::scopeContainingLayer const):
(WebCore::OverlapMapContainer::rootScope const):
(WebCore::OverlapMapContainer::rootScope):
(WebCore::OverlapMapContainer::add):
(WebCore::OverlapMapContainer::overlapsLayers const):
(WebCore::OverlapMapContainer::mergeClippingScopesRecursive):
(WebCore::OverlapMapContainer::append):
(WebCore::OverlapMapContainer::ensureClippingScopeForLayers):
(WebCore::OverlapMapContainer::findClippingScopeForLayers const):
(WebCore::OverlapMapContainer::recursiveOutputToStream const):
(WebCore::OverlapMapContainer::dump const):
(WebCore::LayerOverlapMap::LayerOverlapMap):
(WebCore::LayerOverlapMap::add):
(WebCore::LayerOverlapMap::overlapsLayers const):
(WebCore::LayerOverlapMap::pushCompositingContainer):
(WebCore::LayerOverlapMap::popCompositingContainer):
(WebCore::OverlapMapContainer::unite): Deleted.
(WebCore::OverlapMapContainer::rectList const): Deleted.

  • rendering/LayerOverlapMap.h:
  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::BackingSharingState::appendSharingLayer):
(WebCore::RenderLayerCompositor::BackingSharingState::updateBeforeDescendantTraversal):
(WebCore::RenderLayerCompositor::updateCompositingLayers):
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
(WebCore::RenderLayerCompositor::computeExtent const):
(WebCore::createsClippingScope):
(WebCore::enclosingClippingScopes):
(WebCore::RenderLayerCompositor::addToOverlapMap const):
(WebCore::RenderLayerCompositor::updateOverlapMap const):
(WebCore::RenderLayerCompositor::layerOverlaps const):

  • rendering/RenderLayerCompositor.h:

Source/WebCore/../../LayoutTests:

  • TestExpectations:
  • compositing/layer-creation/clipping-scope/nested-scroller-overlap-expected.txt: Added.
  • compositing/layer-creation/clipping-scope/nested-scroller-overlap.html: Added.
  • compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller-expected.txt: Added.
  • compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller.html: Added.
  • compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller-expected.txt: Added.
  • compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller.html: Added.
  • compositing/layer-creation/clipping-scope/scroller-with-negative-z-children-expected.txt: Added.
  • compositing/layer-creation/clipping-scope/scroller-with-negative-z-children.html: Added.
  • compositing/layer-creation/clipping-scope/shared-layers-in-scroller-expected.txt: Added.
  • compositing/layer-creation/clipping-scope/shared-layers-in-scroller.html: Added.
  • platform/ios-wk2/TestExpectations:
  • platform/ios-wk2/compositing/layer-creation/clipping-scope/nested-scroller-overlap-expected.txt: Added.
  • platform/ios-wk2/compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller-expected.txt: Added.
  • platform/ios-wk2/compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller-expected.txt: Added.
  • platform/ios-wk2/compositing/layer-creation/clipping-scope/scroller-with-negative-z-children-expected.txt: Added.
  • platform/ios-wk2/compositing/layer-creation/clipping-scope/shared-layers-in-scroller-expected.txt: Added.
  • platform/mac-wk2/TestExpectations:
Location:
trunk
Files:
17 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245598 r245602  
    1919        * fast/text/variations/resources/Amstelvar/COPYRIGHT.md: Added.
    2020        * fast/text/variations/resources/Amstelvar/OFL.txt: Added.
     21
     222019-05-21  Simon Fraser  <simon.fraser@apple.com>
     23
     24        Layer flashing and poor perf during scrolling of message list on gmail.com and hotmail.com - overlap testing needs to constrained to clipping scopes
     25        https://bugs.webkit.org/show_bug.cgi?id=198091
     26        <rdar://problem/49403082>
     27
     28        Reviewed by Antti Koivisto.
     29
     30        * TestExpectations:
     31        * compositing/layer-creation/clipping-scope/nested-scroller-overlap-expected.txt: Added.
     32        * compositing/layer-creation/clipping-scope/nested-scroller-overlap.html: Added.
     33        * compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller-expected.txt: Added.
     34        * compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller.html: Added.
     35        * compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller-expected.txt: Added.
     36        * compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller.html: Added.
     37        * compositing/layer-creation/clipping-scope/scroller-with-negative-z-children-expected.txt: Added.
     38        * compositing/layer-creation/clipping-scope/scroller-with-negative-z-children.html: Added.
     39        * compositing/layer-creation/clipping-scope/shared-layers-in-scroller-expected.txt: Added.
     40        * compositing/layer-creation/clipping-scope/shared-layers-in-scroller.html: Added.
     41        * platform/ios-wk2/TestExpectations:
     42        * platform/ios-wk2/compositing/layer-creation/clipping-scope/nested-scroller-overlap-expected.txt: Added.
     43        * platform/ios-wk2/compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller-expected.txt: Added.
     44        * platform/ios-wk2/compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller-expected.txt: Added.
     45        * platform/ios-wk2/compositing/layer-creation/clipping-scope/scroller-with-negative-z-children-expected.txt: Added.
     46        * platform/ios-wk2/compositing/layer-creation/clipping-scope/shared-layers-in-scroller-expected.txt: Added.
     47        * platform/mac-wk2/TestExpectations:
    2148
    22492019-05-21  Antti Koivisto  <antti@apple.com>
  • trunk/LayoutTests/TestExpectations

    r245494 r245602  
    6464compositing/shared-backing/overflow-scroll [ Skip ]
    6565compositing/scrolling/async-overflow-scrolling [ Skip ]
     66compositing/layer-creation/clipping-scope [ Skip ]
    6667
    6768# WebKit2 only.
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r245568 r245602  
    1010compositing/shared-backing/overflow-scroll [ Pass ]
    1111compositing/scrolling/async-overflow-scrolling [ Pass ]
     12compositing/layer-creation/clipping-scope [ Pass ]
    1213fast/device-orientation [ Pass ]
    1314fast/history/ios [ Pass ]
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r245517 r245602  
    88compositing/shared-backing/overflow-scroll [ Pass ]
    99compositing/scrolling/async-overflow-scrolling [ Pass ]
     10compositing/layer-creation/clipping-scope [ Pass ]
    1011editing/find [ Pass ]
    1112editing/undo-manager [ Pass ]
  • trunk/Source/WebCore/ChangeLog

    r245598 r245602  
    3838        * platform/graphics/mac/FontCustomPlatformData.cpp:
    3939        (WebCore::FontCustomPlatformData::fontPlatformData):
     40
     412019-05-21  Simon Fraser  <simon.fraser@apple.com>
     42
     43        Layer flashing and poor perf during scrolling of message list on gmail.com and hotmail.com - overlap testing needs to constrained to clipping scopes
     44        https://bugs.webkit.org/show_bug.cgi?id=198091
     45        <rdar://problem/49403082>
     46
     47        Reviewed by Antti Koivisto.
     48       
     49        When overflow:scroll is scrolled asynchronously, we need to have already created compositing layers where necessary
     50        for clipped-out layers in the scrolled content so that we have something to reveal. We also have ensure
     51        that layers inside the scroller (but scrolled out of view) don't trigger overlap with layers outside the scroller.
     52        All this has to work when the containing block hierarchy (clipping/scrolling) doesn't match the paint order hierarchy (structure
     53        of the z-order and compositing trees).
     54
     55        Overlap testing previously simply used a list of rectangles per compositing container (OverlapMapContainer). This is
     56        a series of layer bounds, built up as we traver the layer tree in z-order. Layers contribute to container N-2, and test
     57        against container N-1.
     58       
     59        To handle overlap with non-stacking-context scrollers, introduce the concept of a ClippingScope, which encompasses
     60        a set of layers sharing the same composited-scrolling containing-block ancestor. Within a ClippingScope, layer bounds
     61        are computed unclipped. Between them, bounds are tested clipped.
     62       
     63        Conceptually, each OverlapMapContainer has a tree of ClippingScopes (reflecting the containing-block order tree of
     64        composited overflow scroll), and rects are added to the appropriate ClippingScope. This tree is currently always
     65        root-relative; the root node is the RenderView's RenderLayer, and will accumulate the bounds of layers not inside
     66        composited overflow scroll (just like the old code).
     67       
     68        When a OverlapMapContainer is popped, the list of rectangles in its ClippingScope tree is merged with that of the previous
     69        container.
     70
     71        Tests: compositing/layer-creation/clipping-scope/nested-scroller-overlap.html
     72               compositing/layer-creation/clipping-scope/overlap-constrained-inside-scroller.html
     73               compositing/layer-creation/clipping-scope/overlap-constrained-inside-stacking-context-scroller.html
     74               compositing/layer-creation/clipping-scope/scroller-with-negative-z-children.html
     75               compositing/layer-creation/clipping-scope/shared-layers-in-scroller.html
     76
     77        * rendering/LayerOverlapMap.cpp:
     78        (WebCore::operator<<):
     79        (WebCore::OverlapMapContainer::OverlapMapContainer):
     80        (WebCore::OverlapMapContainer::ClippingScope::ClippingScope):
     81        (WebCore::OverlapMapContainer::ClippingScope::childWithLayer const):
     82        (WebCore::OverlapMapContainer::ClippingScope::addChildWithLayerAndBounds):
     83        (WebCore::OverlapMapContainer::ClippingScope::addChild):
     84        (WebCore::OverlapMapContainer::ClippingScope::appendRect):
     85        (WebCore::OverlapMapContainer::clippingScopeContainingLayerChildRecursive):
     86        (WebCore::OverlapMapContainer::scopeContainingLayer const):
     87        (WebCore::OverlapMapContainer::rootScope const):
     88        (WebCore::OverlapMapContainer::rootScope):
     89        (WebCore::OverlapMapContainer::add):
     90        (WebCore::OverlapMapContainer::overlapsLayers const):
     91        (WebCore::OverlapMapContainer::mergeClippingScopesRecursive):
     92        (WebCore::OverlapMapContainer::append):
     93        (WebCore::OverlapMapContainer::ensureClippingScopeForLayers):
     94        (WebCore::OverlapMapContainer::findClippingScopeForLayers const):
     95        (WebCore::OverlapMapContainer::recursiveOutputToStream const):
     96        (WebCore::OverlapMapContainer::dump const):
     97        (WebCore::LayerOverlapMap::LayerOverlapMap):
     98        (WebCore::LayerOverlapMap::add):
     99        (WebCore::LayerOverlapMap::overlapsLayers const):
     100        (WebCore::LayerOverlapMap::pushCompositingContainer):
     101        (WebCore::LayerOverlapMap::popCompositingContainer):
     102        (WebCore::OverlapMapContainer::unite): Deleted.
     103        (WebCore::OverlapMapContainer::rectList const): Deleted.
     104        * rendering/LayerOverlapMap.h:
     105        * rendering/RenderLayerCompositor.cpp:
     106        (WebCore::RenderLayerCompositor::BackingSharingState::appendSharingLayer):
     107        (WebCore::RenderLayerCompositor::BackingSharingState::updateBeforeDescendantTraversal):
     108        (WebCore::RenderLayerCompositor::updateCompositingLayers):
     109        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
     110        (WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
     111        (WebCore::RenderLayerCompositor::computeExtent const):
     112        (WebCore::createsClippingScope):
     113        (WebCore::enclosingClippingScopes):
     114        (WebCore::RenderLayerCompositor::addToOverlapMap const):
     115        (WebCore::RenderLayerCompositor::updateOverlapMap const):
     116        (WebCore::RenderLayerCompositor::layerOverlaps const):
     117        * rendering/RenderLayerCompositor.h:
    40118
    411192019-05-21  Antoine Quint  <graouts@apple.com>
  • trunk/Source/WebCore/rendering/LayerOverlapMap.cpp

    r245370 r245602  
    2626#include "config.h"
    2727#include "LayerOverlapMap.h"
     28#include "RenderLayer.h"
    2829#include <wtf/text/TextStream.h>
    2930
     
    5960};
    6061
     62static TextStream& operator<<(TextStream& ts, const RectList& rectList)
     63{
     64    ts << "bounds " << rectList.boundingRect << " (" << rectList.rects << " rects)";
     65    return ts;
     66}
     67
     68// Used to store overlap rects in a way that takes overflow into account.
     69// It stores a tree whose nodes are layers with composited scrolling. The tree is built lazily as layers are added whose containing block
     70// chains contain composited scrollers. The tree always starts at the root layer.
     71// Checking for overlap involves finding the node for the clipping layer enclosing the given layer (or the root),
     72// and comparing against the bounds of earlier siblings.
    6173class OverlapMapContainer {
    6274public:
    63     void add(const LayoutRect& bounds)
    64     {
    65         m_rectList.append(bounds);
    66     }
    67 
    68     bool overlapsLayers(const LayoutRect& bounds) const
    69     {
    70         return m_rectList.intersects(bounds);
    71     }
    72 
    73     void unite(const OverlapMapContainer& otherContainer)
    74     {
    75         m_rectList.append(otherContainer.m_rectList);
    76     }
    77    
    78     const RectList& rectList() const { return m_rectList; }
     75    OverlapMapContainer(const RenderLayer& rootLayer)
     76        : m_rootScope(rootLayer)
     77    {
     78    }
     79
     80    // Layers are added in z-order, lazily creating clipping scopes as necessary.
     81    void add(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers);
     82    bool overlapsLayers(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const;
     83    void append(std::unique_ptr<OverlapMapContainer>&&);
     84   
     85    String dump(unsigned) const;
    7986
    8087private:
    81     RectList m_rectList;
     88    struct ClippingScope {
     89        ClippingScope(const RenderLayer& inLayer)
     90            : layer(inLayer)
     91        {
     92        }
     93
     94        ClippingScope(const LayerOverlapMap::LayerAndBounds& layerAndBounds)
     95            : layer(layerAndBounds.layer)
     96            , bounds(layerAndBounds.bounds)
     97        {
     98        }
     99
     100        ClippingScope* childWithLayer(const RenderLayer& layer) const
     101        {
     102            for (auto& child : children) {
     103                if (&child.layer == &layer)
     104                    return const_cast<ClippingScope*>(&child);
     105            }
     106            return nullptr;
     107        }
     108
     109        ClippingScope* addChildWithLayerAndBounds(const LayerOverlapMap::LayerAndBounds& layerAndBounds)
     110        {
     111            children.append({ layerAndBounds });
     112            return &children.last();
     113        }
     114
     115        ClippingScope* addChild(const ClippingScope& child)
     116        {
     117            children.append(child);
     118            return &children.last();
     119        }
     120
     121        void appendRect(const LayoutRect& bounds)
     122        {
     123            rectList.append(bounds);
     124        }
     125
     126        const RenderLayer& layer;
     127        LayoutRect bounds; // Bounds of the composited clip.
     128        Vector<ClippingScope> children;
     129        RectList rectList;
     130    };
     131
     132    static ClippingScope* clippingScopeContainingLayerChildRecursive(const ClippingScope& currNode, const RenderLayer& layer)
     133    {
     134        for (auto& child : currNode.children) {
     135            if (&layer == &child.layer)
     136                return const_cast<ClippingScope*>(&currNode);
     137
     138            if (auto* foundNode = clippingScopeContainingLayerChildRecursive(child, layer))
     139                return foundNode;
     140        }
     141
     142        return nullptr;
     143    }
     144
     145    ClippingScope* scopeContainingLayer(const RenderLayer& layer) const
     146    {
     147        return clippingScopeContainingLayerChildRecursive(m_rootScope, layer);
     148    }
     149   
     150    static void mergeClippingScopesRecursive(const ClippingScope& sourceScope, ClippingScope& destScope);
     151
     152    ClippingScope* ensureClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers);
     153    ClippingScope* findClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const;
     154
     155    void recursiveOutputToStream(TextStream&, const ClippingScope&, unsigned depth) const;
     156
     157    const ClippingScope& rootScope() const { return m_rootScope; }
     158    ClippingScope& rootScope() { return m_rootScope; }
     159
     160    ClippingScope m_rootScope;
    82161};
    83162
    84 LayerOverlapMap::LayerOverlapMap()
     163void OverlapMapContainer::add(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers)
     164{
     165    auto* layerScope = ensureClippingScopeForLayers(enclosingClippingLayers);
     166    layerScope->appendRect(bounds);
     167}
     168
     169bool OverlapMapContainer::overlapsLayers(const RenderLayer&, const LayoutRect& bounds, const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const
     170{
     171    if (m_rootScope.rectList.intersects(bounds))
     172        return true;
     173
     174    if (m_rootScope.children.isEmpty())
     175        return false;
     176
     177    // Find the ClippingScope for which this layer is a child.
     178    auto* clippingScope = findClippingScopeForLayers(enclosingClippingLayers);
     179    if (!clippingScope)
     180        return false;
     181
     182    if (clippingScope->rectList.intersects(bounds))
     183        return true;
     184
     185    // FIXME: In some cases do we have to walk up the ancestor clipping scope chain?
     186    return false;
     187}
     188
     189void OverlapMapContainer::mergeClippingScopesRecursive(const ClippingScope& sourceScope, ClippingScope& destScope)
     190{
     191    ASSERT(&sourceScope.layer == &destScope.layer);
     192    destScope.rectList.append(sourceScope.rectList);
     193
     194    for (auto& sourceChildScope : sourceScope.children) {
     195        ClippingScope* destChild = destScope.childWithLayer(sourceChildScope.layer);
     196        if (destChild) {
     197            destChild->rectList.append(sourceChildScope.rectList);
     198            mergeClippingScopesRecursive(sourceChildScope, *destChild);
     199        } else {
     200            // New child, just copy the whole subtree.
     201            destScope.addChild(sourceScope);
     202        }
     203    }
     204}
     205
     206void OverlapMapContainer::append(std::unique_ptr<OverlapMapContainer>&& otherContainer)
     207{
     208    mergeClippingScopesRecursive(otherContainer->rootScope(), m_rootScope);
     209}
     210
     211OverlapMapContainer::ClippingScope* OverlapMapContainer::ensureClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers)
     212{
     213    ASSERT(enclosingClippingLayers.size());
     214    ASSERT(enclosingClippingLayers[0].layer.isRenderViewLayer());
     215
     216    auto* currScope = &m_rootScope;
     217    for (unsigned i = 1; i < enclosingClippingLayers.size(); ++i) {
     218        auto& scopeLayerAndBounds = enclosingClippingLayers[i];
     219        auto* childScope = currScope->childWithLayer(scopeLayerAndBounds.layer);
     220        if (!childScope) {
     221            currScope = currScope->addChildWithLayerAndBounds(scopeLayerAndBounds);
     222            break;
     223        }
     224
     225        currScope = childScope;
     226    }
     227
     228    return const_cast<ClippingScope*>(currScope);
     229}
     230
     231OverlapMapContainer::ClippingScope* OverlapMapContainer::findClippingScopeForLayers(const Vector<LayerOverlapMap::LayerAndBounds>& enclosingClippingLayers) const
     232{
     233    ASSERT(enclosingClippingLayers.size());
     234    ASSERT(enclosingClippingLayers[0].layer.isRenderViewLayer());
     235
     236    const auto* currScope = &m_rootScope;
     237    for (unsigned i = 1; i < enclosingClippingLayers.size(); ++i) {
     238        auto& scopeLayerAndBounds = enclosingClippingLayers[i];
     239        auto* childScope = currScope->childWithLayer(scopeLayerAndBounds.layer);
     240        if (!childScope)
     241            return nullptr;
     242
     243        currScope = childScope;
     244    }
     245
     246    return const_cast<ClippingScope*>(currScope);
     247}
     248
     249void OverlapMapContainer::recursiveOutputToStream(TextStream& ts, const ClippingScope& scope, unsigned depth) const
     250{
     251    ts << "\n" << indent << TextStream::Repeat { 2 * depth, ' ' } << " scope for layer " << &scope.layer << " rects " << scope.rectList;
     252    for (auto& childScope : scope.children)
     253        recursiveOutputToStream(ts, childScope, depth + 1);
     254}
     255
     256String OverlapMapContainer::dump(unsigned indent) const
     257{
     258    TextStream multilineStream;
     259    multilineStream.increaseIndent(indent);
     260    multilineStream << "overlap container - root scope layer " <<  &m_rootScope.layer << " rects " << m_rootScope.rectList;
     261
     262    for (auto& childScope : m_rootScope.children)
     263        recursiveOutputToStream(multilineStream, childScope, 1);
     264
     265    return multilineStream.release();
     266}
     267
     268LayerOverlapMap::LayerOverlapMap(const RenderLayer& rootLayer)
    85269    : m_geometryMap(UseTransforms)
     270    , m_rootLayer(rootLayer)
    86271{
    87272    // Begin assuming the root layer will be composited so that there is
     
    93278LayerOverlapMap::~LayerOverlapMap() = default;
    94279
    95 void LayerOverlapMap::add(const LayoutRect& bounds)
     280void LayerOverlapMap::add(const RenderLayer& layer, const LayoutRect& bounds, const Vector<LayerAndBounds>& enclosingClippingLayers)
    96281{
    97282    // Layers do not contribute to overlap immediately--instead, they will
     
    99284    // recursively processed and popped off the stack.
    100285    ASSERT(m_overlapStack.size() >= 2);
    101     m_overlapStack[m_overlapStack.size() - 2]->add(bounds);
     286    m_overlapStack[m_overlapStack.size() - 2]->add(layer, bounds, enclosingClippingLayers);
     287   
    102288    m_isEmpty = false;
    103289}
    104290
    105 bool LayerOverlapMap::overlapsLayers(const LayoutRect& bounds) const
    106 {
    107     return m_overlapStack.last()->overlapsLayers(bounds);
     291bool LayerOverlapMap::overlapsLayers(const RenderLayer& layer, const LayoutRect& bounds, const Vector<LayerAndBounds>& enclosingClippingLayers) const
     292{
     293    return m_overlapStack.last()->overlapsLayers(layer, bounds, enclosingClippingLayers);
    108294}
    109295
    110296void LayerOverlapMap::pushCompositingContainer()
    111297{
    112     m_overlapStack.append(std::make_unique<OverlapMapContainer>());
     298    m_overlapStack.append(std::make_unique<OverlapMapContainer>(m_rootLayer));
    113299}
    114300
    115301void LayerOverlapMap::popCompositingContainer()
    116302{
    117     m_overlapStack[m_overlapStack.size() - 2]->unite(*m_overlapStack.last());
     303    m_overlapStack[m_overlapStack.size() - 2]->append(WTFMove(m_overlapStack.last()));
    118304    m_overlapStack.removeLast();
    119305}
    120306
    121 static TextStream& operator<<(TextStream& ts, const RectList& rectList)
    122 {
    123     ts << "bounds " << rectList.boundingRect << " (" << rectList.rects << " rects)";
     307static TextStream& operator<<(TextStream& ts, const OverlapMapContainer& container)
     308{
     309    ts << container.dump(ts.indent());
    124310    return ts;
    125311}
    126312
    127 static TextStream& operator<<(TextStream& ts, const OverlapMapContainer& container)
    128 {
    129     ts << container.rectList();
    130     return ts;
    131 }
    132 
    133313TextStream& operator<<(TextStream& ts, const LayerOverlapMap& overlapMap)
    134314{
     
    136316
    137317    TextStream::GroupScope scope(ts);
    138     multilineStream << indent << "LayerOverlapMap\n";
    139 
    140     for (auto& container : overlapMap.overlapStack())
    141         multilineStream << "  " << *container << "\n";
     318    multilineStream << "LayerOverlapMap\n";
     319    multilineStream.increaseIndent(2);
     320
     321    bool needNewline = false;
     322    for (auto& container : overlapMap.overlapStack()) {
     323        if (needNewline)
     324            multilineStream << "\n";
     325        else
     326            needNewline = true;
     327        multilineStream << indent << *container;
     328    }
    142329
    143330    ts << multilineStream.release();
     
    146333
    147334} // namespace WebCore
     335
  • trunk/Source/WebCore/rendering/LayerOverlapMap.h

    r245370 r245602  
    3535namespace WebCore {
    3636
     37class OverflowAwareOverlapContainer;
    3738class OverlapMapContainer;
     39class RenderLayer;
    3840
    3941class LayerOverlapMap {
    4042    WTF_MAKE_NONCOPYABLE(LayerOverlapMap);
    4143public:
    42     LayerOverlapMap();
     44    LayerOverlapMap(const RenderLayer& rootLayer);
    4345    ~LayerOverlapMap();
     46   
     47    struct LayerAndBounds {
     48        RenderLayer& layer;
     49        LayoutRect bounds;
     50    };
    4451
    45     void add(const LayoutRect& bounds);
    46     bool overlapsLayers(const LayoutRect&) const;
     52    void add(const RenderLayer&, const LayoutRect&, const Vector<LayerAndBounds>& enclosingClippingLayers);
     53    bool overlapsLayers(const RenderLayer&, const LayoutRect&, const Vector<LayerAndBounds>& enclosingClippingLayers) const;
    4754    bool isEmpty() const { return m_isEmpty; }
    4855
     
    5865    Vector<std::unique_ptr<OverlapMapContainer>> m_overlapStack;
    5966    RenderGeometryMap m_geometryMap;
     67    const RenderLayer& m_rootLayer;
    6068    bool m_isEmpty { true };
    6169};
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r245502 r245602  
    206206    void appendSharingLayer(RenderLayer& layer)
    207207    {
    208         LOG_WITH_STREAM(Compositing, stream << &layer << " appendSharingLayer " << &layer << " for backing provider " << m_backingProviderCandidate);
    209208        m_backingSharingLayers.append(makeWeakPtr(layer));
    210209    }
     
    250249    if (willBeComposited) {
    251250        m_backingSharingLayers.removeAll(&layer);
    252         LOG_WITH_STREAM(Compositing, stream << "Pre-descendant compositing of " << &layer << ", ending sharing sequence for " << m_backingProviderCandidate << " with " << m_backingSharingLayers.size() << " sharing layers");
    253251        endBackingSharingSequence();
    254252    }
     
    769767    // FIXME: optimize root-only update.
    770768    if (updateRoot->hasDescendantNeedingCompositingRequirementsTraversal() || updateRoot->needsCompositingRequirementsTraversal()) {
     769        auto& rootLayer = rootRenderLayer();
    771770        CompositingState compositingState(updateRoot);
    772771        BackingSharingState backingSharingState;
    773         LayerOverlapMap overlapMap;
     772        LayerOverlapMap overlapMap(rootLayer);
    774773
    775774        bool descendantHas3DTransform = false;
    776         computeCompositingRequirements(nullptr, rootRenderLayer(), overlapMap, compositingState, backingSharingState, descendantHas3DTransform);
     775        computeCompositingRequirements(nullptr, rootLayer, overlapMap, compositingState, backingSharingState, descendantHas3DTransform);
    777776    }
    778777
     
    884883    // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map
    885884    if (!willBeComposited && !overlapMap.isEmpty() && compositingState.testingOverlap) {
    886         computeExtent(overlapMap, layer, layerExtent);
    887 
    888885        // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
    889         if (overlapMap.overlapsLayers(layerExtent.bounds)) {
     886        if (layerOverlaps(overlapMap, layer, layerExtent)) {
    890887            if (backingSharingState.backingProviderCandidate() && canBeComposited(layer) && backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate(), layer)) {
    891888                backingSharingState.appendSharingLayer(layer);
     
    17871784        extent.bounds.setSize(LayoutSize(1, 1));
    17881785
    1789 
    17901786    RenderLayerModelObject& renderer = layer.renderer();
    17911787    if (renderer.isFixedPositioned() && renderer.container() == &m_renderView) {
     
    17991795}
    18001796
     1797static bool createsClippingScope(const RenderLayer& layer)
     1798{
     1799    return layer.hasCompositedScrollableOverflow();
     1800}
     1801
     1802static Vector<LayerOverlapMap::LayerAndBounds> enclosingClippingScopes(const RenderLayer& layer, const RenderLayer& rootLayer)
     1803{
     1804    Vector<LayerOverlapMap::LayerAndBounds> clippingScopes;
     1805    clippingScopes.append({ const_cast<RenderLayer&>(rootLayer), { } });
     1806
     1807    if (!layer.hasCompositedScrollingAncestor())
     1808        return clippingScopes;
     1809
     1810    bool containingBlockCanSkipLayers = layer.renderer().isAbsolutelyPositioned();
     1811    for (const auto* ancestorLayer = layer.parent(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
     1812        bool inContainingBlockChain = true;
     1813        if (containingBlockCanSkipLayers) {
     1814            inContainingBlockChain = ancestorLayer->renderer().canContainAbsolutelyPositionedObjects();
     1815            if (inContainingBlockChain)
     1816                containingBlockCanSkipLayers = ancestorLayer->renderer().isAbsolutelyPositioned();
     1817        }
     1818       
     1819        if (inContainingBlockChain && createsClippingScope(*ancestorLayer)) {
     1820            LayoutRect clipRect;
     1821            if (is<RenderBox>(ancestorLayer->renderer())) {
     1822                // FIXME: This is expensive. Broken with transforms.
     1823                LayoutPoint offsetFromRoot = ancestorLayer->convertToLayerCoords(&rootLayer, { });
     1824                clipRect = downcast<RenderBox>(ancestorLayer->renderer()).overflowClipRect(offsetFromRoot);
     1825            }
     1826
     1827            LayerOverlapMap::LayerAndBounds layerAndBounds { const_cast<RenderLayer&>(*ancestorLayer), clipRect };
     1828            clippingScopes.insert(1, layerAndBounds); // Order is roots to leaves.
     1829        }
     1830    }
     1831
     1832    return clippingScopes;
     1833}
     1834
    18011835void RenderLayerCompositor::addToOverlapMap(LayerOverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent) const
    18021836{
     
    18061840    computeExtent(overlapMap, layer, extent);
    18071841
    1808     LayoutRect clipRect = layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), AbsoluteClipRects)).rect(); // FIXME: Incorrect for CSS regions.
    1809 
    1810     // On iOS, pageScaleFactor() is not applied by RenderView, so we should not scale here.
    1811     if (!m_renderView.settings().delegatesPageScaling())
    1812         clipRect.scale(pageScaleFactor());
    1813     clipRect.intersect(extent.bounds);
    1814     overlapMap.add(clipRect);
     1842    // FIXME: constrain the scopes (by composited stacking context ancestor I think).
     1843    auto clippingScopes = enclosingClippingScopes(layer, rootRenderLayer());
     1844
     1845    LayoutRect clipRect;
     1846    if (layer.hasCompositedScrollingAncestor()) {
     1847        // Compute a clip up to the composited scrolling ancestor, then convert it to absolute coordinates.
     1848        auto& scrollingScope = clippingScopes.last();
     1849        clipRect = layer.backgroundClipRect(RenderLayer::ClipRectsContext(&scrollingScope.layer, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip)).rect();
     1850        if (!clipRect.isInfinite())
     1851            clipRect.setLocation(layer.convertToLayerCoords(&rootRenderLayer(), clipRect.location()));
     1852    } else
     1853        clipRect = layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), AbsoluteClipRects)).rect(); // FIXME: Incorrect for CSS regions.
     1854
     1855    auto clippedBounds = extent.bounds;
     1856    if (!clipRect.isInfinite()) {
     1857        // On iOS, pageScaleFactor() is not applied by RenderView, so we should not scale here.
     1858        if (!m_renderView.settings().delegatesPageScaling())
     1859            clipRect.scale(pageScaleFactor());
     1860
     1861        clippedBounds.intersect(clipRect);
     1862    }
     1863
     1864    overlapMap.add(layer, clippedBounds, clippingScopes);
    18151865}
    18161866
     
    18481898{
    18491899    if (addLayerToOverlap) {
     1900        auto clippingScopes = enclosingClippingScopes(layer, rootRenderLayer());
    18501901        addToOverlapMap(overlapMap, layer, layerExtent);
    18511902        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " contributes to overlap, added to map " << overlapMap);
     
    18621913        LOG_WITH_STREAM(CompositingOverlap, stream << "layer " << &layer << " is composited or shared, popped container " << overlapMap);
    18631914    }
     1915}
     1916
     1917bool RenderLayerCompositor::layerOverlaps(const LayerOverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& layerExtent) const
     1918{
     1919    computeExtent(overlapMap, layer, layerExtent);
     1920
     1921    auto clippingScopes = enclosingClippingScopes(layer, rootRenderLayer());
     1922    return overlapMap.overlapsLayers(layer, layerExtent.bounds, clippingScopes);
    18641923}
    18651924
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r245502 r245602  
    410410    void addDescendantsToOverlapMapRecursive(LayerOverlapMap&, const RenderLayer&, const RenderLayer* ancestorLayer = nullptr) const;
    411411    void updateOverlapMap(LayerOverlapMap&, const RenderLayer&, OverlapExtent&, bool didPushContainer, bool addLayerToOverlap, bool addDescendantsToOverlap = false) const;
     412    bool layerOverlaps(const LayerOverlapMap&, const RenderLayer&, OverlapExtent&) const;
    412413
    413414    void updateCompositingLayersTimerFired();
Note: See TracChangeset for help on using the changeset viewer.