Unify CSS grouping properties

This patch unifies the grouping property logic used for stacking
contexts (ComputedStyle::UpdateIsStackingContextWithoutContainment),
PaintLayer creation (LayoutBox::LayerTypeRequired), 3d transform
flattening (ComputedStyle::UsedTransformStyle3D), and svg isolation
(SVGLayoutSupport::IsIsolationRequired). Grouping properties
are specified in [1]. This patch reduces complexity and is likely to
improve performance with fewer checks in LayoutBox::LayerTypeRequired.

Box reflection (-webkit-box-reflect) only applies to boxes but is used
to create a stacking context for all objects. To avoid changing this
behavior, a parameter is used for HasGroupingProperty.

By recognizing CSS clip as a grouping property, compositing reason
finder is able to force layers for clips with composited descendants
(CSS clip -> HasClipRelatedProperty -> kClipsCompositingDescendants),
which results in some test changes.

[1] https://drafts.csswg.org/css-transforms-2/#grouping-property-values

Bug: 1068596
Change-Id: I86ca4a41b0324f2966c557dce6396b3bba684598
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2234541
Commit-Queue: Philip Rogers <pdr@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#776581}
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 4436e4c8..c9f5a37 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -266,9 +266,7 @@
 LayoutBox::~LayoutBox() = default;
 
 PaintLayerType LayoutBox::LayerTypeRequired() const {
-  // TODO(pdr): IsStacked() includes many of the same checks as CreatesGroup()
-  // and these can be unified to do fewer redundant checks.
-  if (IsStacked() || CreatesGroup() || HasHiddenBackface() ||
+  if (IsStacked() || HasHiddenBackface() ||
       (StyleRef().SpecifiesColumns() && !CanTraversePhysicalFragments()) ||
       IsEffectiveRootScroller())
     return kNormalPaintLayer;
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 1bd7786..b42ea96 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2137,9 +2137,8 @@
                                  TransformationMatrix&) const;
 
   bool CreatesGroup() const {
-    return StyleRef().HasOpacity() || HasMask() || HasClipPath() ||
-           HasFilterInducingProperty() || HasNonInitialBackdropFilter() ||
-           StyleRef().HasBlendMode();
+    // See |HasReflection()| for why |StyleRef().BoxReflect()| is not used.
+    return StyleRef().HasGroupingProperty(HasReflection());
   }
 
   Vector<PhysicalRect> OutlineRects(const PhysicalOffset& additional_offset,
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc
index 6fad3ca..6b6c5af1 100644
--- a/third_party/blink/renderer/core/layout/layout_object_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -95,15 +95,18 @@
     <div id=target2 style="will-change: backdrop-filter"></div>
     <div id=target3 style="position: relative"></div>
   )HTML");
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty());
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target1")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target2")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D());
 
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target3")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target3")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target3")->StyleRef().Preserves3D());
 }
 
@@ -115,12 +118,14 @@
     <div id=target1 style="mix-blend-mode: multiply"></div>
     <div id=target2 style="position: relative"></div>
   )HTML");
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target1")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D());
 
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target2")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D());
 }
 
@@ -134,15 +139,18 @@
     </div>
     <div id=target3 style="position: relative"></div>
   )HTML");
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target1")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D());
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target2")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D());
 
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target3")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target3")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target3")->StyleRef().Preserves3D());
 }
 
@@ -154,12 +162,14 @@
     <div id=target1 style="clip-path: circle(40%)"></div>
     <div id=target2 style="position: relative"></div>
   )HTML");
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target1")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D());
 
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target2")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D());
 }
 
@@ -171,12 +181,14 @@
     <div id=target1 style="isolation: isolate"></div>
     <div id=target2 style="position: relative"></div>
   )HTML");
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target1")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D());
 
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target2")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D());
 }
 
@@ -189,12 +201,14 @@
     </div>
     <div id=target2 style="position: relative"></div>
   )HTML");
-  EXPECT_TRUE(
-      GetLayoutObjectByElementId("target1")->StyleRef().HasGroupingProperty());
+  EXPECT_TRUE(GetLayoutObjectByElementId("target1")
+                  ->StyleRef()
+                  .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_FALSE(GetLayoutObjectByElementId("target1")->StyleRef().Preserves3D());
 
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target2")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target2")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetLayoutObjectByElementId("target2")->StyleRef().Preserves3D());
 }
 
@@ -203,8 +217,9 @@
     <style> div { transform-style: preserve-3d; } </style>
     <div id=target style="backdrop-filter: blur(2px)"></div>
   )HTML");
-  EXPECT_FALSE(
-      GetLayoutObjectByElementId("target")->StyleRef().HasGroupingProperty());
+  EXPECT_FALSE(GetLayoutObjectByElementId("target")
+                   ->StyleRef()
+                   .HasGroupingPropertyForUsedTransformStyle3D());
   EXPECT_TRUE(GetDocument().IsUseCounted(
       WebFeature::kAdditionalGroupingPropertiesForCompat));
 }
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc b/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
index 14eabbb..996b0bb 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
@@ -531,10 +531,8 @@
 
 bool SVGLayoutSupport::WillIsolateBlendingDescendantsForStyle(
     const ComputedStyle& style) {
-  const SVGComputedStyle& svg_style = style.SvgStyle();
-
-  return style.HasIsolation() || style.HasOpacity() || style.HasBlendMode() ||
-         style.HasFilter() || svg_style.HasMasker() || style.ClipPath();
+  return style.HasGroupingProperty(style.BoxReflect()) ||
+         style.SvgStyle().HasMasker();
 }
 
 bool SVGLayoutSupport::WillIsolateBlendingDescendantsForObject(
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
index ace8d80..237b057 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -56,11 +56,12 @@
 
   // If the implementation of CreatesGroup changes, we need to be aware of that
   // in this part of code.
-  DCHECK((style.HasOpacity() || layout_object.HasMask() ||
+  DCHECK((style.HasNonInitialOpacity() || layout_object.HasMask() ||
           layout_object.HasClipPath() ||
           layout_object.HasFilterInducingProperty() ||
-          layout_object.HasNonInitialBackdropFilter() ||
-          style.HasBlendMode()) == layout_object.CreatesGroup());
+          layout_object.HasNonInitialBackdropFilter() || style.HasBlendMode() ||
+          (!style.HasAutoClip() && style.HasOutOfFlowPosition()) ||
+          style.HasIsolation()) == layout_object.CreatesGroup());
 
   if (style.HasMask() || style.ClipPath())
     reasons |= CompositingReason::kMaskWithCompositedDescendants;
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc
index 8d3b1cd..4be57bac 100644
--- a/third_party/blink/renderer/core/style/computed_style.cc
+++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1050,17 +1050,6 @@
   return false;
 }
 
-bool ComputedStyle::HasGroupingProperty() const {
-  if (RuntimeEnabledFeatures::TransformInteropEnabled() &&
-      (HasNonInitialBackdropFilter() || HasBlendMode() ||
-       (!HasAutoClip() && HasOutOfFlowPosition()) || ClipPath() ||
-       HasIsolation() || HasMask()))
-    return true;
-
-  return !IsOverflowVisible() || HasFilterInducingProperty() ||
-         HasNonInitialOpacity();
-}
-
 void ComputedStyle::UpdateIsStackingContextWithoutContainment(
     bool is_document_element,
     bool is_in_top_layer,
@@ -1070,20 +1059,18 @@
 
   // Force a stacking context for transform-style: preserve-3d. This happens
   // even if preserves-3d is ignored due to a 'grouping property' being present
-  // which requires flattening. See ComputedStyle::UsedTransformStyle3D() and
-  // ComputedStyle::HasGroupingProperty().
+  // which requires flattening. See:
+  // ComputedStyle::HasGroupingPropertyForUsedTransformStyle3D().
   // This is legacy behavior that is left ambiguous in the official specs.
-  // See https://crbug.com/663650 for more details."
+  // See https://crbug.com/663650 for more details.
   if (TransformStyle3D() == ETransformStyle3D::kPreserve3d) {
     SetIsStackingContextWithoutContainment(true);
     return;
   }
 
   if (is_document_element || is_in_top_layer || is_svg_stacking ||
-      StyleType() == kPseudoIdBackdrop || HasOpacity() ||
-      HasTransformRelatedProperty() || HasMask() || ClipPath() ||
-      BoxReflect() || HasFilterInducingProperty() || HasBackdropFilter() ||
-      HasBlendMode() || HasIsolation() || HasViewportConstrainedPosition() ||
+      StyleType() == kPseudoIdBackdrop || HasTransformRelatedProperty() ||
+      HasGroupingProperty(BoxReflect()) || HasViewportConstrainedPosition() ||
       GetPosition() == EPosition::kSticky ||
       HasPropertyThatCreatesStackingContext(WillChangeProperties()) ||
       /* TODO(882625): This becomes unnecessary when will-change correctly takes
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index d026ca5..3f3a133 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2328,8 +2328,9 @@
     return !Transform().Operations().IsEmpty();
   }
   ETransformStyle3D UsedTransformStyle3D() const {
-    return HasGroupingProperty() ? ETransformStyle3D::kFlat
-                                 : TransformStyle3D();
+    return HasGroupingPropertyForUsedTransformStyle3D()
+               ? ETransformStyle3D::kFlat
+               : TransformStyle3D();
   }
   // Returns whether the transform operations for |otherStyle| differ from the
   // operations for this style instance. Note that callers may want to also
@@ -2390,12 +2391,46 @@
   }
 
   // Returns whether this style contains any grouping property as defined by
-  // [css-transforms].  The main purpose of this is to adjust the used value of
-  // transform-style property.
-  // Note: We currently don't include every grouping property on the spec to
-  // maintain backward compatibility.  [css-transforms]
-  // https://drafts.csswg.org/css-transforms/#grouping-property-values
-  CORE_EXPORT bool HasGroupingProperty() const;
+  // https://drafts.csswg.org/css-transforms-2/#grouping-property-values.
+  //
+  // |has_box_reflection| is a parameter instead of checking |BoxReflect()|
+  // because box reflection styles only apply for some objects (see:
+  // |LayoutObject::HasReflection()|).
+  bool HasGroupingProperty(bool has_box_reflection) const {
+    // TODO(pdr): Spec requires "overflow: any value other than visible or clip"
+    if (HasNonInitialOpacity())
+      return true;
+    if (HasNonInitialFilter())
+      return true;
+    if (has_box_reflection)
+      return true;
+    if (!HasAutoClip() && HasOutOfFlowPosition())
+      return true;
+    if (ClipPath())
+      return true;
+    if (HasIsolation())
+      return true;
+    if (HasMask())
+      return true;
+    if (HasBlendMode())
+      return true;
+    if (HasNonInitialBackdropFilter())
+      return true;
+    return false;
+  }
+
+  // Grouping requires creating a flattened representation of the descendant
+  // elements before they can be applied, and therefore force the element to
+  // have a used style of flat for preserve-3d.
+  // Until |RuntimeEnabledFeatures::TransformInteropEnabled()| launches, the
+  // approach is different from the spec to maintain backwards compatibility.
+  // TODO(chrishtr): replace this with |HasGroupingProperty()|.
+  CORE_EXPORT bool HasGroupingPropertyForUsedTransformStyle3D() const {
+    if (RuntimeEnabledFeatures::TransformInteropEnabled())
+      return HasGroupingProperty(BoxReflect()) || !IsOverflowVisible();
+    return !IsOverflowVisible() || HasFilterInducingProperty() ||
+           HasNonInitialOpacity();
+  }
 
   // Return true if any transform related property (currently
   // transform/motionPath, transformStyle3D, perspective, or
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
index 985efdd..09f0784 100644
--- a/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
@@ -16,10 +16,17 @@
       "transform": 2
     },
     {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='box'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited inner'",
       "bounds": [120, 120],
       "backgroundColor": "#00000033",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -48,7 +55,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [210, 10, 0, 1]
+        [220, 20, 0, 1]
       ]
     },
     {
@@ -58,6 +65,16 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
+        [-10, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     }
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
index 4ecd57ef..2970901 100644
--- a/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
@@ -17,10 +17,18 @@
       "transform": 2
     },
     {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='box'",
+      "position": [5, 15],
+      "bounds": [90, 80],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited inner'",
       "bounds": [120, 120],
       "backgroundColor": "#00000033",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -49,7 +57,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [210, 10, 0, 1]
+        [220, 20, 0, 1]
       ]
     },
     {
@@ -59,6 +67,16 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
+        [-10, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     }
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
index 1e39f033..9fd7490 100644
--- a/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
+++ b/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
@@ -14,10 +14,17 @@
       "transform": 2
     },
     {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='box'",
+      "position": [-2, -2],
+      "bounds": [106, 106],
+      "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
       "name": "LayoutNGBlockFlow (relative positioned) DIV class='composited inner'",
       "bounds": [120, 120],
       "backgroundColor": "#00000033",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -46,7 +53,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [210, 10, 0, 1]
+        [220, 20, 0, 1]
       ]
     },
     {
@@ -56,6 +63,16 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
+        [-10, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     }
diff --git a/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt b/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt
index f8b30f8..2716b85 100644
--- a/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt
+++ b/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt
@@ -7,44 +7,56 @@
       "backgroundColor": "#FFFFFF"
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='box'",
-      "bounds": [100, 150],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 2
+      "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
+      "position": [20, 10],
+      "bounds": [60, 70],
+      "transform": 1
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box'",
       "bounds": [100, 150],
       "contentsOpaque": true,
       "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
+      "position": [20, 10],
+      "bounds": [60, 70],
       "transform": 4
     },
     {
-      "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
-      "position": [20, 10],
-      "bounds": [60, 70],
-      "transform": 5
-    },
-    {
       "name": "LayoutNGBlockFlow DIV class='box'",
       "bounds": [100, 150],
       "contentsOpaque": true,
       "backgroundColor": "#808080",
+      "transform": 6
+    },
+    {
+      "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
+      "position": [20, 10],
+      "bounds": [60, 70],
       "transform": 7
     },
     {
+      "name": "LayoutNGBlockFlow DIV class='box'",
+      "bounds": [100, 150],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 9
+    },
+    {
       "name": "LayoutNGBlockFlow (positioned) DIV class='container'",
       "position": [20, 10],
       "bounds": [60, 70],
-      "transform": 8
+      "transform": 10
     },
     {
       "name": "LayoutNGBlockFlow DIV class='box'",
       "bounds": [100, 150],
       "contentsOpaque": true,
       "backgroundColor": "#808080",
-      "transform": 10
+      "transform": 12
     }
   ],
   "transforms": [
@@ -54,7 +66,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [50, 50, 0, 1]
+        [28, 28, 0, 1]
       ]
     },
     {
@@ -64,21 +76,12 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [0, 0, 1, 1]
+        [22, 22, 0, 1]
       ]
     },
     {
       "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [242, 50, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
+      "parent": 2,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
@@ -87,12 +90,22 @@
       ]
     },
     {
-      "id": 5,
+      "id": 4,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [28, 220, 0, 1]
+        [220, 28, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [22, 22, 0, 1]
       ]
     },
     {
@@ -102,26 +115,26 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [22, 22, 0, 1]
-      ]
-    },
-    {
-      "id": 7,
-      "parent": 6,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     },
     {
-      "id": 8,
+      "id": 7,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [220, 220, 0, 1]
+        [28, 220, 0, 1]
+      ]
+    },
+    {
+      "id": 8,
+      "parent": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [22, 22, 0, 1]
       ]
     },
     {
@@ -131,12 +144,31 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [22, 22, 0, 1]
+        [0, 0, 1, 1]
       ]
     },
     {
       "id": 10,
-      "parent": 9,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [220, 220, 0, 1]
+      ]
+    },
+    {
+      "id": 11,
+      "parent": 10,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [22, 22, 0, 1]
+      ]
+    },
+    {
+      "id": 12,
+      "parent": 11,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt
index e1486a7..01b0ef8 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-expected.txt
@@ -16,10 +16,17 @@
       "transform": 2
     },
     {
+      "name": "LayoutBlockFlow (positioned) DIV class='box'",
+      "bounds": [100, 100],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
       "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'",
       "bounds": [120, 120],
       "backgroundColor": "#00000033",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -48,7 +55,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [210, 10, 0, 1]
+        [220, 20, 0, 1]
       ]
     },
     {
@@ -58,6 +65,16 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
+        [-10, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt
index 6e4e9471..8521c86 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-inside-expected.txt
@@ -17,10 +17,18 @@
       "transform": 2
     },
     {
+      "name": "LayoutBlockFlow (positioned) DIV class='box'",
+      "position": [5, 15],
+      "bounds": [90, 80],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
       "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'",
       "bounds": [120, 120],
       "backgroundColor": "#00000033",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -49,7 +57,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [210, 10, 0, 1]
+        [220, 20, 0, 1]
       ]
     },
     {
@@ -59,6 +67,16 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
+        [-10, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt
index 3267a22..9c670e5 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/geometry/clip-with-shadow-expected.txt
@@ -14,10 +14,17 @@
       "transform": 2
     },
     {
+      "name": "LayoutBlockFlow (positioned) DIV class='box'",
+      "position": [-2, -2],
+      "bounds": [106, 106],
+      "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
       "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'",
       "bounds": [120, 120],
       "backgroundColor": "#00000033",
-      "transform": 4
+      "transform": 5
     }
   ],
   "transforms": [
@@ -46,7 +53,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [210, 10, 0, 1]
+        [220, 20, 0, 1]
       ]
     },
     {
@@ -56,6 +63,16 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
+        [-10, -10, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/clip-descendents-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/clip-descendents-expected.txt
index 51cba51..4fc9111 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/clip-descendents-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/clip-descendents-expected.txt
@@ -7,44 +7,56 @@
       "backgroundColor": "#FFFFFF"
     },
     {
-      "name": "LayoutBlockFlow DIV class='box'",
-      "bounds": [100, 150],
-      "contentsOpaque": true,
-      "backgroundColor": "#808080",
-      "transform": 2
+      "name": "LayoutBlockFlow (positioned) DIV class='container'",
+      "position": [20, 10],
+      "bounds": [60, 70],
+      "transform": 1
     },
     {
       "name": "LayoutBlockFlow DIV class='box'",
       "bounds": [100, 150],
       "contentsOpaque": true,
       "backgroundColor": "#808080",
+      "transform": 3
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='container'",
+      "position": [20, 10],
+      "bounds": [60, 70],
       "transform": 4
     },
     {
-      "name": "LayoutBlockFlow (positioned) DIV class='container'",
-      "position": [20, 10],
-      "bounds": [60, 70],
-      "transform": 5
-    },
-    {
       "name": "LayoutBlockFlow DIV class='box'",
       "bounds": [100, 150],
       "contentsOpaque": true,
       "backgroundColor": "#808080",
+      "transform": 6
+    },
+    {
+      "name": "LayoutBlockFlow (positioned) DIV class='container'",
+      "position": [20, 10],
+      "bounds": [60, 70],
       "transform": 7
     },
     {
+      "name": "LayoutBlockFlow DIV class='box'",
+      "bounds": [100, 150],
+      "contentsOpaque": true,
+      "backgroundColor": "#808080",
+      "transform": 9
+    },
+    {
       "name": "LayoutBlockFlow (positioned) DIV class='container'",
       "position": [20, 10],
       "bounds": [60, 70],
-      "transform": 8
+      "transform": 10
     },
     {
       "name": "LayoutBlockFlow DIV class='box'",
       "bounds": [100, 150],
       "contentsOpaque": true,
       "backgroundColor": "#808080",
-      "transform": 10
+      "transform": 12
     }
   ],
   "transforms": [
@@ -54,7 +66,7 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [50, 50, 0, 1]
+        [28, 28, 0, 1]
       ]
     },
     {
@@ -64,21 +76,12 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [0, 0, 1, 1]
+        [22, 22, 0, 1]
       ]
     },
     {
       "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [242, 50, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
+      "parent": 2,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
@@ -87,12 +90,22 @@
       ]
     },
     {
-      "id": 5,
+      "id": 4,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [28, 220, 0, 1]
+        [220, 28, 0, 1]
+      ]
+    },
+    {
+      "id": 5,
+      "parent": 4,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [22, 22, 0, 1]
       ]
     },
     {
@@ -102,26 +115,26 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [22, 22, 0, 1]
-      ]
-    },
-    {
-      "id": 7,
-      "parent": 6,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
         [0, 0, 1, 1]
       ]
     },
     {
-      "id": 8,
+      "id": 7,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [220, 220, 0, 1]
+        [28, 220, 0, 1]
+      ]
+    },
+    {
+      "id": 8,
+      "parent": 7,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [22, 22, 0, 1]
       ]
     },
     {
@@ -131,12 +144,31 @@
         [1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
-        [22, 22, 0, 1]
+        [0, 0, 1, 1]
       ]
     },
     {
       "id": 10,
-      "parent": 9,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [220, 220, 0, 1]
+      ]
+    },
+    {
+      "id": 11,
+      "parent": 10,
+      "transform": [
+        [1, 0, 0, 0],
+        [0, 1, 0, 0],
+        [0, 0, 1, 0],
+        [22, 22, 0, 1]
+      ]
+    },
+    {
+      "id": 12,
+      "parent": 11,
       "transform": [
         [1, 0, 0, 0],
         [0, 1, 0, 0],