Support backface-visibility in spv2

In slimming paint v2, backface visibility is a property of a paint
chunks (aka a sequence of display items with the same paint props). This
patch adds a new bool to PaintChunkProperties for whether a chunk's
backface is hidden.

LocalBorderBoxProperties has been refactored to only contain the local
border box properties and not all paint chunk properties, which should
make it more clear that paint chunk properties (such as the new
backfaceHidden property) are not set in the paint property tree builder.

There is a large remaining task to implement preserves3D which is the
common usecase for backface visibility.

Backface-visibility is treated as stacking context property in this
change, as it is currently in blink. A followup email to public-fx will
be sent out for more clarification.

BUG=587236

Review URL: https://codereview.chromium.org/1715113002

Cr-Commit-Position: refs/heads/master@{#376922}
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 1f86336..92b746b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -452,6 +452,8 @@
 crbug.com/580355 virtual/spv2/fast/block/positioning/height-change.html [ Pass ]
 crbug.com/580355 virtual/spv2/fast/block/positioning/relayout-on-position-change.html [ Pass ]
 crbug.com/537409 virtual/spv2/svg/as-image/svg-image-with-data-uri.html [ Pass ]
+crbug.com/587236 virtual/spv2/compositing/backface-visibility/backface-visibility-3d.html [ Pass ]
+crbug.com/587236 virtual/spv2/compositing/backface-visibility/backface-visibility-simple.html [ Pass ]
 
 # In imported/web-platform-tests/html/, we prefer checking in failure
 # expectation files. The following tests with [ Failure ] don't have failure
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 7998578b..c43f70b6 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -190,7 +190,7 @@
   },
   {
     "prefix": "spv2",
-    "base": "paint",
+    "base": "compositing",
     "args": ["--enable-slimming-paint-v2"]
   },
   {
@@ -205,6 +205,11 @@
   },
   {
     "prefix": "spv2",
+    "base": "paint",
+    "args": ["--enable-slimming-paint-v2"]
+  },
+  {
+    "prefix": "spv2",
     "base": "svg",
     "args": ["--enable-slimming-paint-v2"]
   },
diff --git a/third_party/WebKit/LayoutTests/virtual/spv2/compositing/README.txt b/third_party/WebKit/LayoutTests/virtual/spv2/compositing/README.txt
new file mode 100644
index 0000000..89dba61c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/spv2/compositing/README.txt
@@ -0,0 +1,3 @@
+# This suite runs tests with --enable-slimming-paint-v2
+# We also have try bots running full set of layout tests for spv2:
+# https://codereview.chromium.org/1283823002
diff --git a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
index fbdf7f7..4928441 100644
--- a/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
+++ b/third_party/WebKit/Source/core/paint/ObjectPaintProperties.h
@@ -64,7 +64,9 @@
     // at the right painting step.
     struct LocalBorderBoxProperties {
         LayoutPoint paintOffset;
-        PaintChunkProperties properties;
+        RefPtr<TransformPaintPropertyNode> transform;
+        RefPtr<ClipPaintPropertyNode> clip;
+        RefPtr<EffectPaintPropertyNode> effect;
     };
     LocalBorderBoxProperties* localBorderBoxProperties() const { return m_localBorderBoxProperties.get(); }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index 0f75f58..247131c 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -348,7 +348,13 @@
         if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
             ObjectPaintProperties* objectPaintProperties = m_paintLayer.layoutObject()->objectPaintProperties();
             ASSERT(objectPaintProperties && objectPaintProperties->localBorderBoxProperties());
-            scopedPaintChunkProperties.emplace(context.paintController(),  objectPaintProperties->localBorderBoxProperties()->properties);
+            PaintChunkProperties properties(context.paintController().currentPaintChunkProperties());
+            auto& localBorderBoxProperties = *objectPaintProperties->localBorderBoxProperties();
+            properties.transform = localBorderBoxProperties.transform;
+            properties.clip = localBorderBoxProperties.clip;
+            properties.effect = localBorderBoxProperties.effect;
+            properties.backfaceHidden = m_paintLayer.layoutObject()->hasHiddenBackface();
+            scopedPaintChunkProperties.emplace(context.paintController(), properties);
         }
 
         bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index e534ded..82db72a7 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -319,9 +319,9 @@
 
     OwnPtr<ObjectPaintProperties::LocalBorderBoxProperties> recordedContext = adoptPtr(new ObjectPaintProperties::LocalBorderBoxProperties);
     recordedContext->paintOffset = context.paintOffset;
-    recordedContext->properties.transform = context.currentTransform;
-    recordedContext->properties.clip = context.currentClip;
-    recordedContext->properties.effect = context.currentEffect;
+    recordedContext->transform = context.currentTransform;
+    recordedContext->clip = context.currentClip;
+    recordedContext->effect = context.currentEffect;
     return recordedContext.release();
 }
 
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index d7e91ef..1e3ffb8 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -594,9 +594,9 @@
     LayoutObject& child = *document().getElementById("child")->layoutObject();
     ObjectPaintProperties* childProperties = child.objectPaintProperties();
 
-    EXPECT_EQ(scrollerProperties->overflowClip(), childProperties->localBorderBoxProperties()->properties.clip);
-    EXPECT_EQ(scrollerProperties->scrollTranslation(), childProperties->localBorderBoxProperties()->properties.transform);
-    EXPECT_EQ(nullptr, childProperties->localBorderBoxProperties()->properties.effect);
+    EXPECT_EQ(scrollerProperties->overflowClip(), childProperties->localBorderBoxProperties()->clip);
+    EXPECT_EQ(scrollerProperties->scrollTranslation(), childProperties->localBorderBoxProperties()->transform);
+    EXPECT_EQ(nullptr, childProperties->localBorderBoxProperties()->effect);
 }
 
 TEST_F(PaintPropertyTreeBuilderTest, TreeContextUnclipFromParentStackingContext)
@@ -619,9 +619,9 @@
     LayoutObject& child = *document().getElementById("child")->layoutObject();
     ObjectPaintProperties* childProperties = child.objectPaintProperties();
 
-    EXPECT_EQ(frameView->contentClip(), childProperties->localBorderBoxProperties()->properties.clip);
-    EXPECT_EQ(frameView->scrollTranslation(), childProperties->localBorderBoxProperties()->properties.transform);
-    EXPECT_EQ(scrollerProperties->effect(), childProperties->localBorderBoxProperties()->properties.effect);
+    EXPECT_EQ(frameView->contentClip(), childProperties->localBorderBoxProperties()->clip);
+    EXPECT_EQ(frameView->scrollTranslation(), childProperties->localBorderBoxProperties()->transform);
+    EXPECT_EQ(scrollerProperties->effect(), childProperties->localBorderBoxProperties()->effect);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
index 6592c1a..061be13 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
@@ -274,6 +274,7 @@
         layer->SetBounds(combinedBounds.size());
         layer->SetTransform(transform);
         layer->SetIsDrawable(true);
+        layer->SetDoubleSided(!paintChunk.properties.backfaceHidden);
         if (paintChunk.knownToBeOpaque)
             layer->SetContentsOpaque(true);
         layer->SetNeedsDisplay();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h
index 14f5e1e2..57e65d2 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintChunkProperties.h
@@ -25,10 +25,14 @@
 // for each type (e.g., either transform or perspective, but not both).
 struct PaintChunkProperties {
     DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
-    // TODO(pdr): Add clip and scroll properties.
+
+    PaintChunkProperties() : backfaceHidden(false) { }
+
+    // TODO(pdr): Add scroll properties.
     RefPtr<TransformPaintPropertyNode> transform;
     RefPtr<ClipPaintPropertyNode> clip;
     RefPtr<EffectPaintPropertyNode> effect;
+    bool backfaceHidden;
 };
 
 // Equality is based only on the pointers and is not 'deep' which would require
@@ -37,7 +41,8 @@
 {
     return a.transform.get() == b.transform.get()
         && a.clip.get() == b.clip.get()
-        && a.effect.get() == b.effect.get();
+        && a.effect.get() == b.effect.get()
+        && a.backfaceHidden == b.backfaceHidden;
 }
 
 inline bool operator!=(const PaintChunkProperties& a, const PaintChunkProperties& b)
diff --git a/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp b/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp
index 259d82fe..abd6383 100644
--- a/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp
+++ b/third_party/WebKit/Source/platform/testing/PaintPrinters.cpp
@@ -55,10 +55,33 @@
 void PrintTo(const PaintChunkProperties& properties, std::ostream* os)
 {
     *os << "PaintChunkProperties(";
+    bool printedProperty = false;
     if (properties.transform) {
         *os << "transform=";
         PrintTo(*properties.transform, os);
+        printedProperty = true;
     }
+
+    if (properties.clip) {
+        if (printedProperty)
+            *os << ", ";
+        *os << "clip=";
+        PrintTo(*properties.clip, os);
+        printedProperty = true;
+    }
+
+    if (properties.effect) {
+        if (printedProperty)
+            *os << ", ";
+        *os << "effect=";
+        PrintTo(*properties.effect, os);
+        printedProperty = true;
+    }
+
+    if (printedProperty)
+        *os << ", ";
+    *os << "backfaceHidden=" << properties.backfaceHidden;
+
     *os << ")";
 }