[go: nahoru, domu]

Refactor cc unittests in layer list mode

When in layer list mode:

- Initialize root properties in LayerTreeTest::SetupTree()
- Provide LayerTreeTest::SetupViewport() (previously global function
  CreateVirtualViewportLayers in layer_tree_test.h). A test needing
  viewport layers and properties can call it from its SetupTree().
- Tests setup their layers and properties in SetupTree().

property_tree_test_utils.h provides helper functions for convenience
of tests to setup properties in the following way:

  scoped_refptr<Layer> layer = Layer::Create();
  ...
  InheritProperties(layer.get(), parent_layer_for_properties);
  auto& transform_node = CreateTransform(layer.get());
  transform_node.xxx = // customize the transform node
  root_layer->AddChild(layer);

This changes the procedure of pixel tests in layer list mode when
setting up layers and properties. Previously we setup property tree
outside of SetupTree() before BeginTest() when layer_tree_host() was
not created yet, causing many inconveninces. Now we always setup
layers and properties in SetupTree().

Bug: 994361
Change-Id: I2b3c0a47037c685618372bdff389551e09b62634
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1761642
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Reviewed-by: enne <enne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689149}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 4ee36cf..91ec472ce 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -484,6 +484,8 @@
     "test/pixel_test_output_surface.h",
     "test/pixel_test_utils.cc",
     "test/pixel_test_utils.h",
+    "test/property_tree_test_utils.cc",
+    "test/property_tree_test_utils.h",
     "test/push_properties_counting_layer.cc",
     "test/push_properties_counting_layer.h",
     "test/push_properties_counting_layer_impl.cc",
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index f517b73..61c2695b 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -128,11 +128,8 @@
 }
 
 void LayerTreeHostPixelResourceTest::RunPixelResourceTestWithLayerList(
-    scoped_refptr<Layer> root_layer,
-    base::FilePath file_name,
-    PropertyTrees* property_trees) {
-  RunPixelTestWithLayerList(renderer_type(), root_layer, file_name,
-                            property_trees);
+    base::FilePath file_name) {
+  RunPixelTestWithLayerList(renderer_type(), file_name);
 }
 
 ParameterizedPixelResourceTest::ParameterizedPixelResourceTest()
diff --git a/cc/test/layer_tree_pixel_resource_test.h b/cc/test/layer_tree_pixel_resource_test.h
index b77c9ad7..f7981de 100644
--- a/cc/test/layer_tree_pixel_resource_test.h
+++ b/cc/test/layer_tree_pixel_resource_test.h
@@ -42,9 +42,7 @@
   void RunPixelResourceTest(scoped_refptr<Layer> content_root,
                             const SkBitmap& expected_bitmap);
 
-  void RunPixelResourceTestWithLayerList(scoped_refptr<Layer> root_layer,
-                                         base::FilePath file_name,
-                                         PropertyTrees* property_trees);
+  void RunPixelResourceTestWithLayerList(base::FilePath file_name);
 
  protected:
   PixelResourceTestCase test_case_;
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index f58569c..c96e0ac6 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -39,7 +39,6 @@
 
 LayerTreePixelTest::LayerTreePixelTest()
     : pixel_comparator_(new ExactPixelComparator(true)),
-      property_trees_(nullptr),
       pending_texture_mailbox_callbacks_(0) {}
 
 LayerTreePixelTest::~LayerTreePixelTest() = default;
@@ -140,7 +139,7 @@
 void LayerTreePixelTest::BeginTest() {
   Layer* target =
       readback_target_ ? readback_target_ : layer_tree_host()->root_layer();
-  if (!property_trees_) {
+  if (!layer_tree_host()->IsUsingLayerLists()) {
     target->RequestCopyOfOutput(CreateCopyOutputRequest());
   } else {
     layer_tree_host()->property_trees()->effect_tree.AddCopyRequest(
@@ -260,51 +259,14 @@
   RunTest(CompositorMode::THREADED);
 }
 
-void LayerTreePixelTest::RunPixelTestWithLayerList(
-    RendererType renderer_type,
-    scoped_refptr<Layer> root_layer,
-    base::FilePath file_name,
-    PropertyTrees* property_trees) {
+void LayerTreePixelTest::RunPixelTestWithLayerList(RendererType renderer_type,
+                                                   base::FilePath file_name) {
   renderer_type_ = renderer_type;
-  content_root_ = root_layer;
-  property_trees_ = property_trees;
   readback_target_ = nullptr;
   ref_file_ = file_name;
   RunTest(CompositorMode::THREADED);
 }
 
-void LayerTreePixelTest::InitializeForLayerListMode(
-    scoped_refptr<Layer>* root_layer,
-    PropertyTrees* property_trees) {
-  ClipNode clip_node;
-  property_trees->clip_tree.Insert(clip_node, 0);
-
-  EffectNode root_effect;
-  root_effect.clip_id = 1;
-  root_effect.stable_id = 1;
-  root_effect.transform_id = 1;
-  root_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  property_trees->effect_tree.Insert(root_effect, 0);
-
-  ScrollNode scroll_node;
-  property_trees->scroll_tree.Insert(scroll_node, 0);
-
-  TransformTree& transform_tree = property_trees->transform_tree;
-  auto& transform_node =
-      *transform_tree.Node(transform_tree.Insert(TransformNode(), 0));
-  transform_node.source_node_id = transform_node.parent_id;
-  transform_tree.set_needs_update(true);
-
-  *root_layer = Layer::Create();
-  (*root_layer)->SetBounds(gfx::Size(100, 100));
-  (*root_layer)->SetEffectTreeIndex(1);
-  (*root_layer)->SetClipTreeIndex(1);
-  (*root_layer)->SetScrollTreeIndex(1);
-  (*root_layer)->SetTransformTreeIndex(1);
-  (*root_layer)
-      ->set_property_tree_sequence_number(property_trees->sequence_number);
-}
-
 void LayerTreePixelTest::RunSingleThreadedPixelTest(
     RendererType renderer_type,
     scoped_refptr<Layer> content_root,
@@ -329,16 +291,16 @@
 }
 
 void LayerTreePixelTest::SetupTree() {
-  if (property_trees_) {
-    layer_tree_host()->SetRootLayer(content_root_);
-    layer_tree_host()->SetPropertyTreesForTesting(property_trees_);
-  } else {
-    scoped_refptr<Layer> root = Layer::Create();
-    root->SetBounds(content_root_->bounds());
-    root->AddChild(content_root_);
-    layer_tree_host()->SetRootLayer(root);
+  if (layer_tree_host()->IsUsingLayerLists()) {
+    // In layer list mode, content_root_ is not used. The subclass should call
+    // SetInitialRootBounds() if needed.
+    LayerTreeTest::SetupTree();
+    return;
   }
+
+  SetInitialRootBounds(content_root_->bounds());
   LayerTreeTest::SetupTree();
+  layer_tree_host()->root_layer()->AddChild(content_root_);
 }
 
 SkBitmap LayerTreePixelTest::CopyMailboxToBitmap(
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h
index 6ddbdec..78af828 100644
--- a/cc/test/layer_tree_pixel_test.h
+++ b/cc/test/layer_tree_pixel_test.h
@@ -78,12 +78,6 @@
       int border_width,
       SkColor border_color);
 
-  // Initializes the root layer and root PropertyTrees for layer list mode.
-  // In this mode, all other layers are direct children of |root_layer| and
-  // any property nodes are descendants of node id 1 in the respective trees.
-  void InitializeForLayerListMode(scoped_refptr<Layer>* root_layer,
-                                  PropertyTrees* property_trees);
-
   void RunPixelTest(RendererType renderer_type,
                     scoped_refptr<Layer> content_root,
                     base::FilePath file_name);
@@ -93,9 +87,7 @@
                     const SkBitmap& expected_bitmap);
 
   void RunPixelTestWithLayerList(RendererType renderer_type,
-                                 scoped_refptr<Layer> root_layer,
-                                 base::FilePath file_name,
-                                 PropertyTrees* property_trees);
+                                 base::FilePath file_name);
 
   void RunSingleThreadedPixelTest(RendererType renderer_type,
                                   scoped_refptr<Layer> content_root,
@@ -129,8 +121,7 @@
 
   gl::DisableNullDrawGLBindings enable_pixel_output_;
   std::unique_ptr<PixelComparator> pixel_comparator_;
-  scoped_refptr<Layer> content_root_;
-  PropertyTrees* property_trees_;
+  scoped_refptr<Layer> content_root_;  // Not used in layer list mode.
   Layer* readback_target_;
   base::FilePath ref_file_;
   SkBitmap expected_bitmap_;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 51368c5..15db8ec 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -134,66 +134,6 @@
 
 }  // namespace
 
-void CreateVirtualViewportLayers(Layer* root_layer,
-                                 scoped_refptr<Layer> outer_scroll_layer,
-                                 const gfx::Size& inner_bounds,
-                                 const gfx::Size& outer_bounds,
-                                 LayerTreeHost* host) {
-  scoped_refptr<Layer> inner_viewport_container_layer = Layer::Create();
-  scoped_refptr<Layer> overscroll_elasticity_layer = Layer::Create();
-  scoped_refptr<Layer> inner_viewport_scroll_layer = Layer::Create();
-  scoped_refptr<Layer> outer_viewport_container_layer = Layer::Create();
-  scoped_refptr<Layer> page_scale_layer = Layer::Create();
-
-  root_layer->AddChild(inner_viewport_container_layer);
-  inner_viewport_container_layer->AddChild(overscroll_elasticity_layer);
-  overscroll_elasticity_layer->AddChild(page_scale_layer);
-  page_scale_layer->AddChild(inner_viewport_scroll_layer);
-  inner_viewport_scroll_layer->AddChild(outer_viewport_container_layer);
-  outer_viewport_container_layer->AddChild(outer_scroll_layer);
-
-  inner_viewport_scroll_layer->SetElementId(
-      LayerIdToElementIdForTesting(inner_viewport_scroll_layer->id()));
-  outer_scroll_layer->SetElementId(
-      LayerIdToElementIdForTesting(outer_scroll_layer->id()));
-  overscroll_elasticity_layer->SetElementId(
-      LayerIdToElementIdForTesting(overscroll_elasticity_layer->id()));
-
-  inner_viewport_container_layer->SetBounds(inner_bounds);
-  inner_viewport_scroll_layer->SetScrollable(inner_bounds);
-  inner_viewport_scroll_layer->SetHitTestable(true);
-  inner_viewport_scroll_layer->SetBounds(outer_bounds);
-  outer_viewport_container_layer->SetBounds(outer_bounds);
-  outer_scroll_layer->SetScrollable(outer_bounds);
-  outer_scroll_layer->SetHitTestable(true);
-
-  inner_viewport_scroll_layer->SetIsContainerForFixedPositionLayers(true);
-  outer_scroll_layer->SetIsContainerForFixedPositionLayers(true);
-  ViewportLayers viewport_layers;
-  viewport_layers.overscroll_elasticity_element_id =
-      overscroll_elasticity_layer->element_id();
-  viewport_layers.page_scale = page_scale_layer;
-  viewport_layers.inner_viewport_container = inner_viewport_container_layer;
-  viewport_layers.outer_viewport_container = outer_viewport_container_layer;
-  viewport_layers.inner_viewport_scroll = inner_viewport_scroll_layer;
-  viewport_layers.outer_viewport_scroll = outer_scroll_layer;
-  host->RegisterViewportLayers(viewport_layers);
-}
-
-void CreateVirtualViewportLayers(Layer* root_layer,
-                                 const gfx::Size& inner_bounds,
-                                 const gfx::Size& outer_bounds,
-                                 const gfx::Size& scroll_bounds,
-                                 LayerTreeHost* host) {
-  scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create();
-
-  outer_viewport_scroll_layer->SetBounds(scroll_bounds);
-  outer_viewport_scroll_layer->SetIsDrawable(true);
-  outer_viewport_scroll_layer->SetHitTestable(true);
-  CreateVirtualViewportLayers(root_layer, outer_viewport_scroll_layer,
-                              inner_bounds, outer_bounds, host);
-}
-
 // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks.
 class LayerTreeHostImplForTesting : public LayerTreeHostImpl {
  public:
@@ -634,7 +574,8 @@
 };
 
 LayerTreeTest::LayerTreeTest()
-    : layer_tree_frame_sink_client_(
+    : initial_root_bounds_(1, 1),
+      layer_tree_frame_sink_client_(
           new LayerTreeTestLayerTreeFrameSinkClient(this)) {
   main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
 
@@ -896,22 +837,103 @@
   }
 }
 
-void LayerTreeTest::SetupTree() {
-  if (!layer_tree_host()->root_layer()) {
-    scoped_refptr<Layer> root_layer = Layer::Create();
-    root_layer->SetBounds(gfx::Size(1, 1));
-    layer_tree_host()->SetRootLayer(root_layer);
+void LayerTreeTest::SetupViewport(scoped_refptr<Layer> outer_scroll_layer,
+                                  const gfx::Size& outer_bounds) {
+  Layer* root = layer_tree_host()->root_layer();
+  DCHECK(root);
+  scoped_refptr<Layer> inner_viewport_container_layer = Layer::Create();
+  scoped_refptr<Layer> overscroll_elasticity_layer = Layer::Create();
+  scoped_refptr<Layer> inner_viewport_scroll_layer = Layer::Create();
+  scoped_refptr<Layer> outer_viewport_container_layer = Layer::Create();
+  scoped_refptr<Layer> page_scale_layer = Layer::Create();
+
+  inner_viewport_scroll_layer->SetElementId(
+      LayerIdToElementIdForTesting(inner_viewport_scroll_layer->id()));
+  outer_scroll_layer->SetElementId(
+      LayerIdToElementIdForTesting(outer_scroll_layer->id()));
+  overscroll_elasticity_layer->SetElementId(
+      LayerIdToElementIdForTesting(overscroll_elasticity_layer->id()));
+
+  inner_viewport_container_layer->SetBounds(root->bounds());
+  inner_viewport_scroll_layer->SetScrollable(root->bounds());
+  inner_viewport_scroll_layer->SetHitTestable(true);
+  inner_viewport_scroll_layer->SetBounds(outer_bounds);
+  outer_viewport_container_layer->SetBounds(outer_bounds);
+  outer_scroll_layer->SetScrollable(outer_bounds);
+  outer_scroll_layer->SetHitTestable(true);
+
+  root->AddChild(inner_viewport_container_layer);
+  if (layer_tree_host()->IsUsingLayerLists()) {
+    root->AddChild(overscroll_elasticity_layer);
+    root->AddChild(page_scale_layer);
+    root->AddChild(inner_viewport_scroll_layer);
+    root->AddChild(outer_viewport_container_layer);
+    root->AddChild(outer_scroll_layer);
+
+    CopyProperties(root, inner_viewport_container_layer.get());
+    CopyProperties(inner_viewport_container_layer.get(),
+                   overscroll_elasticity_layer.get());
+    CreateTransformNode(overscroll_elasticity_layer.get());
+    CopyProperties(overscroll_elasticity_layer.get(), page_scale_layer.get());
+    CreateTransformNode(page_scale_layer.get());
+    CopyProperties(page_scale_layer.get(), inner_viewport_scroll_layer.get());
+    CopyProperties(inner_viewport_scroll_layer.get(),
+                   outer_viewport_container_layer.get());
+    CopyProperties(outer_viewport_container_layer.get(),
+                   outer_scroll_layer.get());
+    // TODO(wangxianzhu): Create other property nodes when they are needed by
+    // tests newly converted to layer list mode.
+  } else {
+    inner_viewport_container_layer->AddChild(overscroll_elasticity_layer);
+    overscroll_elasticity_layer->AddChild(page_scale_layer);
+    page_scale_layer->AddChild(inner_viewport_scroll_layer);
+    inner_viewport_scroll_layer->AddChild(outer_viewport_container_layer);
+    outer_viewport_container_layer->AddChild(outer_scroll_layer);
+
+    inner_viewport_scroll_layer->SetIsContainerForFixedPositionLayers(true);
+    outer_scroll_layer->SetIsContainerForFixedPositionLayers(true);
+    layer_tree_host()->property_trees()->needs_rebuild = true;
   }
 
-  gfx::Size root_bounds = layer_tree_host()->root_layer()->bounds();
+  ViewportLayers viewport_layers;
+  viewport_layers.overscroll_elasticity_element_id =
+      overscroll_elasticity_layer->element_id();
+  viewport_layers.page_scale = page_scale_layer;
+  viewport_layers.inner_viewport_container = inner_viewport_container_layer;
+  viewport_layers.outer_viewport_container = outer_viewport_container_layer;
+  viewport_layers.inner_viewport_scroll = inner_viewport_scroll_layer;
+  viewport_layers.outer_viewport_scroll = outer_scroll_layer;
+  layer_tree_host()->RegisterViewportLayers(viewport_layers);
+}
+
+void LayerTreeTest::SetupViewport(const gfx::Size& outer_bounds,
+                                  const gfx::Size& scroll_bounds) {
+  scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create();
+  outer_viewport_scroll_layer->SetBounds(scroll_bounds);
+  outer_viewport_scroll_layer->SetIsDrawable(true);
+  outer_viewport_scroll_layer->SetHitTestable(true);
+  SetupViewport(outer_viewport_scroll_layer, outer_bounds);
+}
+
+void LayerTreeTest::SetupTree() {
+  if (!layer_tree_host()->root_layer()) {
+    layer_tree_host()->SetRootLayer(Layer::Create());
+    layer_tree_host()->root_layer()->SetBounds(initial_root_bounds_);
+  }
+
+  Layer* root_layer = layer_tree_host()->root_layer();
+  gfx::Size root_bounds = root_layer->bounds();
   gfx::Size device_root_bounds =
       gfx::ScaleToCeiledSize(root_bounds, initial_device_scale_factor_);
   layer_tree_host()->SetViewportSizeAndScale(device_root_bounds,
                                              initial_device_scale_factor_,
                                              viz::LocalSurfaceIdAllocation());
-  layer_tree_host()->root_layer()->SetIsDrawable(true);
-  layer_tree_host()->root_layer()->SetHitTestable(true);
+  root_layer->SetIsDrawable(true);
+  root_layer->SetHitTestable(true);
   layer_tree_host()->SetElementIdsForTesting();
+
+  if (layer_tree_host()->IsUsingLayerLists())
+    SetupRootProperties(root_layer);
 }
 
 void LayerTreeTest::Timeout() {
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 97ac4b4..743351a 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -8,6 +8,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread.h"
 #include "cc/animation/animation_delegate.h"
+#include "cc/test/property_tree_test_utils.h"
 #include "cc/test/test_hooks.h"
 #include "cc/test/test_task_graph_runner.h"
 #include "cc/trees/compositor_mode.h"
@@ -33,23 +34,6 @@
 class TestLayerTreeFrameSink;
 class TestTaskGraphRunner;
 
-// Creates the virtual viewport layer hierarchy under the given root_layer.
-// Convenient overload of the method below that creates a scrolling layer as
-// the outer viewport scroll layer.
-void CreateVirtualViewportLayers(Layer* root_layer,
-                                 const gfx::Size& inner_bounds,
-                                 const gfx::Size& outer_bounds,
-                                 const gfx::Size& scroll_bounds,
-                                 LayerTreeHost* host);
-
-// Creates the virtual viewport layer hierarchy under the given root_layer.
-// Uses the given scroll layer as the content "outer viewport scroll layer".
-void CreateVirtualViewportLayers(Layer* root_layer,
-                                 scoped_refptr<Layer> outer_scroll_layer,
-                                 const gfx::Size& outer_bounds,
-                                 const gfx::Size& scroll_bounds,
-                                 LayerTreeHost* host);
-
 class LayerTreeHostClientForTesting;
 
 // The LayerTreeTests runs with the main loop running. It instantiates a single
@@ -123,7 +107,18 @@
 
   AnimationHost* animation_host() const { return animation_host_.get(); }
 
-  void SetUseLayerList() { settings_.use_layer_lists = true; }
+  // Creates viewport layers and (in layer list mode) paint properties.
+  // Convenient overload of the method below that creates a scrolling layer as
+  // the outer viewport scroll layer.
+  void SetupViewport(const gfx::Size& outer_bounds,
+                     const gfx::Size& scroll_bounds);
+
+  // Creates viewport layers and (in layer list mode) paint properties.
+  // Uses the given scroll layer as the content "outer viewport scroll layer".
+  void SetupViewport(scoped_refptr<Layer> outer_scroll_layer,
+                     const gfx::Size& outer_bounds);
+
+  void SetUseLayerLists() { settings_.use_layer_lists = true; }
 
  protected:
   LayerTreeTest();
@@ -138,6 +133,12 @@
   void SetInitialDeviceScaleFactor(float initial_device_scale_factor) {
     initial_device_scale_factor_ = initial_device_scale_factor;
   }
+  // Used when LayerTreeTest::SetupTree() creates the root layer. Not used if
+  // the root layer is created before LayerTreeTest::SetupTree() is called.
+  // The default is 1x1.
+  void SetInitialRootBounds(const gfx::Size& bounds) {
+    initial_root_bounds_ = bounds;
+  }
 
   virtual void AfterTest() {}
   virtual void WillBeginTest();
@@ -237,6 +238,7 @@
 
   LayerTreeSettings settings_;
   float initial_device_scale_factor_ = 1.f;
+  gfx::Size initial_root_bounds_;
 
   CompositorMode mode_;
 
diff --git a/cc/test/property_tree_test_utils.cc b/cc/test/property_tree_test_utils.cc
new file mode 100644
index 0000000..c381f58
--- /dev/null
+++ b/cc/test/property_tree_test_utils.cc
@@ -0,0 +1,181 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/test/property_tree_test_utils.h"
+
+#include "cc/layers/layer.h"
+#include "cc/layers/layer_impl.h"
+#include "cc/trees/clip_node.h"
+#include "cc/trees/effect_node.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_host_common.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/property_tree.h"
+#include "cc/trees/scroll_node.h"
+#include "cc/trees/transform_node.h"
+
+namespace cc {
+
+namespace {
+
+template <typename LayerType>
+void SetupRootPropertiesInternal(LayerType* root) {
+  root->set_property_tree_sequence_number(
+      GetPropertyTrees(root)->sequence_number);
+
+  auto& root_transform_node =
+      CreateTransformNode(root, TransformTree::kRootNodeId);
+  DCHECK_EQ(root_transform_node.id, TransformTree::kContentsRootNodeId);
+
+  auto& root_clip_node = CreateClipNode(root, ClipTree::kRootNodeId);
+  DCHECK_EQ(root_clip_node.id, ClipTree::kViewportNodeId);
+  root_clip_node.clip = gfx::RectF(gfx::SizeF(800, 600));
+
+  auto& root_effect_node = CreateEffectNode(root, EffectTree::kRootNodeId);
+  DCHECK_EQ(root_effect_node.id, EffectTree::kContentsRootNodeId);
+  root_effect_node.render_surface_reason = RenderSurfaceReason::kRoot;
+
+  auto& root_scroll_node = CreateScrollNode(root, ScrollTree::kRootNodeId);
+  DCHECK_EQ(root_scroll_node.id, ScrollTree::kSecondaryRootNodeId);
+}
+
+template <typename LayerType>
+void CopyPropertiesInternal(const LayerType* from, LayerType* to) {
+  to->SetTransformTreeIndex(from->transform_tree_index());
+  to->SetClipTreeIndex(from->clip_tree_index());
+  to->SetEffectTreeIndex(from->effect_tree_index());
+  to->SetScrollTreeIndex(from->scroll_tree_index());
+}
+
+int ParentId(int parent_id, int default_id) {
+  return parent_id == TransformTree::kInvalidNodeId ? default_id : parent_id;
+}
+
+template <typename LayerType>
+TransformNode& CreateTransformNodeInternal(LayerType* layer, int parent_id) {
+  auto* property_trees = GetPropertyTrees(layer);
+  auto& transform_tree = property_trees->transform_tree;
+  int id = transform_tree.Insert(
+      TransformNode(), ParentId(parent_id, layer->transform_tree_index()));
+  layer->SetTransformTreeIndex(id);
+  auto* node = transform_tree.Node(id);
+  node->source_node_id = node->parent_id;
+  node->element_id = layer->element_id();
+  if (node->element_id) {
+    property_trees->element_id_to_transform_node_index[node->element_id] =
+        node->id;
+  }
+  transform_tree.set_needs_update(true);
+  return *node;
+}
+
+template <typename LayerType>
+ClipNode& CreateClipNodeInternal(LayerType* layer, int parent_id) {
+  auto& clip_tree = GetPropertyTrees(layer)->clip_tree;
+  int id = clip_tree.Insert(ClipNode(),
+                            ParentId(parent_id, layer->clip_tree_index()));
+  layer->SetClipTreeIndex(id);
+  auto* node = clip_tree.Node(id);
+  node->clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP;
+  node->transform_id = layer->transform_tree_index();
+  clip_tree.set_needs_update(true);
+  return *node;
+}
+
+template <typename LayerType>
+EffectNode& CreateEffectNodeInternal(LayerType* layer, int parent_id) {
+  auto* property_trees = GetPropertyTrees(layer);
+  auto& effect_tree = property_trees->effect_tree;
+  int id = effect_tree.Insert(EffectNode(),
+                              ParentId(parent_id, layer->effect_tree_index()));
+  layer->SetEffectTreeIndex(id);
+  auto* node = effect_tree.Node(id);
+  node->stable_id = layer->id();
+  node->transform_id = layer->transform_tree_index();
+  node->clip_id = layer->clip_tree_index();
+  if (layer->element_id()) {
+    property_trees->element_id_to_effect_node_index[layer->element_id()] =
+        node->id;
+  }
+  effect_tree.set_needs_update(true);
+  return *node;
+}
+
+template <typename LayerType>
+ScrollNode& CreateScrollNodeInternal(LayerType* layer, int parent_id) {
+  auto* property_trees = GetPropertyTrees(layer);
+  auto& scroll_tree = property_trees->scroll_tree;
+  int id = scroll_tree.Insert(ScrollNode(),
+                              ParentId(parent_id, layer->scroll_tree_index()));
+  layer->SetScrollTreeIndex(id);
+  auto* node = scroll_tree.Node(id);
+  node->element_id = layer->element_id();
+  if (node->element_id) {
+    property_trees->element_id_to_scroll_node_index[node->element_id] =
+        node->id;
+  }
+  node->transform_id = layer->transform_tree_index();
+  node->container_bounds = layer->bounds();
+  scroll_tree.set_needs_update(true);
+  return *node;
+}
+
+}  // anonymous namespace
+
+void SetupRootProperties(Layer* root) {
+  SetupRootPropertiesInternal(root);
+}
+
+void SetupRootProperties(LayerImpl* root) {
+  SetupRootPropertiesInternal(root);
+}
+
+void CopyProperties(const Layer* from, Layer* to) {
+  DCHECK(from->layer_tree_host()->IsUsingLayerLists());
+  to->SetLayerTreeHost(from->layer_tree_host());
+  to->set_property_tree_sequence_number(from->property_tree_sequence_number());
+  CopyPropertiesInternal(from, to);
+}
+
+void CopyProperties(const LayerImpl* from, LayerImpl* to) {
+  CopyPropertiesInternal(from, to);
+}
+
+TransformNode& CreateTransformNode(Layer* layer, int parent_id) {
+  DCHECK(layer->layer_tree_host()->IsUsingLayerLists());
+  return CreateTransformNodeInternal(layer, parent_id);
+}
+
+TransformNode& CreateTransformNode(LayerImpl* layer, int parent_id) {
+  return CreateTransformNodeInternal(layer, parent_id);
+}
+
+ClipNode& CreateClipNode(Layer* layer, int parent_id) {
+  DCHECK(layer->layer_tree_host()->IsUsingLayerLists());
+  return CreateClipNodeInternal(layer, parent_id);
+}
+
+ClipNode& CreateClipNode(LayerImpl* layer, int parent_id) {
+  return CreateClipNodeInternal(layer, parent_id);
+}
+
+EffectNode& CreateEffectNode(Layer* layer, int parent_id) {
+  DCHECK(layer->layer_tree_host()->IsUsingLayerLists());
+  return CreateEffectNodeInternal(layer, parent_id);
+}
+
+EffectNode& CreateEffectNode(LayerImpl* layer, int parent_id) {
+  return CreateEffectNodeInternal(layer, parent_id);
+}
+
+ScrollNode& CreateScrollNode(Layer* layer, int parent_id) {
+  DCHECK(layer->layer_tree_host()->IsUsingLayerLists());
+  return CreateScrollNodeInternal(layer, parent_id);
+}
+
+ScrollNode& CreateScrollNode(LayerImpl* layer, int parent_id) {
+  return CreateScrollNodeInternal(layer, parent_id);
+}
+
+}  // namespace cc
diff --git a/cc/test/property_tree_test_utils.h b/cc/test/property_tree_test_utils.h
new file mode 100644
index 0000000..2caacc4
--- /dev/null
+++ b/cc/test/property_tree_test_utils.h
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TEST_PROPERTY_TREE_TEST_UTILS_H_
+#define CC_TEST_PROPERTY_TREE_TEST_UTILS_H_
+
+#include "cc/trees/clip_node.h"
+#include "cc/trees/effect_node.h"
+#include "cc/trees/property_tree.h"
+#include "cc/trees/scroll_node.h"
+#include "cc/trees/transform_node.h"
+
+namespace cc {
+
+class Layer;
+class LayerImpl;
+
+// Sets up properties that apply to the root layer.
+void SetupRootProperties(Layer* root);
+void SetupRootProperties(LayerImpl* root);
+
+// Copies property tree indexes from |from| to |to|. For the |Layer| form, also
+// copies |from|'s layer_host_host and property_tree_sequence_number to |to|.
+void CopyProperties(const Layer* from, Layer* to);
+void CopyProperties(const LayerImpl* from, LayerImpl* to);
+
+// Each of the following methods creates a property node for the layer,
+// and sets the new node as the layer's property node of the type.
+// The new property node's parent will be |parent_id| if it's specified.
+// Otherwise the layer's current property node of the corresponding type will
+// be the parent. The latter case is useful to create property nodes after
+// CopyProperties() under the copied properties.
+TransformNode& CreateTransformNode(
+    Layer*,
+    int parent_id = TransformTree::kInvalidNodeId);
+TransformNode& CreateTransformNode(
+    LayerImpl*,
+    int parent_id = TransformTree::kInvalidNodeId);
+ClipNode& CreateClipNode(Layer*, int parent_id = ClipTree::kInvalidNodeId);
+ClipNode& CreateClipNode(LayerImpl*, int parent_id = ClipTree::kInvalidNodeId);
+EffectNode& CreateEffectNode(Layer*,
+                             int parent_id = EffectTree::kInvalidNodeId);
+EffectNode& CreateEffectNode(LayerImpl*,
+                             int parent_id = EffectTree::kInvalidNodeId);
+ScrollNode& CreateScrollNode(Layer*,
+                             int parent_id = ScrollTree::kInvalidNodeId);
+ScrollNode& CreateScrollNode(LayerImpl*,
+                             int parent_id = ScrollTree::kInvalidNodeId);
+
+// TODO(wangxianzhu): Add functions to create property nodes not based on
+// layers when needed.
+
+}  // namespace cc
+
+#endif  // CC_TEST_PROPERTY_TREE_TEST_UTILS_H_
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 1dcc664c..a2c70cf 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -94,6 +94,7 @@
   }
 
  private:
+  base::OnceClosure custom_setup_tree_;
   gfx::Size bounds_;
 };
 
@@ -119,137 +120,72 @@
                        base::FilePath(FILE_PATH_LITERAL("mask_of_layer.png")));
 }
 
-class LayerTreeHostLayerListPixelTest : public ParameterizedPixelResourceTest {
+class LayerTreeHostMaskPixelTestWithLayerList
+    : public ParameterizedPixelResourceTest {
  protected:
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->use_layer_lists = true;
-    settings->gpu_rasterization_forced = use_vulkan();
+  LayerTreeHostMaskPixelTestWithLayerList() : mask_bounds_(50, 50) {
+    SetUseLayerLists();
   }
+
+  // Setup three layers for testing masks: a white background, a green layer,
+  // and a mask layer with kDstIn blend mode.
+  void SetupTree() override {
+    SetInitialRootBounds(gfx::Size(100, 100));
+    ParameterizedPixelResourceTest::SetupTree();
+
+    Layer* root = layer_tree_host()->root_layer();
+
+    scoped_refptr<SolidColorLayer> background =
+        CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
+    CopyProperties(root, background.get());
+    root->AddChild(background);
+
+    scoped_refptr<SolidColorLayer> green =
+        CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
+    CopyProperties(background.get(), green.get());
+    auto& isolation_effect = CreateEffectNode(green.get());
+    isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
+    root->AddChild(green);
+
+    DCHECK(mask_layer_) << "The test should create mask_layer_ before calling "
+                        << "RunPixelResourceTestWithLayerList()";
+    mask_layer_->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
+    mask_layer_->SetBounds(mask_bounds_);
+    mask_layer_->SetIsDrawable(true);
+    CopyProperties(green.get(), mask_layer_.get());
+    auto& mask_effect = CreateEffectNode(mask_layer_.get());
+    mask_effect.blend_mode = SkBlendMode::kDstIn;
+    root->AddChild(mask_layer_);
+  }
+
+  gfx::Size mask_bounds_;
+  scoped_refptr<Layer> mask_layer_;
 };
 
 INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
-                         LayerTreeHostLayerListPixelTest,
+                         LayerTreeHostMaskPixelTestWithLayerList,
                          CombineWithLayerMaskTypes(kTestCases));
 
-TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffect) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
-
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
-
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 2;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
-
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
-
-  root_layer->AddChild(green);
-
-  gfx::Size mask_bounds(50, 50);
-  MaskContentLayerClient client(mask_bounds);
-
-  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
-  root_layer->AddChild(mask);
+TEST_P(LayerTreeHostMaskPixelTestWithLayerList, MaskWithEffect) {
+  MaskContentLayerClient client(mask_bounds_);
+  mask_layer_ = PictureLayer::Create(&client);
 
   pixel_comparator_ =
       std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */);
-
   RunPixelResourceTestWithLayerList(
-      root_layer, base::FilePath(FILE_PATH_LITERAL("mask_with_effect.png")),
-      &property_trees);
+      base::FilePath(FILE_PATH_LITERAL("mask_with_effect.png")));
 }
 
 // This tests that a solid color empty layer with mask effect works correctly.
-TEST_P(LayerTreeHostLayerListPixelTest, SolidColorLayerEmptyMaskWithEffect) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
-
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
-
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 3;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
-
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
-
-  root_layer->AddChild(green);
-
+TEST_P(LayerTreeHostMaskPixelTestWithLayerList,
+       SolidColorLayerEmptyMaskWithEffect) {
   // Apply a mask that is empty and solid-color. This should result in
   // the green layer being entirely clipped out.
-  gfx::Size mask_bounds(50, 50);
-  scoped_refptr<SolidColorLayer> mask =
+  mask_layer_ =
       CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), SK_ColorTRANSPARENT);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
-  root_layer->AddChild(mask);
 
-  RunPixelResourceTestWithLayerList(
-      root_layer,
-      base::FilePath(
-          FILE_PATH_LITERAL("solid_color_empty_mask_with_effect.png")),
-      &property_trees);
+  RunPixelResourceTestWithLayerList(base::FilePath(
+      FILE_PATH_LITERAL("solid_color_empty_mask_with_effect.png")));
 }
 
 class SolidColorEmptyMaskContentLayerClient : public ContentLayerClient {
@@ -275,304 +211,110 @@
   gfx::Size bounds_;
 };
 
-TEST_P(LayerTreeHostLayerListPixelTest, SolidColorEmptyMaskWithEffect) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
-
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
-
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 3;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
-
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
-
-  root_layer->AddChild(green);
-
+TEST_P(LayerTreeHostMaskPixelTestWithLayerList, SolidColorEmptyMaskWithEffect) {
   // Apply a mask that is empty and solid-color. This should result in
   // the green layer being entirely clipped out.
-  gfx::Size mask_bounds(50, 50);
-  SolidColorEmptyMaskContentLayerClient client(mask_bounds);
+  SolidColorEmptyMaskContentLayerClient client(mask_bounds_);
+  mask_layer_ = PictureLayer::Create(&client);
 
-  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
-  root_layer->AddChild(mask);
-
-  RunPixelResourceTestWithLayerList(
-      root_layer,
-      base::FilePath(
-          FILE_PATH_LITERAL("solid_color_empty_mask_with_effect.png")),
-      &property_trees);
+  RunPixelResourceTestWithLayerList(base::FilePath(
+      FILE_PATH_LITERAL("solid_color_empty_mask_with_effect.png")));
 }
 
-// same as SolidColorEmptyMaskWithEffect, except the mask has a render surface.
-TEST_P(LayerTreeHostLayerListPixelTest,
-       SolidColorEmptyMaskWithEffectAndRenderSurface) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
+// Same as SolidColorEmptyMaskWithEffect, except the mask has a render surface.
+class LayerTreeHostMaskPixelTest_SolidColorEmptyMaskWithEffectAndRenderSurface
+    : public LayerTreeHostMaskPixelTestWithLayerList {
+ protected:
+  void SetupTree() override {
+    LayerTreeHostMaskPixelTestWithLayerList::SetupTree();
 
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
+    auto* effect = layer_tree_host()->property_trees()->effect_tree.Node(
+        mask_layer_->effect_tree_index());
+    effect->render_surface_reason = RenderSurfaceReason::kTest;
+  }
+};
 
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 3;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  mask_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  property_trees.effect_tree.Insert(mask_effect, 2);
+INSTANTIATE_TEST_SUITE_P(
+    PixelResourceTest,
+    LayerTreeHostMaskPixelTest_SolidColorEmptyMaskWithEffectAndRenderSurface,
+    CombineWithLayerMaskTypes(kTestCases));
 
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
-
-  root_layer->AddChild(green);
-
+TEST_P(LayerTreeHostMaskPixelTest_SolidColorEmptyMaskWithEffectAndRenderSurface,
+       Test) {
   // Apply a mask that is empty and solid-color. This should result in
   // the green layer being entirely clipped out.
-  gfx::Size mask_bounds(50, 50);
-  SolidColorEmptyMaskContentLayerClient client(mask_bounds);
+  SolidColorEmptyMaskContentLayerClient client(mask_bounds_);
+  mask_layer_ = PictureLayer::Create(&client);
 
-  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
-  root_layer->AddChild(mask);
-
-  RunPixelResourceTestWithLayerList(
-      root_layer,
-      base::FilePath(
-          FILE_PATH_LITERAL("solid_color_empty_mask_with_effect.png")),
-      &property_trees);
+  RunPixelResourceTestWithLayerList(base::FilePath(
+      FILE_PATH_LITERAL("solid_color_empty_mask_with_effect.png")));
 }
 
 // Tests a situation in which there is no other content in the target
 // render surface that the mask applies to. In this situation, the mask
 // should have no effect on the rendered output.
-TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffectNoContentToMask) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
+class LayerTreeHostMaskPixelTest_MaskWithEffectNoContentToMask
+    : public LayerTreeHostMaskPixelTestWithLayerList {
+ protected:
+  void SetupTree() override {
+    LayerTreeHostMaskPixelTestWithLayerList::SetupTree();
 
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
+    LayerList layers = layer_tree_host()->root_layer()->children();
+    DCHECK_EQ(3u, layers.size());
+    // Set background to red.
+    layers[0]->SetBackgroundColor(SK_ColorRED);
+    // Remove the green layer.
+    layers.erase(layers.begin() + 1);
+    layer_tree_host()->root_layer()->SetChildLayerList(layers);
+  }
+};
 
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 2;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
+INSTANTIATE_TEST_SUITE_P(
+    PixelResourceTest,
+    LayerTreeHostMaskPixelTest_MaskWithEffectNoContentToMask,
+    CombineWithLayerMaskTypes(kTestCases));
 
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorRED);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  gfx::Size mask_bounds(50, 50);
-  MaskContentLayerClient client(mask_bounds);
-
-  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(0, 0));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
-  root_layer->AddChild(mask);
+TEST_P(LayerTreeHostMaskPixelTest_MaskWithEffectNoContentToMask, Test) {
+  MaskContentLayerClient client(mask_bounds_);
+  mask_layer_ = PictureLayer::Create(&client);
 
   RunPixelResourceTestWithLayerList(
-      root_layer,
-      base::FilePath(FILE_PATH_LITERAL("mask_with_effect_no_content.png")),
-      &property_trees);
+      base::FilePath(FILE_PATH_LITERAL("mask_with_effect_no_content.png")));
 }
 
-TEST_P(LayerTreeHostLayerListPixelTest, ScaledMaskWithEffect) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
-
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
-
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 2;
-  mask_effect.transform_id = 2;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
-
+class LayerTreeHostMaskPixelTest_ScaledMaskWithEffect
+    : public LayerTreeHostMaskPixelTestWithLayerList {
+ protected:
   // Scale the mask with a non-integral transform. This will trigger the
   // AA path in the renderer.
-  TransformTree& transform_tree = property_trees.transform_tree;
-  auto& transform_node =
-      *transform_tree.Node(transform_tree.Insert(TransformNode(), 1));
-  transform_node.source_node_id = transform_node.parent_id;
-  transform_node.local = gfx::Transform();
-  transform_node.local.Scale(1.5, 1.5);
+  void SetupTree() override {
+    LayerTreeHostMaskPixelTestWithLayerList::SetupTree();
 
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
+    auto& transform = CreateTransformNode(mask_layer_.get());
+    transform.local.Scale(1.5, 1.5);
+  }
+};
 
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
+INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
+                         LayerTreeHostMaskPixelTest_ScaledMaskWithEffect,
+                         CombineWithLayerMaskTypes(kTestCases));
 
-  root_layer->AddChild(green);
-
-  gfx::Size mask_bounds(50, 50);
-  MaskContentLayerClient client(mask_bounds);
-
-  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(2);
-  root_layer->AddChild(mask);
+TEST_P(LayerTreeHostMaskPixelTest_ScaledMaskWithEffect, Test) {
+  MaskContentLayerClient client(mask_bounds_);
+  mask_layer_ = PictureLayer::Create(&client);
 
   pixel_comparator_ =
       std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */);
 
   RunPixelResourceTestWithLayerList(
-      root_layer,
       base::FilePath(FILE_PATH_LITERAL("scaled_mask_with_effect_.png"))
-          .InsertBeforeExtensionASCII(GetRendererSuffix()),
-      &property_trees);
+          .InsertBeforeExtensionASCII(GetRendererSuffix()));
 }
 
-TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffectDifferentSize) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
-
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
-
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 2;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
-
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
-
-  root_layer->AddChild(green);
-
-  gfx::Size mask_bounds(25, 25);
-  MaskContentLayerClient client(mask_bounds);
-
-  scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client);
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
-  root_layer->AddChild(mask);
+TEST_P(LayerTreeHostMaskPixelTestWithLayerList, MaskWithEffectDifferentSize) {
+  mask_bounds_ = gfx::Size(25, 25);
+  MaskContentLayerClient client(mask_bounds_);
+  mask_layer_ = PictureLayer::Create(&client);
 
   pixel_comparator_ =
       std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */);
@@ -580,61 +322,12 @@
   // The mask is half the size of thing it's masking. In layer-list mode,
   // the mask is not automatically scaled to match the other layer.
   RunPixelResourceTestWithLayerList(
-      root_layer,
-      base::FilePath(FILE_PATH_LITERAL("mask_with_effect_different_size.png")),
-      &property_trees);
+      base::FilePath(FILE_PATH_LITERAL("mask_with_effect_different_size.png")));
 }
 
-TEST_P(LayerTreeHostLayerListPixelTest, ImageMaskWithEffect) {
-  PropertyTrees property_trees;
-  scoped_refptr<Layer> root_layer;
-  InitializeForLayerListMode(&root_layer, &property_trees);
-
-  EffectNode isolation_effect;
-  isolation_effect.clip_id = 1;
-  isolation_effect.stable_id = 2;
-  isolation_effect.render_surface_reason = RenderSurfaceReason::kTest;
-  isolation_effect.transform_id = 1;
-  property_trees.effect_tree.Insert(isolation_effect, 1);
-
-  EffectNode mask_effect;
-  mask_effect.clip_id = 1;
-  mask_effect.stable_id = 2;
-  mask_effect.transform_id = 1;
-  mask_effect.blend_mode = SkBlendMode::kDstIn;
-  property_trees.effect_tree.Insert(mask_effect, 2);
-
-  scoped_refptr<SolidColorLayer> background =
-      CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
-  background->set_property_tree_sequence_number(property_trees.sequence_number);
-  background->SetClipTreeIndex(1);
-  background->SetEffectTreeIndex(1);
-  background->SetScrollTreeIndex(1);
-  background->SetTransformTreeIndex(1);
-  root_layer->AddChild(background);
-
-  scoped_refptr<SolidColorLayer> green =
-      CreateSolidColorLayer(gfx::Rect(25, 25, 50, 50), kCSSGreen);
-  green->set_property_tree_sequence_number(property_trees.sequence_number);
-  green->SetClipTreeIndex(1);
-  green->SetEffectTreeIndex(2);
-  green->SetScrollTreeIndex(1);
-  green->SetTransformTreeIndex(1);
-
-  root_layer->AddChild(green);
-
-  gfx::Size mask_bounds(50, 50);
-  MaskContentLayerClient client(mask_bounds);
-
-  scoped_refptr<PictureImageLayer> mask = PictureImageLayer::Create();
-  mask->SetOffsetToTransformParent(gfx::Vector2dF(25, 25));
-  mask->set_property_tree_sequence_number(property_trees.sequence_number);
-  mask->SetBounds(mask_bounds);
-  mask->SetIsDrawable(true);
-  mask->SetClipTreeIndex(1);
-  mask->SetEffectTreeIndex(3);
-  mask->SetScrollTreeIndex(1);
-  mask->SetTransformTreeIndex(1);
+TEST_P(LayerTreeHostMaskPixelTestWithLayerList, ImageMaskWithEffect) {
+  MaskContentLayerClient client(mask_bounds_);
+  scoped_refptr<PictureImageLayer> mask_layer = PictureImageLayer::Create();
 
   sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(200, 200);
   SkCanvas* canvas = surface->getCanvas();
@@ -643,13 +336,13 @@
       client.PaintContentsToDisplayList(
           ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
   mask_display_list->Raster(canvas);
-  mask->SetImage(PaintImageBuilder::WithDefault()
-                     .set_id(PaintImage::GetNextId())
-                     .set_image(surface->makeImageSnapshot(),
-                                PaintImage::GetNextContentId())
-                     .TakePaintImage(),
-                 SkMatrix::I(), false);
-  root_layer->AddChild(mask);
+  mask_layer->SetImage(PaintImageBuilder::WithDefault()
+                           .set_id(PaintImage::GetNextId())
+                           .set_image(surface->makeImageSnapshot(),
+                                      PaintImage::GetNextContentId())
+                           .TakePaintImage(),
+                       SkMatrix::I(), false);
+  mask_layer_ = mask_layer;
 
   pixel_comparator_ =
       std::make_unique<FuzzyPixelOffByOneComparator>(true /* discard_alpha */);
@@ -657,9 +350,7 @@
   // The mask is half the size of thing it's masking. In layer-list mode,
   // the mask is not automatically scaled to match the other layer.
   RunPixelResourceTestWithLayerList(
-      root_layer,
-      base::FilePath(FILE_PATH_LITERAL("image_mask_with_effect.png")),
-      &property_trees);
+      base::FilePath(FILE_PATH_LITERAL("image_mask_with_effect.png")));
 }
 
 TEST_P(LayerTreeHostMasksPixelTest, ImageMaskOfLayer) {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 511c129..17c3b10d 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -99,7 +99,7 @@
   return node->subtree_has_copy_request;
 }
 
-class LayerTreeHostTest : public LayerTreeTest {};
+using LayerTreeHostTest = LayerTreeTest;
 
 class LayerTreeHostTestHasImplThreadTest : public LayerTreeHostTest {
  public:
@@ -756,9 +756,7 @@
 class LayerTreeHostTestPushPropertiesTo : public LayerTreeHostTest {
  protected:
   void SetupTree() override {
-    scoped_refptr<Layer> root = Layer::Create();
-    root->SetBounds(gfx::Size(10, 10));
-    layer_tree_host()->SetRootLayer(root);
+    SetInitialRootBounds(gfx::Size(10, 10));
     LayerTreeHostTest::SetupTree();
   }
 
@@ -1130,42 +1128,36 @@
 
 class LayerTreeHostTestLayerListSurfaceDamage : public LayerTreeHostTest {
  protected:
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->use_layer_lists = true;
-  }
+  LayerTreeHostTestLayerListSurfaceDamage() { SetUseLayerLists(); }
 
   void SetupTree() override {
-    root_ = Layer::Create();
-    child_a_ = Layer::Create();
-    child_b_ = Layer::Create();
-    child_c_ = Layer::Create();
-
-    layer_tree_host()->SetRootLayer(root_);
-
-    root_->AddChild(child_a_);
-    root_->AddChild(child_b_);
-    root_->AddChild(child_c_);
-
-    root_->SetBounds(gfx::Size(50, 50));
-
-    child_a_->SetBounds(gfx::Size(10, 20));
-    child_a_->SetForceRenderSurfaceForTesting(true);
-    child_a_->SetIsDrawable(true);
-
-    child_b_->SetBounds(gfx::Size(20, 10));
-    child_b_->SetForceRenderSurfaceForTesting(true);
-    child_b_->SetIsDrawable(true);
-
-    child_c_->SetBounds(gfx::Size(15, 15));
-    child_c_->SetForceRenderSurfaceForTesting(true);
-    child_c_->SetIsDrawable(true);
-
-    // TODO(pdr): Do not use the property tree builder for testing in layer list
-    // mode. This will require rewriting this test to manually build property
-    // trees.
-    layer_tree_host()->BuildPropertyTreesForTesting();
-
+    SetInitialRootBounds(gfx::Size(50, 50));
     LayerTreeHostTest::SetupTree();
+    root_ = layer_tree_host()->root_layer();
+
+    child_a_ = Layer::Create();
+    child_a_->SetBounds(gfx::Size(10, 20));
+    child_a_->SetIsDrawable(true);
+    CopyProperties(root_, child_a_.get());
+    auto& effect_a = CreateEffectNode(child_a_.get());
+    effect_a.render_surface_reason = RenderSurfaceReason::kTest;
+    root_->AddChild(child_a_);
+
+    child_b_ = Layer::Create();
+    child_b_->SetBounds(gfx::Size(20, 10));
+    child_b_->SetIsDrawable(true);
+    CopyProperties(root_, child_b_.get());
+    auto& effect_b = CreateEffectNode(child_b_.get());
+    effect_b.render_surface_reason = RenderSurfaceReason::kTest;
+    root_->AddChild(child_b_);
+
+    child_c_ = Layer::Create();
+    child_c_->SetBounds(gfx::Size(15, 15));
+    child_c_->SetIsDrawable(true);
+    CopyProperties(root_, child_c_.get());
+    auto& effect_c = CreateEffectNode(child_c_.get());
+    effect_c.render_surface_reason = RenderSurfaceReason::kTest;
+    root_->AddChild(child_c_);
   }
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
@@ -1284,7 +1276,7 @@
   }
 
  private:
-  scoped_refptr<Layer> root_;
+  Layer* root_;
   scoped_refptr<Layer> child_a_;
   scoped_refptr<Layer> child_b_;
   scoped_refptr<Layer> child_c_;
@@ -1701,44 +1693,16 @@
 
 SINGLE_THREAD_TEST_F(LayerTreeHostTestPropertyTreesChangedSync);
 
-// Simple base class for tests that just need to mutate the layer tree
-// host and observe results without any impl thread, multi-layer, or
-// multi-frame antics.
-class LayerTreeHostTestLayerListsTest : public LayerTreeHostTest {
- public:
-  explicit LayerTreeHostTestLayerListsTest(bool use_layer_lists)
-      : use_layer_lists_(use_layer_lists) {}
-
- protected:
-  void InitializeSettings(LayerTreeSettings* settings) override {
-    settings->use_layer_lists = use_layer_lists_;
-  }
-
-  void SetupTree() override {
-    root_ = Layer::Create();
-    layer_tree_host()->SetRootLayer(root_);
-    LayerTreeHostTest::SetupTree();
-  }
-
-  scoped_refptr<Layer> root_;
-
- private:
-  bool use_layer_lists_;
-};
-
 class LayerTreeHostTestAnimationOpacityMutatedNotUsingLayerLists
-    : public LayerTreeHostTestLayerListsTest {
- public:
-  LayerTreeHostTestAnimationOpacityMutatedNotUsingLayerLists()
-      : LayerTreeHostTestLayerListsTest(false) {}
-
+    : public LayerTreeHostTest {
  protected:
   void BeginTest() override {
-    EXPECT_EQ(1.0f, root_->opacity());
-    layer_tree_host()->SetElementOpacityMutated(root_->element_id(),
+    Layer* root = layer_tree_host()->root_layer();
+    EXPECT_EQ(1.0f, root->opacity());
+    layer_tree_host()->SetElementOpacityMutated(root->element_id(),
                                                 ElementListType::ACTIVE, 0.3f);
     // When not using layer lists, opacity is stored on the layer.
-    EXPECT_EQ(0.3f, root_->opacity());
+    EXPECT_EQ(0.3f, root->opacity());
     EndTest();
   }
 };
@@ -1747,40 +1711,31 @@
     LayerTreeHostTestAnimationOpacityMutatedNotUsingLayerLists);
 
 class LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists
-    : public LayerTreeHostTestLayerListsTest {
+    : public LayerTreeHostTest {
  public:
-  LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists()
-      : LayerTreeHostTestLayerListsTest(true) {}
+  LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists() {
+    SetUseLayerLists();
+  }
 
  protected:
   void BeginTest() override {
-    // Insert a dummy effect node to observe its mutation. This would
-    // normally have been created by PaintArtifactCompositor.
-    int effect_node_id =
-        layer_tree_host()->property_trees()->effect_tree.Insert(
-            EffectNode(), EffectTree::kInvalidNodeId);
-    layer_tree_host()
-        ->property_trees()
-        ->element_id_to_effect_node_index[root_->element_id()] = effect_node_id;
+    Layer* root = layer_tree_host()->root_layer();
+    EXPECT_EQ(1.0f, root->opacity());
+    EXPECT_EQ(1.0f, layer_tree_host()
+                        ->property_trees()
+                        ->effect_tree.FindNodeFromElementId(root->element_id())
+                        ->opacity);
 
-    EXPECT_EQ(1.0f, root_->opacity());
-    EXPECT_EQ(1.0f,
-              layer_tree_host()
-                  ->property_trees()
-                  ->effect_tree.FindNodeFromElementId(root_->element_id())
-                  ->opacity);
-
-    layer_tree_host()->SetElementOpacityMutated(root_->element_id(),
+    layer_tree_host()->SetElementOpacityMutated(root->element_id(),
                                                 ElementListType::ACTIVE, 0.3f);
 
     // When using layer lists, we don't have to store the opacity on the layer.
-    EXPECT_EQ(1.0f, root_->opacity());
+    EXPECT_EQ(1.0f, root->opacity());
     // The opacity should have been set directly on the effect node instead.
-    EXPECT_EQ(0.3f,
-              layer_tree_host()
-                  ->property_trees()
-                  ->effect_tree.FindNodeFromElementId(root_->element_id())
-                  ->opacity);
+    EXPECT_EQ(0.3f, layer_tree_host()
+                        ->property_trees()
+                        ->effect_tree.FindNodeFromElementId(root->element_id())
+                        ->opacity);
     EndTest();
   }
 };
@@ -1788,20 +1743,17 @@
 SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationOpacityMutatedUsingLayerLists);
 
 class LayerTreeHostTestAnimationTransformMutatedNotUsingLayerLists
-    : public LayerTreeHostTestLayerListsTest {
- public:
-  LayerTreeHostTestAnimationTransformMutatedNotUsingLayerLists()
-      : LayerTreeHostTestLayerListsTest(false) {}
-
+    : public LayerTreeHostTest {
  protected:
   void BeginTest() override {
-    EXPECT_EQ(gfx::Transform(), root_->transform());
+    Layer* root = layer_tree_host()->root_layer();
+    EXPECT_EQ(gfx::Transform(), root->transform());
     gfx::Transform expected_transform;
     expected_transform.Translate(42, 42);
     layer_tree_host()->SetElementTransformMutated(
-        root_->element_id(), ElementListType::ACTIVE, expected_transform);
+        root->element_id(), ElementListType::ACTIVE, expected_transform);
     // When not using layer lists, transform is stored on the layer.
-    EXPECT_EQ(expected_transform, root_->transform());
+    EXPECT_EQ(expected_transform, root->transform());
     EndTest();
   }
 };
@@ -1810,44 +1762,36 @@
     LayerTreeHostTestAnimationTransformMutatedNotUsingLayerLists);
 
 class LayerTreeHostTestAnimationTransformMutatedUsingLayerLists
-    : public LayerTreeHostTestLayerListsTest {
+    : public LayerTreeHostTest {
  public:
-  LayerTreeHostTestAnimationTransformMutatedUsingLayerLists()
-      : LayerTreeHostTestLayerListsTest(true) {}
+  LayerTreeHostTestAnimationTransformMutatedUsingLayerLists() {
+    SetUseLayerLists();
+  }
 
  protected:
   void BeginTest() override {
-    // Insert a dummy transform node to observe its mutation. This would
-    // normally have been created by PaintArtifactCompositor.
-    int transform_node_id =
-        layer_tree_host()->property_trees()->transform_tree.Insert(
-            TransformNode(), TransformTree::kInvalidNodeId);
-    layer_tree_host()
-        ->property_trees()
-        ->element_id_to_transform_node_index[root_->element_id()] =
-        transform_node_id;
-
-    EXPECT_EQ(gfx::Transform(), root_->transform());
+    Layer* root = layer_tree_host()->root_layer();
+    EXPECT_EQ(gfx::Transform(), root->transform());
     EXPECT_EQ(gfx::Transform(),
               layer_tree_host()
                   ->property_trees()
-                  ->transform_tree.FindNodeFromElementId(root_->element_id())
+                  ->transform_tree.FindNodeFromElementId(root->element_id())
                   ->local);
 
     gfx::Transform expected_transform;
     expected_transform.Translate(42, 42);
     layer_tree_host()->SetElementTransformMutated(
-        root_->element_id(), ElementListType::ACTIVE, expected_transform);
+        root->element_id(), ElementListType::ACTIVE, expected_transform);
 
     // When using layer lists, we don't have to store the transform on the
     // layer.
-    EXPECT_EQ(gfx::Transform(), root_->transform());
+    EXPECT_EQ(gfx::Transform(), root->transform());
     // The transform should have been set directly on the transform node
     // instead.
     EXPECT_EQ(expected_transform,
               layer_tree_host()
                   ->property_trees()
-                  ->transform_tree.FindNodeFromElementId(root_->element_id())
+                  ->transform_tree.FindNodeFromElementId(root->element_id())
                   ->local);
     EndTest();
   }
@@ -1856,21 +1800,18 @@
 SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationTransformMutatedUsingLayerLists);
 
 class LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists
-    : public LayerTreeHostTestLayerListsTest {
- public:
-  LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists()
-      : LayerTreeHostTestLayerListsTest(false) {}
-
+    : public LayerTreeHostTest {
  protected:
   void BeginTest() override {
+    Layer* root = layer_tree_host()->root_layer();
     FilterOperations filters;
-    EXPECT_EQ(FilterOperations(), root_->filters());
+    EXPECT_EQ(FilterOperations(), root->filters());
     filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
     layer_tree_host()->SetElementFilterMutated(
-        root_->element_id(), ElementListType::ACTIVE, filters);
+        root->element_id(), ElementListType::ACTIVE, filters);
     // When not using layer lists, filters are just stored directly on the
     // layer.
-    EXPECT_EQ(filters, root_->filters());
+    EXPECT_EQ(filters, root->filters());
     EndTest();
   }
 };
@@ -1878,41 +1819,34 @@
 SINGLE_THREAD_TEST_F(LayerTreeHostTestAnimationFilterMutatedNotUsingLayerLists);
 
 class LayerTreeHostTestAnimationFilterMutatedUsingLayerLists
-    : public LayerTreeHostTestLayerListsTest {
+    : public LayerTreeHostTest {
  public:
-  LayerTreeHostTestAnimationFilterMutatedUsingLayerLists()
-      : LayerTreeHostTestLayerListsTest(true) {}
+  LayerTreeHostTestAnimationFilterMutatedUsingLayerLists() {
+    SetUseLayerLists();
+  }
 
  protected:
   void BeginTest() override {
-    // Insert a dummy effect node to observe its mutation. This would
-    // normally have been created by PaintArtifactCompositor.
-    int effect_node_id =
-        layer_tree_host()->property_trees()->effect_tree.Insert(
-            EffectNode(), EffectTree::kInvalidNodeId);
-    layer_tree_host()
-        ->property_trees()
-        ->element_id_to_effect_node_index[root_->element_id()] = effect_node_id;
-
-    EXPECT_EQ(FilterOperations(), root_->filters());
+    Layer* root = layer_tree_host()->root_layer();
+    EXPECT_EQ(FilterOperations(), root->filters());
     EXPECT_EQ(FilterOperations(),
               layer_tree_host()
                   ->property_trees()
-                  ->effect_tree.FindNodeFromElementId(root_->element_id())
+                  ->effect_tree.FindNodeFromElementId(root->element_id())
                   ->filters);
 
     FilterOperations filters;
     filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
     layer_tree_host()->SetElementFilterMutated(
-        root_->element_id(), ElementListType::ACTIVE, filters);
+        root->element_id(), ElementListType::ACTIVE, filters);
 
     // When using layer lists, we don't have to store the filters on the layer.
-    EXPECT_EQ(FilterOperations(), root_->filters());
+    EXPECT_EQ(FilterOperations(), root->filters());
     // The filter should have been set directly on the effect node instead.
     EXPECT_EQ(filters,
               layer_tree_host()
                   ->property_trees()
-                  ->effect_tree.FindNodeFromElementId(root_->element_id())
+                  ->effect_tree.FindNodeFromElementId(root->element_id())
                   ->filters);
     EndTest();
   }
@@ -3176,8 +3110,7 @@
                                        2 * root_layer->bounds().height()));
     scroll_layer_->SetScrollOffset(gfx::ScrollOffset());
 
-    CreateVirtualViewportLayers(root_layer, scroll_layer_, root_layer->bounds(),
-                                root_layer->bounds(), layer_tree_host());
+    SetupViewport(scroll_layer_, root_layer->bounds());
 
     layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
     client_.set_bounds(root_layer->bounds());
@@ -8250,26 +8183,18 @@
 
 class LayerTreeHostTestHudLayerWithLayerLists : public LayerTreeHostTest {
  public:
+  LayerTreeHostTestHudLayerWithLayerLists() { SetUseLayerLists(); }
+
   void InitializeSettings(LayerTreeSettings* settings) override {
     settings->initial_debug_state.show_paint_rects = true;
-    settings->use_layer_lists = true;
   }
 
-  void SetupTree() override {
-    LayerTreeHostTest::SetupTree();
-
-    // Build the property trees for the root layer.
-    // TODO(pdr): Do not use the property tree builder for testing in layer list
-    // mode. This will require rewriting this test to manually build property
-    // trees.
-    layer_tree_host()->BuildPropertyTreesForTesting();
-
-    // The HUD layer should not have been setup by the property tree building.
+  void BeginTest() override {
+    // The HUD layer should not have been setup.
     DCHECK_EQ(layer_tree_host()->hud_layer(), nullptr);
+    PostSetNeedsCommitToMainThread();
   }
 
-  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
-
   void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); }
 
   void DidCommit() override {
diff --git a/cc/trees/layer_tree_host_unittest_masks.cc b/cc/trees/layer_tree_host_unittest_masks.cc
index ce2efbff..9847b71 100644
--- a/cc/trees/layer_tree_host_unittest_masks.cc
+++ b/cc/trees/layer_tree_host_unittest_masks.cc
@@ -57,9 +57,7 @@
     LayerTreeTest::SetupTree();
     scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create();
     outer_viewport_scroll_layer->SetBounds(layer_size);
-    CreateVirtualViewportLayers(root.get(), outer_viewport_scroll_layer,
-                                gfx::Size(50, 50), gfx::Size(50, 50),
-                                layer_tree_host());
+    SetupViewport(outer_viewport_scroll_layer, gfx::Size(50, 50));
     layer_tree_host()->outer_viewport_container_layer()->SetMasksToBounds(true);
     outer_viewport_scroll_layer->AddChild(content_layer);
 
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index fd53e85..5759c6b 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -83,9 +83,7 @@
     gfx::Size scroll_layer_bounds(root_layer->bounds().width() + 100,
                                   root_layer->bounds().height() + 100);
 
-    CreateVirtualViewportLayers(root_layer, root_layer->bounds(),
-                                root_layer->bounds(), scroll_layer_bounds,
-                                layer_tree_host());
+    SetupViewport(root_layer->bounds(), scroll_layer_bounds);
   }
 };
 
@@ -562,9 +560,9 @@
 
   void SetupTree() override {
     SetInitialDeviceScaleFactor(device_scale_factor_);
-
-    scoped_refptr<Layer> root_layer = Layer::Create();
-    root_layer->SetBounds(gfx::Size(10, 10));
+    SetInitialRootBounds(gfx::Size(10, 10));
+    LayerTreeHostScrollTest::SetupTree();
+    Layer* root_layer = layer_tree_host()->root_layer();
 
     root_scroll_layer_ = FakePictureLayer::Create(&fake_content_layer_client_);
     root_scroll_layer_->SetElementId(
@@ -573,9 +571,7 @@
     root_scroll_layer_->SetPosition(gfx::PointF());
     root_scroll_layer_->SetIsDrawable(true);
 
-    CreateVirtualViewportLayers(root_layer.get(), root_scroll_layer_,
-                                root_layer->bounds(), root_layer->bounds(),
-                                layer_tree_host());
+    SetupViewport(root_scroll_layer_, root_layer->bounds());
 
     child_layer_ = FakePictureLayer::Create(&fake_content_layer_client_);
     child_layer_->set_did_scroll_callback(
@@ -612,9 +608,6 @@
     }
 
     expected_scroll_layer_->SetScrollOffset(initial_offset_);
-
-    layer_tree_host()->SetRootLayer(root_layer);
-    LayerTreeTest::SetupTree();
     fake_content_layer_client_.set_bounds(root_layer->bounds());
 
     layer_tree_host()->outer_viewport_scroll_layer()->set_did_scroll_callback(
@@ -1328,9 +1321,7 @@
     Layer* root_layer = layer_tree_host()->root_layer();
     root_layer->SetBounds(gfx::Size(10, 10));
 
-    CreateVirtualViewportLayers(root_layer, root_layer->bounds(),
-                                root_layer->bounds(), root_layer->bounds(),
-                                layer_tree_host());
+    SetupViewport(root_layer->bounds(), root_layer->bounds());
 
     Layer* outer_scroll_layer =
         layer_tree_host()->outer_viewport_scroll_layer();
@@ -2215,145 +2206,49 @@
 
 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplSideInvalidation);
 
-// Version of LayerTreeHostScrollTest that uses layer lists which means the
-// property trees and layer list are explicitly specified instead of running
-// the cc property tree builder.
-class LayerListLayerTreeHostScrollTest : public LayerTreeHostScrollTest {
+class NonScrollingNonFastScrollableRegion : public LayerTreeHostScrollTest {
  public:
-  // The id of the root property tree nodes.
-  static constexpr int kRootNodeId = 1;
+  NonScrollingNonFastScrollableRegion() { SetUseLayerLists(); }
 
-  LayerListLayerTreeHostScrollTest() { SetUseLayerList(); }
-
-  void SetupTree() override {
-    // Setup the root transform, effect, clip, and scroll property tree nodes.
-    auto& transform_tree = layer_tree_host()->property_trees()->transform_tree;
-    auto& root_transform_node = *transform_tree.Node(
-        transform_tree.Insert(TransformNode(), kRealRootNodeId));
-    DCHECK_EQ(root_transform_node.id, kRootNodeId);
-    root_transform_node.source_node_id = root_transform_node.parent_id;
-    transform_tree.set_needs_update(true);
-
-    auto& effect_tree = layer_tree_host()->property_trees()->effect_tree;
-    auto& root_effect_node =
-        *effect_tree.Node(effect_tree.Insert(EffectNode(), kRealRootNodeId));
-    DCHECK_EQ(root_effect_node.id, kRootNodeId);
-    root_effect_node.stable_id = 1;
-    root_effect_node.transform_id = kRealRootNodeId;
-    root_effect_node.clip_id = kRealRootNodeId;
-    root_effect_node.render_surface_reason = RenderSurfaceReason::kRoot;
-    effect_tree.set_needs_update(true);
-
-    auto& clip_tree = layer_tree_host()->property_trees()->clip_tree;
-    auto& root_clip_node =
-        *clip_tree.Node(clip_tree.Insert(ClipNode(), kRealRootNodeId));
-    DCHECK_EQ(root_clip_node.id, kRootNodeId);
-    root_clip_node.clip_type = ClipNode::ClipType::APPLIES_LOCAL_CLIP;
-    root_clip_node.clip = gfx::RectF(gfx::SizeF(800, 600));
-    root_clip_node.transform_id = kRealRootNodeId;
-    clip_tree.set_needs_update(true);
-
-    auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree;
-    auto& root_scroll_node =
-        *scroll_tree.Node(scroll_tree.Insert(ScrollNode(), kRealRootNodeId));
-    DCHECK_EQ(root_scroll_node.id, kRootNodeId);
-    root_scroll_node.transform_id = kRealRootNodeId;
-    scroll_tree.set_needs_update(true);
-
-    // Setup the root Layer which should be used to attach the layer list.
-    root_ = Layer::Create();
-    root_->SetBounds(gfx::Size(800, 600));
-    root_->SetIsDrawable(true);
-    root_->SetHitTestable(true);
-    root_->SetTransformTreeIndex(root_transform_node.id);
-    root_->SetEffectTreeIndex(root_effect_node.id);
-    root_->SetScrollTreeIndex(root_scroll_node.id);
-    root_->SetClipTreeIndex(root_clip_node.id);
-    layer_tree_host()->SetRootLayer(root_);
-
-    layer_tree_host()->SetViewportSizeAndScale(gfx::Size(800, 600), 1.f,
-                                               viz::LocalSurfaceIdAllocation());
-
-    layer_tree_host()->property_trees()->sequence_number =
-        root_->property_tree_sequence_number();
-
-    root_->SetNeedsCommit();
-  }
-
-  Layer* root() const { return root_.get(); }
-
- private:
-  // The compositor is hard-coded to use 0 for the root nodes (always non-null).
-  static constexpr int kRealRootNodeId = 0;
-
-  scoped_refptr<Layer> root_;
-};
-
-class NonScrollingNonFastScrollableRegion
-    : public LayerListLayerTreeHostScrollTest {
- public:
   // Setup 3 Layers:
   // 1) bottom_ which has a non-fast region in the bottom-right.
   // 2) middle_scrollable_ which is scrollable.
   // 3) top_ which has a non-fast region in the top-left and is offset by
   //    |middle_scrollable_|'s scroll offset.
   void SetupTree() override {
-    LayerListLayerTreeHostScrollTest::SetupTree();
-
-    fake_content_layer_client_.set_bounds(root()->bounds());
-
-    std::vector<scoped_refptr<Layer>> layer_list;
+    SetInitialRootBounds(gfx::Size(800, 600));
+    LayerTreeHostScrollTest::SetupTree();
+    Layer* root = layer_tree_host()->root_layer();
+    fake_content_layer_client_.set_bounds(root->bounds());
 
     bottom_ = FakePictureLayer::Create(&fake_content_layer_client_);
     bottom_->SetElementId(LayerIdToElementIdForTesting(bottom_->id()));
     bottom_->SetBounds(gfx::Size(100, 100));
     bottom_->SetNonFastScrollableRegion(Region(gfx::Rect(50, 50, 50, 50)));
     bottom_->SetHitTestable(true);
-    bottom_->SetTransformTreeIndex(kRootNodeId);
-    bottom_->SetEffectTreeIndex(kRootNodeId);
-    bottom_->SetScrollTreeIndex(kRootNodeId);
-    bottom_->SetClipTreeIndex(kRootNodeId);
-    bottom_->set_property_tree_sequence_number(
-        root()->property_tree_sequence_number());
-    layer_list.push_back(bottom_);
+    CopyProperties(root, bottom_.get());
+    root->AddChild(bottom_);
 
-    auto& scroll_tree = layer_tree_host()->property_trees()->scroll_tree;
-    auto& scroll_node =
-        *scroll_tree.Node(scroll_tree.Insert(ScrollNode(), kRootNodeId));
-    scroll_node.transform_id = kRootNodeId;
     middle_scrollable_ = FakePictureLayer::Create(&fake_content_layer_client_);
     middle_scrollable_->SetElementId(
         LayerIdToElementIdForTesting(middle_scrollable_->id()));
-    scroll_node.element_id = middle_scrollable_->element_id();
-    scroll_node.scrollable = true;
-    scroll_node.bounds = gfx::Size(100, 200);
-    scroll_node.container_bounds = gfx::Size(100, 100);
     middle_scrollable_->SetBounds(gfx::Size(100, 100));
     middle_scrollable_->SetIsDrawable(true);
     middle_scrollable_->SetScrollable(gfx::Size(100, 200));
     middle_scrollable_->SetHitTestable(true);
-    middle_scrollable_->SetTransformTreeIndex(kRootNodeId);
-    middle_scrollable_->SetEffectTreeIndex(kRootNodeId);
-    middle_scrollable_->SetScrollTreeIndex(scroll_node.id);
-    middle_scrollable_->SetClipTreeIndex(kRootNodeId);
-    middle_scrollable_->set_property_tree_sequence_number(
-        root()->property_tree_sequence_number());
-    layer_list.push_back(middle_scrollable_);
+    CopyProperties(bottom_.get(), middle_scrollable_.get());
+    auto& scroll_node = CreateScrollNode(middle_scrollable_.get());
+    scroll_node.scrollable = true;
+    scroll_node.bounds = gfx::Size(100, 200);
+    root->AddChild(middle_scrollable_);
 
     top_ = FakePictureLayer::Create(&fake_content_layer_client_);
     top_->SetElementId(LayerIdToElementIdForTesting(top_->id()));
     top_->SetBounds(gfx::Size(100, 100));
     top_->SetNonFastScrollableRegion(Region(gfx::Rect(0, 0, 50, 50)));
     top_->SetHitTestable(true);
-    top_->SetTransformTreeIndex(kRootNodeId);
-    top_->SetEffectTreeIndex(kRootNodeId);
-    top_->SetScrollTreeIndex(scroll_node.id);
-    top_->SetClipTreeIndex(kRootNodeId);
-    top_->set_property_tree_sequence_number(
-        root()->property_tree_sequence_number());
-
-    layer_list.push_back(top_);
-    root()->SetChildLayerList(std::move(layer_list));
+    CopyProperties(middle_scrollable_.get(), top_.get());
+    root->AddChild(top_);
   }
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }