- Revision
- 246018
- Author
- [email protected]
- Date
- 2019-06-01 19:55:57 -0700 (Sat, 01 Jun 2019)
Log 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.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (246017 => 246018)
--- trunk/LayoutTests/ChangeLog 2019-06-01 21:40:04 UTC (rev 246017)
+++ trunk/LayoutTests/ChangeLog 2019-06-02 02:55:57 UTC (rev 246018)
@@ -1,5 +1,20 @@
2019-06-01 Simon Fraser <[email protected]>
+ 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.
+
+ * 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.
+
+2019-06-01 Simon Fraser <[email protected]>
+
Non-composited negative z-order children should not trigger creation of a foreground layer
https://bugs.webkit.org/show_bug.cgi?id=198455
Added: trunk/LayoutTests/compositing/geometry/scroller-with-clipping-and-foreground-layers-expected.html (0 => 246018)
--- trunk/LayoutTests/compositing/geometry/scroller-with-clipping-and-foreground-layers-expected.html (rev 0)
+++ trunk/LayoutTests/compositing/geometry/scroller-with-clipping-and-foreground-layers-expected.html 2019-06-02 02:55:57 UTC (rev 246018)
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ body {
+ margin: 0;
+ }
+
+ #scroller {
+ position: relative;
+ z-index: 0;
+ width: 400px;
+ height: 400px;
+ margin: 20px;
+ overflow: scroll;
+ padding: 20px;
+ border: 30px solid orange;
+ box-sizing: border-box;
+ border-radius: 80px 200px;
+ background-color: silver;
+ }
+
+ .negative {
+ position: absolute;
+ top: 20px;
+ left: 30px;
+ z-index: 1;
+ padding: 20px;
+ background-color: gray;
+ transform: translateZ(0);
+ }
+
+ .contents {
+ height: 1000px;
+ background: linear-gradient(green, blue);
+ }
+
+ .masker {
+ position: absolute;
+ top: 49px;
+ left: 49px;
+ width: 342px;
+ height: 342px;
+ box-sizing: border-box;
+ border: 3px solid gray;
+ border-radius: 49px 170px;
+ }
+ </style>
+ <script>
+ window.addEventListener('load', () => {
+ scroller.scrollTo(0, 250);
+ }, false);
+ </script>
+</head>
+<body>
+ <div id="scroller">
+ <div class="negative"></div>
+ <div class="contents"></div>
+ </div>
+ <div class="masker"></div>
+</body>
+</html>
+
Added: trunk/LayoutTests/compositing/geometry/scroller-with-clipping-and-foreground-layers.html (0 => 246018)
--- trunk/LayoutTests/compositing/geometry/scroller-with-clipping-and-foreground-layers.html (rev 0)
+++ trunk/LayoutTests/compositing/geometry/scroller-with-clipping-and-foreground-layers.html 2019-06-02 02:55:57 UTC (rev 246018)
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ body {
+ margin: 0;
+ }
+
+ #scroller {
+ position: relative;
+ z-index: 0;
+ width: 400px;
+ height: 400px;
+ margin: 20px;
+ overflow: scroll;
+ padding: 20px;
+ border: 30px solid orange;
+ box-sizing: border-box;
+ border-radius: 80px 200px;
+ background-color: silver;
+ }
+
+ .negative {
+ position: absolute;
+ top: 20px;
+ left: 30px;
+ z-index: -1;
+ padding: 20px;
+ background-color: gray;
+ transform: translateZ(0);
+ }
+
+ .contents {
+ height: 1000px;
+ background: linear-gradient(green, blue);
+ }
+
+ .masker {
+ position: absolute;
+ top: 49px;
+ left: 49px;
+ width: 342px;
+ height: 342px;
+ box-sizing: border-box;
+ border: 3px solid gray;
+ border-radius: 49px 170px;
+ }
+ </style>
+ <script>
+ window.addEventListener('load', () => {
+ scroller.scrollTo(0, 250);
+ }, false);
+ </script>
+</head>
+<body>
+ <div id="scroller">
+ <div class="negative"></div>
+ <div class="contents"></div>
+ </div>
+ <div class="masker"></div>
+</body>
+</html>
+
Added: trunk/LayoutTests/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt (0 => 246018)
--- trunk/LayoutTests/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt (rev 0)
+++ trunk/LayoutTests/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt 2019-06-02 02:55:57 UTC (rev 246018)
@@ -0,0 +1,54 @@
+Scrolled contents
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (children 1
+ (GraphicsLayer
+ (position 8.00 8.00)
+ (bounds 322.00 322.00)
+ (drawsContent 1)
+ (repaint rects
+ (rect 306.00 1.00 15.00 104.00)
+ (rect 306.00 60.00 15.00 91.00)
+ (rect 306.00 105.00 15.00 201.00)
+ )
+ (children 1
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=1)
+ (position 1.00 1.00)
+ (bounds 305.00 305.00)
+ (children 1
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=1)
+ (scrollOffset (0,200))
+ (position 0.00 -200.00)
+ (anchor 0.00 0.00)
+ (bounds 305.00 1020.00)
+ (drawsContent 1)
+ (children 2
+ (GraphicsLayer
+ (position 30.00 50.00)
+ (bounds 102.00 102.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ )
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=-199)
+ (bounds 305.00 1020.00)
+ (drawsContent 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/compositing/repaint/scroller-with-foreground-layer-repaints.html (0 => 246018)
--- trunk/LayoutTests/compositing/repaint/scroller-with-foreground-layer-repaints.html (rev 0)
+++ trunk/LayoutTests/compositing/repaint/scroller-with-foreground-layer-repaints.html 2019-06-02 02:55:57 UTC (rev 246018)
@@ -0,0 +1,57 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:AsyncOverflowScrollingEnabled=true ] --><html>
+<head>
+ <style>
+ #scroller {
+ position: relative;
+ z-index: 0;
+ width: 300px;
+ height: 300px;
+ border: 1px solid black;
+ overflow: scroll;
+ padding: 10px;
+ }
+
+ .contents {
+ height: 1000px;
+ }
+
+ .negative {
+ position: absolute;
+ z-index: -1;
+ top: 50px;
+ left: 30px;
+ width: 100px;
+ height: 100px;
+ background-color: blue;
+ border: 1px solid green;
+ transform: translateZ(0);
+ }
+ </style>
+ <script>
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ window.addEventListener('load', () => {
+ setTimeout(() => {
+ if (window.internals)
+ internals.startTrackingRepaints();
+
+ scroller.scrollTo(0, 200);
+ document.getElementById('layers').textContent = internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_REPAINT_RECTS);
+
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }, 0);
+ }, false);
+ </script>
+</head>
+<body>
+ <div id="scroller">
+ <div class="negative"></div>
+ <div class="contents">Scrolled contents</div>
+ </div>
+<pre id="layers"></pre>
+</body>
+</html>
Added: trunk/LayoutTests/platform/ios-wk2/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt (0 => 246018)
--- trunk/LayoutTests/platform/ios-wk2/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/ios-wk2/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt 2019-06-02 02:55:57 UTC (rev 246018)
@@ -0,0 +1,49 @@
+Scrolled contents
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (children 1
+ (GraphicsLayer
+ (position 8.00 8.00)
+ (bounds 322.00 322.00)
+ (drawsContent 1)
+ (children 1
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=1)
+ (position 1.00 1.00)
+ (bounds origin 0.00 200.00)
+ (bounds 320.00 320.00)
+ (children 1
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=1)
+ (scrollOffset (0,200))
+ (anchor 0.00 0.00)
+ (bounds 320.00 1020.00)
+ (drawsContent 1)
+ (children 2
+ (GraphicsLayer
+ (position 30.00 50.00)
+ (bounds 102.00 102.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ )
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=-199)
+ (bounds 320.00 1020.00)
+ (drawsContent 1)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
Added: trunk/LayoutTests/platform/mac-wk1/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt (0 => 246018)
--- trunk/LayoutTests/platform/mac-wk1/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/mac-wk1/compositing/repaint/scroller-with-foreground-layer-repaints-expected.txt 2019-06-02 02:55:57 UTC (rev 246018)
@@ -0,0 +1,48 @@
+Scrolled contents
+(GraphicsLayer
+ (anchor 0.00 0.00)
+ (bounds 800.00 600.00)
+ (children 1
+ (GraphicsLayer
+ (bounds 800.00 600.00)
+ (contentsOpaque 1)
+ (children 1
+ (GraphicsLayer
+ (position 8.00 8.00)
+ (bounds 322.00 322.00)
+ (drawsContent 1)
+ (repaint rects
+ (rect 0.00 0.00 322.00 322.00)
+ (rect 306.00 1.00 15.00 104.00)
+ (rect 306.00 60.00 15.00 91.00)
+ (rect 306.00 105.00 15.00 201.00)
+ )
+ (children 1
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=1)
+ (position 1.00 1.00)
+ (bounds 305.00 305.00)
+ (children 2
+ (GraphicsLayer
+ (position 30.00 -150.00)
+ (bounds 102.00 102.00)
+ (contentsOpaque 1)
+ (drawsContent 1)
+ )
+ (GraphicsLayer
+ (offsetFromRenderer width=1 height=1)
+ (bounds 305.00 305.00)
+ (drawsContent 1)
+ (repaint rects
+ (rect 0.00 0.00 305.00 305.00)
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
Modified: trunk/Source/WebCore/ChangeLog (246017 => 246018)
--- trunk/Source/WebCore/ChangeLog 2019-06-01 21:40:04 UTC (rev 246017)
+++ trunk/Source/WebCore/ChangeLog 2019-06-02 02:55:57 UTC (rev 246018)
@@ -1,5 +1,31 @@
2019-06-01 Simon Fraser <[email protected]>
+ 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.
+
+ 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):
+
+2019-06-01 Simon Fraser <[email protected]>
+
Non-composited negative z-order children should not trigger creation of a foreground layer
https://bugs.webkit.org/show_bug.cgi?id=198455
Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (246017 => 246018)
--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2019-06-01 21:40:04 UTC (rev 246017)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp 2019-06-02 02:55:57 UTC (rev 246018)
@@ -2598,18 +2598,18 @@
if (!shapeMaskLayer) {
shapeMaskLayer = createPlatformCALayer(PlatformCALayer::LayerTypeShapeLayer, this);
- shapeMaskLayer->setAnchorPoint(FloatPoint3D());
+ shapeMaskLayer->setAnchorPoint({ });
shapeMaskLayer->setName("shape mask");
}
- shapeMaskLayer->setPosition(FloatPoint());
- shapeMaskLayer->setBounds(clippingLayer.bounds());
+ shapeMaskLayer->setPosition(roundedRect.rect().location() - offsetFromRenderer());
+ FloatRect shapeBounds({ }, roundedRect.rect().size());
+ shapeMaskLayer->setBounds(shapeBounds);
+ FloatRoundedRect offsetRoundedRect(shapeBounds, roundedRect.radii());
+ shapeMaskLayer->setShapeRoundedRect(offsetRoundedRect);
clippingLayer.setCornerRadius(0);
clippingLayer.setMask(shapeMaskLayer.get());
-
- FloatRoundedRect offsetRoundedRect(clippingLayer.bounds(), roundedRect.radii());
- shapeMaskLayer->setShapeRoundedRect(offsetRoundedRect);
}
void GraphicsLayerCA::updateContentsRects()
Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (246017 => 246018)
--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2019-06-01 21:40:04 UTC (rev 246017)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp 2019-06-02 02:55:57 UTC (rev 246018)
@@ -1204,39 +1204,6 @@
m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
}
- if (m_foregroundLayer) {
- FloatPoint foregroundPosition;
- FloatSize foregroundSize = primaryGraphicsLayerRect.size();
- FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
- if (hasClippingLayer()) {
- // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
- // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
- foregroundSize = FloatSize(clippingBox.size());
- foregroundOffset = toFloatSize(clippingBox.location());
- }
-
- m_foregroundLayer->setPosition(foregroundPosition);
- m_foregroundLayer->setSize(foregroundSize);
- m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
- }
-
- if (m_backgroundLayer) {
- FloatPoint backgroundPosition;
- FloatSize backgroundSize = primaryGraphicsLayerRect.size();
- if (backgroundLayerPaintsFixedRootBackground()) {
- const FrameView& frameView = renderer().view().frameView();
- backgroundPosition = frameView.scrollPositionForFixedPosition();
- backgroundSize = frameView.layoutSize();
- } else {
- auto boundingBox = renderer().objectBoundingBox();
- backgroundPosition = boundingBox.location();
- backgroundSize = boundingBox.size();
- }
- m_backgroundLayer->setPosition(backgroundPosition);
- m_backgroundLayer->setSize(backgroundSize);
- m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
- }
-
if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
reflectionBacking->updateGeometry();
@@ -1282,15 +1249,50 @@
m_scrolledContentsLayer->setSize(scrollSize);
m_scrolledContentsLayer->setScrollOffset(scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
m_scrolledContentsLayer->setOffsetFromRenderer(toLayoutSize(paddingBoxIncludingScrollbar.location()), GraphicsLayer::DontSetNeedsDisplay);
-
- if (m_foregroundLayer) {
- m_foregroundLayer->setSize(m_scrolledContentsLayer->size());
- m_foregroundLayer->setOffsetFromRenderer(m_scrolledContentsLayer->offsetFromRenderer() - toLayoutSize(m_scrolledContentsLayer->scrollOffset()));
- }
adjustTiledBackingCoverage();
}
+ if (m_foregroundLayer) {
+ FloatSize foregroundSize;
+ FloatSize foregroundOffset;
+ GraphicsLayer::ShouldSetNeedsDisplay needsDisplayOnOffsetChange = GraphicsLayer::SetNeedsDisplay;
+ if (m_scrolledContentsLayer) {
+ foregroundSize = m_scrolledContentsLayer->size();
+ foregroundOffset = m_scrolledContentsLayer->offsetFromRenderer() - toLayoutSize(m_scrolledContentsLayer->scrollOffset());
+ needsDisplayOnOffsetChange = GraphicsLayer::DontSetNeedsDisplay;
+ } else if (hasClippingLayer()) {
+ // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
+ // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
+ foregroundSize = FloatSize(clippingBox.size());
+ foregroundOffset = toFloatSize(clippingBox.location());
+ } else {
+ foregroundSize = primaryGraphicsLayerRect.size();
+ foregroundOffset = m_graphicsLayer->offsetFromRenderer();
+ }
+
+ m_foregroundLayer->setPosition({ });
+ m_foregroundLayer->setSize(foregroundSize);
+ m_foregroundLayer->setOffsetFromRenderer(foregroundOffset, needsDisplayOnOffsetChange);
+ }
+
+ if (m_backgroundLayer) {
+ FloatPoint backgroundPosition;
+ FloatSize backgroundSize = primaryGraphicsLayerRect.size();
+ if (backgroundLayerPaintsFixedRootBackground()) {
+ const FrameView& frameView = renderer().view().frameView();
+ backgroundPosition = frameView.scrollPositionForFixedPosition();
+ backgroundSize = frameView.layoutSize();
+ } else {
+ auto boundingBox = renderer().objectBoundingBox();
+ backgroundPosition = boundingBox.location();
+ backgroundSize = boundingBox.size();
+ }
+ m_backgroundLayer->setPosition(backgroundPosition);
+ m_backgroundLayer->setSize(backgroundSize);
+ m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+ }
+
// If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
LayoutRect ancestorCompositedBounds = compositedAncestor ? compositedAncestor->backing()->compositedBounds() : LayoutRect();
setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compositedAncestor,