Backing-sharing layers with transforms render incorrectly
https://bugs.webkit.org/show_bug.cgi?id=197692
<rdar://problem/50652127>

Reviewed by Antti Koivisto.
Source/WebCore:

Layers that paint into shared backing need to enter the RenderLayer painting code
in a way that paints the filters, transforms, opacity and blending.

RenderLayerBacking::paintIntoLayer() normally enters at paintLayerContents(), because
the effects are rendered via the GraphicsLayer, but shared layers will paint effects.
Note that if the backing-provider has effects, it will be the stacking context
for the shared layers, so it's correct that sharing layers are impacted by effects
on the backing-provider.

In addition, we have to ensure that we don't over-eagerly make layers shared.
Consider:

<div class="clipping">
    <div class="sharing">
        <div class="inner">
        </div>
    </div>
</div>

Here "clipping" is the provider layer, "sharing" paints into shared backing, but
we don't want to also mark "inner" as sharing, since "sharing" will just paint it.
This is akin to avoiding unnecessary compositing of z-order descendants when they can just
paint.

To do this we need to ensure that sharing layers are treated like compositing layers
in the overlap map, i.e. when a layer is sharing, we call overlapMap.pushCompositingContainer(),
and later overlapMap.popCompositingContainer().

Tests: compositing/shared-backing/nested-shared-layers-with-opacity.html
       compositing/shared-backing/shared-layer-has-blending.html
       compositing/shared-backing/shared-layer-has-filter.html
       compositing/shared-backing/shared-layer-has-opacity.html
       compositing/shared-backing/shared-layer-has-reflection.html
       compositing/shared-backing/shared-layer-has-transform.html
       compositing/shared-backing/shared-layer-isolates-blending.html
       compositing/shared-backing/shared-transformed-layer-bounds.html
       compositing/shared-backing/sharing-layer-becomes-non-scrollable.html
       compositing/shared-backing/sharing-layer-has-effect.html

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintLayer):
(WebCore::RenderLayer::paintLayerWithEffects):
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::paintIntoLayer):
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::CompositingState::stateForPaintOrderChildren const):
(WebCore::backingProviderLayerCanIncludeLayer):
(WebCore::RenderLayerCompositor::computeCompositingRequirements):
(WebCore::RenderLayerCompositor::traverseUnchangedSubtree):

LayoutTests:

Ref tests for effects on sharing layers. The references make "clipping" be stacking context via z-index,
which eliminates sharing.

* compositing/shared-backing/nested-shared-layers-with-opacity-expected.html: Added.
* compositing/shared-backing/nested-shared-layers-with-opacity.html: Added.
* compositing/shared-backing/shared-layer-has-blending-expected.html: Added.
* compositing/shared-backing/shared-layer-has-blending.html: Added.
* compositing/shared-backing/shared-layer-has-filter-expected.html: Added.
* compositing/shared-backing/shared-layer-has-filter.html: Added.
* compositing/shared-backing/shared-layer-has-opacity-expected.html: Added.
* compositing/shared-backing/shared-layer-has-opacity.html: Added.
* compositing/shared-backing/shared-layer-has-reflection-expected.html: Added.
* compositing/shared-backing/shared-layer-has-reflection.html: Added.
* compositing/shared-backing/shared-layer-has-transform-expected.html: Added.
* compositing/shared-backing/shared-layer-has-transform.html: Added.
* compositing/shared-backing/shared-layer-isolates-blending-expected.html: Added.
* compositing/shared-backing/shared-layer-isolates-blending.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245205 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 512e521..cfb54ec 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,29 @@
+2019-05-11  Simon Fraser  <simon.fraser@apple.com>
+
+        Backing-sharing layers with transforms render incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=197692
+        <rdar://problem/50652127>
+
+        Reviewed by Antti Koivisto.
+        
+        Ref tests for effects on sharing layers. The references make "clipping" be stacking context via z-index,
+        which eliminates sharing.
+
+        * compositing/shared-backing/nested-shared-layers-with-opacity-expected.html: Added.
+        * compositing/shared-backing/nested-shared-layers-with-opacity.html: Added.
+        * compositing/shared-backing/shared-layer-has-blending-expected.html: Added.
+        * compositing/shared-backing/shared-layer-has-blending.html: Added.
+        * compositing/shared-backing/shared-layer-has-filter-expected.html: Added.
+        * compositing/shared-backing/shared-layer-has-filter.html: Added.
+        * compositing/shared-backing/shared-layer-has-opacity-expected.html: Added.
+        * compositing/shared-backing/shared-layer-has-opacity.html: Added.
+        * compositing/shared-backing/shared-layer-has-reflection-expected.html: Added.
+        * compositing/shared-backing/shared-layer-has-reflection.html: Added.
+        * compositing/shared-backing/shared-layer-has-transform-expected.html: Added.
+        * compositing/shared-backing/shared-layer-has-transform.html: Added.
+        * compositing/shared-backing/shared-layer-isolates-blending-expected.html: Added.
+        * compositing/shared-backing/shared-layer-isolates-blending.html: Added.
+
 2019-05-10  Zalan Bujtas  <zalan@apple.com>
 
         [iOS] baidu.com: Synthetic bold renders too far apart, appears doubled.
diff --git a/LayoutTests/compositing/shared-backing/nested-shared-layers-with-opacity-expected.html b/LayoutTests/compositing/shared-backing/nested-shared-layers-with-opacity-expected.html
new file mode 100644
index 0000000..75547c3
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/nested-shared-layers-with-opacity-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with opacity into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+
+		.box {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+		}
+		
+		.opacity {
+            opacity: 0.5;
+		}
+    
+        .composited {
+            transform: translateZ(0);
+        }
+        
+        .trigger {
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing opacity box">
+			<div class="opacity box"></div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/nested-shared-layers-with-opacity.html b/LayoutTests/compositing/shared-backing/nested-shared-layers-with-opacity.html
new file mode 100644
index 0000000..fa947f2
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/nested-shared-layers-with-opacity.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with opacity into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+
+		.box {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+		}
+		
+		.opacity {
+            opacity: 0.5;
+		}
+    
+        .composited {
+            transform: translateZ(0);
+        }
+        
+        .trigger {
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing opacity box">
+			<div class="opacity box"></div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-blending-expected.html b/LayoutTests/compositing/shared-backing/shared-layer-has-blending-expected.html
new file mode 100644
index 0000000..8f47023
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-blending-expected.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .blending {
+            mix-blend-mode: difference;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing blending box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-blending.html b/LayoutTests/compositing/shared-backing/shared-layer-has-blending.html
new file mode 100644
index 0000000..483240c
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-blending.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with mix-blend-mode into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .blending {
+            mix-blend-mode: difference;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing blending box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-filter-expected.html b/LayoutTests/compositing/shared-backing/shared-layer-has-filter-expected.html
new file mode 100644
index 0000000..9d38f9b
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-filter-expected.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .filtered {
+            filter: saturate(0);
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing filtered box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-filter.html b/LayoutTests/compositing/shared-backing/shared-layer-has-filter.html
new file mode 100644
index 0000000..7b7a01e
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-filter.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with a filter into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .filtered {
+            filter: saturate(0);
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing filtered box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-opacity-expected.html b/LayoutTests/compositing/shared-backing/shared-layer-has-opacity-expected.html
new file mode 100644
index 0000000..faf3306
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-opacity-expected.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with opacity into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .opacity {
+            opacity: 0.5;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing opacity box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-opacity.html b/LayoutTests/compositing/shared-backing/shared-layer-has-opacity.html
new file mode 100644
index 0000000..0143d8f
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-opacity.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with opacity into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .opacity {
+            opacity: 0.5;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing opacity box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-reflection-expected.html b/LayoutTests/compositing/shared-backing/shared-layer-has-reflection-expected.html
new file mode 100644
index 0000000..8be25b2
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-reflection-expected.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 160px;
+            background-color: green;
+            border-bottom: 20px solid orange;
+        }
+        
+        .reflected {
+            -webkit-box-reflect: below 10px;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing reflected box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-reflection.html b/LayoutTests/compositing/shared-backing/shared-layer-has-reflection.html
new file mode 100644
index 0000000..9872332
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-reflection.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with a reflection into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 160px;
+            background-color: green;
+            border-bottom: 20px solid orange;
+        }
+        
+        .reflected {
+            -webkit-box-reflect: below 10px;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing reflected box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-transform-expected.html b/LayoutTests/compositing/shared-backing/shared-layer-has-transform-expected.html
new file mode 100644
index 0000000..82c0710
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-transform-expected.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .transformed {
+            transform: rotate(45deg);
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing transformed box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-has-transform.html b/LayoutTests/compositing/shared-backing/shared-layer-has-transform.html
new file mode 100644
index 0000000..44d8ccd
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-has-transform.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer with a transform into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 50px;
+			left: 50px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .transformed {
+            transform: rotate(45deg);
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+        
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing transformed box">
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-isolates-blending-expected.html b/LayoutTests/compositing/shared-backing/shared-layer-isolates-blending-expected.html
new file mode 100644
index 0000000..cffc6a8
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-isolates-blending-expected.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        .clipping {
+            position: absolute;
+            z-index: 0;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 30px;
+			left: 30px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .isolation {
+            isolation: isolate;
+        }
+        
+        .blending {
+            position: relative;
+            top: 50px;
+            left: 50px;
+            width: 180px;
+            height: 180px;
+            mix-blend-mode: multiply;
+            background-color: green;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing isolation box">
+            <div class="blending"></div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/compositing/shared-backing/shared-layer-isolates-blending.html b/LayoutTests/compositing/shared-backing/shared-layer-isolates-blending.html
new file mode 100644
index 0000000..0a77c83
--- /dev/null
+++ b/LayoutTests/compositing/shared-backing/shared-layer-isolates-blending.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Tests painting of a layer which isolates blending into shared backing</title>
+    <style>
+        .clipping {
+            position: absolute;
+            top: 20px;
+            left: 20px;
+            overflow: hidden;
+            height: 300px;
+            width: 300px;
+            margin: 10px;
+            border: 1px solid black;
+        }
+        
+        .sharing {
+			position: relative;
+			top: 30px;
+			left: 30px;
+            width: 180px;
+            height: 180px;
+            background-color: green;
+        }
+        
+        .isolation {
+            isolation: isolate;
+        }
+        
+        .blending {
+            position: relative;
+            top: 50px;
+            left: 50px;
+            width: 180px;
+            height: 180px;
+            mix-blend-mode: multiply;
+            background-color: green;
+        }
+
+        .trigger {
+            transform: translateZ(0);
+            width: 50px;
+            height: 50px;
+            background-color: silver;
+        }
+    </style>
+</head>
+<body>
+    <div class="composited trigger"></div>
+    <div class="clipping">
+        <div class="sharing isolation box">
+            <div class="blending"></div>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 08adb42..d53874b 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,62 @@
+2019-05-11  Simon Fraser  <simon.fraser@apple.com>
+
+        Backing-sharing layers with transforms render incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=197692
+        <rdar://problem/50652127>
+
+        Reviewed by Antti Koivisto.
+
+        Layers that paint into shared backing need to enter the RenderLayer painting code
+        in a way that paints the filters, transforms, opacity and blending.
+        
+        RenderLayerBacking::paintIntoLayer() normally enters at paintLayerContents(), because
+        the effects are rendered via the GraphicsLayer, but shared layers will paint effects.
+        Note that if the backing-provider has effects, it will be the stacking context
+        for the shared layers, so it's correct that sharing layers are impacted by effects
+        on the backing-provider.
+
+        In addition, we have to ensure that we don't over-eagerly make layers shared.
+        Consider:
+        
+        <div class="clipping">
+            <div class="sharing">
+                <div class="inner">
+                </div>
+            </div>
+        </div>
+        
+        Here "clipping" is the provider layer, "sharing" paints into shared backing, but
+        we don't want to also mark "inner" as sharing, since "sharing" will just paint it.
+        This is akin to avoiding unnecessary compositing of z-order descendants when they can just
+        paint.
+        
+        To do this we need to ensure that sharing layers are treated like compositing layers
+        in the overlap map, i.e. when a layer is sharing, we call overlapMap.pushCompositingContainer(),
+        and later overlapMap.popCompositingContainer().
+
+        Tests: compositing/shared-backing/nested-shared-layers-with-opacity.html
+               compositing/shared-backing/shared-layer-has-blending.html
+               compositing/shared-backing/shared-layer-has-filter.html
+               compositing/shared-backing/shared-layer-has-opacity.html
+               compositing/shared-backing/shared-layer-has-reflection.html
+               compositing/shared-backing/shared-layer-has-transform.html
+               compositing/shared-backing/shared-layer-isolates-blending.html
+               compositing/shared-backing/shared-transformed-layer-bounds.html
+               compositing/shared-backing/sharing-layer-becomes-non-scrollable.html
+               compositing/shared-backing/sharing-layer-has-effect.html
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paintLayer):
+        (WebCore::RenderLayer::paintLayerWithEffects):
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::paintIntoLayer):
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::CompositingState::stateForPaintOrderChildren const):
+        (WebCore::backingProviderLayerCanIncludeLayer):
+        (WebCore::RenderLayerCompositor::computeCompositingRequirements):
+        (WebCore::RenderLayerCompositor::traverseUnchangedSubtree):
+
 2019-05-10  Youenn Fablet  <youenn@apple.com>
 
         A service worker instance should be terminated when its SWServer is destroyed
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index b062d0b..185a875 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -4100,13 +4100,18 @@
         return;
     }
 
+    paintLayerWithEffects(context, paintingInfo, paintFlags);
+}
+
+void RenderLayer::paintLayerWithEffects(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags)
+{
     // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
     if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
         return;
 
     if (shouldSuppressPaintingLayer(this))
         return;
-    
+
     // If this layer is totally invisible then there is nothing to paint.
     if (!renderer().opacity())
         return;
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index da4beb9..22be9bc 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -1003,6 +1003,8 @@
     void applyFilters(GraphicsContext& originalContext, const LayerPaintingInfo&, const LayerFragments&);
 
     void paintLayer(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>);
+    void paintLayerWithEffects(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>);
+
     void paintLayerContentsAndReflection(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>);
     void paintLayerByApplyingTransform(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>, const LayoutSize& translationOffset = LayoutSize());
     void paintLayerContents(GraphicsContext&, const LayerPaintingInfo&, OptionSet<PaintLayerFlag>);
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 35a14c1..c3fcb9f 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -2668,10 +2668,13 @@
 
         RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer);
 
-        layer.paintLayerContents(context, paintingInfo, paintFlags);
+        if (&layer == &m_owningLayer) {
+            layer.paintLayerContents(context, paintingInfo, paintFlags);
 
-        if (layer.containsDirtyOverlayScrollbars())
-            layer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
+            if (layer.containsDirtyOverlayScrollbars())
+                layer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
+        } else
+            layer.paintLayerWithEffects(context, paintingInfo, paintFlags);
 
         if (layer.isRenderViewLayer())
             renderer().view().frameView().didPaintContents(context, paintDirtyRect, paintingState);
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 790791b..ca5424e 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -241,6 +241,7 @@
         else
             childState.stackingContextAncestor = stackingContextAncestor;
 
+        childState.backingSharingAncestor = backingSharingAncestor;
         childState.subtreeIsCompositing = false;
         childState.testingOverlap = testingOverlap;
         childState.fullPaintOrderTraversalRequired = fullPaintOrderTraversalRequired;
@@ -268,6 +269,7 @@
     }
 
     RenderLayer* compositingAncestor;
+    RenderLayer* backingSharingAncestor { nullptr };
     RenderLayer* stackingContextAncestor { nullptr };
     bool subtreeIsCompositing { false };
     bool testingOverlap { true };
@@ -860,6 +862,10 @@
 
 static bool backingProviderLayerCanIncludeLayer(const RenderLayer& sharedLayer, const RenderLayer& layer)
 {
+    // Disable sharing when painting shared layers doesn't work correctly.
+    if (layer.hasReflection())
+        return false;
+
     return layer.ancestorLayerIsInContainingBlockChain(sharedLayer);
 }
 
@@ -981,6 +987,9 @@
         // Compositing for any reason disables backing sharing.
         LOG_WITH_STREAM(Compositing, stream << &layer << " is compositing - flushing sharing to " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
         backingSharingState.resetBackingProviderCandidate();
+    } else if (layerPaintsIntoProvidedBacking) {
+        childState.backingSharingAncestor = &layer;
+        overlapMap.pushCompositingContainer();
     }
 
 #if !ASSERT_DISABLED
@@ -1064,7 +1073,7 @@
         compositingState.hasNotIsolatedCompositedBlendingDescendants = true;
 #endif
 
-    if (childState.compositingAncestor == &layer && !layer.isRenderViewLayer())
+    if ((childState.compositingAncestor == &layer && !layer.isRenderViewLayer()) || childState.backingSharingAncestor == &layer)
         overlapMap.popCompositingContainer();
 
     // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need
@@ -1228,7 +1237,7 @@
         compositingState.hasNotIsolatedCompositedBlendingDescendants = true;
 #endif
 
-    if (childState.compositingAncestor == &layer && !layer.isRenderViewLayer())
+    if ((childState.compositingAncestor == &layer && !layer.isRenderViewLayer()) || childState.backingSharingAncestor == &layer)
         overlapMap.popCompositingContainer();
 
     if (layer.isComposited())