Chromium Code Reviews| Index: Source/core/rendering/RenderLayerBacking.cpp |
| diff --git a/Source/core/rendering/RenderLayerBacking.cpp b/Source/core/rendering/RenderLayerBacking.cpp |
| index 991d529755e2b4362627f51818ffca24254383f2..3073fc89e053cec14522a41be73f95d11236c3dc 100644 |
| --- a/Source/core/rendering/RenderLayerBacking.cpp |
| +++ b/Source/core/rendering/RenderLayerBacking.cpp |
| @@ -40,6 +40,7 @@ |
| #include "core/page/Settings.h" |
| #include "core/page/animation/AnimationController.h" |
| #include "core/page/scrolling/ScrollingCoordinator.h" |
| +#include "core/platform/chromium/TraceEvent.h" |
| #include "core/platform/graphics/FontCache.h" |
| #include "core/platform/graphics/GraphicsContext.h" |
| #include "core/platform/graphics/GraphicsLayer.h" |
| @@ -171,7 +172,7 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) |
| RenderLayerBacking::~RenderLayerBacking() |
| { |
| - updateClippingLayers(false, false); |
| + updateClippingLayers(false, false, false); |
| updateOverflowControlsLayers(false, false, false); |
| updateForegroundLayer(false); |
| updateBackgroundLayer(false); |
| @@ -418,7 +419,9 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() |
| if (m_owningLayer->needsCompositedScrolling()) |
| needsDescendentsClippingLayer = false; |
| - if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer)) |
| + bool needsAncestorClip = compositor->clippedByAncestor(m_owningLayer); |
| + bool needsScrollClip = compositor->clippedByScrollingAncestor(m_owningLayer); |
| + if (updateClippingLayers(needsAncestorClip, needsDescendentsClippingLayer, needsScrollClip)) |
| layerConfigChanged = true; |
| if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer())) |
| @@ -427,6 +430,13 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration() |
| if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling())) |
| layerConfigChanged = true; |
| + updateScrollParent(); |
| + |
| + // If the clip we want to ignore is established by a stacking sibling, it won't affect us. |
| + // We've already made sure that we don't get a troublesome m_ancestorClippingLayer in this case. |
| + if (!needsAncestorClip) |
| + updateClipParent(); |
| + |
| if (layerConfigChanged) |
| updateInternalHierarchy(); |
| @@ -543,21 +553,65 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() |
| graphicsLayerParentLocation = scrollOrigin - scrollOffset; |
| } |
| + RenderLayer* scrollAncestor = 0; |
| + if (compAncestor && m_ancestorScrollClippingLayer) { |
| + scrollAncestor = m_owningLayer->ancestorScrollingLayer(); |
| + ASSERT(scrollAncestor); |
| + RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip, scrollAncestor); |
| + IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions. |
| + ASSERT(parentClipRect != PaintInfo::infiniteRect()); |
| + |
| + m_ancestorScrollClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation)); |
| + m_ancestorScrollClippingLayer->setSize(parentClipRect.size()); |
| + |
| + // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. |
| + m_ancestorScrollClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta); |
| + |
| + graphicsLayerParentLocation = parentClipRect.location(); |
| + } |
| + |
| if (compAncestor && m_ancestorClippingLayer) { |
| // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this |
| // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects |
| - // for a compositing layer, rootLayer is the layer itself. |
| - RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip); |
| + // for a compositing layer, rootLayer is the layer itself. Also note that if we have an ancestor clipping |
| + // layer, then we have a scroll parent. As such, we consider ourself unclipped with respect to that |
| + // scroll parent -- it's as if we are contained within a large, unclipped scrolling layer that moves |
| + // beneath the clip established by our scroll parent. If we did not do this, we would be completely |
| + // clipped and ignored when we slid outside our scroll parent's clip, preventing us from being |
| + // prepainted, etc. |
| + RenderLayer* clipRoot = compAncestor; |
| + IntPoint scrollToCompAncestorOffset; |
| + IntPoint compToScrollAncestorOffset; |
| + if (m_ancestorScrollClippingLayer) { |
| + ASSERT(m_owningLayer->renderer()->containingBlock()->enclosingLayer() != scrollAncestor); |
| + ASSERT(scrollAncestor && scrollAncestor->hasAncestor(compAncestor)); |
| + clipRoot = scrollAncestor; |
| + scrollAncestor->convertToPixelSnappedLayerCoords(compAncestor, compToScrollAncestorOffset); |
| + scrollToCompAncestorOffset = -compToScrollAncestorOffset; |
|
enne (OOO)
2013/08/22 20:54:30
Is this the equivalent of the "scroll buddy" scrol
|
| + } |
| + |
| + RenderLayer::ClipRectsContext clipRectsContext(clipRoot, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip); |
| IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions. |
| + |
| ASSERT(parentClipRect != PaintInfo::infiniteRect()); |
| - m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation)); |
| + |
| + // If we have an ancestor scroll clipping layer, then our clip rects will already be in our scroll |
| + // parent's space (it would be the clip root), so there is no need to adjust the position of the |
| + // ancestor clip's graphics layer. Otherwise, our clip is with respect to compAncestor, so we must |
| + // adjust here. |
| + IntPoint positionOffset; |
| + if (!m_ancestorScrollClippingLayer) |
| + positionOffset = graphicsLayerParentLocation; |
| + |
| + m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - positionOffset)); |
| m_ancestorClippingLayer->setSize(parentClipRect.size()); |
| - // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. |
| - m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta); |
| + // backgroundRect is relative to clipRoot, so subtract deltaX/deltaY and the scrollToCompAncestorOffset to get back to local coords. |
| + IntPoint clipToLocalOffset = delta + scrollToCompAncestorOffset; |
| + m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - clipToLocalOffset); |
| // The primary layer is then parented in, and positioned relative to this clipping layer. |
| - graphicsLayerParentLocation = parentClipRect.location(); |
| + graphicsLayerParentLocation = parentClipRect.location() + compToScrollAncestorOffset; |
| } |
| FloatSize contentsSize = relativeCompositingBounds.size(); |
| @@ -749,6 +803,9 @@ void RenderLayerBacking::registerScrollingLayers() |
| void RenderLayerBacking::updateInternalHierarchy() |
| { |
| + if (m_ancestorScrollClippingLayer) |
| + m_ancestorScrollClippingLayer->removeAllChildren(); |
| + |
| // m_foregroundLayer has to be inserted in the correct order with child layers, |
| // so it's not inserted here. |
| if (m_ancestorClippingLayer) |
| @@ -759,6 +816,13 @@ void RenderLayerBacking::updateInternalHierarchy() |
| if (m_ancestorClippingLayer) |
| m_ancestorClippingLayer->addChild(m_graphicsLayer.get()); |
| + if (m_ancestorScrollClippingLayer) { |
| + if (m_ancestorClippingLayer) |
| + m_ancestorScrollClippingLayer->addChild(m_ancestorClippingLayer.get()); |
| + else |
| + m_ancestorScrollClippingLayer->addChild(m_graphicsLayer.get()); |
| + } |
| + |
| if (m_childContainmentLayer) { |
| m_childContainmentLayer->removeFromParent(); |
| m_graphicsLayer->addChild(m_childContainmentLayer.get()); |
| @@ -838,8 +902,14 @@ void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer) |
| } |
| // Return true if the layers changed. |
| -bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip) |
| +bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip, bool needsScrollClip) |
| { |
| + TRACE_EVENT_INSTANT2( |
| + "comp-scroll", |
| + "RenderLayerBacking::updateClippingLayers", |
| + "needsAncestorClip", needsAncestorClip, |
| + "needsScrollClip", needsScrollClip); |
| + |
| bool layersChanged = false; |
| if (needsAncestorClip) { |
| @@ -868,6 +938,18 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs |
| layersChanged = true; |
| } |
| + if (needsScrollClip) { |
| + if (!m_ancestorScrollClippingLayer) { |
| + m_ancestorScrollClippingLayer = createGraphicsLayer(CompositingReasonLayerForClip); |
| + m_ancestorScrollClippingLayer->setMasksToBounds(true); |
| + layersChanged = true; |
| + } |
| + } else if (m_ancestorScrollClippingLayer) { |
| + m_ancestorScrollClippingLayer->removeFromParent(); |
| + m_ancestorScrollClippingLayer = nullptr; |
| + layersChanged = true; |
| + } |
| + |
| return layersChanged; |
| } |
| @@ -1090,6 +1172,34 @@ bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers) |
| return layerChanged; |
| } |
| +void RenderLayerBacking::updateScrollParent() |
| +{ |
| + ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); |
| + if (!scrollingCoordinator) |
| + return; |
| + |
| + RenderLayer* scrollParent = 0; |
| + if (m_owningLayer->compositingReasons() & CompositingReasonOverflowScrollingParent) |
| + scrollParent = m_owningLayer->ancestorScrollingLayer(); |
| + |
| + scrollingCoordinator->updateScrollParentForLayer(m_owningLayer, scrollParent); |
| +} |
| + |
| +void RenderLayerBacking::updateClipParent() |
| +{ |
| + ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); |
| + if (!scrollingCoordinator) |
| + return; |
| + |
| + RenderLayer* clipParent = 0; |
| + if (m_owningLayer->compositingReasons() & CompositingReasonOutOfFlowClipping) { |
| + if (RenderObject* containingBlock = m_owningLayer->renderer()->containingBlock()) |
|
enne (OOO)
2013/08/22 20:54:30
Can you help me understand the containing block lo
|
| + clipParent = containingBlock->enclosingLayer()->enclosingCompositingLayer(true); |
| + } |
| + |
| + scrollingCoordinator->updateClipParentForLayer(m_owningLayer, clipParent); |
| +} |
| + |
| GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const |
| { |
| unsigned phase = 0; |
| @@ -1105,6 +1215,9 @@ GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() co |
| phase |= GraphicsLayerPaintCompositedScroll; |
| } |
| + if (m_owningLayer->compositingReasons() & CompositingReasonOverflowScrollingParent) |
|
enne (OOO)
2013/08/22 20:54:30
Use your shiny new unused m_owningLayer->hasScroll
|
| + phase |= GraphicsLayerPaintCompositedScroll; |
| + |
| return static_cast<GraphicsLayerPaintingPhase>(phase); |
| } |
| @@ -1442,6 +1555,9 @@ GraphicsLayer* RenderLayerBacking::parentForSublayers() const |
| GraphicsLayer* RenderLayerBacking::childForSuperlayers() const |
| { |
| + if (m_ancestorScrollClippingLayer) |
| + return m_ancestorScrollClippingLayer.get(); |
| + |
| if (m_ancestorClippingLayer) |
| return m_ancestorClippingLayer.get(); |