cc: Fix computation of layer backfacing-ness when using property trees

When using property trees, layers whose transform is tested for
backfacing-ness might not have up-to-date draw properties (e.g.,
such layers might not draw content). This means that instead of
using the layer's draw_transform() draw property, we need to
call DrawTransformFromPropertyTrees.

BUG=553580
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

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

Cr-Commit-Position: refs/heads/master@{#358683}
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 649f6c2..345182c 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -445,14 +445,22 @@
   return layer->Is3dSorted();
 }
 
-static bool IsLayerBackFaceVisible(LayerImpl* layer) {
+static bool IsLayerBackFaceVisible(LayerImpl* layer,
+                                   bool use_property_trees,
+                                   const TransformTree& transform_tree) {
   // The current W3C spec on CSS transforms says that backface visibility should
   // be determined differently depending on whether the layer is in a "3d
   // rendering context" or not. For Chromium code, we can determine whether we
   // are in a 3d rendering context by checking if the parent preserves 3d.
 
-  if (LayerIsInExisting3DRenderingContext(layer))
-    return layer->draw_transform().IsBackFaceVisible();
+  if (LayerIsInExisting3DRenderingContext(layer)) {
+    if (use_property_trees) {
+      return DrawTransformFromPropertyTrees(layer, transform_tree)
+          .IsBackFaceVisible();
+    } else {
+      return layer->draw_transform().IsBackFaceVisible();
+    }
+  }
 
   // In this case, either the layer establishes a new 3d rendering context, or
   // is not in a 3d rendering context at all.
@@ -519,7 +527,10 @@
       layer_rect_in_target_space, layer->draw_transform());
 }
 
-static bool LayerShouldBeSkipped(LayerImpl* layer, bool layer_is_drawn) {
+static bool LayerShouldBeSkipped(LayerImpl* layer,
+                                 bool layer_is_drawn,
+                                 bool use_property_trees,
+                                 const TransformTree& transform_tree) {
   // Layers can be skipped if any of these conditions are met.
   //   - is not drawn due to it or one of its ancestors being hidden (or having
   //     no copy requests).
@@ -553,7 +564,8 @@
   // The layer should not be drawn if (1) it is not double-sided and (2) the
   // back of the layer is known to be facing the screen.
   if (!backface_test_layer->double_sided() &&
-      IsLayerBackFaceVisible(backface_test_layer))
+      IsLayerBackFaceVisible(backface_test_layer, use_property_trees,
+                             transform_tree))
     return true;
 
   return false;
@@ -2542,7 +2554,9 @@
 
   size_t descendants_size = descendants->size();
 
-  bool layer_should_be_skipped = LayerShouldBeSkipped(layer, layer_is_drawn);
+  bool layer_should_be_skipped =
+      LayerShouldBeSkipped(layer, layer_is_drawn, use_property_trees,
+                           property_trees->transform_tree);
   if (!layer_should_be_skipped) {
     MarkLayerWithRenderSurfaceLayerListId(layer,
                                           current_render_surface_layer_list_id);
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index e42460d..5e862ef 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -6067,6 +6067,48 @@
                     .size());
 }
 
+TEST_F(LayerTreeHostCommonTest, DoNotIncludeBackfaceInvisibleLayers) {
+  LayerImpl* root = root_layer();
+  LayerImpl* child = AddChild<LayerImpl>(root);
+  LayerImpl* grand_child = AddChild<LayerImpl>(child);
+  grand_child->SetDrawsContent(true);
+
+  child->SetDoubleSided(false);
+  grand_child->SetUseParentBackfaceVisibility(true);
+
+  gfx::Transform identity_transform;
+  SetLayerPropertiesForTesting(root, identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(50, 50), false, true,
+                               true);
+  SetLayerPropertiesForTesting(child, identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(30, 30), false, true,
+                               false);
+  SetLayerPropertiesForTesting(grand_child, identity_transform, gfx::Point3F(),
+                               gfx::PointF(), gfx::Size(20, 20), false, true,
+                               false);
+
+  ExecuteCalculateDrawProperties(root);
+
+  EXPECT_EQ(1u, render_surface_layer_list_impl()->size());
+  EXPECT_EQ(grand_child, render_surface_layer_list_impl()
+                             ->at(0)
+                             ->render_surface()
+                             ->layer_list()[0]);
+  gfx::Transform rotation_transform = identity_transform;
+  rotation_transform.RotateAboutXAxis(180.0);
+
+  child->SetTransform(rotation_transform);
+  child->layer_tree_impl()->property_trees()->needs_rebuild = true;
+
+  ExecuteCalculateDrawProperties(root);
+  EXPECT_EQ(1u, render_surface_layer_list_impl()->size());
+  EXPECT_EQ(0u, render_surface_layer_list_impl()
+                    ->at(0)
+                    ->render_surface()
+                    ->layer_list()
+                    .size());
+}
+
 TEST_F(LayerTreeHostCommonTest, ClippedByScrollParent) {
   // Checks that the simple case (being clipped by a scroll parent that would
   // have been processed before you anyhow) results in the right clips.