Fix painting phases for composited scrolling
https://bugs.webkit.org/show_bug.cgi?id=107618
Reviewed by Simon Fraser.
With composited scrolling, the scrolling contents layer paints the
foreground and the main graphics layer paints the background. This
causes a few problems:
1) If we create a foreground layer, we end up with two layers painting
the foreground phase.
2) Focus rings / outlines paint into the foreground layer, so they end
up moving around with the scrolling contents.
3) Neg z-order descendants paint in the the main graphics layer and
will therefore not scroll.
To deal with 1) we need to stop painting the foreground into both the
foreground and scrolling contents layers. We also need to ensure that
the foreground layer is the right size and has the right offset from
renderer if we're on the composited scrolling path.
To deal with 2) and 3), I have added a new graphics layer painting phase
flag -- GraphicsLayerPaintCompositedScroll -- and applied it to two
layers in the subtree created by RenderLayerBacking. This ultimately
affects the paint phase passed to RenderLayer::paintLayerContents and
allows us to paint the focus rings, outlines and negative z-order
descendants into the proper layers.
Source/WebCore:
Tests: compositing/overflow/composited-scrolling-paint-phases.html
compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html
compositing/overflow/paint-neg-z-order-descendants-into-scrolling-contents-layer.html
* page/Frame.h:
Added a flag for including painting phases in the layer tree dump.
(WebCore::GraphicsLayer::dumpProperties):
Can now dump painting phase information, but only if requested.
* platform/graphics/GraphicsLayerClient.h:
Added a new entry to GraphicsLayerPaintingPhaseFlags for comp-scroll.
(WebCore::RenderLayer::paintLayerContents):
Updated the logic to account for the new comp-scroll-related paint
phase flag.
* rendering/RenderLayer.h:
Added the RenderLayer painting phase counterpart to
GraphicsLayerPaintCompositedScroll.
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
Ensures that the foreground layer is sized correctly for comp-scroll.
(WebCore::RenderLayerBacking::updateScrollingLayers):
If we have a foreground layer, the scrolling contents layer no
longer gets assigned the foreground painting phase.
(WebCore::RenderLayerBacking::paintingPhaseForPrimaryLayer):
If we're comp-scrolling, then the primary layer gets the new phase.
(WebCore::RenderLayerBacking::paintIntoLayer):
Simply translates the new graphics layer painting phase to its
render layer counterpart.
(WebCore::RenderLayerCompositor::layerTreeAsText):
* testing/Internals.cpp:
(WebCore::Internals::layerTreeAsText):
* testing/Internals.h:
* testing/Internals.idl:
The above changes are solely plumbing to allow layout tests to
request that paint phase information be included in the layer tree
dump.
LayoutTests:
* compositing/overflow/composited-scrolling-paint-phases-expected.txt: Added.
* compositing/overflow/composited-scrolling-paint-phases.html: Added.
* platform/mac/compositing/overflom/composited-scrolling-paint-phases-expected.txt: Added.
This is a text-based test that checks that the graphics layer
painting phases are correct with composited scrolling + foreground
layers.
* compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html: Added.
* compositing/overflow/paint-neg-z-order-descendants-into-scrolling-contents-layer.html: Added.
These tests cover cases 2) and 3) above.
* platform/chromium/TestExpectations:
* platform/mac-wk2/TestExpectations:
* platform/mac/TestExpectations:
These have been updated to reflect the missing baselines.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@145067 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index b364a06..c253a59 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -813,6 +813,13 @@
m_scrollingContentsLayer->setSize(scrollSize);
// FIXME: The paint offset and the scroll offset should really be separate concepts.
m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
+
+ if (m_foregroundLayer) {
+ if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
+ m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
+ m_foregroundLayer->setNeedsDisplay();
+ m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
+ }
}
// If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
@@ -1211,7 +1218,10 @@
// Inner layer which renders the content that scrolls.
m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
m_scrollingContentsLayer->setDrawsContent(true);
- m_scrollingContentsLayer->setPaintingPhase(GraphicsLayerPaintForeground | GraphicsLayerPaintOverflowContents);
+ GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
+ if (!m_foregroundLayer)
+ paintPhase |= GraphicsLayerPaintForeground;
+ m_scrollingContentsLayer->setPaintingPhase(paintPhase);
m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
layerChanged = true;
@@ -1281,8 +1291,10 @@
if (!m_maskLayer)
phase |= GraphicsLayerPaintMask;
- if (m_scrollingContentsLayer)
+ if (m_scrollingContentsLayer) {
phase &= ~GraphicsLayerPaintForeground;
+ phase |= GraphicsLayerPaintCompositedScroll;
+ }
return static_cast<GraphicsLayerPaintingPhase>(phase);
}
@@ -1813,6 +1825,8 @@
paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
if (paintingPhase & GraphicsLayerPaintOverflowContents)
paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
+ if (paintingPhase & GraphicsLayerPaintCompositedScroll)
+ paintFlags |= RenderLayer::PaintLayerPaintingCompositingScrollingPhase;
if (graphicsLayer == m_backgroundLayer)
paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.