Title: [260950] trunk
Revision
260950
Author
[email protected]
Date
2020-04-30 07:39:02 -0700 (Thu, 30 Apr 2020)

Log Message

border-radius fails to clip iframe contents
https://bugs.webkit.org/show_bug.cgi?id=211199
Source/WebCore:

<rdar://problem/61945671>

Reviewed by Zalan Bujtas.

iframes need to use the same composited clipping strategy that we use for other
replaced elements with composited contents, like video and WebGL. To achieve this,
change GraphicsLayer to allow child GraphicsLayers to be parented in the contents
clipping layer, just like content layers are. (We don't want to do this unconditionally,
because it will change behavior for video with controls.)

Add GraphicsLayer::contentsRectClipsDescendants(), and used it to run code that
creates the contents clipping (and optional shape) layers even when no contents
layer is present. Fix up the sublayer list building to parent layers from
children in the contents clipping layer.

Tests: compositing/iframes/border-radius-composited-frame.html
       compositing/iframes/border-uneven-radius-composited-frame.html

* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::GraphicsLayer):
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::contentsRectClipsDescendants const):
(WebCore::GraphicsLayer::setContentsRectClipsDescendants):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::setContentsRectClipsDescendants):
(WebCore::GraphicsLayerCA::updateSublayerList):
(WebCore::GraphicsLayerCA::updateContentsRects):
(WebCore::GraphicsLayerCA::createTransformAnimationsFromKeyframes):
* platform/graphics/ca/GraphicsLayerCA.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateConfiguration):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::isCompositedSubframeRenderer):
* rendering/RenderLayerCompositor.h:

LayoutTests:

Reviewed by Zalan Bujtas.

* compositing/iframes/border-radius-composited-frame-expected.html: Added.
* compositing/iframes/border-radius-composited-frame.html: Added.
* compositing/iframes/border-uneven-radius-composited-frame-expected.html: Added.
* compositing/iframes/border-uneven-radius-composited-frame.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (260949 => 260950)


--- trunk/LayoutTests/ChangeLog	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/LayoutTests/ChangeLog	2020-04-30 14:39:02 UTC (rev 260950)
@@ -1,3 +1,15 @@
+2020-04-30  Simon Fraser  <[email protected]>
+
+        border-radius fails to clip iframe contents
+        https://bugs.webkit.org/show_bug.cgi?id=211199
+
+        Reviewed by Zalan Bujtas.
+
+        * compositing/iframes/border-radius-composited-frame-expected.html: Added.
+        * compositing/iframes/border-radius-composited-frame.html: Added.
+        * compositing/iframes/border-uneven-radius-composited-frame-expected.html: Added.
+        * compositing/iframes/border-uneven-radius-composited-frame.html: Added.
+
 2020-04-30  Philippe Normand  <[email protected]>
 
         [SOUP] http/tests/media/video-accept-encoding.html fails

Added: trunk/LayoutTests/compositing/iframes/border-radius-composited-frame-expected.html (0 => 260950)


--- trunk/LayoutTests/compositing/iframes/border-radius-composited-frame-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/iframes/border-radius-composited-frame-expected.html	2020-04-30 14:39:02 UTC (rev 260950)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .wrapper {
+            height: 400px;
+            width: 400px;
+            border: 10px solid black;
+            box-sizing: border-box;
+            border-radius: 50%;
+            overflow: hidden;
+            transform: translateZ(0);
+        }
+        
+        .composited {
+            transform: translateZ(0);
+        }
+        
+        .box {
+            width: 100%;
+            height: 100%;
+            background-color: silver;
+        }
+    </style>
+</head>
+<body>
+    <div class="wrapper">
+        <div class="composited box">asd
+        </div>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/compositing/iframes/border-radius-composited-frame.html (0 => 260950)


--- trunk/LayoutTests/compositing/iframes/border-radius-composited-frame.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/iframes/border-radius-composited-frame.html	2020-04-30 14:39:02 UTC (rev 260950)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        iframe {
+            height: 400px;
+            width: 400px;
+            border: 10px solid black;
+            box-sizing: border-box;
+            border-radius: 50%;
+        }
+    </style>
+</head>
+<body>
+    <iframe srcdoc="
+	<style>
+        body {
+            background-color: silver;
+            margin: 0;
+		    transform: translateZ(0);
+        }
+	</style>
+    "></iframe>
+</body>
+</html>

Added: trunk/LayoutTests/compositing/iframes/border-uneven-radius-composited-frame-expected.html (0 => 260950)


--- trunk/LayoutTests/compositing/iframes/border-uneven-radius-composited-frame-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/iframes/border-uneven-radius-composited-frame-expected.html	2020-04-30 14:39:02 UTC (rev 260950)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .wrapper {
+            height: 400px;
+            width: 400px;
+            border: 10px solid black;
+            box-sizing: border-box;
+            border-top-left-radius: 30%;
+            overflow: hidden;
+            transform: translateZ(0);
+        }
+        
+        .composited {
+            transform: translateZ(0);
+        }
+        
+        .box {
+            width: 100%;
+            height: 100%;
+            background-color: silver;
+        }
+    </style>
+</head>
+<body>
+    <div class="wrapper">
+        <div class="composited box">asd
+        </div>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/compositing/iframes/border-uneven-radius-composited-frame.html (0 => 260950)


--- trunk/LayoutTests/compositing/iframes/border-uneven-radius-composited-frame.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/iframes/border-uneven-radius-composited-frame.html	2020-04-30 14:39:02 UTC (rev 260950)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        iframe {
+            height: 400px;
+            width: 400px;
+            border: 10px solid black;
+            box-sizing: border-box;
+            border-top-left-radius: 30%;
+        }
+    </style>
+</head>
+<body>
+    <iframe srcdoc="
+	<style>
+        body {
+            background-color: silver;
+            margin: 0;
+		    transform: translateZ(0);
+        }
+	</style>
+    "></iframe>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (260949 => 260950)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2020-04-30 14:39:02 UTC (rev 260950)
@@ -389,6 +389,7 @@
 fast/scrolling/overflow-scrollable-after-back.html [ Skip ]
 
 compositing/rtl/rtl-fixed-overflow-scrolled.html [ Failure ]
+compositing/iframes/border-uneven-radius-composited-frame.html [ ImageOnlyFailure ]
 compositing/iframes/overlapped-nested-iframes.html [ Pass Failure ]
 compositing/clipping/border-radius-async-overflow-non-stacking.html [ ImageOnlyFailure ]
 compositing/visibility/visibility-change-in-subframe.html [ Failure ]

Modified: trunk/Source/WebCore/ChangeLog (260949 => 260950)


--- trunk/Source/WebCore/ChangeLog	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/ChangeLog	2020-04-30 14:39:02 UTC (rev 260950)
@@ -1,3 +1,42 @@
+2020-04-30  Simon Fraser  <[email protected]>
+
+        border-radius fails to clip iframe contents
+        https://bugs.webkit.org/show_bug.cgi?id=211199
+        <rdar://problem/61945671>
+
+        Reviewed by Zalan Bujtas.
+
+        iframes need to use the same composited clipping strategy that we use for other
+        replaced elements with composited contents, like video and WebGL. To achieve this,
+        change GraphicsLayer to allow child GraphicsLayers to be parented in the contents
+        clipping layer, just like content layers are. (We don't want to do this unconditionally,
+        because it will change behavior for video with controls.)
+
+        Add GraphicsLayer::contentsRectClipsDescendants(), and used it to run code that
+        creates the contents clipping (and optional shape) layers even when no contents
+        layer is present. Fix up the sublayer list building to parent layers from
+        children in the contents clipping layer.
+
+        Tests: compositing/iframes/border-radius-composited-frame.html
+               compositing/iframes/border-uneven-radius-composited-frame.html
+
+        * platform/graphics/GraphicsLayer.cpp:
+        (WebCore::GraphicsLayer::GraphicsLayer):
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::contentsRectClipsDescendants const):
+        (WebCore::GraphicsLayer::setContentsRectClipsDescendants):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::setContentsRectClipsDescendants):
+        (WebCore::GraphicsLayerCA::updateSublayerList):
+        (WebCore::GraphicsLayerCA::updateContentsRects):
+        (WebCore::GraphicsLayerCA::createTransformAnimationsFromKeyframes):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateConfiguration):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::isCompositedSubframeRenderer):
+        * rendering/RenderLayerCompositor.h:
+
 2020-04-30  Zalan Bujtas  <[email protected]>
 
         [LFC][TFC] Adjust the available vertical space with the row span for cell layout

Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp (260949 => 260950)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp	2020-04-30 14:39:02 UTC (rev 260950)
@@ -135,6 +135,7 @@
     , m_masksToBounds(false)
     , m_drawsContent(false)
     , m_contentsVisible(true)
+    , m_contentsRectClipsDescendants(false)
     , m_acceleratesDrawing(false)
     , m_usesDisplayListDrawing(false)
     , m_appliesPageScale(false)

Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (260949 => 260950)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2020-04-30 14:39:02 UTC (rev 260950)
@@ -451,6 +451,10 @@
     // Set a rounded rect that will be used to clip the layer contents.
     FloatRoundedRect contentsClippingRect() const { return m_contentsClippingRect; }
     virtual void setContentsClippingRect(const FloatRoundedRect& roundedRect) { m_contentsClippingRect = roundedRect; }
+    
+    // If true, contentsClippingRect is used to clip child GraphicsLayers.
+    bool contentsRectClipsDescendants() const { return m_contentsRectClipsDescendants; }
+    virtual void setContentsRectClipsDescendants(bool b) { m_contentsRectClipsDescendants = b; }
 
     // Set a rounded rect that is used to clip this layer and its descendants (implies setting masksToBounds).
     // Returns false if the platform can't support this rounded clip, and we should fall back to painting a mask.
@@ -711,6 +715,7 @@
     bool m_masksToBounds : 1;
     bool m_drawsContent : 1;
     bool m_contentsVisible : 1;
+    bool m_contentsRectClipsDescendants : 1;
     bool m_acceleratesDrawing : 1;
     bool m_usesDisplayListDrawing : 1;
     bool m_appliesPageScale : 1; // Set for the layer which has the page scale applied to it.

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (260949 => 260950)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2020-04-30 14:39:02 UTC (rev 260950)
@@ -967,6 +967,15 @@
     noteLayerPropertyChanged(ContentsRectsChanged);
 }
 
+void GraphicsLayerCA::setContentsRectClipsDescendants(bool contentsRectClipsDescendants)
+{
+    if (contentsRectClipsDescendants == m_contentsRectClipsDescendants)
+        return;
+
+    GraphicsLayer::setContentsRectClipsDescendants(contentsRectClipsDescendants);
+    noteLayerPropertyChanged(ChildrenChanged | ContentsRectsChanged);
+}
+
 bool GraphicsLayerCA::setMasksToBoundsRect(const FloatRoundedRect& roundedRect)
 {
     if (roundedRect == m_masksToBoundsRect)
@@ -2019,19 +2028,31 @@
 #endif
     };
 
+    auto buildChildLayerList = [&](PlatformCALayerList& list) {
+        appendLayersFromChildren(list);
+        appendDebugLayers(list);
+    };
+
     PlatformCALayerList primaryLayerChildren;
     appendCustomAndClippingLayers(primaryLayerChildren);
 
+    bool clippingLayerHostsChildren = m_contentsRectClipsDescendants && m_contentsClippingLayer;
+    if (clippingLayerHostsChildren) {
+        PlatformCALayerList clippingChildren;
+        buildChildLayerList(clippingChildren);
+        m_contentsClippingLayer->setSublayers(clippingChildren);
+    }
+
     if (m_structuralLayer) {
         PlatformCALayerList layerList;
         appendStructuralLayerChildren(layerList);
-        appendLayersFromChildren(layerList);
-        appendDebugLayers(layerList);
+
+        if (!clippingLayerHostsChildren)
+            buildChildLayerList(layerList);
+
         m_structuralLayer->setSublayers(layerList);
-    } else {
-        appendLayersFromChildren(primaryLayerChildren);
-        appendDebugLayers(primaryLayerChildren);
-    }
+    } else if (!clippingLayerHostsChildren)
+        buildChildLayerList(primaryLayerChildren);
 
     m_layer->setSublayers(primaryLayerChildren);
 }
@@ -2677,7 +2698,7 @@
 
 void GraphicsLayerCA::updateContentsRects()
 {
-    if (!m_contentsLayer)
+    if (!m_contentsLayer && !m_contentsRectClipsDescendants)
         return;
 
     auto contentBounds = FloatRect { { }, m_contentsRect.size() };
@@ -2700,13 +2721,14 @@
         
         updateClippingStrategy(*m_contentsClippingLayer, m_contentsShapeMaskLayer, m_contentsClippingRect);
 
-        if (gainedOrLostClippingLayer) {
+        if (m_contentsLayer && gainedOrLostClippingLayer) {
             m_contentsLayer->removeFromSuperlayer();
             m_contentsClippingLayer->appendSublayer(*m_contentsLayer);
         }
     } else {
         if (m_contentsClippingLayer) {
-            m_contentsLayer->removeFromSuperlayer();
+            if (m_contentsLayer)
+                m_contentsLayer->removeFromSuperlayer();
 
             m_contentsClippingLayer->removeFromSuperlayer();
             m_contentsClippingLayer->setOwner(nullptr);
@@ -2724,8 +2746,10 @@
     if (gainedOrLostClippingLayer)
         noteSublayersChanged(DontScheduleFlush);
 
-    m_contentsLayer->setPosition(m_contentsRect.location());
-    m_contentsLayer->setBounds(contentBounds);
+    if (m_contentsLayer) {
+        m_contentsLayer->setPosition(m_contentsRect.location());
+        m_contentsLayer->setBounds(contentBounds);
+    }
 
     if (m_layerClones) {
         for (auto& layer : m_layerClones->contentsLayerClones.values()) {
@@ -3615,7 +3639,13 @@
 
 PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const
 {
-    return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); 
+    if (contentsRectClipsDescendants() && m_contentsClippingLayer)
+        return m_contentsClippingLayer.get();
+
+    if (m_structuralLayer)
+        return m_structuralLayer.get();
+
+    return m_layer.get();
 }
 
 PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (260949 => 260950)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2020-04-30 14:39:02 UTC (rev 260950)
@@ -120,6 +120,7 @@
     
     WEBCORE_EXPORT void setContentsRect(const FloatRect&) override;
     WEBCORE_EXPORT void setContentsClippingRect(const FloatRoundedRect&) override;
+    WEBCORE_EXPORT void setContentsRectClipsDescendants(bool) override;
     WEBCORE_EXPORT bool setMasksToBoundsRect(const FloatRoundedRect&) override;
 
     WEBCORE_EXPORT void setShapeLayerPath(const Path&) override;

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (260949 => 260950)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2020-04-30 14:39:02 UTC (rev 260950)
@@ -967,6 +967,11 @@
         layerConfigChanged = true;
     }
 
+    if (RenderLayerCompositor::isCompositedSubframeRenderer(renderer())) {
+        m_graphicsLayer->setContentsRectClipsDescendants(true);
+        updateContentsRects();
+    }
+
     if (is<RenderImage>(renderer()) && downcast<RenderImage>(renderer()).isEditableImage()) {
         auto element = renderer().element();
         if (is<HTMLImageElement>(element)) {

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp (260949 => 260950)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp	2020-04-30 14:39:02 UTC (rev 260950)
@@ -2823,6 +2823,14 @@
     return containerScrollingNodeID;
 }
 
+bool RenderLayerCompositor::isCompositedSubframeRenderer(const RenderObject& renderer)
+{
+    if (!is<RenderWidget>(renderer))
+        return false;
+
+    return downcast<RenderWidget>(renderer).requiresAcceleratedCompositing();
+}
+
 // Return true if the given layer is a stacking context and has compositing child
 // layers that it needs to clip. In this case we insert a clipping GraphicsLayer
 // into the hierarchy between this layer and its children in the z-order hierarchy.

Modified: trunk/Source/WebCore/rendering/RenderLayerCompositor.h (260949 => 260950)


--- trunk/Source/WebCore/rendering/RenderLayerCompositor.h	2020-04-30 14:04:51 UTC (rev 260949)
+++ trunk/Source/WebCore/rendering/RenderLayerCompositor.h	2020-04-30 14:39:02 UTC (rev 260950)
@@ -295,6 +295,7 @@
     // to know if there is non-affine content, e.g. for drawing into an image.
     bool has3DContent() const;
     
+    static bool isCompositedSubframeRenderer(const RenderObject&);
     static RenderLayerCompositor* frameContentsCompositor(RenderWidget&);
     // Return true if the layers changed.
     bool parentFrameContentLayers(RenderWidget&);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to