Changeset 245772 in webkit


Ignore:
Timestamp:
May 25, 2019 8:01:14 AM (5 years ago)
Author:
Simon Fraser
Message:

[Async overflow scrolling] Absolute positioned element inside async overflow scroll didn't get composited sometimes
https://bugs.webkit.org/show_bug.cgi?id=198237

Reviewed by Antti Koivisto.

Source/WebCore:

The logic in requiresCompositingForIndirectReason() that decides if we need to do
compositing for a layer that needs to move independently of its enclosing scroller
was wrong.

Instead of asking question about the enclosing compositing layer, it needs to ask
whether it has different positioning behavior from the layer that it would
otherwise paint into, which is its paint-order parent.

"paintsIntoProvidedBacking" already does a containing-block check against the
scroller, so we know we don't have to do the check in that case.

Test: scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller.html

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::enclosingCompositedScrollingLayer):
(WebCore::isScrolledByOverflowScrollLayer):
(WebCore::isNonScrolledLayerInsideScrolledCompositedAncestor):
(WebCore::RenderLayerCompositor::requiresCompositingForIndirectReason const):

  • rendering/RenderLayerCompositor.h:

LayoutTests:

  • platform/ios-wk2/scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller-expected.txt: Added.
  • scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller-expected.txt: Added.
  • scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller.html: Added.
Location:
trunk
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r245771 r245772  
     12019-05-25  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [Async overflow scrolling] Absolute positioned element inside async overflow scroll didn't get composited sometimes
     4        https://bugs.webkit.org/show_bug.cgi?id=198237
     5
     6        Reviewed by Antti Koivisto.
     7
     8        * platform/ios-wk2/scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller-expected.txt: Added.
     9        * scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller-expected.txt: Added.
     10        * scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller.html: Added.
     11
    1122019-05-25  Simon Fraser  <simon.fraser@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r245771 r245772  
     12019-05-25  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [Async overflow scrolling] Absolute positioned element inside async overflow scroll didn't get composited sometimes
     4        https://bugs.webkit.org/show_bug.cgi?id=198237
     5
     6        Reviewed by Antti Koivisto.
     7
     8        The logic in requiresCompositingForIndirectReason() that decides if we need to do
     9        compositing for a layer that needs to move independently of its enclosing scroller
     10        was wrong.
     11
     12        Instead of asking question about the enclosing compositing layer, it needs to ask
     13        whether it has different positioning behavior from the layer that it would
     14        otherwise paint into, which is its paint-order parent.
     15
     16        "paintsIntoProvidedBacking" already does a containing-block check against the
     17        scroller, so we know we don't have to do the check in that case.
     18
     19        Test: scrollingcoordinator/scrolling-tree/absolute-inside-stacking-in-scroller.html
     20
     21        * rendering/RenderLayerCompositor.cpp:
     22        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
     23        (WebCore::enclosingCompositedScrollingLayer):
     24        (WebCore::isScrolledByOverflowScrollLayer):
     25        (WebCore::isNonScrolledLayerInsideScrolledCompositedAncestor):
     26        (WebCore::RenderLayerCompositor::requiresCompositingForIndirectReason const):
     27        * rendering/RenderLayerCompositor.h:
     28
    1292019-05-25  Simon Fraser  <simon.fraser@apple.com>
    230
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r245682 r245772  
    10101010    IndirectCompositingReason indirectCompositingReason;
    10111011    if (!willBeComposited && canBeComposited(layer)
    1012         && requiresCompositingForIndirectReason(layer, compositingState.compositingAncestor, currentState.subtreeIsCompositing, anyDescendantHas3DTransform, layerPaintsIntoProvidedBacking, indirectCompositingReason)) {
     1012        && requiresCompositingForIndirectReason(layer, currentState.subtreeIsCompositing, anyDescendantHas3DTransform, layerPaintsIntoProvidedBacking, indirectCompositingReason)) {
    10131013        layer.setIndirectCompositingReason(indirectCompositingReason);
    10141014        layerWillCompositePostDescendants();
     
    29172917}
    29182918
     2919static RenderLayer* enclosingCompositedScrollingLayer(const RenderLayer& layer, const RenderLayer& intermediateLayer, bool& sawIntermediateLayer)
     2920{
     2921    const auto* ancestorLayer = layer.parent();
     2922    while (ancestorLayer) {
     2923        if (ancestorLayer == &intermediateLayer)
     2924            sawIntermediateLayer = true;
     2925
     2926        if (ancestorLayer->hasCompositedScrollableOverflow())
     2927            return const_cast<RenderLayer*>(ancestorLayer);
     2928
     2929        ancestorLayer = ancestorLayer->parent();
     2930    }
     2931
     2932    return nullptr;
     2933}
     2934
     2935static bool isScrolledByOverflowScrollLayer(const RenderLayer& layer, const RenderLayer& overflowScrollLayer)
     2936{
     2937    bool scrolledByOverflowScroll = false;
     2938    traverseAncestorLayers(layer, [&](const RenderLayer& ancestorLayer, bool inContainingBlockChain, bool) {
     2939        if (&ancestorLayer == &overflowScrollLayer) {
     2940            scrolledByOverflowScroll = inContainingBlockChain;
     2941            return AncestorTraversal::Stop;
     2942        }
     2943        return AncestorTraversal::Continue;
     2944    });
     2945    return scrolledByOverflowScroll;
     2946}
     2947
     2948static bool isNonScrolledLayerInsideScrolledCompositedAncestor(const RenderLayer& layer, const RenderLayer& compositedAncestor, const RenderLayer& scrollingAncestor)
     2949{
     2950    bool ancestorMovedByScroller = &compositedAncestor == &scrollingAncestor || isScrolledByOverflowScrollLayer(compositedAncestor, scrollingAncestor);
     2951    bool layerMovedByScroller = isScrolledByOverflowScrollLayer(layer, scrollingAncestor);
     2952
     2953    return ancestorMovedByScroller && !layerMovedByScroller;
     2954}
     2955
    29192956// FIXME: why doesn't this handle the clipping cases?
    2920 bool RenderLayerCompositor::requiresCompositingForIndirectReason(const RenderLayer& layer, const RenderLayer* compositingAncestor, bool hasCompositedDescendants, bool has3DTransformedDescendants, bool paintsIntoProvidedBacking, IndirectCompositingReason& reason) const
     2957bool RenderLayerCompositor::requiresCompositingForIndirectReason(const RenderLayer& layer, bool hasCompositedDescendants, bool has3DTransformedDescendants, bool paintsIntoProvidedBacking, IndirectCompositingReason& reason) const
    29212958{
    29222959    // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
     
    29422979    }
    29432980
    2944     if (!paintsIntoProvidedBacking && renderer.isAbsolutelyPositioned() && compositingAncestor && layer.hasCompositedScrollingAncestor()) {
    2945         if (layerContainingBlockCrossesCoordinatedScrollingBoundary(layer, *compositingAncestor)) {
     2981    // If this layer scrolls independently from the layer that it would paint into, it needs to get composited.
     2982    if (!paintsIntoProvidedBacking && layer.hasCompositedScrollingAncestor()) {
     2983        auto* paintDestination = layer.paintOrderParent();
     2984        bool paintDestinationIsScrolling = false;
     2985        auto* scrollingAncestor = enclosingCompositedScrollingLayer(layer, *paintDestination, paintDestinationIsScrolling);
     2986        if (isNonScrolledLayerInsideScrolledCompositedAncestor(layer, *paintDestination, *scrollingAncestor)) {
    29462987            reason = IndirectCompositingReason::OverflowScrollPositioning;
    29472988            return true;
     
    30443085
    30453086    return false;
    3046 }
    3047 
    3048 static RenderLayer* enclosingCompositedScrollingLayer(const RenderLayer& layer, const RenderLayer& intermediateLayer, bool& sawIntermediateLayer)
    3049 {
    3050     const auto* currLayer = layer.parent();
    3051     while (currLayer) {
    3052         if (currLayer == &intermediateLayer)
    3053             sawIntermediateLayer = true;
    3054 
    3055         if (currLayer->hasCompositedScrollableOverflow())
    3056             return const_cast<RenderLayer*>(currLayer);
    3057 
    3058         currLayer = currLayer->parent();
    3059     }
    3060 
    3061     return nullptr;
    3062 }
    3063 
    3064 static bool isScrolledByOverflowScrollLayer(const RenderLayer& layer, const RenderLayer& overflowScrollLayer)
    3065 {
    3066     bool scrolledByOverflowScroll = false;
    3067     traverseAncestorLayers(layer, [&](const RenderLayer& ancestorLayer, bool inContainingBlockChain, bool) {
    3068         if (&ancestorLayer == &overflowScrollLayer) {
    3069             scrolledByOverflowScroll = inContainingBlockChain;
    3070             return AncestorTraversal::Stop;
    3071         }
    3072         return AncestorTraversal::Continue;
    3073     });
    3074     return scrolledByOverflowScroll;
    3075 }
    3076 
    3077 static bool isNonScrolledLayerInsideScrolledCompositedAncestor(const RenderLayer& layer, const RenderLayer& compositedAncestor, const RenderLayer& scrollingAncestor)
    3078 {
    3079     bool ancestorMovedByScroller = &compositedAncestor == &scrollingAncestor || isScrolledByOverflowScrollLayer(compositedAncestor, scrollingAncestor);
    3080     bool layerMovedByScroller = isScrolledByOverflowScrollLayer(layer, scrollingAncestor);
    3081 
    3082     return ancestorMovedByScroller && !layerMovedByScroller;
    30833087}
    30843088
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.h

    r245602 r245772  
    480480    bool requiresCompositingForOverflowScrolling(const RenderLayer&, RequiresCompositingData&) const;
    481481    bool requiresCompositingForEditableImage(RenderLayerModelObject&) const;
    482     bool requiresCompositingForIndirectReason(const RenderLayer&, const RenderLayer* compositingAncestor, bool hasCompositedDescendants, bool has3DTransformedDescendants, bool paintsIntoProvidedBacking, IndirectCompositingReason&) const;
     482    bool requiresCompositingForIndirectReason(const RenderLayer&, bool hasCompositedDescendants, bool has3DTransformedDescendants, bool paintsIntoProvidedBacking, IndirectCompositingReason&) const;
    483483
    484484    static bool layerContainingBlockCrossesCoordinatedScrollingBoundary(const RenderLayer&, const RenderLayer& compositedAncestor);
Note: See TracChangeset for help on using the changeset viewer.