Fix Border-radius clipping issue on a composited descendants
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Jan 2015 10:22:16 +0000 (10:22 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Jan 2015 10:22:16 +0000 (10:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=138551

Patch by Byungseon Shin <sun.shin@lge.com> on 2015-01-07
Reviewed by Simon Fraser.

Fix clipping compositing descendants of an accelerated layer having
border radius and clip overflow issue by using layer corner-radius
or a CAShapeLayer mask on Mac, and setting up a separate mask layer
on the childContainmentLayer on other platforms.

This patch is extracted from following Blink revisions:
<http://src.chromium.org/viewvc/blink?view=revision&revision=162463>
<http://src.chromium.org/viewvc/blink?view=revision&revision=158258>
by <rosca@adobe.com>

Clip accelerated descendants of an accelerated layer having border radius and clip overflow.
Large canvas does not honor containing div's border radius.

and <http://src.chromium.org/viewvc/blink?view=revision&revision=160578>
by <junov@chromium.org>

Fix for CSS clip-path with accelerated 2D canvas.

* WebCore.exp.in:
* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::dumpProperties):
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::applyClippingBorder):
(WebCore::GraphicsLayer::clearClippingBorder):
(WebCore::GraphicsLayer::needsClippingMaskLayer):
* platform/graphics/GraphicsLayerClient.h:
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::applyClippingBorder):
(WebCore::GraphicsLayerCA::clearClippingBorder):
* platform/graphics/ca/GraphicsLayerCA.h:
* rendering/PaintPhase.h:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintObject):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::paintClippingMask):
* rendering/RenderBox.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::paintChildClippingMaskForFragments):
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::~RenderLayerBacking):
(WebCore::RenderLayerBacking::destroyGraphicsLayers):
(WebCore::RenderLayerBacking::updateConfiguration):
(WebCore::RenderLayerBacking::updateGeometry):
(WebCore::RenderLayerBacking::updateChildClippingStrategy):
(WebCore::RenderLayerBacking::setContentsNeedDisplay):
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
(WebCore::RenderLayerBacking::paintIntoLayer):
(WebCore::RenderLayerBacking::paintContents):
(WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
* rendering/RenderLayerBacking.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@178029 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/platform/graphics/GraphicsLayer.cpp
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/GraphicsLayerClient.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/rendering/PaintPhase.h
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderLayerBacking.h

index 4e2350d..d1b7654 100644 (file)
@@ -1,3 +1,63 @@
+2015-01-07  Byungseon Shin  <sun.shin@lge.com>
+
+        Fix Border-radius clipping issue on a composited descendants
+        https://bugs.webkit.org/show_bug.cgi?id=138551
+
+        Reviewed by Simon Fraser.
+
+        Fix clipping compositing descendants of an accelerated layer having
+        border radius and clip overflow issue by using layer corner-radius
+        or a CAShapeLayer mask on Mac, and setting up a separate mask layer
+        on the childContainmentLayer on other platforms.
+
+        This patch is extracted from following Blink revisions:
+        <http://src.chromium.org/viewvc/blink?view=revision&revision=162463>
+        <http://src.chromium.org/viewvc/blink?view=revision&revision=158258>
+        by <rosca@adobe.com>
+
+        Clip accelerated descendants of an accelerated layer having border radius and clip overflow.
+        Large canvas does not honor containing div's border radius.
+
+        and <http://src.chromium.org/viewvc/blink?view=revision&revision=160578>
+        by <junov@chromium.org>
+
+        Fix for CSS clip-path with accelerated 2D canvas.
+
+        * WebCore.exp.in:
+        * platform/graphics/GraphicsLayer.cpp:
+        (WebCore::GraphicsLayer::dumpProperties):
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::applyClippingBorder):
+        (WebCore::GraphicsLayer::clearClippingBorder):
+        (WebCore::GraphicsLayer::needsClippingMaskLayer):
+        * platform/graphics/GraphicsLayerClient.h:
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::applyClippingBorder):
+        (WebCore::GraphicsLayerCA::clearClippingBorder):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * rendering/PaintPhase.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paintObject):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::paintClippingMask):
+        * rendering/RenderBox.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paintLayerContents):
+        (WebCore::RenderLayer::paintChildClippingMaskForFragments):
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::~RenderLayerBacking):
+        (WebCore::RenderLayerBacking::destroyGraphicsLayers):
+        (WebCore::RenderLayerBacking::updateConfiguration):
+        (WebCore::RenderLayerBacking::updateGeometry):
+        (WebCore::RenderLayerBacking::updateChildClippingStrategy):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplay):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
+        (WebCore::RenderLayerBacking::paintIntoLayer):
+        (WebCore::RenderLayerBacking::paintContents):
+        (WebCore::RenderLayerBacking::backingStoreMemoryEstimate):
+        * rendering/RenderLayerBacking.h:
+
 2015-01-06  Antti Koivisto  <antti@apple.com>
 
         Use HashMap instead of CFDictionary for composite font reference map
index 1afad67..44d0c9c 100644 (file)
@@ -589,6 +589,8 @@ __ZN7WebCore15GraphicsLayerCA18setContentsVisibleEb
 __ZN7WebCore15GraphicsLayerCA18setOpacityInternalEf
 __ZN7WebCore15GraphicsLayerCA18setReplicatedLayerEPNS_13GraphicsLayerE
 __ZN7WebCore15GraphicsLayerCA18setShowDebugBorderEb
+__ZN7WebCore15GraphicsLayerCA19applyClippingBorderERKNS_16FloatRoundedRectE
+__ZN7WebCore15GraphicsLayerCA19clearClippingBorderEv
 __ZN7WebCore15GraphicsLayerCA19setCustomAppearanceENS_13GraphicsLayer16CustomAppearanceE
 __ZN7WebCore15GraphicsLayerCA20setChildrenTransformERKNS_20TransformationMatrixE
 __ZN7WebCore15GraphicsLayerCA20setReplicatedByLayerEPNS_13GraphicsLayerE
index 62d2516..d6288b7 100644 (file)
@@ -761,6 +761,10 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBe
             writeIndent(ts, indent + 2);
             ts << "GraphicsLayerPaintMask\n";
         }
+        if (paintingPhase() & GraphicsLayerPaintChildClippingMask) {
+            writeIndent(ts, indent + 2);
+            ts << "GraphicsLayerPaintChildClippingMask\n";
+        }
         if (paintingPhase() & GraphicsLayerPaintOverflowContents) {
             writeIndent(ts, indent + 2);
             ts << "GraphicsLayerPaintOverflowContents\n";
index 7be6a9f..c4d22b6 100644 (file)
@@ -368,6 +368,9 @@ public:
     FloatRoundedRect contentsClippingRect() const { return m_contentsClippingRect; }
     virtual void setContentsClippingRect(const FloatRoundedRect& roundedRect) { m_contentsClippingRect = roundedRect; }
 
+    virtual bool applyClippingBorder(const FloatRoundedRect&) { return false; }
+    virtual void clearClippingBorder() { return; }
+
     // Transitions are identified by a special animation name that cannot clash with a keyframe identifier.
     static String animationNameForTransition(AnimatedPropertyID);
     
@@ -498,6 +501,8 @@ public:
     virtual bool isGraphicsLayerCARemote() const { return false; }
     virtual bool isGraphicsLayerTextureMapper() const { return false; }
 
+    virtual bool needsClippingMaskLayer() { return true; };
+
 protected:
     // Should be called from derived class destructors. Should call willBeDestroyed() on super.
     WEBCORE_EXPORT virtual void willBeDestroyed();
index b45df1c..1d9ae1c 100644 (file)
@@ -44,6 +44,7 @@ enum GraphicsLayerPaintingPhaseFlags {
     GraphicsLayerPaintMask = (1 << 2),
     GraphicsLayerPaintOverflowContents = (1 << 3),
     GraphicsLayerPaintCompositedScroll = (1 << 4),
+    GraphicsLayerPaintChildClippingMask = (1 << 5),
     GraphicsLayerPaintAllWithOverflowClip = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
 };
 typedef unsigned GraphicsLayerPaintingPhase;
index da7e495..c51a64a 100644 (file)
@@ -2027,6 +2027,38 @@ void GraphicsLayerCA::updateContentsColorLayer()
     }
 }
 
+bool GraphicsLayerCA::applyClippingBorder(const FloatRoundedRect& roundedRect)
+{
+    if (roundedRect.radii().isUniformCornerRadius()) {
+        m_layer->setMask(nullptr);
+        m_layer->setMasksToBounds(true);
+        m_layer->setCornerRadius(roundedRect.radii().topLeft().width());
+    } else {
+        if (!m_shapeMaskLayer) {
+            m_shapeMaskLayer = createPlatformCALayer(PlatformCALayer::LayerTypeShapeLayer, this);
+            m_shapeMaskLayer->setAnchorPoint(FloatPoint3D());
+        }
+
+        m_shapeMaskLayer->setPosition(FloatPoint());
+        m_shapeMaskLayer->setBounds(m_layer->bounds());
+    
+        m_layer->setCornerRadius(0);
+        m_layer->setMask(m_shapeMaskLayer.get());
+
+        FloatRoundedRect offsetClippingRoundedRect(m_layer->bounds(), roundedRect.radii());
+        m_shapeMaskLayer->setShapeRoundedRect(offsetClippingRoundedRect);
+    }
+
+    return true;
+}
+
+void GraphicsLayerCA::clearClippingBorder()
+{
+    m_layer->setCornerRadius(0);
+    m_layer->setMasksToBounds(false);
+    m_layer->setMask(nullptr);
+}
+
 // The clipping strategy depends on whether the rounded rect has equal corner radii.
 void GraphicsLayerCA::updateClippingStrategy(PlatformCALayer& clippingLayer, RefPtr<PlatformCALayer>& shapeMaskLayer, const FloatRoundedRect& roundedRect)
 {
index 8424472..495f578 100644 (file)
@@ -173,6 +173,9 @@ protected:
 private:
     virtual bool isGraphicsLayerCA() const override { return true; }
 
+    virtual bool applyClippingBorder(const FloatRoundedRect&) override;
+    virtual void clearClippingBorder() override;
+
     WEBCORE_EXPORT virtual void willBeDestroyed() override;
 
     // PlatformCALayerClient overrides
index 0bbf99a..a448d92 100644 (file)
@@ -49,7 +49,8 @@ enum PaintPhase {
     PaintPhaseSelection,
     PaintPhaseCollapsedTableBorders,
     PaintPhaseTextClip,
-    PaintPhaseMask
+    PaintPhaseMask,
+    PaintPhaseClippingMask
 };
 
 enum PaintBehaviorFlags {
index 686d9be..a087d57 100644 (file)
@@ -1575,6 +1575,11 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
         return;
     }
 
+    if (paintPhase == PaintPhaseClippingMask && style().visibility() == VISIBLE) {
+        paintClippingMask(paintInfo, paintOffset);
+        return;
+    }
+
     // If just painting the root background, then return.
     if (paintInfo.paintRootBackgroundOnly())
         return;
index f464310..63998a1 100644 (file)
@@ -1480,6 +1480,15 @@ void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
     paintMaskImages(paintInfo, paintRect);
 }
 
+void RenderBox::paintClippingMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(*this) || style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask || paintInfo.context->paintingDisabled())
+        return;
+
+    LayoutRect paintRect = LayoutRect(paintOffset, size());
+    paintInfo.context->fillRect(snappedIntRect(paintRect), Color::black, style().colorSpace());
+}
+
 void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
 {
     // Figure out if we need to push a transparency layer to render our mask.
index b548de9..5c7dbab 100644 (file)
@@ -495,6 +495,7 @@ public:
     virtual void paintObject(PaintInfo&, const LayoutPoint&) { ASSERT_NOT_REACHED(); }
     virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
     virtual void paintMask(PaintInfo&, const LayoutPoint&);
+    virtual void paintClippingMask(PaintInfo&, const LayoutPoint&);
     virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) override;
 
     // Called when a positioned object moves but doesn't necessarily change size.  A simplified layout is attempted
index 1e9f495..b583c90 100644 (file)
@@ -4195,6 +4195,11 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
         paintMaskForFragments(layerFragments, context, localPaintingInfo, subtreePaintRootForRenderer);
     }
 
+    if ((localPaintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly) {
+        // Paint the border radius mask for the fragments.
+        paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, subtreePaintRootForRenderer);
+    }
+
     // End our transparency layer
     if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
         context->endTransparencyLayer();
@@ -4613,6 +4618,26 @@ void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, Gr
     }
 }
 
+void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
+    RenderObject* subtreePaintRootForRenderer)
+{
+    for (size_t i = 0; i < layerFragments.size(); ++i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if (!fragment.shouldPaintContent)
+            continue;
+
+        if (localPaintingInfo.clipToDirtyRect)
+            clipToRect(localPaintingInfo, context, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
+
+        // Paint the clipped mask.
+        PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhaseClippingMask, PaintBehaviorNormal, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer());
+        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelAccumulation));
+
+        if (localPaintingInfo.clipToDirtyRect)
+            restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
+    }
+}
+
 void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo)
 {
     for (size_t i = 0; i < layerFragments.size(); ++i) {
index 22630a2..e09df91 100644 (file)
@@ -667,6 +667,7 @@ public:
         PaintLayerPaintingOverflowContents = 1 << 9,
         PaintLayerPaintingRootBackgroundOnly = 1 << 10,
         PaintLayerPaintingSkipRootBackground = 1 << 11,
+        PaintLayerPaintingChildClippingMaskPhase = 1 << 12,
         PaintLayerPaintingCompositingAllPhases = (PaintLayerPaintingCompositingBackgroundPhase | PaintLayerPaintingCompositingForegroundPhase | PaintLayerPaintingCompositingMaskPhase)
     };
     
@@ -1009,6 +1010,7 @@ private:
     void paintOutlineForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
     void paintOverflowControlsForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&);
     void paintMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer);
+    void paintChildClippingMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer);
     void paintTransformedLayerIntoFragments(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
 
     RenderLayer* transparentPaintingAncestor();
index 9beb4ef..1710903 100644 (file)
@@ -147,6 +147,7 @@ RenderLayerBacking::~RenderLayerBacking()
     updateForegroundLayer(false);
     updateBackgroundLayer(false);
     updateMaskLayer(false);
+    updateChildClippingStrategy(false);
     updateScrollingLayers(false);
     detachFromScrollingCoordinator();
     destroyGraphicsLayers();
@@ -348,6 +349,7 @@ void RenderLayerBacking::destroyGraphicsLayers()
     m_backgroundLayer = nullptr;
     m_childContainmentLayer = nullptr;
     m_maskLayer = nullptr;
+    m_childClippingMaskLayer = nullptr;
 
     m_scrollingLayer = nullptr;
     m_scrollingContentsLayer = nullptr;
@@ -569,6 +571,8 @@ bool RenderLayerBacking::updateConfiguration()
 
     updateMaskLayer(renderer().hasMask());
 
+    updateChildClippingStrategy(needsDescendentsClippingLayer);
+
     if (m_owningLayer.hasReflection()) {
         if (m_owningLayer.reflectionLayer()->backing()) {
             GraphicsLayer* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
@@ -814,6 +818,12 @@ void RenderLayerBacking::updateGeometry()
         clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
         clipLayer->setSize(clippingBox.size());
         clipLayer->setOffsetFromRenderer(toFloatSize(clippingBox.location()));
+
+        if (m_childClippingMaskLayer && !m_scrollingLayer) {
+            m_childClippingMaskLayer->setSize(clipLayer->size());
+            m_childClippingMaskLayer->setPosition(FloatPoint());
+            m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer());
+        }
     }
     
     if (m_maskLayer) {
@@ -942,6 +952,12 @@ void RenderLayerBacking::updateGeometry()
         FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
         m_scrollingLayer->setOffsetFromRenderer(-toFloatSize(paddingBox.location()));
 
+        if (m_childClippingMaskLayer) {
+            m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
+            m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
+            m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBox.location()));
+        }
+
         bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
 
         IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
@@ -1414,6 +1430,37 @@ void RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
         m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
 }
 
+void RenderLayerBacking::updateChildClippingStrategy(bool needsDescendentsClippingLayer)
+{
+    if (hasClippingLayer() && needsDescendentsClippingLayer) {
+        if (is<RenderBox>(renderer())) {
+            LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
+            FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
+            contentsClippingRect.move(contentOffsetInCompostingLayer());
+            if (clippingLayer()->applyClippingBorder(contentsClippingRect)) {
+                if (m_childClippingMaskLayer) 
+                    m_childClippingMaskLayer = nullptr;
+                return;
+            }
+        }
+
+        if (!m_childClippingMaskLayer) {
+            m_childClippingMaskLayer = createGraphicsLayer("Child Clipping Mask Layer");
+            m_childClippingMaskLayer->setDrawsContent(true);
+            m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
+            clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
+        }
+    } else {
+        if (m_childClippingMaskLayer) {
+            m_childClippingMaskLayer = nullptr;
+            if (hasClippingLayer())
+                clippingLayer()->setMaskLayer(nullptr);
+        } else 
+            if (hasClippingLayer())
+                clippingLayer()->clearClippingBorder();
+    }
+}
+
 bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
 {
     if (needsScrollingLayers == !!m_scrollingLayer)
@@ -2065,6 +2112,9 @@ void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer
     if (m_maskLayer && m_maskLayer->drawsContent())
         m_maskLayer->setNeedsDisplay();
 
+    if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent())
+        m_childClippingMaskLayer->setNeedsDisplay();
+
     if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
         m_scrollingContentsLayer->setNeedsDisplay();
 }
@@ -2104,6 +2154,12 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, Graph
         m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
     }
 
+    if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) {
+        FloatRect layerDirtyRect = r;
+        layerDirtyRect.move(-m_childClippingMaskLayer->offsetFromRenderer());
+        m_childClippingMaskLayer->setNeedsDisplayInRect(layerDirtyRect);
+    }
+
     if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
         FloatRect layerDirtyRect = pixelSnappedRectForPainting;
         layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
@@ -2138,6 +2194,8 @@ void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, Grap
         paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
     if (paintingPhase & GraphicsLayerPaintMask)
         paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
+    if (paintingPhase & GraphicsLayerPaintChildClippingMask)
+        paintFlags |= RenderLayer::PaintLayerPaintingChildClippingMaskPhase;
     if (paintingPhase & GraphicsLayerPaintOverflowContents)
         paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
     if (paintingPhase & GraphicsLayerPaintCompositedScroll)
@@ -2202,6 +2260,7 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
         || graphicsLayer == m_foregroundLayer.get()
         || graphicsLayer == m_backgroundLayer.get()
         || graphicsLayer == m_maskLayer.get()
+        || graphicsLayer == m_childClippingMaskLayer.get()
         || graphicsLayer == m_scrollingContentsLayer.get()) {
         InspectorInstrumentation::willPaint(&renderer());
 
@@ -2578,6 +2637,8 @@ double RenderLayerBacking::backingStoreMemoryEstimate() const
         backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
     if (m_maskLayer)
         backingMemory += m_maskLayer->backingStoreMemoryEstimate();
+    if (m_childClippingMaskLayer)
+        backingMemory += m_childClippingMaskLayer->backingStoreMemoryEstimate();
 
     if (m_scrollingContentsLayer)
         backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
index 1ff8f54..4a72aa7 100644 (file)
@@ -139,6 +139,7 @@ public:
     ScrollingNodeID scrollingNodeIDForChildren() const { return m_scrollingNodeID ? m_scrollingNodeID : m_viewportConstrainedNodeID; }
 
     bool hasMaskLayer() const { return m_maskLayer != 0; }
+    bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer != nullptr; }
 
     GraphicsLayer* parentForSublayers() const;
     GraphicsLayer* childForSuperlayers() const;
@@ -268,6 +269,7 @@ private:
     bool requiresScrollCornerLayer() const;
     bool updateScrollingLayers(bool scrollingLayers);
     void updateDrawsContent(bool isSimpleContainer);
+    void updateChildClippingStrategy(bool needsDescendentsClippingLayer);
     
     void updateRootLayerConfiguration();
 
@@ -335,6 +337,7 @@ private:
     std::unique_ptr<GraphicsLayer> m_backgroundLayer; // Only used in cases where we need to draw the background separately.
     std::unique_ptr<GraphicsLayer> m_childContainmentLayer; // Only used if we have clipping on a stacking context with compositing children, or if the layer has a tile cache.
     std::unique_ptr<GraphicsLayer> m_maskLayer; // Only used if we have a mask.
+    std::unique_ptr<GraphicsLayer> m_childClippingMaskLayer; // Only used if we have to clip child layers or accelerated contents with border radius or clip-path.
 
     std::unique_ptr<GraphicsLayer> m_layerForHorizontalScrollbar;
     std::unique_ptr<GraphicsLayer> m_layerForVerticalScrollbar;