⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 246018 in webkit


Ignore:
Timestamp:
Jun 1, 2019, 7:55:57 PM (7 years ago)
Author:
Simon Fraser
Message:

Async overflow scroll on iOS paints slowly if it has a negative z-index child
https://bugs.webkit.org/show_bug.cgi?id=196508
rdar://problem/49532709

Reviewed by Dean Jackson.
Source/WebCore:

If a RenderLayerBacking had a foreground layer and a scrolled contents layer, every geometry
update would change the size and offsetFromRenderer of the foreground layer between two
states, triggering repaint.

Fix by updating the fore- and background-layers last (nothing elese has dependencies
on their geometry), and using GraphicsLayer::DontSetNeedsDisplay as we do for the
scrolled contents layer.

The test also revealed a bug where the shapeMaskLayer would get incorrect geometry when scrollbars
were visible, because it would be squished by setting the wrong bounds, so fix that.

Test: compositing/repaint/scroller-with-foreground-layer-repaints.html

  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::updateClippingStrategy):

  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateGeometry):

LayoutTests:

  • compositing/geometry/scroller-with-clipping-and-foreground-layers-expected.html: Added.
  • compositing/geometry/scroller-with-clipping-and-foreground-layers.html: Added.
  • compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt: Added.
  • compositing/repaint/scroller-with-foreground-layer-repaints.html: Added.
  • platform/ios-wk2/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt: Added.
  • platform/mac-wk1/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt: Added.
Location:
trunk
Files:
6 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r246017 r246018  
     12019-06-01  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Async overflow scroll on iOS paints slowly if it has a negative z-index child
     4        https://bugs.webkit.org/show_bug.cgi?id=196508
     5        rdar://problem/49532709
     6
     7        Reviewed by Dean Jackson.
     8
     9        * compositing/geometry/scroller-with-clipping-and-foreground-layers-expected.html: Added.
     10        * compositing/geometry/scroller-with-clipping-and-foreground-layers.html: Added.
     11        * compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt: Added.
     12        * compositing/repaint/scroller-with-foreground-layer-repaints.html: Added.
     13        * platform/ios-wk2/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt: Added.
     14        * platform/mac-wk1/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt: Added.
     15
    1162019-06-01  Simon Fraser  <simon.fraser@apple.com>
    217
  • trunk/Source/WebCore/ChangeLog

    r246017 r246018  
     12019-06-01  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Async overflow scroll on iOS paints slowly if it has a negative z-index child
     4        https://bugs.webkit.org/show_bug.cgi?id=196508
     5        rdar://problem/49532709
     6
     7        Reviewed by Dean Jackson.
     8       
     9        If a RenderLayerBacking had a foreground layer and a scrolled contents layer, every geometry
     10        update would change the size and offsetFromRenderer of the foreground layer between two
     11        states, triggering repaint.
     12
     13        Fix by updating the fore- and background-layers last (nothing elese has dependencies
     14        on their geometry), and using GraphicsLayer::DontSetNeedsDisplay as we do for the
     15        scrolled contents layer.
     16       
     17        The test also revealed a bug where the shapeMaskLayer would get incorrect geometry when scrollbars
     18        were visible, because it would be squished by setting the wrong bounds, so fix that.
     19
     20        Test: compositing/repaint/scroller-with-foreground-layer-repaints.html
     21
     22        * platform/graphics/ca/GraphicsLayerCA.cpp:
     23        (WebCore::GraphicsLayerCA::updateClippingStrategy):
     24        * rendering/RenderLayerBacking.cpp:
     25        (WebCore::RenderLayerBacking::updateGeometry):
     26
    1272019-06-01  Simon Fraser  <simon.fraser@apple.com>
    228
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r245974 r246018  
    25992599    if (!shapeMaskLayer) {
    26002600        shapeMaskLayer = createPlatformCALayer(PlatformCALayer::LayerTypeShapeLayer, this);
    2601         shapeMaskLayer->setAnchorPoint(FloatPoint3D());
     2601        shapeMaskLayer->setAnchorPoint({ });
    26022602        shapeMaskLayer->setName("shape mask");
    26032603    }
    26042604   
    2605     shapeMaskLayer->setPosition(FloatPoint());
    2606     shapeMaskLayer->setBounds(clippingLayer.bounds());
     2605    shapeMaskLayer->setPosition(roundedRect.rect().location() - offsetFromRenderer());
     2606    FloatRect shapeBounds({ }, roundedRect.rect().size());
     2607    shapeMaskLayer->setBounds(shapeBounds);
     2608    FloatRoundedRect offsetRoundedRect(shapeBounds, roundedRect.radii());
     2609    shapeMaskLayer->setShapeRoundedRect(offsetRoundedRect);
    26072610
    26082611    clippingLayer.setCornerRadius(0);
    26092612    clippingLayer.setMask(shapeMaskLayer.get());
    2610    
    2611     FloatRoundedRect offsetRoundedRect(clippingLayer.bounds(), roundedRect.radii());
    2612     shapeMaskLayer->setShapeRoundedRect(offsetRoundedRect);
    26132613}
    26142614
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r245977 r246018  
    12051205    }
    12061206
     1207    if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
     1208        auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
     1209        reflectionBacking->updateGeometry();
     1210       
     1211        // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
     1212        // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
     1213        FloatRect layerBounds = this->compositedBounds();
     1214        FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
     1215        reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
     1216    }
     1217
     1218    if (m_scrollContainerLayer) {
     1219        ASSERT(m_scrolledContentsLayer);
     1220        auto& renderBox = downcast<RenderBox>(renderer());
     1221        LayoutRect paddingBoxIncludingScrollbar = renderBox.paddingBoxRectIncludingScrollbar();
     1222        LayoutRect parentLayerBounds = clippingLayer() ? clippingBox : compositedBounds();
     1223
     1224        // FIXME: need to do some pixel snapping here.
     1225        m_scrollContainerLayer->setPosition(FloatPoint(paddingBoxIncludingScrollbar.location() - parentLayerBounds.location()));
     1226        m_scrollContainerLayer->setSize(roundedIntSize(LayoutSize(renderBox.paddingBoxWidth(), renderBox.paddingBoxHeight())));
     1227
     1228        ScrollOffset scrollOffset = m_owningLayer.scrollOffset();
     1229        updateScrollOffset(scrollOffset);
     1230#if PLATFORM(IOS_FAMILY)
     1231        m_scrolledContentsLayer->setPosition({ }); // FIXME: necessary?
     1232#endif
     1233
     1234        FloatSize oldScrollingLayerOffset = m_scrollContainerLayer->offsetFromRenderer();
     1235        m_scrollContainerLayer->setOffsetFromRenderer(toFloatSize(paddingBoxIncludingScrollbar.location()));
     1236
     1237        if (m_childClippingMaskLayer) {
     1238            m_childClippingMaskLayer->setPosition(m_scrollContainerLayer->position());
     1239            m_childClippingMaskLayer->setSize(m_scrollContainerLayer->size());
     1240            m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBoxIncludingScrollbar.location()));
     1241        }
     1242
     1243        bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollContainerLayer->offsetFromRenderer();
     1244
     1245        IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
     1246        if (scrollSize != m_scrolledContentsLayer->size() || paddingBoxOffsetChanged)
     1247            m_scrolledContentsLayer->setNeedsDisplay();
     1248
     1249        m_scrolledContentsLayer->setSize(scrollSize);
     1250        m_scrolledContentsLayer->setScrollOffset(scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
     1251        m_scrolledContentsLayer->setOffsetFromRenderer(toLayoutSize(paddingBoxIncludingScrollbar.location()), GraphicsLayer::DontSetNeedsDisplay);
     1252       
     1253        adjustTiledBackingCoverage();
     1254    }
     1255
    12071256    if (m_foregroundLayer) {
    1208         FloatPoint foregroundPosition;
    1209         FloatSize foregroundSize = primaryGraphicsLayerRect.size();
    1210         FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
    1211         if (hasClippingLayer()) {
     1257        FloatSize foregroundSize;
     1258        FloatSize foregroundOffset;
     1259        GraphicsLayer::ShouldSetNeedsDisplay needsDisplayOnOffsetChange = GraphicsLayer::SetNeedsDisplay;
     1260        if (m_scrolledContentsLayer) {
     1261            foregroundSize = m_scrolledContentsLayer->size();
     1262            foregroundOffset = m_scrolledContentsLayer->offsetFromRenderer() - toLayoutSize(m_scrolledContentsLayer->scrollOffset());
     1263            needsDisplayOnOffsetChange = GraphicsLayer::DontSetNeedsDisplay;
     1264        } else if (hasClippingLayer()) {
    12121265            // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
    12131266            // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
    12141267            foregroundSize = FloatSize(clippingBox.size());
    12151268            foregroundOffset = toFloatSize(clippingBox.location());
    1216         }
    1217 
    1218         m_foregroundLayer->setPosition(foregroundPosition);
     1269        } else {
     1270            foregroundSize = primaryGraphicsLayerRect.size();
     1271            foregroundOffset = m_graphicsLayer->offsetFromRenderer();
     1272        }
     1273
     1274        m_foregroundLayer->setPosition({ });
    12191275        m_foregroundLayer->setSize(foregroundSize);
    1220         m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
     1276        m_foregroundLayer->setOffsetFromRenderer(foregroundOffset, needsDisplayOnOffsetChange);
    12211277    }
    12221278
     
    12361292        m_backgroundLayer->setSize(backgroundSize);
    12371293        m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
    1238     }
    1239 
    1240     if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
    1241         auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
    1242         reflectionBacking->updateGeometry();
    1243        
    1244         // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
    1245         // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
    1246         FloatRect layerBounds = this->compositedBounds();
    1247         FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
    1248         reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
    1249     }
    1250 
    1251     if (m_scrollContainerLayer) {
    1252         ASSERT(m_scrolledContentsLayer);
    1253         auto& renderBox = downcast<RenderBox>(renderer());
    1254         LayoutRect paddingBoxIncludingScrollbar = renderBox.paddingBoxRectIncludingScrollbar();
    1255         LayoutRect parentLayerBounds = clippingLayer() ? clippingBox : compositedBounds();
    1256 
    1257         // FIXME: need to do some pixel snapping here.
    1258         m_scrollContainerLayer->setPosition(FloatPoint(paddingBoxIncludingScrollbar.location() - parentLayerBounds.location()));
    1259         m_scrollContainerLayer->setSize(roundedIntSize(LayoutSize(renderBox.paddingBoxWidth(), renderBox.paddingBoxHeight())));
    1260 
    1261         ScrollOffset scrollOffset = m_owningLayer.scrollOffset();
    1262         updateScrollOffset(scrollOffset);
    1263 #if PLATFORM(IOS_FAMILY)
    1264         m_scrolledContentsLayer->setPosition({ }); // FIXME: necessary?
    1265 #endif
    1266 
    1267         FloatSize oldScrollingLayerOffset = m_scrollContainerLayer->offsetFromRenderer();
    1268         m_scrollContainerLayer->setOffsetFromRenderer(toFloatSize(paddingBoxIncludingScrollbar.location()));
    1269 
    1270         if (m_childClippingMaskLayer) {
    1271             m_childClippingMaskLayer->setPosition(m_scrollContainerLayer->position());
    1272             m_childClippingMaskLayer->setSize(m_scrollContainerLayer->size());
    1273             m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBoxIncludingScrollbar.location()));
    1274         }
    1275 
    1276         bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollContainerLayer->offsetFromRenderer();
    1277 
    1278         IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
    1279         if (scrollSize != m_scrolledContentsLayer->size() || paddingBoxOffsetChanged)
    1280             m_scrolledContentsLayer->setNeedsDisplay();
    1281 
    1282         m_scrolledContentsLayer->setSize(scrollSize);
    1283         m_scrolledContentsLayer->setScrollOffset(scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
    1284         m_scrolledContentsLayer->setOffsetFromRenderer(toLayoutSize(paddingBoxIncludingScrollbar.location()), GraphicsLayer::DontSetNeedsDisplay);
    1285 
    1286         if (m_foregroundLayer) {
    1287             m_foregroundLayer->setSize(m_scrolledContentsLayer->size());
    1288             m_foregroundLayer->setOffsetFromRenderer(m_scrolledContentsLayer->offsetFromRenderer() - toLayoutSize(m_scrolledContentsLayer->scrollOffset()));
    1289         }
    1290        
    1291         adjustTiledBackingCoverage();
    12921294    }
    12931295
Note: See TracChangeset for help on using the changeset viewer.