[go: nahoru, domu]

Add cc::CommitState to snapshot state for compositor commit

Currently, compositor commit accesses LayerTreeHost directly from the
impl thread. This is safe because the main thread is blocked during
commit. However, Non-Blocking Commit is a project to eliminate main
thread blocking during commit; so accessing LayerTreeHost from the
impl thread during commit will no longer be safe.

This CL adds struct CommitState, which contains a snapshot of (almost)
all the information from LayerTreeHost needed for compositor commit. A
bunch of member fields are moved out of LayerTreeHost and into
CommitState; and LayerTreeHost gets pending_commit_state_ and
active_commit_state_. pending_commit_state_ is read and written from
the main thread while an animation frame is being prepared.
active_commit_state_ is passed to the impl thread, which uses it to
drive commit; it is only non-null while commit is running.

Broadly speaking, LayerTreeHost data that is used by commit falls into
two categories: attributes that persist from one commit to the next;
and queues that are drained and passed to commit for processing.
CommitState makes this distinction explicit. Rather than copying data
from the pending state to the active state, LTH::ActivateCommitState()
simply swaps pointers; assigns pending_commit_state_ to a new empty
CommitState; and then copies back all persistent fields from the
now-active CommitState.

With this CL, there are still three data sources used during commit
that are not thread safe: the layer tree, the property trees, and
animation state. The strategy for Non-BlockingCommit is to enforce
thread safety for these data by blocking the main thread only at the
point where the main thread needs to modify them. Subsequent CL's will
do that by adding calls to LTH::WaitForCommitCompletion() where
necessary.

Bug: 1237973,1255972
Change-Id: I3e9742e87539632ba1b0a7a13a79ccc5e08df1c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3228195
Reviewed-by: Khushal <khushalsagar@chromium.org>
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Reviewed-by: vmpstr <vmpstr@chromium.org>
Reviewed-by: enne <enne@chromium.org>
Commit-Queue: Stefan Zager <szager@chromium.org>
Cr-Commit-Position: refs/heads/main@{#936106}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 8390b690..0331f54 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -341,6 +341,8 @@
     "trees/clip_expander.h",
     "trees/clip_node.cc",
     "trees/clip_node.h",
+    "trees/commit_state.cc",
+    "trees/commit_state.h",
     "trees/compositor_commit_data.cc",
     "trees/compositor_commit_data.h",
     "trees/compositor_mode.h",
@@ -434,6 +436,7 @@
     "trees/ukm_manager.h",
     "trees/viewport_layers.cc",
     "trees/viewport_layers.h",
+    "trees/viewport_property_ids.h",
   ]
 
   public_deps = [
diff --git a/cc/benchmarks/micro_benchmark_controller.cc b/cc/benchmarks/micro_benchmark_controller.cc
index 0a941be..e703f5f 100644
--- a/cc/benchmarks/micro_benchmark_controller.cc
+++ b/cc/benchmarks/micro_benchmark_controller.cc
@@ -87,8 +87,9 @@
   return (*it)->ProcessMessage(std::move(message));
 }
 
-void MicroBenchmarkController::ScheduleImplBenchmarks(
-    LayerTreeHostImpl* host_impl) {
+std::vector<std::unique_ptr<MicroBenchmarkImpl>>
+MicroBenchmarkController::CreateImplBenchmarks() const {
+  std::vector<std::unique_ptr<MicroBenchmarkImpl>> result;
   for (const auto& benchmark : benchmarks_) {
     std::unique_ptr<MicroBenchmarkImpl> benchmark_impl;
     if (!benchmark->ProcessedForBenchmarkImpl()) {
@@ -97,8 +98,9 @@
     }
 
     if (benchmark_impl.get())
-      host_impl->ScheduleMicroBenchmark(std::move(benchmark_impl));
+      result.push_back(std::move(benchmark_impl));
   }
+  return result;
 }
 
 void MicroBenchmarkController::DidUpdateLayers() {
diff --git a/cc/benchmarks/micro_benchmark_controller.h b/cc/benchmarks/micro_benchmark_controller.h
index c4fc548..3645ac9 100644
--- a/cc/benchmarks/micro_benchmark_controller.h
+++ b/cc/benchmarks/micro_benchmark_controller.h
@@ -20,7 +20,7 @@
 namespace cc {
 
 class LayerTreeHost;
-class LayerTreeHostImpl;
+
 class CC_EXPORT MicroBenchmarkController {
  public:
   explicit MicroBenchmarkController(LayerTreeHost* host);
@@ -38,7 +38,7 @@
   // Returns true if the message was successfully delivered and handled.
   bool SendMessage(int id, base::Value message);
 
-  void ScheduleImplBenchmarks(LayerTreeHostImpl* host_impl);
+  std::vector<std::unique_ptr<MicroBenchmarkImpl>> CreateImplBenchmarks() const;
 
  private:
   void CleanUpFinishedBenchmarks();
diff --git a/cc/benchmarks/micro_benchmark_controller_unittest.cc b/cc/benchmarks/micro_benchmark_controller_unittest.cc
index 83902e95..f0d0f5ef 100644
--- a/cc/benchmarks/micro_benchmark_controller_unittest.cc
+++ b/cc/benchmarks/micro_benchmark_controller_unittest.cc
@@ -128,11 +128,12 @@
       base::BindOnce(&IncrementCallCount, base::Unretained(&run_count)));
   EXPECT_GT(id, 0);
 
-  // Schedule impl benchmarks. In production code, this is run in commit.
-  layer_tree_host_->GetMicroBenchmarkController()->ScheduleImplBenchmarks(
-      layer_tree_host_impl_.get());
-
-  // Now complete the commit (as if on the impl thread).
+  // Scheduling benchmarks on the impl thread is usually done during
+  // LayerTreeHostImpl::FinishCommit().
+  for (auto& benchmark : layer_tree_host_->GetMicroBenchmarkController()
+                             ->CreateImplBenchmarks()) {
+    layer_tree_host_impl_->ScheduleMicroBenchmark(std::move(benchmark));
+  }
   layer_tree_host_impl_->CommitComplete();
 
   // Make sure all posted messages run.
diff --git a/cc/layers/heads_up_display_layer.cc b/cc/layers/heads_up_display_layer.cc
index ec59418fa..a9c4e6a 100644
--- a/cc/layers/heads_up_display_layer.cc
+++ b/cc/layers/heads_up_display_layer.cc
@@ -85,8 +85,9 @@
   web_vital_metrics_ = std::move(web_vital_metrics);
 }
 
-void HeadsUpDisplayLayer::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void HeadsUpDisplayLayer::PushPropertiesTo(LayerImpl* layer,
+                                           const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
   TRACE_EVENT0("cc", "HeadsUpDisplayLayer::PushPropertiesTo");
   HeadsUpDisplayLayerImpl* layer_impl =
       static_cast<HeadsUpDisplayLayerImpl*>(layer);
diff --git a/cc/layers/heads_up_display_layer.h b/cc/layers/heads_up_display_layer.h
index 9d497439..1b5cf52 100644
--- a/cc/layers/heads_up_display_layer.h
+++ b/cc/layers/heads_up_display_layer.h
@@ -36,7 +36,8 @@
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
 
   // Layer overrides.
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
  protected:
   HeadsUpDisplayLayer();
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index f5fb341..ea4900e 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -243,6 +243,7 @@
 }
 
 void Layer::SetParent(Layer* layer) {
+  DCHECK(IsMutationAllowed());
   DCHECK(!layer || !layer->HasAncestor(this));
 
   parent_ = layer;
@@ -397,6 +398,7 @@
 
 void Layer::SetChildLayerList(LayerList new_children) {
   DCHECK(layer_tree_host_->IsUsingLayerLists());
+  DCHECK(IsMutationAllowed());
 
   // Early out without calling |LayerTreeHost::SetNeedsFullTreeSync| if no
   // layer has changed.
@@ -507,7 +509,7 @@
   SetNeedsPushProperties();
 }
 
-SkColor Layer::SafeOpaqueBackgroundColor() const {
+SkColor Layer::SafeOpaqueBackgroundColor(SkColor host_background_color) const {
   if (contents_opaque()) {
     if (!layer_tree_host_ || !layer_tree_host_->IsUsingLayerLists()) {
       // In layer tree mode, PropertyTreeBuilder should have calculated the safe
@@ -522,7 +524,7 @@
     // background_color() if it's not transparent, or layer_tree_host_'s
     // background_color(), with the alpha channel forced to be opaque.
     SkColor color = background_color() == SK_ColorTRANSPARENT
-                        ? layer_tree_host_->background_color()
+                        ? host_background_color
                         : background_color();
     return SkColorSetA(color, SK_AlphaOPAQUE);
   }
@@ -536,6 +538,14 @@
   return background_color();
 }
 
+SkColor Layer::SafeOpaqueBackgroundColor() const {
+  SkColor host_background_color =
+      layer_tree_host_
+          ? layer_tree_host_->pending_commit_state()->background_color
+          : layer_tree_inputs()->safe_opaque_background_color;
+  return SafeOpaqueBackgroundColor(host_background_color);
+}
+
 void Layer::SetMasksToBounds(bool masks_to_bounds) {
   DCHECK(IsPropertyChangeAllowed());
   auto& inputs = EnsureLayerTreeInputs();
@@ -1339,7 +1349,8 @@
   return false;
 }
 
-void Layer::PushPropertiesTo(LayerImpl* layer) {
+void Layer::PushPropertiesTo(LayerImpl* layer,
+                             const CommitState& commit_state) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "Layer::PushPropertiesTo");
   DCHECK(layer_tree_host_);
@@ -1350,7 +1361,8 @@
   layer->SetElementId(inputs_.element_id);
   layer->SetHasTransformNode(has_transform_node_);
   layer->SetBackgroundColor(inputs_.background_color);
-  layer->SetSafeOpaqueBackgroundColor(SafeOpaqueBackgroundColor());
+  layer->SetSafeOpaqueBackgroundColor(
+      SafeOpaqueBackgroundColor(commit_state.background_color));
   layer->SetBounds(inputs_.bounds);
   layer->SetTransformTreeIndex(transform_tree_index());
   layer->SetEffectTreeIndex(effect_tree_index());
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 0f4642c..161ba6c 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -51,6 +51,8 @@
 class LayerTreeImpl;
 class PictureLayer;
 
+struct CommitState;
+
 // For tracing and debugging. The info will be attached to this layer's tracing
 // output.
 struct CC_EXPORT LayerDebugInfo {
@@ -161,11 +163,15 @@
   // If the layer says contents_opaque() is true, in layer tree mode, this
   // returns the value set by SetSafeOpaqueBackgroundColor() which should be an
   // opaque color, and in layer list mode, returns an opaque color calculated
-  // from background_color() and layer_tree_host()->background_color().
+  // from background_color() and the argument host_background_color.
   // Otherwise, it returns something non-opaque. It prefers to return the
   // background_color(), but if the background_color() is opaque (and this layer
   // claims to not be), then SK_ColorTRANSPARENT is returned to avoid intrusive
   // checkerboard where the layer is not covered by the background_color().
+  SkColor SafeOpaqueBackgroundColor(SkColor host_background_color) const;
+
+  // Same as the one-argument version, except that host_background_color is
+  // layer_tree_host()->pending_commit_state()->background_color.
   SkColor SafeOpaqueBackgroundColor() const;
 
   // For layer tree mode only.
@@ -632,7 +638,8 @@
   // that state as well. The |layer| passed in will be of the type created by
   // CreateLayerImpl(), so can be safely down-casted if the subclass uses a
   // different type for the compositor thread.
-  virtual void PushPropertiesTo(LayerImpl* layer);
+  virtual void PushPropertiesTo(LayerImpl* layer,
+                                const CommitState& commit_state);
 
   // Internal method to be overridden by Layer subclasses that need to do work
   // during a main frame. The method should compute any state that will need to
diff --git a/cc/layers/layer_perftest.cc b/cc/layers/layer_perftest.cc
index 52c7195..2af5f3c 100644
--- a/cc/layers/layer_perftest.cc
+++ b/cc/layers/layer_perftest.cc
@@ -85,7 +85,12 @@
     test_layer->SetContentsOpaque(contents_opaque);
     test_layer->SetHideLayerAndSubtree(hide_layer_and_subtree);
     test_layer->SetMasksToBounds(masks_to_bounds);
-    test_layer->PushPropertiesTo(impl_layer.get());
+    // Here and elsewhere: when doing a full commit, we would call
+    // layer_tree_host_->ActivateCommitState() and the second argument would
+    // come from layer_tree_host_->active_commit_state(); we use
+    // pending_commit_state() just to keep the test code simple.
+    test_layer->PushPropertiesTo(impl_layer.get(),
+                                 *layer_tree_host_->pending_commit_state());
 
     transform_origin_z += 0.01f;
     scrollable = !scrollable;
@@ -103,7 +108,8 @@
   // Properties didn't change.
   timer_.Reset();
   do {
-    test_layer->PushPropertiesTo(impl_layer.get());
+    test_layer->PushPropertiesTo(impl_layer.get(),
+                                 *layer_tree_host_->pending_commit_state());
     timer_.NextLap();
   } while (!timer_.HasTimeLimitExpired());
 
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 3cf02da..a7d5dd3 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -57,37 +57,25 @@
     Mock::VerifyAndClearExpectations(layer_tree_host_.get());               \
   } while (false)
 
-#define EXECUTE_AND_VERIFY_SUBTREE_CHANGED(code_to_test)                     \
-  code_to_test;                                                              \
-  root->layer_tree_host()->BuildPropertyTreesForTesting();                   \
-  EXPECT_FALSE(root->subtree_property_changed());                            \
-  EXPECT_TRUE(top->subtree_property_changed());                              \
-  EXPECT_TRUE(base::Contains(                                                \
-      top->layer_tree_host()->LayersThatShouldPushProperties(), top.get())); \
-  EXPECT_TRUE(child->subtree_property_changed());                            \
-  EXPECT_TRUE(base::Contains(                                                \
-      child->layer_tree_host()->LayersThatShouldPushProperties(),            \
-      child.get()));                                                         \
-  EXPECT_TRUE(grand_child->subtree_property_changed());                      \
-  EXPECT_TRUE(base::Contains(                                                \
-      grand_child->layer_tree_host()->LayersThatShouldPushProperties(),      \
-      grand_child.get()));
-
-#define EXECUTE_AND_VERIFY_SUBTREE_NOT_CHANGED(code_to_test)                 \
-  code_to_test;                                                              \
-  root->layer_tree_host()->BuildPropertyTreesForTesting();                   \
-  EXPECT_FALSE(root->subtree_property_changed());                            \
-  EXPECT_FALSE(top->subtree_property_changed());                             \
-  EXPECT_FALSE(base::Contains(                                               \
-      top->layer_tree_host()->LayersThatShouldPushProperties(), top.get())); \
-  EXPECT_FALSE(child->subtree_property_changed());                           \
-  EXPECT_FALSE(base::Contains(                                               \
-      child->layer_tree_host()->LayersThatShouldPushProperties(),            \
-      child.get()));                                                         \
-  EXPECT_FALSE(grand_child->subtree_property_changed());                     \
-  EXPECT_FALSE(base::Contains(                                               \
-      grand_child->layer_tree_host()->LayersThatShouldPushProperties(),      \
-      grand_child.get()));
+#define EXECUTE_AND_VERIFY_SUBTREE_CHANGED(code_to_test)               \
+  code_to_test;                                                        \
+  root->layer_tree_host()->BuildPropertyTreesForTesting();             \
+  EXPECT_FALSE(root->subtree_property_changed());                      \
+  EXPECT_TRUE(top->subtree_property_changed());                        \
+  EXPECT_TRUE(base::Contains(top->layer_tree_host()                    \
+                                 ->pending_commit_state()              \
+                                 ->layers_that_should_push_properties, \
+                             top.get()));                              \
+  EXPECT_TRUE(child->subtree_property_changed());                      \
+  EXPECT_TRUE(base::Contains(child->layer_tree_host()                  \
+                                 ->pending_commit_state()              \
+                                 ->layers_that_should_push_properties, \
+                             child.get()));                            \
+  EXPECT_TRUE(grand_child->subtree_property_changed());                \
+  EXPECT_TRUE(base::Contains(grand_child->layer_tree_host()            \
+                                 ->pending_commit_state()              \
+                                 ->layers_that_should_push_properties, \
+                             grand_child.get()));
 
 #define EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(code_to_test) \
   code_to_test;                                                \
@@ -171,7 +159,15 @@
 
   void SimulateCommitForLayer(Layer* layer) {
     layer->PushPropertiesTo(
-        layer->CreateLayerImpl(host_impl_.active_tree()).get());
+        layer->CreateLayerImpl(host_impl_.active_tree()).get(),
+        *layer_tree_host_->pending_commit_state());
+  }
+
+  void CommitAndPushProperties(Layer* layer, LayerImpl* layer_impl) {
+    auto* commit_state = layer_tree_host_->WillCommit(
+        /*completion_event=*/nullptr, /*has_updates=*/true);
+    layer->PushPropertiesTo(layer_impl, *commit_state);
+    layer_tree_host_->CommitComplete();
   }
 
   void VerifyTestTreeInitialState() const {
@@ -291,7 +287,10 @@
   EXPECT_SET_NEEDS_COMMIT(0, mask_layer1->SetBounds(arbitrary_size));
   EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(1);
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(AtLeast(1));
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetMaskLayer(mask_layer1));
+  layer_tree_host_->CommitComplete();
 
   // Set up the impl layers after the full tree is constructed, including the
   // mask layer.
@@ -310,12 +309,15 @@
   host_impl_.active_tree()->set_source_frame_number(
       host_impl_.active_tree()->source_frame_number() + 1);
 
+  auto* commit_state = layer_tree_host_->WillCommit(
+      /*completion_event=*/nullptr, /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get());
-      mask_layer1->PushPropertiesTo(mask_layer1_impl.get()););
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state);
+      mask_layer1->PushPropertiesTo(mask_layer1_impl.get(), *commit_state););
+  layer_tree_host_->CommitComplete();
 
   // Once there is a mask layer, resizes require subtree properties to update.
   arbitrary_size = gfx::Size(11, 22);
@@ -325,60 +327,88 @@
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetMasksToBounds(true));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetContentsOpaque(true));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetTrilinearFiltering(true));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetTrilinearFiltering(false));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2);
   top->SetRoundedCorner({1, 2, 3, 4});
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetIsFastRoundedCorner(true));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetHideLayerAndSubtree(true));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetBlendMode(arbitrary_blend_mode));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   // Should be a different size than previous call, to ensure it marks tree
   // changed.
@@ -386,30 +416,42 @@
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetBounds(arbitrary_size));
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(mask_layer1->SetBounds(arbitrary_size));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   FilterOperations arbitrary_filters;
   arbitrary_filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(top->SetFilters(arbitrary_filters));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(
       top->SetBackdropFilters(arbitrary_filters));
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get()));
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state));
+  layer_tree_host_->CommitComplete();
 
   gfx::PointF arbitrary_point_f = gfx::PointF(0.125f, 0.25f);
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
@@ -417,12 +459,16 @@
   TransformNode* node = layer_tree_host_->property_trees()->transform_tree.Node(
       top->transform_tree_index());
   EXPECT_TRUE(node->transform_changed);
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get());
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state);
       layer_tree_host_->property_trees()->ResetAllChangeTracking());
+  layer_tree_host_->CommitComplete();
   EXPECT_FALSE(node->transform_changed);
 
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
@@ -430,10 +476,14 @@
   node = layer_tree_host_->property_trees()->transform_tree.Node(
       child->transform_tree_index());
   EXPECT_TRUE(node->transform_changed);
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      child->PushPropertiesTo(child_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get());
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state);
       layer_tree_host_->property_trees()->ResetAllChangeTracking());
+  layer_tree_host_->CommitComplete();
   node = layer_tree_host_->property_trees()->transform_tree.Node(
       child->transform_tree_index());
   EXPECT_FALSE(node->transform_changed);
@@ -444,12 +494,16 @@
   node = layer_tree_host_->property_trees()->transform_tree.Node(
       top->transform_tree_index());
   EXPECT_TRUE(node->transform_changed);
+
+  commit_state = layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                                              /*has_updates=*/true);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
-      top->PushPropertiesTo(top_impl.get());
-      child->PushPropertiesTo(child_impl.get());
-      child2->PushPropertiesTo(child2_impl.get());
-      grand_child->PushPropertiesTo(grand_child_impl.get());
+      top->PushPropertiesTo(top_impl.get(), *commit_state);
+      child->PushPropertiesTo(child_impl.get(), *commit_state);
+      child2->PushPropertiesTo(child2_impl.get(), *commit_state);
+      grand_child->PushPropertiesTo(grand_child_impl.get(), *commit_state);
       layer_tree_host_->property_trees()->ResetAllChangeTracking());
+  layer_tree_host_->CommitComplete();
 
   gfx::Transform arbitrary_transform;
   arbitrary_transform.Scale3d(0.1f, 0.2f, 0.3f);
@@ -584,7 +638,9 @@
   EXPECT_EQ(child2, parent->children()[1]);
   EXPECT_EQ(child3, parent->children()[2]);
 
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
+  layer_tree_host_->CommitComplete();
 
   LayerList new_children_order;
   new_children_order.emplace_back(child3);
@@ -596,8 +652,9 @@
   EXPECT_EQ(child2, parent->children()[2]);
 
   for (const auto& child : parent->children()) {
-    EXPECT_FALSE(base::Contains(
-        layer_tree_host_->LayersThatShouldPushProperties(), child.get()));
+    EXPECT_FALSE(base::Contains(layer_tree_host_->pending_commit_state()
+                                    ->layers_that_should_push_properties,
+                                child.get()));
     EXPECT_TRUE(child->subtree_property_changed());
   }
 }
@@ -963,20 +1020,20 @@
   host_impl_.active_tree()->SetRootLayerForTesting(std::move(impl_layer));
   LayerImpl* impl_layer_ptr = host_impl_.active_tree()->LayerById(1);
   test_layer->SetNeedsDisplayRect(gfx::Rect(5, 5));
-  test_layer->PushPropertiesTo(impl_layer_ptr);
+  CommitAndPushProperties(test_layer.get(), impl_layer_ptr);
   EXPECT_EQ(gfx::Rect(0, 0, 5, 5), impl_layer_ptr->update_rect());
 
   // The LayerImpl's update_rect() should be accumulated here, since we did not
   // do anything to clear it.
   test_layer->SetNeedsDisplayRect(gfx::Rect(10, 10, 5, 5));
-  test_layer->PushPropertiesTo(impl_layer_ptr);
+  CommitAndPushProperties(test_layer.get(), impl_layer_ptr);
   EXPECT_EQ(gfx::Rect(0, 0, 15, 15), impl_layer_ptr->update_rect());
 
   // If we do clear the LayerImpl side, then the next update_rect() should be
   // fresh without accumulation.
   host_impl_.active_tree()->ResetAllChangeTracking();
   test_layer->SetNeedsDisplayRect(gfx::Rect(10, 10, 5, 5));
-  test_layer->PushPropertiesTo(impl_layer_ptr);
+  CommitAndPushProperties(test_layer.get(), impl_layer_ptr);
   EXPECT_EQ(gfx::Rect(10, 10, 5, 5), impl_layer_ptr->update_rect());
 }
 
@@ -994,7 +1051,7 @@
 
   EXPECT_FALSE(impl_layer->LayerPropertyChanged());
 
-  test_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(test_layer.get(), impl_layer.get());
 
   EXPECT_TRUE(impl_layer->LayerPropertyChanged());
   EXPECT_FALSE(impl_layer->LayerPropertyChangedFromPropertyTrees());
@@ -1014,7 +1071,7 @@
 
   EXPECT_FALSE(impl_layer->LayerPropertyChanged());
 
-  test_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(test_layer.get(), impl_layer.get());
 
   EXPECT_TRUE(impl_layer->LayerPropertyChanged());
   EXPECT_FALSE(impl_layer->LayerPropertyChangedFromPropertyTrees());
@@ -1033,7 +1090,7 @@
 
   EXPECT_FALSE(impl_layer->LayerPropertyChanged());
 
-  test_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(test_layer.get(), impl_layer.get());
 
   EXPECT_TRUE(impl_layer->LayerPropertyChanged());
   EXPECT_FALSE(impl_layer->LayerPropertyChangedFromPropertyTrees());
@@ -1354,7 +1411,7 @@
   // A layer that draws content should be hit testable.
   root_layer->SetIsDrawable(true);
   root_layer->SetHitTestable(true);
-  root_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(root_layer.get(), impl_layer.get());
   EXPECT_TRUE(impl_layer->DrawsContent());
   EXPECT_TRUE(impl_layer->HitTestable());
 
@@ -1362,14 +1419,14 @@
   // content should not be hit testable.
   root_layer->SetIsDrawable(false);
   root_layer->SetHitTestable(false);
-  root_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(root_layer.get(), impl_layer.get());
   EXPECT_FALSE(impl_layer->DrawsContent());
   EXPECT_FALSE(impl_layer->HitTestable());
 
   // |SetHitTestableWithoutDrawsContent| should cause a layer to become hit
   // testable even though it does not draw content.
   root_layer->SetHitTestable(true);
-  root_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(root_layer.get(), impl_layer.get());
   EXPECT_FALSE(impl_layer->DrawsContent());
   EXPECT_TRUE(impl_layer->HitTestable());
 }
@@ -1531,7 +1588,7 @@
 
   EXPECT_FALSE(impl_layer->element_id());
 
-  test_layer->PushPropertiesTo(impl_layer.get());
+  CommitAndPushProperties(test_layer.get(), impl_layer.get());
 
   EXPECT_EQ(ElementId(2), impl_layer->element_id());
 }
@@ -1607,47 +1664,60 @@
 TEST_F(LayerTest, UpdateMirrorCount) {
   scoped_refptr<Layer> test_layer = Layer::Create();
   test_layer->SetLayerTreeHost(layer_tree_host_.get());
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
+  layer_tree_host_->CommitComplete();
   layer_tree_host_->property_trees()->needs_rebuild = false;
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
   EXPECT_EQ(0, test_layer->mirror_count());
   EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_EQ(0u, layer_tree_host_->LayersThatShouldPushProperties().size());
+  EXPECT_EQ(0u, layer_tree_host_->pending_commit_state()
+                    ->layers_that_should_push_properties.size());
 
   // Incrementing mirror count from zero should trigger property trees rebuild.
   test_layer->IncrementMirrorCount();
   EXPECT_EQ(1, test_layer->mirror_count());
   EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
+  EXPECT_TRUE(base::Contains(layer_tree_host_->pending_commit_state()
+                                 ->layers_that_should_push_properties,
                              test_layer.get()));
 
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
+  layer_tree_host_->CommitComplete();
   layer_tree_host_->property_trees()->needs_rebuild = false;
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
 
   // Incrementing mirror count from non-zero should not trigger property trees
   // rebuild.
   test_layer->IncrementMirrorCount();
   EXPECT_EQ(2, test_layer->mirror_count());
   EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
+  EXPECT_TRUE(base::Contains(layer_tree_host_->pending_commit_state()
+                                 ->layers_that_should_push_properties,
                              test_layer.get()));
 
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
+  layer_tree_host_->CommitComplete();
 
   // Decrementing mirror count to non-zero should not trigger property trees
   // rebuild.
   test_layer->DecrementMirrorCount();
   EXPECT_EQ(1, test_layer->mirror_count());
   EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
+  EXPECT_TRUE(base::Contains(layer_tree_host_->pending_commit_state()
+                                 ->layers_that_should_push_properties,
                              test_layer.get()));
 
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
+  layer_tree_host_->CommitComplete();
 
   // Decrementing mirror count to zero should trigger property trees rebuild.
   test_layer->DecrementMirrorCount();
   EXPECT_EQ(0, test_layer->mirror_count());
   EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
+  EXPECT_TRUE(base::Contains(layer_tree_host_->pending_commit_state()
+                                 ->layers_that_should_push_properties,
                              test_layer.get()));
 
   test_layer->SetLayerTreeHost(nullptr);
diff --git a/cc/layers/mirror_layer.cc b/cc/layers/mirror_layer.cc
index b89e300d..26db296 100644
--- a/cc/layers/mirror_layer.cc
+++ b/cc/layers/mirror_layer.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <utility>
+
 #include "cc/layers/mirror_layer.h"
 
 #include "cc/layers/mirror_layer_impl.h"
@@ -13,8 +15,9 @@
   return MirrorLayerImpl::Create(tree_impl, id());
 }
 
-void MirrorLayer::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void MirrorLayer::PushPropertiesTo(LayerImpl* layer,
+                                   const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
 
   auto* mirror_layer = static_cast<MirrorLayerImpl*>(layer);
   mirror_layer->SetMirroredLayerId(mirrored_layer_->id());
diff --git a/cc/layers/mirror_layer.h b/cc/layers/mirror_layer.h
index 9915dcf..ff5b473 100644
--- a/cc/layers/mirror_layer.h
+++ b/cc/layers/mirror_layer.h
@@ -5,6 +5,8 @@
 #ifndef CC_LAYERS_MIRROR_LAYER_H_
 #define CC_LAYERS_MIRROR_LAYER_H_
 
+#include <memory>
+
 #include "base/memory/scoped_refptr.h"
 #include "cc/cc_export.h"
 #include "cc/layers/layer.h"
@@ -23,7 +25,8 @@
 
   // Layer overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
 
  protected:
diff --git a/cc/layers/mirror_layer_unittest.cc b/cc/layers/mirror_layer_unittest.cc
index deaa92c..9040f10d 100644
--- a/cc/layers/mirror_layer_unittest.cc
+++ b/cc/layers/mirror_layer_unittest.cc
@@ -25,8 +25,8 @@
 
   // Synchronizes |layer_tree_host_| and |host_impl_| and pushes surface ids.
   void SynchronizeTrees() {
-    TreeSynchronizer::PushLayerProperties(layer_tree_host_.get(),
-                                          host_impl_.pending_tree());
+    TreeSynchronizer::PushLayerProperties(
+        layer_tree_host_->pending_commit_state(), host_impl_.pending_tree());
   }
 
  protected:
@@ -87,8 +87,10 @@
   auto mirrored = Layer::Create();
   mirrored->SetLayerTreeHost(layer_tree_host_.get());
 
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
+  layer_tree_host_->CommitComplete();
   layer_tree_host_->property_trees()->needs_rebuild = false;
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
   EXPECT_EQ(0, mirrored->mirror_count());
 
   // Creating the first mirror layer should trigger property trees rebuild.
@@ -96,22 +98,20 @@
   EXPECT_EQ(1, mirrored->mirror_count());
   EXPECT_EQ(mirrored.get(), mirror1->mirrored_layer());
   EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
-                             mirrored.get()));
-
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()
+          ->layers_that_should_push_properties.contains(mirrored.get()));
   layer_tree_host_->property_trees()->needs_rebuild = false;
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
 
   // Creating a second mirror layer should not trigger property trees rebuild.
   auto mirror2 = MirrorLayer::Create(mirrored);
   EXPECT_EQ(2, mirrored->mirror_count());
   EXPECT_EQ(mirrored.get(), mirror2->mirrored_layer());
   EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
-                             mirrored.get()));
-
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()
+          ->layers_that_should_push_properties.contains(mirrored.get()));
   layer_tree_host_->property_trees()->needs_rebuild = false;
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
 
   // Destroying one of the mirror layers should not trigger property trees
   // rebuild.
@@ -119,10 +119,9 @@
   mirror1 = nullptr;
   EXPECT_EQ(1, mirrored->mirror_count());
   EXPECT_FALSE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_EQ(1u, layer_tree_host_->LayersThatShouldPushProperties().size());
-
+  EXPECT_EQ(1u, layer_tree_host_->pending_commit_state()
+                    ->layers_that_should_push_properties.size());
   layer_tree_host_->property_trees()->needs_rebuild = false;
-  layer_tree_host_->ClearLayersThatShouldPushProperties();
 
   // Destroying the only remaining mirror layer should trigger property trees
   // rebuild.
@@ -130,8 +129,10 @@
   mirror2 = nullptr;
   EXPECT_EQ(0, mirrored->mirror_count());
   EXPECT_TRUE(layer_tree_host_->property_trees()->needs_rebuild);
-  EXPECT_TRUE(base::Contains(layer_tree_host_->LayersThatShouldPushProperties(),
-                             mirrored.get()));
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()
+          ->layers_that_should_push_properties.contains(mirrored.get()));
+  layer_tree_host_->property_trees()->needs_rebuild = false;
 
   mirrored->SetLayerTreeHost(nullptr);
 }
diff --git a/cc/layers/nine_patch_layer.cc b/cc/layers/nine_patch_layer.cc
index d17ad28..fac969a 100644
--- a/cc/layers/nine_patch_layer.cc
+++ b/cc/layers/nine_patch_layer.cc
@@ -65,8 +65,9 @@
   SetNeedsCommit();
 }
 
-void NinePatchLayer::PushPropertiesTo(LayerImpl* layer) {
-  UIResourceLayer::PushPropertiesTo(layer);
+void NinePatchLayer::PushPropertiesTo(LayerImpl* layer,
+                                      const CommitState& commit_state) {
+  UIResourceLayer::PushPropertiesTo(layer, commit_state);
   TRACE_EVENT0("cc", "NinePatchLayer::PushPropertiesTo");
   NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer);
 
diff --git a/cc/layers/nine_patch_layer.h b/cc/layers/nine_patch_layer.h
index f492e6e..079043f 100644
--- a/cc/layers/nine_patch_layer.h
+++ b/cc/layers/nine_patch_layer.h
@@ -22,7 +22,8 @@
   NinePatchLayer(const NinePatchLayer&) = delete;
   NinePatchLayer& operator=(const NinePatchLayer&) = delete;
 
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   // |border| is the space around the center rectangular region in layer space
   // (known as aperture in image space).  |border.x()| and |border.y()| are the
diff --git a/cc/layers/painted_overlay_scrollbar_layer.cc b/cc/layers/painted_overlay_scrollbar_layer.cc
index 2aef708..a93d8cd 100644
--- a/cc/layers/painted_overlay_scrollbar_layer.cc
+++ b/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -62,8 +62,10 @@
   return true;
 }
 
-void PaintedOverlayScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
-  ScrollbarLayerBase::PushPropertiesTo(layer);
+void PaintedOverlayScrollbarLayer::PushPropertiesTo(
+    LayerImpl* layer,
+    const CommitState& commit_state) {
+  ScrollbarLayerBase::PushPropertiesTo(layer, commit_state);
 
   PaintedOverlayScrollbarLayerImpl* scrollbar_layer =
       static_cast<PaintedOverlayScrollbarLayerImpl*>(layer);
@@ -81,9 +83,11 @@
   }
 
   if (thumb_resource_.get()) {
-    scrollbar_layer->SetImageBounds(
-        layer_tree_host()->GetUIResourceManager()->GetUIResourceSize(
-            thumb_resource_->id()));
+    auto iter = commit_state.ui_resource_sizes.find(thumb_resource_->id());
+    gfx::Size image_bounds = (iter == commit_state.ui_resource_sizes.end())
+                                 ? gfx::Size()
+                                 : iter->second;
+    scrollbar_layer->SetImageBounds(image_bounds);
     scrollbar_layer->SetAperture(aperture_);
     scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id());
   } else {
diff --git a/cc/layers/painted_overlay_scrollbar_layer.h b/cc/layers/painted_overlay_scrollbar_layer.h
index 8651c6f..48374d8 100644
--- a/cc/layers/painted_overlay_scrollbar_layer.h
+++ b/cc/layers/painted_overlay_scrollbar_layer.h
@@ -5,6 +5,8 @@
 #ifndef CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_
 #define CC_LAYERS_PAINTED_OVERLAY_SCROLLBAR_LAYER_H_
 
+#include <memory>
+
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/layer.h"
@@ -34,7 +36,8 @@
   bool OpacityCanAnimateOnImplThread() const override;
   bool Update() override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   ScrollbarLayerType GetScrollbarLayerType() const override;
 
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc
index 76480c8..cd98bfc 100644
--- a/cc/layers/painted_scrollbar_layer.cc
+++ b/cc/layers/painted_scrollbar_layer.cc
@@ -55,8 +55,9 @@
   return is_overlay_;
 }
 
-void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
-  ScrollbarLayerBase::PushPropertiesTo(layer);
+void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer,
+                                             const CommitState& commit_state) {
+  ScrollbarLayerBase::PushPropertiesTo(layer, commit_state);
 
   PaintedScrollbarLayerImpl* scrollbar_layer =
       static_cast<PaintedScrollbarLayerImpl*>(layer);
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h
index a449ffc..aec07ab 100644
--- a/cc/layers/painted_scrollbar_layer.h
+++ b/cc/layers/painted_scrollbar_layer.h
@@ -5,6 +5,8 @@
 #ifndef CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_
 #define CC_LAYERS_PAINTED_SCROLLBAR_LAYER_H_
 
+#include <memory>
+
 #include "cc/cc_export.h"
 #include "cc/input/scrollbar.h"
 #include "cc/layers/layer.h"
@@ -33,7 +35,8 @@
   bool OpacityCanAnimateOnImplThread() const override;
   bool Update() override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   const gfx::Size& internal_content_bounds() const {
     return internal_content_bounds_;
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 290cf5e..6fd5530 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -51,13 +51,14 @@
   return PictureLayerImpl::Create(tree_impl, id());
 }
 
-void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
+void PictureLayer::PushPropertiesTo(LayerImpl* base_layer,
+                                    const CommitState& commit_state) {
   // TODO(enne): http://crbug.com/918126 debugging
   CHECK(this);
 
   PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
 
-  Layer::PushPropertiesTo(base_layer);
+  Layer::PushPropertiesTo(base_layer, commit_state);
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
                "PictureLayer::PushPropertiesTo");
   DropRecordingSourceContentIfInvalid(
@@ -65,7 +66,7 @@
 
   layer_impl->SetNearestNeighbor(picture_layer_inputs_.nearest_neighbor);
   layer_impl->set_gpu_raster_max_texture_size(
-      layer_tree_host()->device_viewport_rect().size());
+      commit_state.device_viewport_rect.size());
   layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask());
   layer_impl->SetDirectlyCompositedImageSize(
       picture_layer_inputs_.directly_composited_image_size);
diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h
index e99202e..a5c93c4 100644
--- a/cc/layers/picture_layer.h
+++ b/cc/layers/picture_layer.h
@@ -41,7 +41,8 @@
   // Layer interface.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
   void SetNeedsDisplayRect(const gfx::Rect& layer_rect) override;
   sk_sp<SkPicture> GetPicture() const override;
   bool Update() override;
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 473269e..0cd8791 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -52,7 +52,7 @@
   layer->Update();
 
   EXPECT_EQ(0, host->SourceFrameNumber());
-  host->WillCommit(nullptr);
+  host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/false);
   EXPECT_EQ(1, host->SourceFrameNumber());
   host->CommitComplete();
   EXPECT_EQ(1, host->SourceFrameNumber());
@@ -68,12 +68,15 @@
   FakeLayerTreeHostImpl host_impl(
       LayerTreeSettings(), &impl_task_runner_provider, &task_graph_runner);
   host_impl.InitializeFrameSink(layer_tree_frame_sink.get());
-  host->WillCommit(nullptr);
   host_impl.CreatePendingTree();
   std::unique_ptr<FakePictureLayerImpl> layer_impl =
       FakePictureLayerImpl::Create(host_impl.pending_tree(), 1);
 
-  layer->PushPropertiesTo(layer_impl.get());
+  // Here and elsewhere: when doing a full commit, we would call
+  // layer_tree_host_->ActivateCommitState() and the second argument would come
+  // from layer_tree_host_->active_commit_state(); we use pending_commit_state()
+  // just to keep the test code simple.
+  layer->PushPropertiesTo(layer_impl.get(), *host->pending_commit_state());
   EXPECT_FALSE(layer_impl->CanHaveTilings());
   EXPECT_TRUE(layer_impl->bounds() == gfx::Size(0, 0));
   EXPECT_EQ(gfx::Size(), layer_impl->raster_source()->GetSize());
@@ -101,8 +104,6 @@
   layer->SetNeedsDisplayRect(invalidation_bounds);
   layer->Update();
 
-  host->WillCommit(nullptr);
-  host->CommitComplete();
   FakeImplTaskRunnerProvider impl_task_runner_provider;
   std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink(
       FakeLayerTreeFrameSink::Create3d());
@@ -116,7 +117,7 @@
       FakePictureLayerImpl::Create(host_impl.pending_tree(), 1));
   FakePictureLayerImpl* layer_impl = static_cast<FakePictureLayerImpl*>(
       host_impl.pending_tree()->root_layer());
-  layer->PushPropertiesTo(layer_impl);
+  layer->PushPropertiesTo(layer_impl, *host->pending_commit_state());
 
   EXPECT_EQ(invalidation_bounds,
             layer_impl->GetPendingInvalidation()->bounds());
@@ -142,8 +143,6 @@
   // The important line is the following (note that we do not call Update):
   layer->SetNeedsDisplayRect(invalidation_bounds);
 
-  host->WillCommit(nullptr);
-  host->CommitComplete();
   FakeImplTaskRunnerProvider impl_task_runner_provider;
   std::unique_ptr<LayerTreeFrameSink> layer_tree_frame_sink(
       FakeLayerTreeFrameSink::Create3d());
@@ -158,7 +157,7 @@
       FakePictureLayerImpl::Create(host_impl.pending_tree(), 1));
   FakePictureLayerImpl* layer_impl = static_cast<FakePictureLayerImpl*>(
       host_impl.pending_tree()->root_layer());
-  layer->PushPropertiesTo(layer_impl);
+  layer->PushPropertiesTo(layer_impl, *host->pending_commit_state());
 
   EXPECT_EQ(gfx::Rect(), layer_impl->GetPendingInvalidation()->bounds());
 }
@@ -181,7 +180,7 @@
   layer->Update();
 
   EXPECT_EQ(0, host->SourceFrameNumber());
-  host->WillCommit(nullptr);
+  host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/false);
   host->CommitComplete();
   EXPECT_EQ(1, host->SourceFrameNumber());
 
@@ -204,11 +203,12 @@
       host_impl.pending_tree()->root_layer());
   SetupRootProperties(layer_impl);
   UpdateDrawProperties(host_impl.pending_tree());
-  host->WillCommit(nullptr);
 
-  layer->PushPropertiesTo(layer_impl);
-
+  auto* commit_state =
+      host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/true);
+  layer->PushPropertiesTo(layer_impl, *commit_state);
   host->CommitComplete();
+
   EXPECT_EQ(2, host->SourceFrameNumber());
 
   host_impl.ActivateSyncTree();
@@ -219,14 +219,13 @@
 
   layer->SetBounds(gfx::Size(11, 11));
 
-  host->WillCommit(nullptr);
   host_impl.CreatePendingTree();
   layer_impl = static_cast<FakePictureLayerImpl*>(
       host_impl.pending_tree()->root_layer());
 
   // We should now have invalid contents and should therefore clear the
   // recording source.
-  layer->PushPropertiesTo(layer_impl);
+  layer->PushPropertiesTo(layer_impl, *host->pending_commit_state());
   UpdateDrawProperties(host_impl.pending_tree());
 
   host_impl.ActivateSyncTree();
diff --git a/cc/layers/scrollbar_layer_base.cc b/cc/layers/scrollbar_layer_base.cc
index 993fd4ad..e252082 100644
--- a/cc/layers/scrollbar_layer_base.cc
+++ b/cc/layers/scrollbar_layer_base.cc
@@ -70,8 +70,9 @@
   SetNeedsCommit();
 }
 
-void ScrollbarLayerBase::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void ScrollbarLayerBase::PushPropertiesTo(LayerImpl* layer,
+                                          const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
 
   auto* scrollbar_layer_impl = static_cast<ScrollbarLayerImplBase*>(layer);
   DCHECK_EQ(scrollbar_layer_impl->orientation(), orientation_);
diff --git a/cc/layers/scrollbar_layer_base.h b/cc/layers/scrollbar_layer_base.h
index 394e508..86bd44a 100644
--- a/cc/layers/scrollbar_layer_base.h
+++ b/cc/layers/scrollbar_layer_base.h
@@ -24,7 +24,8 @@
     return is_left_side_vertical_scrollbar_;
   }
 
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   enum ScrollbarLayerType {
     kSolidColor,
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc
index 624d7727..cd96b905 100644
--- a/cc/layers/scrollbar_layer_unittest.cc
+++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -247,7 +247,8 @@
 
   // Simulate commit to compositor thread.
   scrollbar_layer->PushPropertiesTo(
-      scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get());
+      scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get(),
+      *layer_tree_host_->pending_commit_state());
   scrollbar_layer->fake_scrollbar()->set_needs_repaint_thumb(false);
   scrollbar_layer->fake_scrollbar()->set_needs_repaint_track(false);
 
@@ -354,13 +355,17 @@
 
   ASSERT_TRUE(layer_tree_host_->needs_commit());
 
+  // WillCommit(_, true) here will ensure that
+  // layer_tree_host_->active_commit_state() is populated, which is required
+  // during FinishCommitOnImplThread().
+  layer_tree_host_->WillCommit(/*completion_event=*/nullptr,
+                               /*has_updates=*/true);
   {
     DebugScopedSetImplThread scoped_impl_thread(
         layer_tree_host_->GetTaskRunnerProvider());
-    layer_tree_host_->FinishCommitOnImplThread(
-        layer_tree_host_->host_impl(),
-        layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises());
+    layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_->host_impl());
   }
+  layer_tree_host_->CommitComplete();
 
   EXPECT_EQ(painted_scrollbar_layer_impl->scroll_element_id_,
             layer_b->element_id());
@@ -1327,7 +1332,8 @@
 
   // Simulate commit to compositor thread.
   scrollbar_layer->PushPropertiesTo(
-      scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get());
+      scrollbar_layer->CreateLayerImpl(layer_tree_host_->active_tree()).get(),
+      *layer_tree_host_->pending_commit_state());
   scrollbar_layer->fake_scrollbar()->set_needs_repaint_thumb(false);
   scrollbar_layer->fake_scrollbar()->set_needs_repaint_track(false);
 
diff --git a/cc/layers/solid_color_layer_impl_unittest.cc b/cc/layers/solid_color_layer_impl_unittest.cc
index e206677..37d7519 100644
--- a/cc/layers/solid_color_layer_impl_unittest.cc
+++ b/cc/layers/solid_color_layer_impl_unittest.cc
@@ -185,10 +185,11 @@
   EXPECT_FALSE(layer->contents_opaque());
   layer->SetBackgroundColor(SkColorSetARGB(255, 10, 20, 30));
   EXPECT_TRUE(layer->contents_opaque());
+
+  host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/true);
   {
     DebugScopedSetImplThread scoped_impl_thread(host->GetTaskRunnerProvider());
-    host->FinishCommitOnImplThread(
-        host->host_impl(), host->GetSwapPromiseManager()->TakeSwapPromises());
+    host->FinishCommitOnImplThread(host->host_impl());
     LayerImpl* layer_impl =
         host->host_impl()->active_tree()->LayerById(layer->id());
 
@@ -209,14 +210,16 @@
     EXPECT_TRUE(
         render_pass->quad_list.front()->shared_quad_state->are_contents_opaque);
   }
+  host->CommitComplete();
 
   EXPECT_TRUE(layer->contents_opaque());
   layer->SetBackgroundColor(SkColorSetARGB(254, 10, 20, 30));
   EXPECT_FALSE(layer->contents_opaque());
+
+  host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/true);
   {
     DebugScopedSetImplThread scoped_impl_thread(host->GetTaskRunnerProvider());
-    host->FinishCommitOnImplThread(
-        host->host_impl(), host->GetSwapPromiseManager()->TakeSwapPromises());
+    host->FinishCommitOnImplThread(host->host_impl());
     LayerImpl* layer_impl =
         host->host_impl()->active_tree()->LayerById(layer->id());
 
@@ -237,6 +240,7 @@
     EXPECT_FALSE(
         render_pass->quad_list.front()->shared_quad_state->are_contents_opaque);
   }
+  host->CommitComplete();
 }
 
 TEST_F(SolidColorLayerImplTest, Occlusion) {
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index cbfb533d..521c309 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -155,8 +155,9 @@
     layer_tree_host()->AddSurfaceRange(surface_range_);
 }
 
-void SurfaceLayer::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void SurfaceLayer::PushPropertiesTo(LayerImpl* layer,
+                                    const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
   TRACE_EVENT0("cc", "SurfaceLayer::PushPropertiesTo");
   SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer);
   layer_impl->SetRange(surface_range_, std::move(deadline_in_frames_));
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h
index 6182a1a3..c19a755 100644
--- a/cc/layers/surface_layer.h
+++ b/cc/layers/surface_layer.h
@@ -64,7 +64,8 @@
   // Layer overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   const viz::SurfaceId& surface_id() const { return surface_range_.end(); }
 
diff --git a/cc/layers/surface_layer_unittest.cc b/cc/layers/surface_layer_unittest.cc
index 7e16956f..b0a67f9 100644
--- a/cc/layers/surface_layer_unittest.cc
+++ b/cc/layers/surface_layer_unittest.cc
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include <iostream>
+#include <limits>
 #include <set>
 #include <vector>
 
@@ -46,9 +47,15 @@
 
   // Synchronizes |layer_tree_host_| and |host_impl_| and pushes surface ids.
   void SynchronizeTrees() {
-    TreeSynchronizer::PushLayerProperties(layer_tree_host_.get(),
+    auto* commit_state = layer_tree_host_->ActivateCommitState();
+    TreeSynchronizer::PushLayerProperties(commit_state,
                                           host_impl_.pending_tree());
-    layer_tree_host_->PushSurfaceRangesTo(host_impl_.pending_tree());
+    if (commit_state->needs_surface_ranges_sync) {
+      host_impl_.pending_tree()->ClearSurfaceRanges();
+      host_impl_.pending_tree()->SetSurfaceRanges(
+          commit_state->SurfaceRanges());
+    }
+    layer_tree_host_->ClearActiveCommitStateForTesting();
   }
 
  protected:
@@ -133,8 +140,10 @@
   layer->SetBackgroundColor(SK_ColorBLUE);
   layer->SetStretchContentToFillBounds(true);
 
-  EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync());
-  EXPECT_EQ(layer_tree_host_->SurfaceRanges().size(), 1u);
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
+  EXPECT_EQ(layer_tree_host_->pending_commit_state()->SurfaceRanges().size(),
+            1u);
 
   // Verify that pending tree has no surface ids already.
   EXPECT_FALSE(host_impl_.pending_tree()->needs_surface_ranges_sync());
@@ -150,7 +159,8 @@
   EXPECT_EQ(host_impl_.pending_tree()->SurfaceRanges().size(), 1u);
 
   // Verify we have reset the state on layer tree host.
-  EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync());
+  EXPECT_FALSE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
 
   // Verify that the primary and fallback SurfaceIds are pushed through.
   EXPECT_EQ(primary_id, layer_impl->range().end());
@@ -169,8 +179,10 @@
 
   // Verify that fallback surface id is not recorded on the layer tree host as
   // surface synchronization is not enabled.
-  EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync());
-  EXPECT_EQ(layer_tree_host_->SurfaceRanges().size(), 1u);
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
+  EXPECT_EQ(layer_tree_host_->pending_commit_state()->SurfaceRanges().size(),
+            1u);
 
   SynchronizeTrees();
 
@@ -216,7 +228,7 @@
   SynchronizeTrees();
 
   // Verify that only |old_surface_id| is going to be referenced.
-  EXPECT_THAT(layer_tree_host_->SurfaceRanges(),
+  EXPECT_THAT(layer_tree_host_->pending_commit_state()->SurfaceRanges(),
               ElementsAre(viz::SurfaceRange(old_surface_id)));
   EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(),
               ElementsAre(viz::SurfaceRange(old_surface_id)));
@@ -232,7 +244,7 @@
   SynchronizeTrees();
 
   // Verify that both surface ids are going to be referenced.
-  EXPECT_THAT(layer_tree_host_->SurfaceRanges(),
+  EXPECT_THAT(layer_tree_host_->pending_commit_state()->SurfaceRanges(),
               ElementsAre(viz::SurfaceRange(old_surface_id),
                           viz::SurfaceRange(new_surface_id)));
   EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(),
@@ -245,7 +257,7 @@
   SynchronizeTrees();
 
   // Verify that only |new_surface_id| is going to be referenced.
-  EXPECT_THAT(layer_tree_host_->SurfaceRanges(),
+  EXPECT_THAT(layer_tree_host_->pending_commit_state()->SurfaceRanges(),
               ElementsAre(viz::SurfaceRange(new_surface_id)));
   EXPECT_THAT(host_impl_.pending_tree()->SurfaceRanges(),
               ElementsAre(viz::SurfaceRange(new_surface_id)));
@@ -268,15 +280,18 @@
 
   // Verify the surface id is in SurfaceLayerIds() and
   // needs_surface_ranges_sync() is true.
-  EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync());
-  EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(1));
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
+  EXPECT_THAT(layer_tree_host_->pending_commit_state()->SurfaceRanges(),
+              SizeIs(1));
 
   std::unique_ptr<SurfaceLayerImpl> layer_impl1 =
       SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer1->id());
   SynchronizeTrees();
 
   // After syncchronizing trees verify needs_surface_ranges_sync() is false.
-  EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync());
+  EXPECT_FALSE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
 
   // Create the second layer that is a clone of the first.
   scoped_refptr<SurfaceLayer> layer2 = SurfaceLayer::Create();
@@ -285,30 +300,36 @@
   layer2->SetOldestAcceptableFallback(surface_id);
 
   // Verify that after creating the second layer with the same surface id that
-  // needs_surface_ranges_sync() is still false.
-  EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync());
-  EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(1));
+  // needs_surface_ranges_sync is still false.
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
+  EXPECT_THAT(layer_tree_host_->pending_commit_state()->SurfaceRanges(),
+              SizeIs(1));
 
   std::unique_ptr<SurfaceLayerImpl> layer_impl2 =
       SurfaceLayerImpl::Create(host_impl_.pending_tree(), layer2->id());
   SynchronizeTrees();
 
-  // Verify needs_surface_ranges_sync() is still false after synchronizing
+  // Verify needs_surface_ranges_sync is still false after synchronizing
   // trees.
-  EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync());
+  EXPECT_FALSE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
 
   // Destroy one of the layers, leaving one layer with the surface id.
   layer1->SetLayerTreeHost(nullptr);
 
-  // Verify needs_surface_ranges_sync() is still false.
-  EXPECT_FALSE(layer_tree_host_->needs_surface_ranges_sync());
+  // Verify needs_surface_ranges_sync is still false.
+  EXPECT_FALSE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
 
   // Destroy the last layer, this should change the set of layer surface ids.
   layer2->SetLayerTreeHost(nullptr);
 
-  // Verify SurfaceLayerIds() is empty and needs_surface_ranges_sync() is true.
-  EXPECT_TRUE(layer_tree_host_->needs_surface_ranges_sync());
-  EXPECT_THAT(layer_tree_host_->SurfaceRanges(), SizeIs(0));
+  // Verify SurfaceLayerIds() is empty and needs_surface_ranges_sync is true.
+  EXPECT_TRUE(
+      layer_tree_host_->pending_commit_state()->needs_surface_ranges_sync);
+  EXPECT_THAT(layer_tree_host_->pending_commit_state()->SurfaceRanges(),
+              SizeIs(0));
 }
 
 }  // namespace
diff --git a/cc/layers/texture_layer.cc b/cc/layers/texture_layer.cc
index 75c00bc..2e0ee94 100644
--- a/cc/layers/texture_layer.cc
+++ b/cc/layers/texture_layer.cc
@@ -191,8 +191,9 @@
   return true;
 }
 
-void TextureLayer::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void TextureLayer::PushPropertiesTo(LayerImpl* layer,
+                                    const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
   TRACE_EVENT0("cc", "TextureLayer::PushPropertiesTo");
 
   TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer);
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h
index 6a08a98e..8847015 100644
--- a/cc/layers/texture_layer.h
+++ b/cc/layers/texture_layer.h
@@ -154,7 +154,8 @@
   void SetLayerTreeHost(LayerTreeHost* layer_tree_host) override;
   bool Update() override;
   bool IsSnappedToPixelGridInTarget() override;
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   // Request a mapping from SharedBitmapId to SharedMemory be registered via the
   // LayerTreeFrameSink with the display compositor. Once this mapping is
diff --git a/cc/layers/ui_resource_layer.cc b/cc/layers/ui_resource_layer.cc
index 0776817..8665b9c 100644
--- a/cc/layers/ui_resource_layer.cc
+++ b/cc/layers/ui_resource_layer.cc
@@ -99,19 +99,19 @@
   return resource_id_ && Layer::HasDrawableContent();
 }
 
-void UIResourceLayer::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void UIResourceLayer::PushPropertiesTo(LayerImpl* layer,
+                                       const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
   TRACE_EVENT0("cc", "UIResourceLayer::PushPropertiesTo");
   UIResourceLayerImpl* layer_impl = static_cast<UIResourceLayerImpl*>(layer);
 
   layer_impl->SetUIResourceId(resource_id_);
   if (resource_id_) {
-    DCHECK(layer_tree_host());
-
-    gfx::Size image_size =
-        layer_tree_host()->GetUIResourceManager()->GetUIResourceSize(
-            resource_id_);
-    layer_impl->SetImageBounds(image_size);
+    auto iter = commit_state.ui_resource_sizes.find(resource_id_);
+    gfx::Size image_bounds = (iter == commit_state.ui_resource_sizes.end())
+                                 ? gfx::Size()
+                                 : iter->second;
+    layer_impl->SetImageBounds(image_bounds);
     layer_impl->SetUV(uv_top_left_, uv_bottom_right_);
     layer_impl->SetVertexOpacity(vertex_opacity_);
   }
diff --git a/cc/layers/ui_resource_layer.h b/cc/layers/ui_resource_layer.h
index 529ef85..bb25356 100644
--- a/cc/layers/ui_resource_layer.h
+++ b/cc/layers/ui_resource_layer.h
@@ -23,7 +23,8 @@
   UIResourceLayer(const UIResourceLayer&) = delete;
   UIResourceLayer& operator=(const UIResourceLayer&) = delete;
 
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   void SetLayerTreeHost(LayerTreeHost* host) override;
 
diff --git a/cc/resources/ui_resource_manager.cc b/cc/resources/ui_resource_manager.cc
index aadb2558..83cfdcc 100644
--- a/cc/resources/ui_resource_manager.cc
+++ b/cc/resources/ui_resource_manager.cc
@@ -5,6 +5,7 @@
 #include "cc/resources/ui_resource_manager.h"
 
 #include <algorithm>
+#include <utility>
 
 #include "cc/resources/scoped_ui_resource.h"
 
@@ -62,13 +63,12 @@
   }
 }
 
-gfx::Size UIResourceManager::GetUIResourceSize(UIResourceId uid) const {
-  const auto iter = ui_resource_client_map_.find(uid);
-  if (iter == ui_resource_client_map_.end())
-    return gfx::Size();
-
-  const UIResourceClientData& data = iter->second;
-  return data.size;
+base::flat_map<UIResourceId, gfx::Size> UIResourceManager::GetUIResourceSizes()
+    const {
+  base::flat_map<UIResourceId, gfx::Size> result;
+  for (const auto pair : ui_resource_client_map_)
+    result.emplace(pair.first, pair.second.size);
+  return result;
 }
 
 std::vector<UIResourceRequest> UIResourceManager::TakeUIResourcesRequests() {
diff --git a/cc/resources/ui_resource_manager.h b/cc/resources/ui_resource_manager.h
index e3e51204..cf18142 100644
--- a/cc/resources/ui_resource_manager.h
+++ b/cc/resources/ui_resource_manager.h
@@ -5,9 +5,11 @@
 #ifndef CC_RESOURCES_UI_RESOURCE_MANAGER_H_
 #define CC_RESOURCES_UI_RESOURCE_MANAGER_H_
 
+#include <memory>
 #include <unordered_map>
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "cc/cc_export.h"
 #include "cc/resources/ui_resource_request.h"
 
@@ -33,7 +35,7 @@
   // Deletes a UI resource.  May safely be called more than once.
   virtual void DeleteUIResource(UIResourceId id);
 
-  virtual gfx::Size GetUIResourceSize(UIResourceId id) const;
+  base::flat_map<UIResourceId, gfx::Size> GetUIResourceSizes() const;
 
   // Methods meant to be used only internally in cc ------------
 
diff --git a/cc/test/fake_layer_tree_host.cc b/cc/test/fake_layer_tree_host.cc
index 2004cb7..e69595b9 100644
--- a/cc/test/fake_layer_tree_host.cc
+++ b/cc/test/fake_layer_tree_host.cc
@@ -88,11 +88,14 @@
 LayerImpl* FakeLayerTreeHost::CommitAndCreateLayerImplTree() {
   // TODO(pdr): Update the LayerTreeImpl lifecycle states here so lifecycle
   // violations can be caught.
-  host_impl_->BeginCommit(SourceFrameNumber());
-  TreeSynchronizer::SynchronizeTrees(root_layer(), active_tree());
+  // When doing a full commit, we would call
+  // layer_tree_host_->ActivateCommitState() and the second argument would come
+  // from layer_tree_host_->active_commit_state(); we use pending_commit_state()
+  // just to keep the test code simple.
+  host_impl_->BeginCommit(pending_commit_state()->source_frame_number);
+  TreeSynchronizer::SynchronizeTrees(pending_commit_state(), active_tree());
   active_tree()->SetPropertyTrees(property_trees());
-  TreeSynchronizer::PushLayerProperties(root_layer()->layer_tree_host(),
-                                        active_tree());
+  TreeSynchronizer::PushLayerProperties(pending_commit_state(), active_tree());
   mutator_host()->PushPropertiesTo(host_impl_->mutator_host());
 
   active_tree()->property_trees()->scroll_tree.PushScrollUpdatesFromMainThread(
@@ -103,11 +106,12 @@
 }
 
 LayerImpl* FakeLayerTreeHost::CommitAndCreatePendingTree() {
+  // pending_commit_state() is used here because this is a phony commit that
+  // doesn't actually call WillCommit() or ActivateCommitState().
   pending_tree()->set_source_frame_number(SourceFrameNumber());
-  TreeSynchronizer::SynchronizeTrees(root_layer(), pending_tree());
+  TreeSynchronizer::SynchronizeTrees(pending_commit_state(), pending_tree());
   pending_tree()->SetPropertyTrees(property_trees());
-  TreeSynchronizer::PushLayerProperties(root_layer()->layer_tree_host(),
-                                        pending_tree());
+  TreeSynchronizer::PushLayerProperties(pending_commit_state(), pending_tree());
   mutator_host()->PushPropertiesTo(host_impl_->mutator_host());
 
   pending_tree()->property_trees()->scroll_tree.PushScrollUpdatesFromMainThread(
diff --git a/cc/test/fake_painted_scrollbar_layer.cc b/cc/test/fake_painted_scrollbar_layer.cc
index 2ee5547d..02fba27 100644
--- a/cc/test/fake_painted_scrollbar_layer.cc
+++ b/cc/test/fake_painted_scrollbar_layer.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <utility>
+
 #include "cc/test/fake_painted_scrollbar_layer.h"
 
 #include "base/auto_reset.h"
@@ -56,8 +58,10 @@
   return updated;
 }
 
-void FakePaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
-  PaintedScrollbarLayer::PushPropertiesTo(layer);
+void FakePaintedScrollbarLayer::PushPropertiesTo(
+    LayerImpl* layer,
+    const CommitState& commit_state) {
+  PaintedScrollbarLayer::PushPropertiesTo(layer, commit_state);
   ++push_properties_count_;
 }
 
diff --git a/cc/test/fake_painted_scrollbar_layer.h b/cc/test/fake_painted_scrollbar_layer.h
index 6b8bcd3..32d64c4 100644
--- a/cc/test/fake_painted_scrollbar_layer.h
+++ b/cc/test/fake_painted_scrollbar_layer.h
@@ -32,7 +32,8 @@
 
   bool Update() override;
 
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
 
   using PaintedScrollbarLayer::IgnoreSetNeedsCommit;
 
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 058d39b6..c2bec701 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -31,7 +31,6 @@
   void SetNeedsUpdateLayers() override {}
   void SetNeedsCommit() override {}
   void SetNeedsRedraw(const gfx::Rect& damage_rect) override {}
-  void SetNextCommitWaitsForActivation() override {}
   void SetTargetLocalSurfaceId(
       const viz::LocalSurfaceId& target_local_surface_id) override {}
   bool RequestedAnimatePending() override;
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 15a61ca5..a210cb6cf 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -456,7 +456,9 @@
     RequestNewLayerTreeFrameSink();
   }
 
-  void WillCommit() override { test_hooks_->WillCommit(); }
+  void WillCommit(CommitState* commit_state) override {
+    test_hooks_->WillCommit(commit_state);
+  }
 
   void DidCommit(const base::TimeTicks, const base::TimeTicks) override {
     test_hooks_->DidCommit();
diff --git a/cc/test/property_tree_test_utils.cc b/cc/test/property_tree_test_utils.cc
index ba12b3c..f88e031 100644
--- a/cc/test/property_tree_test_utils.cc
+++ b/cc/test/property_tree_test_utils.cc
@@ -205,11 +205,11 @@
 // TODO(wangxianzhu): Viewport properties can exist without layers, but for now
 // it's more convenient to create properties based on layers.
 template <typename LayerType>
-LayerTreeHost::ViewportPropertyIds SetupViewportProperties(
+ViewportPropertyIds SetupViewportProperties(
     LayerType* root,
     LayerType* inner_viewport_scroll_layer,
     LayerType* outer_viewport_scroll_layer) {
-  LayerTreeHost::ViewportPropertyIds viewport_property_ids;
+  ViewportPropertyIds viewport_property_ids;
   auto* property_trees = GetPropertyTrees(root);
 
   viewport_property_ids.overscroll_elasticity_transform =
diff --git a/cc/test/push_properties_counting_layer.cc b/cc/test/push_properties_counting_layer.cc
index 44d1c23d..c2303a93 100644
--- a/cc/test/push_properties_counting_layer.cc
+++ b/cc/test/push_properties_counting_layer.cc
@@ -21,8 +21,10 @@
 
 PushPropertiesCountingLayer::~PushPropertiesCountingLayer() = default;
 
-void PushPropertiesCountingLayer::PushPropertiesTo(LayerImpl* layer) {
-  Layer::PushPropertiesTo(layer);
+void PushPropertiesCountingLayer::PushPropertiesTo(
+    LayerImpl* layer,
+    const CommitState& commit_state) {
+  Layer::PushPropertiesTo(layer, commit_state);
   AddPushPropertiesCount();
 }
 
diff --git a/cc/test/push_properties_counting_layer.h b/cc/test/push_properties_counting_layer.h
index d1a9cc4..53c4a28c 100644
--- a/cc/test/push_properties_counting_layer.h
+++ b/cc/test/push_properties_counting_layer.h
@@ -24,7 +24,8 @@
       delete;
 
   // Layer implementation.
-  void PushPropertiesTo(LayerImpl* layer) override;
+  void PushPropertiesTo(LayerImpl* layer,
+                        const CommitState& commit_state) override;
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
 
   // Something to make this layer push properties, but no other layer.
diff --git a/cc/test/stub_layer_tree_host_client.h b/cc/test/stub_layer_tree_host_client.h
index 23b5e1c..dcee3bc 100644
--- a/cc/test/stub_layer_tree_host_client.h
+++ b/cc/test/stub_layer_tree_host_client.h
@@ -13,6 +13,8 @@
 
 namespace cc {
 
+struct CommitState;
+
 class StubLayerTreeHostClient : public LayerTreeHostClient {
  public:
   ~StubLayerTreeHostClient() override;
@@ -40,7 +42,7 @@
   void RequestNewLayerTreeFrameSink() override {}
   void DidInitializeLayerTreeFrameSink() override {}
   void DidFailToInitializeLayerTreeFrameSink() override {}
-  void WillCommit() override {}
+  void WillCommit(CommitState*) override {}
   void DidCommit(base::TimeTicks, base::TimeTicks) override {}
   void DidCommitAndDrawFrame() override {}
   void DidObserveFirstScrollDelay(
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h
index 282cf8e..fa140c9c 100644
--- a/cc/test/test_hooks.h
+++ b/cc/test/test_hooks.h
@@ -117,7 +117,7 @@
   virtual void DidInitializeLayerTreeFrameSink() {}
   virtual void DidFailToInitializeLayerTreeFrameSink() {}
   virtual void DidAddAnimation() {}
-  virtual void WillCommit() {}
+  virtual void WillCommit(CommitState*) {}
   virtual void DidCommit() {}
   virtual void DidCommitAndDrawFrame() {}
   virtual void DidReceiveCompositorFrameAck() {}
diff --git a/cc/trees/commit_state.cc b/cc/trees/commit_state.cc
new file mode 100644
index 0000000..ea985888
--- /dev/null
+++ b/cc/trees/commit_state.cc
@@ -0,0 +1,59 @@
+// Copyright 2021 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/trees/commit_state.h"
+
+namespace cc {
+
+CommitState::CommitState() = default;
+CommitState::~CommitState() = default;
+CommitState::CommitState(const CommitState& prev)
+    : surface_ranges(prev.surface_ranges),
+      visual_properties_update_duration(prev.visual_properties_update_duration),
+      have_scroll_event_handlers(prev.have_scroll_event_handlers),
+      is_external_pinch_gesture_active(prev.is_external_pinch_gesture_active),
+      is_viewport_mobile_optimized(prev.is_viewport_mobile_optimized),
+      may_throttle_if_undrawn_frames(prev.may_throttle_if_undrawn_frames),
+      prefers_reduced_motion(prev.prefers_reduced_motion),
+      browser_controls_params(prev.browser_controls_params),
+      bottom_controls_shown_ratio(prev.bottom_controls_shown_ratio),
+      device_scale_factor(prev.device_scale_factor),
+      external_page_scale_factor(prev.external_page_scale_factor),
+      max_page_scale_factor(prev.max_page_scale_factor),
+      min_page_scale_factor(prev.min_page_scale_factor),
+      page_scale_factor(prev.page_scale_factor),
+      painted_device_scale_factor(prev.painted_device_scale_factor),
+      top_controls_shown_ratio(prev.top_controls_shown_ratio),
+      display_color_spaces(prev.display_color_spaces),
+      display_transform_hint(prev.display_transform_hint),
+      device_viewport_rect(prev.device_viewport_rect),
+      visual_device_viewport_size(prev.visual_device_viewport_size),
+      elastic_overscroll(prev.elastic_overscroll),
+      hud_layer_id(prev.hud_layer_id),
+      source_frame_number(prev.source_frame_number),
+      selection(prev.selection),
+      debug_state(prev.debug_state),
+      overscroll_behavior(prev.overscroll_behavior),
+      root_layer(prev.root_layer),
+      background_color(prev.background_color),
+      viewport_property_ids(prev.viewport_property_ids),
+      local_surface_id_from_parent(prev.local_surface_id_from_parent) {
+  memcpy(event_listener_properties, prev.event_listener_properties,
+         sizeof(event_listener_properties));
+}
+
+base::flat_set<viz::SurfaceRange> CommitState::SurfaceRanges() const {
+  base::flat_set<viz::SurfaceRange> ranges;
+  for (auto& map_entry : surface_ranges)
+    ranges.insert(map_entry.first);
+  return ranges;
+}
+
+EventListenerProperties CommitState::GetEventListenerProperties(
+    EventListenerClass listener_class) const {
+  DCHECK(listener_class >= EventListenerClass::kPointerRawUpdate);
+  DCHECK(listener_class <= EventListenerClass::kTouchEndOrCancel);
+  return event_listener_properties[static_cast<size_t>(listener_class)];
+}
+}  // namespace cc
diff --git a/cc/trees/commit_state.h b/cc/trees/commit_state.h
new file mode 100644
index 0000000..ef0867cd
--- /dev/null
+++ b/cc/trees/commit_state.h
@@ -0,0 +1,159 @@
+// Copyright 2021 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_TREES_COMMIT_STATE_H_
+#define CC_TREES_COMMIT_STATE_H_
+
+#include <memory>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/time/time.h"
+#include "cc/benchmarks/micro_benchmark_impl.h"
+#include "cc/cc_export.h"
+#include "cc/debug/layer_tree_debug_state.h"
+#include "cc/document_transition/document_transition_request.h"
+#include "cc/input/event_listener_properties.h"
+#include "cc/input/layer_selection_bound.h"
+#include "cc/input/overscroll_behavior.h"
+#include "cc/input/page_scale_animation.h"
+#include "cc/layers/layer.h"
+#include "cc/layers/layer_list_iterator.h"
+#include "cc/metrics/begin_main_frame_metrics.h"
+#include "cc/metrics/event_metrics.h"
+#include "cc/paint/paint_image.h"
+#include "cc/resources/ui_resource_request.h"
+#include "cc/trees/browser_controls_params.h"
+#include "cc/trees/presentation_time_callback_buffer.h"
+#include "cc/trees/swap_promise.h"
+#include "cc/trees/viewport_property_ids.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/delegated_ink_metadata.h"
+#include "ui/gfx/display_color_spaces.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gfx/overlay_transform.h"
+
+namespace cc {
+
+// This is used to snapshot all LayerTreeHost state that is accessed during
+// compositor commit.
+struct CC_EXPORT CommitState {
+  CommitState();
+  // Note: the copy constructor only copies persistent fields
+  CommitState(const CommitState&);
+  CommitState& operator=(const CommitState&) = delete;
+  ~CommitState();
+
+  LayerListIterator begin() const {
+    return LayerListIterator(root_layer.get());
+  }
+  LayerListIterator end() const { return LayerListIterator(nullptr); }
+
+  base::flat_set<viz::SurfaceRange> SurfaceRanges() const;
+  EventListenerProperties GetEventListenerProperties(EventListenerClass) const;
+
+  // -------------------------------------------------------------------------
+  // Persistent: these values persist on the LayerTreeHost between commits.
+  // When a new persistent field is added, it must also be added to the copy
+  // constructor.
+
+  base::flat_map<viz::SurfaceRange, int> surface_ranges;
+  base::TimeDelta visual_properties_update_duration;
+  bool needs_gpu_rasterization_histogram = false;
+  bool have_scroll_event_handlers = false;
+  bool is_external_pinch_gesture_active = false;
+  // Set to true if viewport is mobile optimized by using meta tag
+  // <meta name="viewport" content="width=device-width">
+  // or
+  // <meta name="viewport" content="initial-scale=1.0">
+  bool is_viewport_mobile_optimized = false;
+  bool may_throttle_if_undrawn_frames = true;
+  bool prefers_reduced_motion = false;
+  BrowserControlsParams browser_controls_params;
+  EventListenerProperties
+      event_listener_properties[static_cast<size_t>(EventListenerClass::kLast) +
+                                1] = {EventListenerProperties::kNone};
+  float bottom_controls_shown_ratio = 0.f;
+  float device_scale_factor = 1.f;
+  float external_page_scale_factor = 1.f;
+  float max_page_scale_factor = 1.f;
+  float min_page_scale_factor = 1.f;
+  float page_scale_factor = 1.f;
+  float painted_device_scale_factor = 1.f;
+  float top_controls_shown_ratio = 0.f;
+  gfx::DisplayColorSpaces display_color_spaces;
+  // Display transform hint to tag generated compositor frames.
+  gfx::OverlayTransform display_transform_hint = gfx::OVERLAY_TRANSFORM_NONE;
+  gfx::Rect device_viewport_rect;
+  gfx::Size visual_device_viewport_size;
+  gfx::Vector2dF elastic_overscroll;
+  int hud_layer_id = Layer::INVALID_ID;
+  int source_frame_number = 0;
+  LayerSelection selection;
+  LayerTreeDebugState debug_state;
+  OverscrollBehavior overscroll_behavior;
+  scoped_refptr<Layer> root_layer;
+  SkColor background_color = SK_ColorWHITE;
+  ViewportPropertyIds viewport_property_ids;
+  viz::LocalSurfaceId local_surface_id_from_parent;
+
+  // -------------------------------------------------------------------------
+  // Take/reset: these values are reset on the LayerTreeHost between commits.
+
+  // Set of layers that need to push properties.
+  base::flat_set<Layer*> layers_that_should_push_properties;
+  // The number of SurfaceLayers that have (fallback,primary) set to
+  // viz::SurfaceRange.
+  bool clear_caches_on_next_commit = false;
+  // Whether we have a pending request to force send RenderFrameMetadata with
+  // the next frame.
+  bool force_send_metadata_request = false;
+  bool commit_waits_for_activation = false;
+  bool needs_full_tree_sync = false;
+  bool needs_surface_ranges_sync = false;
+  bool new_local_surface_id_request = false;
+  bool next_commit_forces_recalculate_raster_scales = false;
+  bool next_commit_forces_redraw = false;
+  EventMetrics::List event_metrics;
+  // Latency information for work done in ProxyMain::BeginMainFrame. The
+  // unique_ptr is allocated in RequestMainFrameUpdate, and passed to Blink's
+  // LocalFrameView that fills in the fields. This object adds the timing for
+  // UpdateLayers. CC reads the data during commit, and clears the unique_ptr.
+  std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics;
+  // Metadata required for drawing a delegated ink trail onto the end of a
+  // stroke. std::unique_ptr was specifically chosen so that it would be
+  // cleared as it is forwarded along the pipeline to avoid old information
+  // incorrectly sticking around and potentially being reused.
+  std::unique_ptr<gfx::DelegatedInkMetadata> delegated_ink_metadata;
+  std::unique_ptr<PendingPageScaleAnimation> pending_page_scale_animation;
+  std::vector<std::pair<int, std::unique_ptr<PaintImage>>> queued_image_decodes;
+  // Presentation time callbacks requested for the next frame are initially
+  // added here.
+  std::vector<PresentationTimeCallbackBuffer::MainCallback>
+      pending_presentation_time_callbacks;
+  std::vector<std::unique_ptr<MicroBenchmarkImpl>> benchmarks;
+  // A list of document transitions that need to be transported from Blink to
+  // Viz, as a CompositorFrameTransitionDirective.
+  std::vector<std::unique_ptr<DocumentTransitionRequest>>
+      document_transition_requests;
+  std::vector<std::unique_ptr<SwapPromise>> swap_promises;
+  std::vector<UIResourceRequest> ui_resource_request_queue;
+  base::flat_map<UIResourceId, gfx::Size> ui_resource_sizes;
+
+  // -------------------------------------------------------------------------
+  // These values are populated on the impl thread during commit. They are
+  // read on the main thread after commit is finished.
+  base::TimeTicks impl_commit_start_time;
+  base::TimeTicks impl_commit_finish_time;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_COMMIT_STATE_H_
diff --git a/cc/trees/draw_properties_unittest.cc b/cc/trees/draw_properties_unittest.cc
index 5f5c3acc..8b34441 100644
--- a/cc/trees/draw_properties_unittest.cc
+++ b/cc/trees/draw_properties_unittest.cc
@@ -104,7 +104,8 @@
     // TODO(https://crbug.com/939968) This call should be handled by
     // FakeLayerTreeHost instead of manually pushing the properties from the
     // layer tree host to the pending tree.
-    host()->PushLayerTreePropertiesTo(host_impl()->pending_tree());
+    LayerTreeHost::PushLayerTreePropertiesTo(host()->pending_commit_state(),
+                                             host_impl()->pending_tree());
 
     UpdateDrawProperties(host_impl()->pending_tree());
   }
@@ -3271,7 +3272,7 @@
   CopyProperties(parent, child_scale);
   CreateTransformNode(child_scale).local = child_scale_matrix;
 
-  LayerTreeImpl::ViewportPropertyIds viewport_property_ids;
+  ViewportPropertyIds viewport_property_ids;
   viewport_property_ids.page_scale_transform =
       page_scale->transform_tree_index();
   host_impl()->active_tree()->SetViewportPropertyIds(viewport_property_ids);
@@ -5973,7 +5974,7 @@
   CopyProperties(page_scale.get(), child2.get());
   CreateTransformNode(child2.get()).local = scale_transform_child2;
 
-  LayerTreeHost::ViewportPropertyIds viewport_property_ids;
+  ViewportPropertyIds viewport_property_ids;
   viewport_property_ids.page_scale_transform =
       page_scale->transform_tree_index();
   host()->RegisterViewportPropertyIds(viewport_property_ids);
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index ec67c4f..6927d8d 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -50,6 +50,7 @@
 #include "cc/resources/ui_resource_manager.h"
 #include "cc/tiles/raster_dark_mode_filter.h"
 #include "cc/trees/clip_node.h"
+#include "cc/trees/commit_state.h"
 #include "cc/trees/compositor_commit_data.h"
 #include "cc/trees/draw_property_utils.h"
 #include "cc/trees/effect_node.h"
@@ -142,38 +143,43 @@
       client_(params.client),
       scheduling_client_(params.scheduling_client),
       rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
+      pending_commit_state_(std::make_unique<CommitState>()),
       settings_(*params.settings),
-      debug_state_(settings_.initial_debug_state),
       id_(s_layer_tree_host_sequence_number.GetNext() + 1),
       task_graph_runner_(params.task_graph_runner),
       main_thread_pipeline_(params.main_thread_pipeline),
       compositor_thread_pipeline_(params.compositor_thread_pipeline),
-      event_listener_properties_(),
       mutator_host_(params.mutator_host),
       dark_mode_filter_(params.dark_mode_filter) {
   DCHECK(task_graph_runner_);
   DCHECK(!settings_.enable_checker_imaging || image_worker_task_runner_);
 
+  pending_commit_state_->needs_gpu_rasterization_histogram =
+      (mode == CompositorMode::THREADED);
+  pending_commit_state_->needs_full_tree_sync = true;
+  pending_commit_state_->debug_state = settings_.initial_debug_state;
+
   mutator_host_->SetMutatorHostClient(this);
 
   rendering_stats_instrumentation_->set_record_rendering_stats(
-      debug_state_.RecordRenderingStats());
+      pending_commit_state_->debug_state.RecordRenderingStats());
 }
 
 bool LayerTreeHost::IsMobileOptimized() const {
   gfx::SizeF scrollable_viewport_size;
-  auto* inner_node =
-      property_trees()->scroll_tree.Node(viewport_property_ids_.inner_scroll);
+  auto* inner_node = property_trees()->scroll_tree.Node(
+      pending_commit_state()->viewport_property_ids.inner_scroll);
   if (!inner_node)
     scrollable_viewport_size = gfx::SizeF();
   else
     scrollable_viewport_size = gfx::ScaleSize(
         gfx::SizeF(inner_node->container_bounds),
-        1.0f / (external_page_scale_factor_ * page_scale_factor()));
+        1.0f / (pending_commit_state()->external_page_scale_factor *
+                page_scale_factor()));
 
   gfx::SizeF scrollable_size;
-  auto* scroll_node =
-      property_trees()->scroll_tree.Node(viewport_property_ids_.outer_scroll);
+  auto* scroll_node = property_trees()->scroll_tree.Node(
+      pending_commit_state()->viewport_property_ids.outer_scroll);
   if (!scroll_node) {
     DCHECK(!inner_node);
     scrollable_size = gfx::SizeF();
@@ -186,7 +192,8 @@
 
   return util::IsMobileOptimized(
       min_page_scale_factor(), max_page_scale_factor(), page_scale_factor(),
-      scrollable_viewport_size, scrollable_size, is_viewport_mobile_optimized_);
+      scrollable_viewport_size, scrollable_size,
+      pending_commit_state()->is_viewport_mobile_optimized);
 }
 
 void LayerTreeHost::InitializeThreaded(
@@ -239,18 +246,19 @@
   // Track when we're inside a main frame to see if compositor is being
   // destroyed midway which causes a crash. crbug.com/895883
   CHECK(!inside_main_frame_);
+  DCHECK(!in_commit());
   TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
 
   // Clear any references into the LayerTreeHost.
   mutator_host_->SetMutatorHostClient(nullptr);
 
-  if (root_layer_) {
-    root_layer_->SetLayerTreeHost(nullptr);
+  if (root_layer()) {
+    root_layer()->SetLayerTreeHost(nullptr);
 
     // The root layer must be destroyed before the layer tree. We've made a
     // contract with our animation controllers that the animation_host will
     // outlive them, and we must make good.
-    root_layer_ = nullptr;
+    pending_commit_state()->root_layer = nullptr;
   }
 
   // Fail any pending image decodes.
@@ -272,7 +280,7 @@
 
 int LayerTreeHost::SourceFrameNumber() const {
   DCHECK(task_runner_provider_->IsMainThread());
-  return source_frame_number_;
+  return pending_commit_state()->source_frame_number;
 }
 
 UIResourceManager* LayerTreeHost::GetUIResourceManager() const {
@@ -332,15 +340,16 @@
 }
 
 const LayerTreeDebugState& LayerTreeHost::GetDebugState() const {
-  return debug_state_;
+  return pending_commit_state()->debug_state;
 }
 
 void LayerTreeHost::RequestMainFrameUpdate(bool report_metrics) {
   client_->UpdateLayerTreeHost();
   if (report_metrics)
-    begin_main_frame_metrics_ = client_->GetBeginMainFrameMetrics();
+    pending_commit_state()->begin_main_frame_metrics =
+        client_->GetBeginMainFrameMetrics();
   else
-    begin_main_frame_metrics_.reset();
+    pending_commit_state()->begin_main_frame_metrics.reset();
 }
 
 // This function commits the LayerTreeHost to an impl tree. When modifying
@@ -348,36 +357,29 @@
 // code that is logically a main thread operation, e.g. deletion of a Layer,
 // should be delayed until the LayerTreeHost::CommitComplete, which will run
 // after the commit, but on the main thread.
-void LayerTreeHost::FinishCommitOnImplThread(
-    LayerTreeHostImpl* host_impl,
-    std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
+void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
   DCHECK(task_runner_provider_->IsImplThread());
+  CommitState* state = active_commit_state();
+  DCHECK(state);
 
   TRACE_EVENT0("cc,benchmark", "LayerTreeHost::FinishCommitOnImplThread");
 
   LayerTreeImpl* sync_tree = host_impl->sync_tree();
   sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kBeginningSync);
 
-  if (next_commit_forces_redraw_) {
+  if (state->next_commit_forces_redraw)
     sync_tree->ForceRedrawNextActivation();
-    next_commit_forces_redraw_ = false;
-  }
-  if (next_commit_forces_recalculate_raster_scales_) {
+  if (state->next_commit_forces_recalculate_raster_scales)
     sync_tree->ForceRecalculateRasterScales();
-    next_commit_forces_recalculate_raster_scales_ = false;
-  }
-
-  if (!pending_presentation_time_callbacks_.empty()) {
+  if (!state->pending_presentation_time_callbacks.empty()) {
     sync_tree->AddPresentationCallbacks(
-        std::move(pending_presentation_time_callbacks_));
-    pending_presentation_time_callbacks_.clear();
+        std::move(state->pending_presentation_time_callbacks));
   }
 
-  if (needs_full_tree_sync_)
-    TreeSynchronizer::SynchronizeTrees(root_layer(), sync_tree);
+  if (state->needs_full_tree_sync)
+    TreeSynchronizer::SynchronizeTrees(state, sync_tree);
 
-  if (clear_caches_on_next_commit_) {
-    clear_caches_on_next_commit_ = false;
+  if (state->clear_caches_on_next_commit) {
     proxy_->ClearHistory();
     host_impl->ClearCaches();
   }
@@ -388,20 +390,22 @@
     PushPropertyTreesTo(sync_tree);
     sync_tree->lifecycle().AdvanceTo(LayerTreeLifecycle::kSyncedPropertyTrees);
 
-    PushSurfaceRangesTo(sync_tree);
-    TreeSynchronizer::PushLayerProperties(this, sync_tree);
+    if (state->needs_surface_ranges_sync) {
+      sync_tree->ClearSurfaceRanges();
+      sync_tree->SetSurfaceRanges(state->SurfaceRanges());
+    }
+    TreeSynchronizer::PushLayerProperties(state, sync_tree);
     sync_tree->lifecycle().AdvanceTo(
         LayerTreeLifecycle::kSyncedLayerProperties);
 
-    PushLayerTreePropertiesTo(sync_tree);
+    PushLayerTreePropertiesTo(state, sync_tree);
     PushLayerTreeHostPropertiesTo(host_impl);
 
-    sync_tree->PassSwapPromises(std::move(swap_promises));
+    sync_tree->PassSwapPromises(std::move(state->swap_promises));
     sync_tree->AppendEventsMetricsFromMainThread(
-        events_metrics_manager_.TakeSavedEventsMetrics());
+        std::move(state->event_metrics));
 
-    sync_tree->set_ui_resource_request_queue(
-        ui_resource_manager_->TakeUIResourcesRequests());
+    sync_tree->set_ui_resource_request_queue(state->ui_resource_request_queue);
 
     // This must happen after synchronizing property trees and after pushing
     // properties, which updates the clobber_active_value flag.
@@ -430,17 +434,16 @@
   }
 
   // Transfer image decode requests to the impl thread.
-  for (auto& request : queued_image_decodes_) {
-    int next_id = s_image_decode_sequence_number.GetNext();
-    pending_image_decodes_[next_id] = std::move(request.second);
-    host_impl->QueueImageDecode(next_id, std::move(request.first));
+  for (auto& entry : state->queued_image_decodes) {
+    host_impl->QueueImageDecode(entry.first, *entry.second);
   }
-  queued_image_decodes_.clear();
 
-  micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl);
+  for (auto& benchmark : state->benchmarks)
+    host_impl->ScheduleMicroBenchmark(std::move(benchmark));
+
   property_trees_.ResetAllChangeTracking();
 
-  SetImplCommitFinishTime(base::TimeTicks::Now());
+  state->impl_commit_finish_time = base::TimeTicks::Now();
 
   // Dump property trees and layers if run with:
   //   --vmodule=layer_tree_host=3
@@ -466,7 +469,8 @@
     // Property trees may store damage status. We preserve the sync tree damage
     // status by pushing the damage status from sync tree property trees to main
     // thread property trees or by moving it onto the layers.
-    if (root_layer_) {
+    DCHECK(active_commit_state());
+    if (active_commit_state()->root_layer) {
       if (property_trees_.sequence_number ==
           tree_impl->property_trees()->sequence_number)
         tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_);
@@ -495,7 +499,9 @@
   // Property trees may store damage status. We preserve the sync tree damage
   // status by pushing the damage status from sync tree property trees to main
   // thread property trees or by moving it onto the layers.
-  if (root_layer_ && property_trees_changed_on_active_tree) {
+  DCHECK(active_commit_state());
+  if (active_commit_state()->root_layer &&
+      property_trees_changed_on_active_tree) {
     if (property_trees_.sequence_number ==
         tree_impl->property_trees()->sequence_number)
       tree_impl->property_trees()->PushChangeTrackingTo(&property_trees_);
@@ -506,15 +512,48 @@
   tree_impl->SetPropertyTrees(&property_trees_);
 }
 
-void LayerTreeHost::WillCommit(std::unique_ptr<CompletionEvent> completion) {
+void LayerTreeHost::SetNextCommitWaitsForActivation() {
+  DCHECK(task_runner_provider_->IsMainThread());
+  pending_commit_state()->commit_waits_for_activation = true;
+}
+
+CommitState* LayerTreeHost::WillCommit(
+    std::unique_ptr<CompletionEvent> completion,
+    bool has_updates) {
   DCHECK(!commit_completion_event_);
   commit_completion_event_ = std::move(completion);
+  CommitState* result = nullptr;
+  if (has_updates)
+    result = ActivateCommitState();
   swap_promise_manager_.WillCommit();
-  client_->WillCommit();
-  source_frame_number_++;
+  client_->WillCommit(result ? result : pending_commit_state());
+  pending_commit_state()->source_frame_number++;
+  return result;
+}
+
+CommitState* LayerTreeHost::ActivateCommitState() {
+  DCHECK(pending_commit_state());
+  DCHECK(!active_commit_state_);
+
+  // Pull state not stored directly on LayerTreeHost
+  pending_commit_state()->event_metrics =
+      events_metrics_manager_.TakeSavedEventsMetrics();
+  pending_commit_state()->swap_promises =
+      GetSwapPromiseManager()->TakeSwapPromises();
+  pending_commit_state()->ui_resource_request_queue =
+      ui_resource_manager_->TakeUIResourcesRequests();
+  pending_commit_state()->ui_resource_sizes =
+      ui_resource_manager_->GetUIResourceSizes();
+  pending_commit_state()->benchmarks =
+      micro_benchmark_controller_.CreateImplBenchmarks();
+
+  active_commit_state_.swap(pending_commit_state_);
+  pending_commit_state_ = std::make_unique<CommitState>(*active_commit_state_);
+  return active_commit_state_.get();
 }
 
 void LayerTreeHost::WaitForCommitCompletion() {
+  DCHECK(task_runner_provider_->IsMainThread());
   if (commit_completion_event_) {
     commit_completion_event_->Wait();
     commit_completion_event_ = nullptr;
@@ -522,8 +561,9 @@
 }
 
 void LayerTreeHost::UpdateDeferMainFrameUpdateInternal() {
-  proxy_->SetDeferMainFrameUpdate(defer_main_frame_update_count_ > 0 ||
-                                  !local_surface_id_from_parent_.is_valid());
+  proxy_->SetDeferMainFrameUpdate(
+      defer_main_frame_update_count_ > 0 ||
+      !pending_commit_state()->local_surface_id_from_parent.is_valid());
 }
 
 bool LayerTreeHost::IsUsingLayerLists() const {
@@ -534,12 +574,18 @@
   // This DCHECK ensures that WaitForCommitCompletion() will not block.
   DCHECK(!in_commit());
   WaitForCommitCompletion();
-  client_->DidCommit(impl_commit_start_time_, impl_commit_finish_time_);
-  impl_commit_start_time_ = impl_commit_finish_time_ = base::TimeTicks();
+  auto* commit_state = active_commit_state_.get();
+  if (commit_state) {
+    client_->DidCommit(commit_state->impl_commit_start_time,
+                       commit_state->impl_commit_finish_time);
+  } else {
+    client_->DidCommit(base::TimeTicks(), base::TimeTicks::Now());
+  }
   if (did_complete_scale_animation_) {
     client_->DidCompletePageScaleAnimation();
     did_complete_scale_animation_ = false;
   }
+  active_commit_state_ = nullptr;
 }
 
 void LayerTreeHost::NotifyTransitionRequestsFinished(
@@ -704,7 +750,7 @@
 }
 
 void LayerTreeHost::SetNeedsRecalculateRasterScales() {
-  next_commit_forces_recalculate_raster_scales_ = true;
+  pending_commit_state()->next_commit_forces_recalculate_raster_scales = true;
   proxy_->SetNeedsCommit();
 }
 
@@ -716,12 +762,8 @@
   return proxy_->CommitRequested();
 }
 
-void LayerTreeHost::SetNextCommitWaitsForActivation() {
-  proxy_->SetNextCommitWaitsForActivation();
-}
-
 void LayerTreeHost::SetNeedsCommitWithForcedRedraw() {
-  next_commit_forces_redraw_ = true;
+  pending_commit_state()->next_commit_forces_redraw = true;
   // This method is used by tests to ensure a commit before grabbing a screen
   // shot or processing input, so do not defer the commit.
   StopDeferringCommits(PaintHoldingCommitTrigger::kFeatureDisabled);
@@ -729,13 +771,14 @@
 }
 
 void LayerTreeHost::SetDebugState(const LayerTreeDebugState& new_debug_state) {
-  if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
+  if (LayerTreeDebugState::Equal(pending_commit_state()->debug_state,
+                                 new_debug_state))
     return;
 
-  debug_state_ = new_debug_state;
+  pending_commit_state()->debug_state = new_debug_state;
 
   rendering_stats_instrumentation_->set_record_rendering_stats(
-      debug_state_.RecordRenderingStats());
+      pending_commit_state()->debug_state.RecordRenderingStats());
 
   SetNeedsCommit();
 }
@@ -744,7 +787,8 @@
   DCHECK(CommitRequested());
   if (page_scale_delta == 1.f)
     return;
-  float page_scale = page_scale_factor_ * page_scale_delta;
+  float page_scale =
+      pending_commit_state()->page_scale_factor * page_scale_delta;
   SetPageScaleFromImplSide(page_scale);
 }
 
@@ -779,7 +823,7 @@
 bool LayerTreeHost::UpdateLayers() {
   if (!root_layer()) {
     property_trees_.clear();
-    viewport_property_ids_ = ViewportPropertyIds();
+    pending_commit_state()->viewport_property_ids = ViewportPropertyIds();
     return false;
   }
 
@@ -792,8 +836,10 @@
   micro_benchmark_controller_.DidUpdateLayers();
 
   base::TimeDelta elapsed_delta = timer.Elapsed();
-  if (begin_main_frame_metrics_)
-    begin_main_frame_metrics_->update_layers = elapsed_delta;
+  if (pending_commit_state()->begin_main_frame_metrics) {
+    pending_commit_state()->begin_main_frame_metrics->update_layers =
+        elapsed_delta;
+  }
   if (const char* client_name = GetClientNameForMetrics()) {
     auto elapsed = elapsed_delta.InMicroseconds();
 
@@ -822,7 +868,8 @@
     const LayerTreeHostImpl* host_impl) {
   // Gpu rasterization is only supported for Renderer compositors.
   // Checking for IsSingleThreaded() to exclude Browser compositors.
-  if (gpu_rasterization_histogram_recorded_ || IsSingleThreaded())
+  DCHECK(active_commit_state());
+  if (!active_commit_state()->needs_gpu_rasterization_histogram)
     return;
 
   bool gpu_rasterization_enabled = false;
@@ -841,7 +888,6 @@
   // mostly used for debugging purposes.
   UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationEnabled",
                         gpu_rasterization_enabled);
-  gpu_rasterization_histogram_recorded_ = true;
 }
 
 std::string LayerTreeHost::LayersAsString() const {
@@ -875,7 +921,14 @@
 
 void LayerTreeHost::AddDocumentTransitionRequest(
     std::unique_ptr<DocumentTransitionRequest> request) {
-  document_transition_requests_.push_back(std::move(request));
+  // Store the commit callback on LayerTreeHost, so that we can invoke them
+  // when the request is finished.
+  DCHECK(
+      !base::Contains(document_transition_callbacks_, request->sequence_id()));
+  document_transition_callbacks_[request->sequence_id()] =
+      request->TakeFinishedCallback();
+  pending_commit_state()->document_transition_requests.push_back(
+      std::move(request));
   SetNeedsCommit();
 }
 
@@ -883,7 +936,7 @@
   TRACE_EVENT1("cc,benchmark", "LayerTreeHost::DoUpdateLayers",
                "source_frame_number", SourceFrameNumber());
 
-  UpdateHudLayer(debug_state_.ShouldCreateHudLayer());
+  UpdateHudLayer(pending_commit_state()->debug_state.ShouldCreateHudLayer());
 
   // In layer lists mode, the cc property trees are built directly and do not
   // need to be built here.
@@ -901,13 +954,13 @@
                          property_trees_.AsTracedValue());
     // The HUD layer is managed outside the layer list sent to LayerTreeHost
     // and needs to have its property tree state set.
-    if (hud_layer_ && root_layer_.get()) {
-      hud_layer_->SetTransformTreeIndex(root_layer_->transform_tree_index());
-      hud_layer_->SetEffectTreeIndex(root_layer_->effect_tree_index());
-      hud_layer_->SetClipTreeIndex(root_layer_->clip_tree_index());
-      hud_layer_->SetScrollTreeIndex(root_layer_->scroll_tree_index());
+    if (hud_layer_ && root_layer()) {
+      hud_layer_->SetTransformTreeIndex(root_layer()->transform_tree_index());
+      hud_layer_->SetEffectTreeIndex(root_layer()->effect_tree_index());
+      hud_layer_->SetClipTreeIndex(root_layer()->clip_tree_index());
+      hud_layer_->SetScrollTreeIndex(root_layer()->scroll_tree_index());
       hud_layer_->set_property_tree_sequence_number(
-          root_layer_->property_tree_sequence_number());
+          root_layer()->property_tree_sequence_number());
     }
   }
 
@@ -927,7 +980,7 @@
   // This is a quick sanity check for readiness of paint properties.
   // TODO(crbug.com/913464): This is to help analysis of crashes of the bug.
   // Remove this CHECK when we close the bug.
-  CHECK(property_trees_.effect_tree.Node(root_layer_->effect_tree_index()));
+  CHECK(property_trees_.effect_tree.Node(root_layer()->effect_tree_index()));
 #endif
 
   draw_property_utils::UpdatePropertyTrees(this);
@@ -976,14 +1029,14 @@
   is_pinch_gesture_active_from_impl_ = commit_data.is_pinch_gesture_active;
 
   if (auto* inner_scroll = property_trees()->scroll_tree.Node(
-          viewport_property_ids_.inner_scroll)) {
+          pending_commit_state()->viewport_property_ids.inner_scroll)) {
     UpdateScrollOffsetFromImpl(
         inner_scroll->element_id, inner_viewport_scroll_delta,
         commit_data.inner_viewport_scroll.snap_target_element_ids);
   }
 
   ApplyPageScaleDeltaFromImplSide(commit_data.page_scale_delta);
-  SetElasticOverscrollFromImplSide(elastic_overscroll_ +
+  SetElasticOverscrollFromImplSide(pending_commit_state()->elastic_overscroll +
                                    commit_data.elastic_overscroll_delta);
   // TODO(ccameron): pass the elastic overscroll here so that input events
   // may be translated appropriately.
@@ -1059,7 +1112,7 @@
     swap_promise_manager_.QueueSwapPromise(std::move(swap_promise));
   }
 
-  if (root_layer_) {
+  if (root_layer()) {
     auto& scroll_tree = property_trees()->scroll_tree;
     for (auto& scroll : commit_data->scrolls) {
       UpdateScrollOffsetFromImpl(scroll.element_id, scroll.scroll_delta,
@@ -1179,7 +1232,8 @@
 
 void LayerTreeHost::RequestPresentationTimeForNextFrame(
     PresentationTimeCallbackBuffer::MainCallback callback) {
-  pending_presentation_time_callbacks_.push_back(std::move(callback));
+  pending_commit_state()->pending_presentation_time_callbacks.push_back(
+      std::move(callback));
 }
 
 void LayerTreeHost::RequestScrollAnimationEndNotification(
@@ -1191,24 +1245,28 @@
     std::move(callback).Run();
 }
 
-void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
-  if (root_layer_.get() == root_layer.get())
+void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> new_root_layer) {
+  if (root_layer() == new_root_layer.get())
     return;
 
-  if (root_layer_.get())
-    root_layer_->SetLayerTreeHost(nullptr);
-  root_layer_ = root_layer;
-  if (root_layer_.get()) {
-    DCHECK(!root_layer_->parent());
-    root_layer_->SetLayerTreeHost(this);
+  if (root_layer()) {
+    WaitForCommitCompletion();
+    root_layer()->SetLayerTreeHost(nullptr);
+  }
+  pending_commit_state()->root_layer = new_root_layer;
+  if (root_layer()) {
+    DCHECK(!root_layer()->parent());
+    root_layer()->SetLayerTreeHost(this);
   }
 
-  if (hud_layer_.get())
+  if (hud_layer_.get()) {
+    WaitForCommitCompletion();
     hud_layer_->RemoveFromParent();
+  }
 
   // Reset gpu rasterization tracking.
   // This flag is sticky until a new tree comes along.
-  gpu_rasterization_histogram_recorded_ = false;
+  pending_commit_state()->needs_gpu_rasterization_histogram = IsThreaded();
 
   SetNeedsFullTreeSync();
 }
@@ -1216,7 +1274,7 @@
 void LayerTreeHost::RegisterViewportPropertyIds(
     const ViewportPropertyIds& ids) {
   DCHECK(IsUsingLayerLists());
-  viewport_property_ids_ = ids;
+  pending_commit_state()->viewport_property_ids = ids;
   // Outer viewport properties exist only if inner viewport property exists.
   DCHECK(ids.inner_scroll != ScrollTree::kInvalidNodeId ||
          (ids.outer_scroll == ScrollTree::kInvalidNodeId &&
@@ -1224,8 +1282,8 @@
 }
 
 Layer* LayerTreeHost::InnerViewportScrollLayerForTesting() const {
-  auto* scroll_node =
-      property_trees()->scroll_tree.Node(viewport_property_ids_.inner_scroll);
+  auto* scroll_node = property_trees()->scroll_tree.Node(
+      pending_commit_state()->viewport_property_ids.inner_scroll);
   return scroll_node ? LayerByElementId(scroll_node->element_id) : nullptr;
 }
 
@@ -1234,34 +1292,34 @@
 }
 
 ElementId LayerTreeHost::OuterViewportScrollElementId() const {
-  auto* scroll_node =
-      property_trees()->scroll_tree.Node(viewport_property_ids_.outer_scroll);
+  auto* scroll_node = property_trees()->scroll_tree.Node(
+      pending_commit_state()->viewport_property_ids.outer_scroll);
   return scroll_node ? scroll_node->element_id : ElementId();
 }
 
 void LayerTreeHost::RegisterSelection(const LayerSelection& selection) {
-  if (selection_ == selection)
+  if (pending_commit_state()->selection == selection)
     return;
 
-  selection_ = selection;
+  pending_commit_state()->selection = selection;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetHaveScrollEventHandlers(bool have_event_handlers) {
-  if (have_scroll_event_handlers_ == have_event_handlers)
+  if (pending_commit_state()->have_scroll_event_handlers == have_event_handlers)
     return;
 
-  have_scroll_event_handlers_ = have_event_handlers;
+  pending_commit_state()->have_scroll_event_handlers = have_event_handlers;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetEventListenerProperties(
     EventListenerClass event_class,
     EventListenerProperties properties) {
-  const size_t index = static_cast<size_t>(event_class);
-  if (event_listener_properties_[index] == properties)
+  if (event_listener_properties(event_class) == properties)
     return;
-  event_listener_properties_[index] = properties;
+  const size_t index = static_cast<size_t>(event_class);
+  pending_commit_state()->event_listener_properties[index] = properties;
   SetNeedsCommit();
 }
 
@@ -1270,7 +1328,7 @@
     float device_scale_factor,
     const viz::LocalSurfaceId& local_surface_id_from_parent) {
   const viz::LocalSurfaceId previous_local_surface_id =
-      local_surface_id_from_parent_;
+      pending_commit_state()->local_surface_id_from_parent;
   SetLocalSurfaceIdFromParent(local_surface_id_from_parent);
 
   TRACE_EVENT_NESTABLE_ASYNC_END1("cc", "LayerTreeHostSize",
@@ -1281,22 +1339,23 @@
                                     local_surface_id_from_parent.ToString());
 
   bool device_viewport_rect_changed = false;
-  if (device_viewport_rect_ != device_viewport_rect) {
-    device_viewport_rect_ = device_viewport_rect;
+  if (pending_commit_state()->device_viewport_rect != device_viewport_rect) {
+    pending_commit_state()->device_viewport_rect = device_viewport_rect;
     device_viewport_rect_changed = true;
   }
   bool painted_device_scale_factor_changed = false;
   bool device_scale_factor_changed = false;
   if (settings_.use_painted_device_scale_factor) {
-    DCHECK_EQ(device_scale_factor_, 1.f);
-    if (painted_device_scale_factor_ != device_scale_factor) {
-      painted_device_scale_factor_ = device_scale_factor;
+    DCHECK_EQ(pending_commit_state()->device_scale_factor, 1.f);
+    if (pending_commit_state()->painted_device_scale_factor !=
+        device_scale_factor) {
+      pending_commit_state()->painted_device_scale_factor = device_scale_factor;
       painted_device_scale_factor_changed = true;
     }
   } else {
-    DCHECK_EQ(painted_device_scale_factor_, 1.f);
-    if (device_scale_factor_ != device_scale_factor) {
-      device_scale_factor_ = device_scale_factor;
+    DCHECK_EQ(pending_commit_state()->painted_device_scale_factor, 1.f);
+    if (pending_commit_state()->device_scale_factor != device_scale_factor) {
+      pending_commit_state()->device_scale_factor = device_scale_factor;
       device_scale_factor_changed = true;
     }
   }
@@ -1325,46 +1384,48 @@
 
 void LayerTreeHost::SetVisualDeviceViewportSize(
     const gfx::Size& visual_device_viewport_size) {
-  if (visual_device_viewport_size == visual_device_viewport_size_)
+  if (visual_device_viewport_size ==
+      pending_commit_state()->visual_device_viewport_size)
     return;
 
-  visual_device_viewport_size_ = visual_device_viewport_size;
+  pending_commit_state()->visual_device_viewport_size =
+      visual_device_viewport_size;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetBrowserControlsParams(
     const BrowserControlsParams& params) {
-  if (browser_controls_params_ == params)
+  if (pending_commit_state()->browser_controls_params == params)
     return;
 
-  browser_controls_params_ = params;
+  pending_commit_state()->browser_controls_params = params;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetBrowserControlsShownRatio(float top_ratio,
                                                  float bottom_ratio) {
-  if (top_controls_shown_ratio_ == top_ratio &&
-      bottom_controls_shown_ratio_ == bottom_ratio)
+  if (pending_commit_state()->top_controls_shown_ratio == top_ratio &&
+      pending_commit_state()->bottom_controls_shown_ratio == bottom_ratio)
     return;
 
-  top_controls_shown_ratio_ = top_ratio;
-  bottom_controls_shown_ratio_ = bottom_ratio;
+  pending_commit_state()->top_controls_shown_ratio = top_ratio;
+  pending_commit_state()->bottom_controls_shown_ratio = bottom_ratio;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetOverscrollBehavior(const OverscrollBehavior& behavior) {
-  if (overscroll_behavior_ == behavior)
+  if (pending_commit_state()->overscroll_behavior == behavior)
     return;
-  overscroll_behavior_ = behavior;
+  pending_commit_state()->overscroll_behavior = behavior;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
                                                 float min_page_scale_factor,
                                                 float max_page_scale_factor) {
-  if (page_scale_factor_ == page_scale_factor &&
-      min_page_scale_factor_ == min_page_scale_factor &&
-      max_page_scale_factor_ == max_page_scale_factor)
+  if (pending_commit_state()->page_scale_factor == page_scale_factor &&
+      pending_commit_state()->min_page_scale_factor == min_page_scale_factor &&
+      pending_commit_state()->max_page_scale_factor == max_page_scale_factor)
     return;
   DCHECK_GE(page_scale_factor, min_page_scale_factor);
   DCHECK_LE(page_scale_factor, max_page_scale_factor);
@@ -1372,13 +1433,14 @@
   // TODO(wjmaclean): Remove this dcheck as a pre-condition to closing the bug.
   // https://crbug.com/845097
   DCHECK(!settings_.is_layer_tree_for_subframe ||
-         page_scale_factor == page_scale_factor_)
-      << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_
+         page_scale_factor == pending_commit_state()->page_scale_factor)
+      << "Setting PSF in oopif subframe: old psf = "
+      << pending_commit_state()->page_scale_factor
       << ", new psf = " << page_scale_factor;
 
-  page_scale_factor_ = page_scale_factor;
-  min_page_scale_factor_ = min_page_scale_factor;
-  max_page_scale_factor_ = max_page_scale_factor;
+  pending_commit_state()->page_scale_factor = page_scale_factor;
+  pending_commit_state()->min_page_scale_factor = min_page_scale_factor;
+  pending_commit_state()->max_page_scale_factor = max_page_scale_factor;
   SetPropertyTreesNeedRebuild();
   SetNeedsCommit();
 }
@@ -1387,14 +1449,15 @@
                                             bool use_anchor,
                                             float scale,
                                             base::TimeDelta duration) {
-  pending_page_scale_animation_ = std::make_unique<PendingPageScaleAnimation>(
-      target_offset, use_anchor, scale, duration);
+  pending_commit_state()->pending_page_scale_animation =
+      std::make_unique<PendingPageScaleAnimation>(target_offset, use_anchor,
+                                                  scale, duration);
 
   SetNeedsCommit();
 }
 
 bool LayerTreeHost::HasPendingPageScaleAnimation() const {
-  return !!pending_page_scale_animation_.get();
+  return !!pending_commit_state()->pending_page_scale_animation.get();
 }
 
 void LayerTreeHost::SetRecordingScaleFactor(float recording_scale_factor) {
@@ -1405,50 +1468,56 @@
 
 void LayerTreeHost::SetDisplayColorSpaces(
     const gfx::DisplayColorSpaces& display_color_spaces) {
-  if (display_color_spaces_ == display_color_spaces)
+  if (pending_commit_state()->display_color_spaces == display_color_spaces)
     return;
-  display_color_spaces_ = display_color_spaces;
+  pending_commit_state()->display_color_spaces = display_color_spaces;
   for (auto* layer : *this)
     layer->SetNeedsDisplay();
 }
 
 void LayerTreeHost::UpdateViewportIsMobileOptimized(
     bool is_viewport_mobile_optimized) {
-  if (is_viewport_mobile_optimized_ == is_viewport_mobile_optimized)
+  if (pending_commit_state()->is_viewport_mobile_optimized ==
+      is_viewport_mobile_optimized)
     return;
-  is_viewport_mobile_optimized_ = is_viewport_mobile_optimized;
+  pending_commit_state()->is_viewport_mobile_optimized =
+      is_viewport_mobile_optimized;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetPrefersReducedMotion(bool prefers_reduced_motion) {
-  if (prefers_reduced_motion_ == prefers_reduced_motion)
+  if (pending_commit_state()->prefers_reduced_motion == prefers_reduced_motion)
     return;
-  prefers_reduced_motion_ = prefers_reduced_motion;
+  pending_commit_state()->prefers_reduced_motion = prefers_reduced_motion;
   SetNeedsCommit();
 }
 
 void LayerTreeHost::SetMayThrottleIfUndrawnFrames(
     bool may_throttle_if_undrawn_frames) {
-  if (may_throttle_if_undrawn_frames_ == may_throttle_if_undrawn_frames)
+  if (pending_commit_state()->may_throttle_if_undrawn_frames ==
+      may_throttle_if_undrawn_frames)
     return;
-  may_throttle_if_undrawn_frames_ = may_throttle_if_undrawn_frames;
+  pending_commit_state()->may_throttle_if_undrawn_frames =
+      may_throttle_if_undrawn_frames;
   SetNeedsCommit();
 }
 
 bool LayerTreeHost::GetMayThrottleIfUndrawnFramesForTesting() const {
-  return may_throttle_if_undrawn_frames_;
+  return pending_commit_state()->may_throttle_if_undrawn_frames;
 }
 
 void LayerTreeHost::SetExternalPageScaleFactor(
     float page_scale_factor,
     bool is_external_pinch_gesture_active) {
-  if (external_page_scale_factor_ == page_scale_factor &&
-      is_external_pinch_gesture_active_ == is_external_pinch_gesture_active) {
+  if (pending_commit_state()->external_page_scale_factor == page_scale_factor &&
+      pending_commit_state()->is_external_pinch_gesture_active ==
+          is_external_pinch_gesture_active) {
     return;
   }
 
-  external_page_scale_factor_ = page_scale_factor;
-  is_external_pinch_gesture_active_ = is_external_pinch_gesture_active;
+  pending_commit_state()->external_page_scale_factor = page_scale_factor;
+  pending_commit_state()->is_external_pinch_gesture_active =
+      is_external_pinch_gesture_active;
   SetNeedsCommit();
 }
 
@@ -1462,10 +1531,11 @@
   //
   // TODO(jonross): Untangle startup so that we don't have this invalid partial
   // state. (https://crbug.com/1185286) (https://crbug.com/419087)
-  if (local_surface_id_from_parent_ == local_surface_id_from_parent)
+  if (pending_commit_state()->local_surface_id_from_parent ==
+      local_surface_id_from_parent)
     return;
   const viz::LocalSurfaceId current_local_surface_id_from_parent =
-      local_surface_id_from_parent_;
+      pending_commit_state()->local_surface_id_from_parent;
 
   // These traces are split into two due to the usage of TRACE_ID_GLOBAL for the
   // incoming flow (it comes from a different process), and TRACE_ID_LOCAL for
@@ -1485,7 +1555,8 @@
       "local_surface_id", local_surface_id_from_parent.ToString());
   // Always update the cached state of the viz::LocalSurfaceId to reflect the
   // latest value received from our parent.
-  local_surface_id_from_parent_ = local_surface_id_from_parent;
+  pending_commit_state()->local_surface_id_from_parent =
+      local_surface_id_from_parent;
 
   // If the parent sequence number has not advanced, then there is no need to
   // commit anything. This can occur when the child sequence number has
@@ -1506,21 +1577,16 @@
 void LayerTreeHost::RequestNewLocalSurfaceId() {
   // We can still request a new viz::LocalSurfaceId but that request will be
   // deferred until we have a valid viz::LocalSurfaceId from the parent.
-  if (new_local_surface_id_request_)
+  if (pending_commit_state()->new_local_surface_id_request)
     return;
-  new_local_surface_id_request_ = true;
+  pending_commit_state()->new_local_surface_id_request = true;
   SetNeedsCommit();
 }
 
-bool LayerTreeHost::TakeNewLocalSurfaceIdRequest() {
-  bool new_local_surface_id_request = new_local_surface_id_request_;
-  new_local_surface_id_request_ = false;
-  return new_local_surface_id_request;
-}
-
 void LayerTreeHost::SetVisualPropertiesUpdateDuration(
     base::TimeDelta visual_properties_update_duration) {
-  visual_properties_update_duration_ = visual_properties_update_duration;
+  pending_commit_state()->visual_properties_update_duration =
+      visual_properties_update_duration;
 }
 
 void LayerTreeHost::RegisterLayer(Layer* layer) {
@@ -1540,7 +1606,7 @@
     mutator_host_->UnregisterElementId(layer->element_id(),
                                        ElementListType::ACTIVE);
   }
-  layers_that_should_push_properties_.erase(layer);
+  pending_commit_state()->layers_that_should_push_properties.erase(layer);
   layer_id_map_.erase(layer->id());
 }
 
@@ -1559,34 +1625,23 @@
 }
 
 void LayerTreeHost::AddSurfaceRange(const viz::SurfaceRange& surface_range) {
-  if (++surface_ranges_[surface_range] == 1)
-    needs_surface_ranges_sync_ = true;
+  if (++pending_commit_state()->surface_ranges[surface_range] == 1)
+    pending_commit_state()->needs_surface_ranges_sync = true;
 }
 
 void LayerTreeHost::RemoveSurfaceRange(const viz::SurfaceRange& surface_range) {
-  auto iter = surface_ranges_.find(surface_range);
-  if (iter == surface_ranges_.end())
+  auto iter = pending_commit_state()->surface_ranges.find(surface_range);
+  if (iter == pending_commit_state()->surface_ranges.end())
     return;
 
   if (--iter->second <= 0) {
-    surface_ranges_.erase(iter);
-    needs_surface_ranges_sync_ = true;
+    pending_commit_state()->surface_ranges.erase(iter);
+    pending_commit_state()->needs_surface_ranges_sync = true;
   }
 }
 
-base::flat_set<viz::SurfaceRange> LayerTreeHost::SurfaceRanges() const {
-  base::flat_set<viz::SurfaceRange> ranges;
-  for (auto& map_entry : surface_ranges_)
-    ranges.insert(map_entry.first);
-  return ranges;
-}
-
 void LayerTreeHost::AddLayerShouldPushProperties(Layer* layer) {
-  layers_that_should_push_properties_.insert(layer);
-}
-
-void LayerTreeHost::ClearLayersThatShouldPushProperties() {
-  layers_that_should_push_properties_.clear();
+  pending_commit_state()->layers_that_should_push_properties.insert(layer);
 }
 
 void LayerTreeHost::SetPageScaleFromImplSide(float page_scale) {
@@ -1595,28 +1650,32 @@
   // TODO(wjmaclean): Remove this check as a pre-condition to closing the bug.
   // https://crbug.com/845097
   DCHECK(!settings_.is_layer_tree_for_subframe ||
-         page_scale == page_scale_factor_)
-      << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_
+         page_scale == pending_commit_state()->page_scale_factor)
+      << "Setting PSF in oopif subframe: old psf = "
+      << pending_commit_state()->page_scale_factor
       << ", new psf = " << page_scale;
-  page_scale_factor_ = page_scale;
+  pending_commit_state()->page_scale_factor = page_scale;
   SetPropertyTreesNeedRebuild();
 }
 
 void LayerTreeHost::SetElasticOverscrollFromImplSide(
     gfx::Vector2dF elastic_overscroll) {
   DCHECK(CommitRequested());
-  elastic_overscroll_ = elastic_overscroll;
+  pending_commit_state()->elastic_overscroll = elastic_overscroll;
 }
 
 void LayerTreeHost::UpdateHudLayer(bool show_hud_info) {
   if (show_hud_info) {
-    if (!hud_layer_.get())
+    if (!hud_layer_.get()) {
       hud_layer_ = HeadsUpDisplayLayer::Create();
-    if (root_layer_.get() && !hud_layer_->parent())
-      root_layer_->AddChild(hud_layer_);
-    hud_layer_->UpdateLocationAndSize(device_viewport_rect_.size(),
-                                      device_scale_factor_);
-    if (debug_state_.show_web_vital_metrics) {
+      pending_commit_state()->hud_layer_id = hud_layer_->id();
+    }
+    if (root_layer() && !hud_layer_->parent())
+      root_layer()->AddChild(hud_layer_);
+    hud_layer_->UpdateLocationAndSize(
+        pending_commit_state()->device_viewport_rect.size(),
+        pending_commit_state()->device_scale_factor);
+    if (pending_commit_state()->debug_state.show_web_vital_metrics) {
       // This WebVitalMetrics is filled by the main frame, which is equivalent
       // to WebPerf's numbers. The main frame's number doesn't include any
       // iframes. UMA/UKM records metrics for the entire page aggregating all
@@ -1629,6 +1688,7 @@
   } else if (hud_layer_.get()) {
     hud_layer_->RemoveFromParent();
     hud_layer_ = nullptr;
+    pending_commit_state()->hud_layer_id = Layer::INVALID_ID;
   }
 }
 
@@ -1637,74 +1697,81 @@
 }
 
 void LayerTreeHost::SetNeedsFullTreeSync() {
-  needs_full_tree_sync_ = true;
+  pending_commit_state()->needs_full_tree_sync = true;
   property_trees_.needs_rebuild = true;
   SetNeedsCommit();
 }
 
+void LayerTreeHost::ResetNeedsFullTreeSyncForTesting() {
+  pending_commit_state()->needs_full_tree_sync = false;
+}
+
 void LayerTreeHost::SetPropertyTreesNeedRebuild() {
   property_trees_.needs_rebuild = true;
   SetNeedsUpdateLayers();
 }
 
-void LayerTreeHost::PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl) {
-  tree_impl->set_needs_full_tree_sync(needs_full_tree_sync_);
-  needs_full_tree_sync_ = false;
+void LayerTreeHost::PushLayerTreePropertiesTo(CommitState* state,
+                                              LayerTreeImpl* tree_impl) {
+  DCHECK(state);
+  tree_impl->set_needs_full_tree_sync(state->needs_full_tree_sync);
 
-  if (hud_layer_.get()) {
-    LayerImpl* hud_impl = tree_impl->LayerById(hud_layer_->id());
+  if (state->hud_layer_id != Layer::INVALID_ID) {
+    LayerImpl* hud_impl = tree_impl->LayerById(state->hud_layer_id);
     tree_impl->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl));
   } else {
     tree_impl->set_hud_layer(nullptr);
   }
 
-  tree_impl->set_background_color(background_color_);
-  tree_impl->set_have_scroll_event_handlers(have_scroll_event_handlers_);
+  tree_impl->set_background_color(state->background_color);
+  tree_impl->set_have_scroll_event_handlers(state->have_scroll_event_handlers);
   tree_impl->set_event_listener_properties(
       EventListenerClass::kTouchStartOrMove,
-      event_listener_properties(EventListenerClass::kTouchStartOrMove));
+      state->GetEventListenerProperties(EventListenerClass::kTouchStartOrMove));
   tree_impl->set_event_listener_properties(
       EventListenerClass::kMouseWheel,
-      event_listener_properties(EventListenerClass::kMouseWheel));
+      state->GetEventListenerProperties(EventListenerClass::kMouseWheel));
   tree_impl->set_event_listener_properties(
       EventListenerClass::kTouchEndOrCancel,
-      event_listener_properties(EventListenerClass::kTouchEndOrCancel));
+      state->GetEventListenerProperties(EventListenerClass::kTouchEndOrCancel));
 
-  tree_impl->SetViewportPropertyIds(viewport_property_ids_);
+  tree_impl->SetViewportPropertyIds(state->viewport_property_ids);
 
-  tree_impl->RegisterSelection(selection_);
+  tree_impl->RegisterSelection(state->selection);
 
-  tree_impl->PushPageScaleFromMainThread(
-      page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_);
+  tree_impl->PushPageScaleFromMainThread(state->page_scale_factor,
+                                         state->min_page_scale_factor,
+                                         state->max_page_scale_factor);
 
-  tree_impl->SetBrowserControlsParams(browser_controls_params_);
-  tree_impl->set_overscroll_behavior(overscroll_behavior_);
-  tree_impl->PushBrowserControlsFromMainThread(top_controls_shown_ratio_,
-                                               bottom_controls_shown_ratio_);
-  tree_impl->elastic_overscroll()->PushMainToPending(elastic_overscroll_);
+  tree_impl->SetBrowserControlsParams(state->browser_controls_params);
+  tree_impl->set_overscroll_behavior(state->overscroll_behavior);
+  tree_impl->PushBrowserControlsFromMainThread(
+      state->top_controls_shown_ratio, state->bottom_controls_shown_ratio);
+  tree_impl->elastic_overscroll()->PushMainToPending(state->elastic_overscroll);
   if (tree_impl->IsActiveTree())
     tree_impl->elastic_overscroll()->PushPendingToActive();
 
-  tree_impl->SetDisplayColorSpaces(display_color_spaces_);
-  tree_impl->SetExternalPageScaleFactor(external_page_scale_factor_);
+  tree_impl->SetDisplayColorSpaces(state->display_color_spaces);
+  tree_impl->SetExternalPageScaleFactor(state->external_page_scale_factor);
 
-  tree_impl->set_painted_device_scale_factor(painted_device_scale_factor_);
-  tree_impl->SetDeviceScaleFactor(device_scale_factor_);
-  tree_impl->SetDeviceViewportRect(device_viewport_rect_);
+  tree_impl->set_painted_device_scale_factor(
+      state->painted_device_scale_factor);
+  tree_impl->SetDeviceScaleFactor(state->device_scale_factor);
+  tree_impl->SetDeviceViewportRect(state->device_viewport_rect);
 
-  if (TakeNewLocalSurfaceIdRequest())
+  if (state->new_local_surface_id_request)
     tree_impl->RequestNewLocalSurfaceId();
 
-  tree_impl->SetLocalSurfaceIdFromParent(local_surface_id_from_parent_);
+  tree_impl->SetLocalSurfaceIdFromParent(state->local_surface_id_from_parent);
   tree_impl->SetVisualPropertiesUpdateDuration(
-      visual_properties_update_duration_);
+      state->visual_properties_update_duration);
 
-  if (pending_page_scale_animation_) {
+  if (state->pending_page_scale_animation) {
     tree_impl->SetPendingPageScaleAnimation(
-        std::move(pending_page_scale_animation_));
+        std::move(state->pending_page_scale_animation));
   }
 
-  if (TakeForceSendMetadataRequest())
+  if (state->force_send_metadata_request)
     tree_impl->RequestForceSendMetadata();
 
   tree_impl->set_has_ever_been_drawn(false);
@@ -1714,51 +1781,39 @@
   // happen, so we must force the impl tree to update its viewports if
   // |top_controls_shown_ratio_| is greater than 0.0f and less than 1.0f
   // (partially shown). crbug.com/875943
-  if (top_controls_shown_ratio_ > 0.0f && top_controls_shown_ratio_ < 1.0f) {
+  if (state->top_controls_shown_ratio > 0.0f &&
+      state->top_controls_shown_ratio < 1.0f) {
     tree_impl->UpdateViewportContainerSizes();
   }
 
-  tree_impl->set_display_transform_hint(display_transform_hint_);
+  tree_impl->set_display_transform_hint(state->display_transform_hint);
 
-  if (delegated_ink_metadata_)
-    tree_impl->set_delegated_ink_metadata(std::move(delegated_ink_metadata_));
+  if (state->delegated_ink_metadata)
+    tree_impl->set_delegated_ink_metadata(
+        std::move(state->delegated_ink_metadata));
 
   // Transfer page transition directives.
-  for (auto& request : document_transition_requests_) {
-    // Store the commit callback on LayerTreeHost, so that we can invoke them
-    // when the request is finished.
-    DCHECK(!base::Contains(document_transition_callbacks_,
-                           request->sequence_id()));
-    document_transition_callbacks_[request->sequence_id()] =
-        request->TakeFinishedCallback();
-
+  for (auto& request : state->document_transition_requests)
     tree_impl->AddDocumentTransitionRequest(std::move(request));
-  }
-  document_transition_requests_.clear();
-}
-
-void LayerTreeHost::PushSurfaceRangesTo(LayerTreeImpl* tree_impl) {
-  if (needs_surface_ranges_sync()) {
-    tree_impl->ClearSurfaceRanges();
-    tree_impl->SetSurfaceRanges(SurfaceRanges());
-    // Reset for next update
-    set_needs_surface_ranges_sync(false);
-  }
 }
 
 void LayerTreeHost::PushLayerTreeHostPropertiesTo(
     LayerTreeHostImpl* host_impl) {
+  CommitState* state = active_commit_state();
+  DCHECK(state);
   // TODO(bokan): The |external_pinch_gesture_active| should not be going
   // through the LayerTreeHost but directly from InputHandler to InputHandler.
-  host_impl->SetExternalPinchGestureActive(is_external_pinch_gesture_active_);
+  host_impl->SetExternalPinchGestureActive(
+      state->is_external_pinch_gesture_active);
 
   RecordGpuRasterizationHistogram(host_impl);
 
-  host_impl->SetDebugState(debug_state_);
-  host_impl->SetVisualDeviceViewportSize(visual_device_viewport_size_);
-  host_impl->set_viewport_mobile_optimized(is_viewport_mobile_optimized_);
-  host_impl->SetPrefersReducedMotion(prefers_reduced_motion_);
-  host_impl->SetMayThrottleIfUndrawnFrames(may_throttle_if_undrawn_frames_);
+  host_impl->SetDebugState(state->debug_state);
+  host_impl->SetVisualDeviceViewportSize(state->visual_device_viewport_size);
+  host_impl->set_viewport_mobile_optimized(state->is_viewport_mobile_optimized);
+  host_impl->SetPrefersReducedMotion(state->prefers_reduced_motion);
+  host_impl->SetMayThrottleIfUndrawnFrames(
+      state->may_throttle_if_undrawn_frames);
 }
 
 Layer* LayerTreeHost::LayerByElementId(ElementId element_id) const {
@@ -1932,12 +1987,15 @@
 void LayerTreeHost::QueueImageDecode(const PaintImage& image,
                                      base::OnceCallback<void(bool)> callback) {
   TRACE_EVENT0("cc", "LayerTreeHost::QueueImageDecode");
-  queued_image_decodes_.emplace_back(image, std::move(callback));
+  int next_id = s_image_decode_sequence_number.GetNext();
+  pending_commit_state()->queued_image_decodes.emplace_back(
+      next_id, std::make_unique<PaintImage>(image));
+  pending_image_decodes_.emplace(next_id, std::move(callback));
   SetNeedsCommit();
 }
 
 LayerListIterator LayerTreeHost::begin() const {
-  return LayerListIterator(root_layer_.get());
+  return LayerListIterator(root_layer());
 }
 
 LayerListIterator LayerTreeHost::end() const {
@@ -1945,7 +2003,7 @@
 }
 
 LayerListReverseIterator LayerTreeHost::rbegin() {
-  return LayerListReverseIterator(root_layer_.get());
+  return LayerListReverseIterator(root_layer());
 }
 
 LayerListReverseIterator LayerTreeHost::rend() {
@@ -1973,11 +2031,11 @@
 void LayerTreeHost::SetSourceURL(ukm::SourceId source_id, const GURL& url) {
   // Clears image caches and resets the scheduling history for the content
   // produced by this host so far.
-  clear_caches_on_next_commit_ = true;
+  pending_commit_state()->clear_caches_on_next_commit = true;
   proxy_->SetSourceURL(source_id, url);
   // If this is not used as a common web page, don't show HUD.
   if (!url.SchemeIsHTTPOrHTTPS())
-    debug_state_.TurnOffHudInfoDisplay();
+    pending_commit_state()->debug_state.TurnOffHudInfoDisplay();
 }
 
 base::ReadOnlySharedMemoryRegion
@@ -1996,12 +2054,6 @@
   proxy_->SetRenderFrameObserver(std::move(observer));
 }
 
-bool LayerTreeHost::TakeForceSendMetadataRequest() {
-  bool force_send_metadata_request = force_send_metadata_request_;
-  force_send_metadata_request_ = false;
-  return force_send_metadata_request;
-}
-
 void LayerTreeHost::SetEnableFrameRateThrottling(
     bool enable_frame_rate_throttling) {
   proxy_->SetEnableFrameRateThrottling(enable_frame_rate_throttling);
@@ -2009,7 +2061,7 @@
 
 void LayerTreeHost::SetDelegatedInkMetadata(
     std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {
-  delegated_ink_metadata_ = std::move(metadata);
+  pending_commit_state()->delegated_ink_metadata = std::move(metadata);
   SetNeedsCommit();
 }
 
@@ -2025,8 +2077,12 @@
   return pipeline;
 }
 
-std::vector<std::unique_ptr<DocumentTransitionRequest>>
-LayerTreeHost::TakeDocumentTransitionRequestsForTesting() {
-  return std::move(document_transition_requests_);
+std::vector<base::OnceClosure>
+LayerTreeHost::TakeDocumentTransitionCallbacksForTesting() {
+  std::vector<base::OnceClosure> result;
+  for (auto& item : document_transition_callbacks_)
+    result.push_back(std::move(item.second));
+  document_transition_callbacks_.clear();
+  return result;
 }
 }  // namespace cc
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 22796d0..71924d5 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -35,6 +35,7 @@
 #include "cc/input/input_handler.h"
 #include "cc/input/layer_selection_bound.h"
 #include "cc/input/scrollbar.h"
+#include "cc/layers/layer.h"
 #include "cc/layers/layer_collections.h"
 #include "cc/layers/layer_list_iterator.h"
 #include "cc/metrics/begin_main_frame_metrics.h"
@@ -42,19 +43,22 @@
 #include "cc/metrics/frame_sequence_tracker.h"
 #include "cc/metrics/web_vital_metrics.h"
 #include "cc/paint/node_id.h"
-#include "cc/trees//presentation_time_callback_buffer.h"
+#include "cc/resources/ui_resource_request.h"
 #include "cc/trees/browser_controls_params.h"
+#include "cc/trees/commit_state.h"
 #include "cc/trees/compositor_mode.h"
 #include "cc/trees/layer_tree_frame_sink.h"
 #include "cc/trees/layer_tree_host_client.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "cc/trees/mutator_host.h"
 #include "cc/trees/paint_holding_reason.h"
+#include "cc/trees/presentation_time_callback_buffer.h"
 #include "cc/trees/proxy.h"
 #include "cc/trees/swap_promise.h"
 #include "cc/trees/swap_promise_manager.h"
 #include "cc/trees/target_property.h"
 #include "cc/trees/viewport_layers.h"
+#include "cc/trees/viewport_property_ids.h"
 #include "components/viz/common/resources/resource_format.h"
 #include "components/viz/common/surfaces/local_surface_id.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -71,7 +75,6 @@
 
 class DocumentTransitionRequest;
 class HeadsUpDisplayLayer;
-class Layer;
 class LayerTreeHostImpl;
 class LayerTreeHostImplClient;
 class LayerTreeHostSingleThreadClient;
@@ -86,9 +89,9 @@
 class UIResourceManager;
 class UkmRecorderFactory;
 
+struct CommitState;
 struct CompositorCommitData;
 struct OverscrollBehavior;
-struct PendingPageScaleAnimation;
 struct RenderingStats;
 
 // Returned from LayerTreeHost::DeferMainFrameUpdate. Automatically un-defers on
@@ -154,6 +157,26 @@
   // Returns the process global unique identifier for this LayerTreeHost.
   int GetId() const;
 
+  // The commit state for the frame being assembled by the compositor host.
+  CommitState* pending_commit_state() {
+    DCHECK(task_runner_provider_->IsMainThread());
+    return pending_commit_state_.get();
+  }
+  const CommitState* pending_commit_state() const {
+    DCHECK(task_runner_provider_->IsMainThread());
+    return pending_commit_state_.get();
+  }
+
+  // The commit state for the frame being committed by the compositor.
+  CommitState* active_commit_state() {
+    DCHECK(task_runner_provider_->IsImplThread());
+    return active_commit_state_.get();
+  }
+  const CommitState* active_commit_state() const {
+    DCHECK(task_runner_provider_->IsImplThread());
+    return active_commit_state_.get();
+  }
+
   // The current source frame number. This is incremented for each main frame
   // update(commit) pushed to the compositor thread. The initial frame number
   // is 0, and it is incremented once commit is completed (which is before the
@@ -358,25 +381,15 @@
   // attached to it and will be added/removed along with the root Layer. The
   // LayerTreeHost retains ownership of a reference to the root Layer.
   void SetRootLayer(scoped_refptr<Layer> root_layer);
-  Layer* root_layer() { return root_layer_.get(); }
-  const Layer* root_layer() const { return root_layer_.get(); }
-
-  struct ViewportPropertyIds {
-    int overscroll_elasticity_transform = TransformTree::kInvalidNodeId;
-    ElementId overscroll_elasticity_effect;
-    int page_scale_transform = TransformTree::kInvalidNodeId;
-    int inner_scroll = ScrollTree::kInvalidNodeId;
-    int outer_clip = ClipTree::kInvalidNodeId;
-    int outer_scroll = ScrollTree::kInvalidNodeId;
-  };
+  Layer* root_layer() const { return pending_commit_state()->root_layer.get(); }
 
   // Sets the collection of viewport property ids, defined to allow viewport
   // pinch-zoom etc. on the compositor thread. This is set only on the
   // main-frame's compositor, i.e., will be unset in OOPIF and UI compositors.
   void RegisterViewportPropertyIds(const ViewportPropertyIds&);
 
-  LayerTreeHost::ViewportPropertyIds ViewportPropertyIdsForTesting() const {
-    return viewport_property_ids_;
+  ViewportPropertyIds ViewportPropertyIdsForTesting() const {
+    return pending_commit_state()->viewport_property_ids;
   }
   Layer* InnerViewportScrollLayerForTesting() const;
   Layer* OuterViewportScrollLayerForTesting() const;
@@ -389,7 +402,9 @@
   // handles are a UI widget above, and not clipped to, the viewport of this
   // LayerTreeHost.
   void RegisterSelection(const LayerSelection& selection);
-  const LayerSelection& selection() const { return selection_; }
+  const LayerSelection& selection() const {
+    return pending_commit_state()->selection;
+  }
 
   // Sets or gets if the client has any scroll event handlers registered. This
   // allows the threaded compositor to prioritize main frames even when
@@ -397,7 +412,7 @@
   // event handler a chance to be part of each frame.
   void SetHaveScrollEventHandlers(bool have_event_handlers);
   bool have_scroll_event_handlers() const {
-    return have_scroll_event_handlers_;
+    return pending_commit_state()->have_scroll_event_handlers;
   }
 
   // Set or get what event handlers exist on the layer tree in order to inform
@@ -409,7 +424,9 @@
                                   EventListenerProperties event_properties);
   EventListenerProperties event_listener_properties(
       EventListenerClass event_class) const {
-    return event_listener_properties_[static_cast<size_t>(event_class)];
+    DCHECK(task_runner_provider_->IsMainThread());
+    return pending_commit_state()
+        ->event_listener_properties[static_cast<size_t>(event_class)];
   }
 
   // Indicates that its acceptable to throttle the frame rate for this content
@@ -438,7 +455,9 @@
   // compositors. This is specified in device viewport coordinate space.
   void SetVisualDeviceViewportSize(const gfx::Size&);
 
-  gfx::Rect device_viewport_rect() const { return device_viewport_rect_; }
+  gfx::Rect device_viewport_rect() const {
+    return pending_commit_state()->device_viewport_rect;
+  }
 
   void UpdateViewportIsMobileOptimized(bool is_viewport_mobile_optimized);
 
@@ -455,24 +474,34 @@
 
   void SetOverscrollBehavior(const OverscrollBehavior& overscroll_behavior);
   const OverscrollBehavior& overscroll_behavior() const {
-    return overscroll_behavior_;
+    return pending_commit_state()->overscroll_behavior;
   }
 
   void SetPageScaleFactorAndLimits(float page_scale_factor,
                                    float min_page_scale_factor,
                                    float max_page_scale_factor);
-  float page_scale_factor() const { return page_scale_factor_; }
-  float min_page_scale_factor() const { return min_page_scale_factor_; }
-  float max_page_scale_factor() const { return max_page_scale_factor_; }
+  float page_scale_factor() const {
+    return pending_commit_state()->page_scale_factor;
+  }
+  float min_page_scale_factor() const {
+    return pending_commit_state()->min_page_scale_factor;
+  }
+  float max_page_scale_factor() const {
+    return pending_commit_state()->max_page_scale_factor;
+  }
 
-  void set_background_color(SkColor color) { background_color_ = color; }
-  SkColor background_color() const { return background_color_; }
+  void set_background_color(SkColor color) {
+    pending_commit_state()->background_color = color;
+  }
+  SkColor background_color() const {
+    return pending_commit_state()->background_color;
+  }
 
   void set_display_transform_hint(gfx::OverlayTransform hint) {
-    display_transform_hint_ = hint;
+    pending_commit_state()->display_transform_hint = hint;
   }
   gfx::OverlayTransform display_transform_hint() const {
-    return display_transform_hint_;
+    return pending_commit_state()->display_transform_hint;
   }
 
   void StartPageScaleAnimation(const gfx::Vector2d& target_offset,
@@ -481,21 +510,19 @@
                                base::TimeDelta duration);
   bool HasPendingPageScaleAnimation() const;
 
-  float device_scale_factor() const { return device_scale_factor_; }
+  float device_scale_factor() const {
+    return pending_commit_state()->device_scale_factor;
+  }
 
   void SetRecordingScaleFactor(float recording_scale_factor);
 
-  float painted_device_scale_factor() const {
-    return painted_device_scale_factor_;
-  }
-
   // If this LayerTreeHost needs a valid viz::LocalSurfaceId then commits will
   // be deferred until a valid viz::LocalSurfaceId is provided.
   void SetLocalSurfaceIdFromParent(
       const viz::LocalSurfaceId& local_surface_id_from_parent);
 
   const viz::LocalSurfaceId& local_surface_id_from_parent() const {
-    return local_surface_id_from_parent_;
+    return pending_commit_state()->local_surface_id_from_parent;
   }
 
   // Requests the allocation of a new LocalSurfaceId on the compositor thread.
@@ -503,9 +530,8 @@
 
   // Returns the current state of the new LocalSurfaceId request and resets
   // the state.
-  bool TakeNewLocalSurfaceIdRequest();
   bool new_local_surface_id_request_for_testing() const {
-    return new_local_surface_id_request_;
+    return pending_commit_state()->new_local_surface_id_request;
   }
 
   // Records the amount of time spent performing an update in response to new
@@ -516,7 +542,7 @@
   void SetDisplayColorSpaces(
       const gfx::DisplayColorSpaces& display_color_spaces);
   const gfx::DisplayColorSpaces& display_color_spaces() const {
-    return display_color_spaces_;
+    return pending_commit_state()->display_color_spaces;
   }
 
   bool HasCompositorDrivenScrollAnimationForTesting() const {
@@ -531,11 +557,13 @@
   void SetExternalPageScaleFactor(float page_scale_factor,
                                   bool is_external_pinch_gesture_active);
   bool is_external_pinch_gesture_active_for_testing() {
-    return is_external_pinch_gesture_active_;
+    return pending_commit_state()->is_external_pinch_gesture_active;
   }
 
   // Requests that we force send RenderFrameMetadata with the next frame.
-  void RequestForceSendMetadata() { force_send_metadata_request_ = true; }
+  void RequestForceSendMetadata() {
+    pending_commit_state()->force_send_metadata_request = true;
+  }
 
   // Returns the state of |force_send_metadata_request_| and resets the
   // variable to false.
@@ -557,27 +585,26 @@
   bool PaintContent(const LayerList& update_layer_list);
   bool in_paint_layer_contents() const { return in_paint_layer_contents_; }
 
+  bool in_commit() const {
+    return commit_completion_event_ && !commit_completion_event_->IsSignaled();
+  }
+
   void SetHasCopyRequest(bool has_copy_request);
   bool has_copy_request() const { return has_copy_request_; }
 
   void AddSurfaceRange(const viz::SurfaceRange& surface_range);
   void RemoveSurfaceRange(const viz::SurfaceRange& surface_range);
-  base::flat_set<viz::SurfaceRange> SurfaceRanges() const;
 
   // Marks or unmarks a layer are needing PushPropertiesTo in the next commit.
   // These are internal methods, called from the Layer itself when changing a
   // property or completing a PushPropertiesTo.
   void AddLayerShouldPushProperties(Layer* layer);
-  void ClearLayersThatShouldPushProperties();
-  // The current set of all Layers attached to the LayerTreeHost's tree that
-  // have been marked as needing PushPropertiesTo in the next commit.
-  const base::flat_set<Layer*>& LayersThatShouldPushProperties() {
-    return layers_that_should_push_properties_;
-  }
 
   void SetPageScaleFromImplSide(float page_scale);
   void SetElasticOverscrollFromImplSide(gfx::Vector2dF elastic_overscroll);
-  gfx::Vector2dF elastic_overscroll() const { return elastic_overscroll_; }
+  gfx::Vector2dF elastic_overscroll() const {
+    return pending_commit_state()->elastic_overscroll;
+  }
 
   // Ensures a HUD layer exists if it is needed, and updates the HUD bounds and
   // position. If a HUD layer exists but is no longer needed, it is destroyed.
@@ -586,18 +613,16 @@
   bool is_hud_layer(const Layer*) const;
 
   virtual void SetNeedsFullTreeSync();
-  bool needs_full_tree_sync() const { return needs_full_tree_sync_; }
-
-  bool needs_surface_ranges_sync() const { return needs_surface_ranges_sync_; }
-  void set_needs_surface_ranges_sync(bool needs_surface_ranges_sync) {
-    needs_surface_ranges_sync_ = needs_surface_ranges_sync;
+  void ResetNeedsFullTreeSyncForTesting();
+  bool needs_full_tree_sync() const {
+    return pending_commit_state()->needs_full_tree_sync;
   }
 
   void SetPropertyTreesNeedRebuild();
 
   void PushPropertyTreesTo(LayerTreeImpl* tree_impl);
-  void PushLayerTreePropertiesTo(LayerTreeImpl* tree_impl);
-  void PushSurfaceRangesTo(LayerTreeImpl* tree_impl);
+  static void PushLayerTreePropertiesTo(CommitState* commit_state,
+                                        LayerTreeImpl* tree_impl);
   void PushLayerTreeHostPropertiesTo(LayerTreeHostImpl* host_impl);
   void MoveChangeTrackingToLayers(LayerTreeImpl* tree_impl);
 
@@ -614,8 +639,8 @@
   void UpdateActiveElements();
 
   void SetElementIdsForTesting();
-
   void BuildPropertyTreesForTesting();
+  void ClearActiveCommitStateForTesting() { active_commit_state_ = nullptr; }
 
   // Layer iterators.
   LayerListIterator begin() const;
@@ -631,13 +656,12 @@
   void BeginMainFrameNotExpectedUntil(base::TimeTicks time);
   void AnimateLayers(base::TimeTicks monotonic_frame_begin_time);
   void RequestMainFrameUpdate(bool report_metrics);
-  void FinishCommitOnImplThread(
-      LayerTreeHostImpl* host_impl,
-      std::vector<std::unique_ptr<SwapPromise>> swap_promises);
-  void WillCommit(std::unique_ptr<CompletionEvent> completion);
-  bool in_commit() const {
-    return commit_completion_event_ && !commit_completion_event_->IsSignaled();
-  }
+  void FinishCommitOnImplThread(LayerTreeHostImpl* host_impl);
+  // If has_updates is true, returns the CommitState that will drive the commit.
+  // Otherwise, returns nullptr.
+  CommitState* WillCommit(std::unique_ptr<CompletionEvent> completion,
+                          bool has_updates);
+  CommitState* ActivateCommitState();
   void WaitForCommitCompletion();
   void CommitComplete();
   void RequestNewLayerTreeFrameSink();
@@ -674,10 +698,6 @@
     return scheduling_client_;
   }
 
-  bool gpu_rasterization_histogram_recorded() const {
-    return gpu_rasterization_histogram_recorded_;
-  }
-
   void CollectRenderingStats(RenderingStats* stats) const;
 
   RenderingStatsInstrumentation* rendering_stats_instrumentation() const {
@@ -756,24 +776,10 @@
   // NodeInfo in |content| and return true, otherwise return false.
   bool CaptureContent(std::vector<NodeInfo>* content);
 
-  std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics() {
-    return std::move(begin_main_frame_metrics_);
-  }
-
-  // Set the the impl proxy when a commit from the main thread begins
-  // processing. Used in metrics to determine the time spent waiting on thread
-  // synchronization.
-  void SetImplCommitStartTime(base::TimeTicks commit_start_time) {
-    impl_commit_start_time_ = commit_start_time;
-  }
-  void SetImplCommitFinishTime(base::TimeTicks commit_finish_time) {
-    impl_commit_finish_time_ = commit_finish_time;
-  }
-
   void SetDelegatedInkMetadata(
       std::unique_ptr<gfx::DelegatedInkMetadata> metadata);
   gfx::DelegatedInkMetadata* DelegatedInkMetadataForTesting() {
-    return delegated_ink_metadata_.get();
+    return pending_commit_state()->delegated_ink_metadata.get();
   }
 
   void DidObserveFirstScrollDelay(base::TimeDelta first_scroll_delay,
@@ -782,8 +788,7 @@
   void AddDocumentTransitionRequest(
       std::unique_ptr<DocumentTransitionRequest> request);
 
-  std::vector<std::unique_ptr<DocumentTransitionRequest>>
-  TakeDocumentTransitionRequestsForTesting();
+  std::vector<base::OnceClosure> TakeDocumentTransitionCallbacksForTesting();
 
  protected:
   LayerTreeHost(InitParams params, CompositorMode mode);
@@ -851,10 +856,12 @@
   std::unique_ptr<Proxy> proxy_;
   std::unique_ptr<TaskRunnerProvider> task_runner_provider_;
 
-  int source_frame_number_ = 0U;
   std::unique_ptr<RenderingStatsInstrumentation>
       rendering_stats_instrumentation_;
 
+  std::unique_ptr<CommitState> pending_commit_state_;
+  std::unique_ptr<CommitState> active_commit_state_;
+
   SwapPromiseManager swap_promise_manager_;
 
   // |current_layer_tree_frame_sink_| can't be updated until we've successfully
@@ -866,19 +873,14 @@
   std::unique_ptr<LayerTreeFrameSink> current_layer_tree_frame_sink_;
 
   const LayerTreeSettings settings_;
-  LayerTreeDebugState debug_state_;
 
   bool visible_ = false;
 
-  bool gpu_rasterization_histogram_recorded_ = false;
-
   // If set, then page scale animation has completed, but the client hasn't been
   // notified about it yet.
   bool did_complete_scale_animation_ = false;
 
-  int id_;
-  bool next_commit_forces_redraw_ = false;
-  bool next_commit_forces_recalculate_raster_scales_ = false;
+  const int id_;
   // Track when we're inside a main frame to see if compositor is being
   // destroyed midway which causes a crash. crbug.com/654672
   bool inside_main_frame_ = false;
@@ -888,83 +890,18 @@
   gfx::RenderingPipeline* main_thread_pipeline_;
   gfx::RenderingPipeline* compositor_thread_pipeline_;
 
-  uint32_t num_consecutive_frames_without_slow_paths_ = 0;
-
-  scoped_refptr<Layer> root_layer_;
-
-  ViewportPropertyIds viewport_property_ids_;
-
-  OverscrollBehavior overscroll_behavior_;
-
-  BrowserControlsParams browser_controls_params_;
-  float top_controls_shown_ratio_ = 0.f;
-  float bottom_controls_shown_ratio_ = 0.f;
-
-  float device_scale_factor_ = 1.f;
-  float painted_device_scale_factor_ = 1.f;
   float recording_scale_factor_ = 1.f;
-  float page_scale_factor_ = 1.f;
-  float min_page_scale_factor_ = 1.f;
-  float max_page_scale_factor_ = 1.f;
-  float external_page_scale_factor_ = 1.f;
-  bool is_external_pinch_gesture_active_ = false;
   // Used to track the out-bound state for ApplyViewportChanges.
   bool is_pinch_gesture_active_from_impl_ = false;
 
-  gfx::DisplayColorSpaces display_color_spaces_;
-
-  bool clear_caches_on_next_commit_ = false;
-  viz::LocalSurfaceId local_surface_id_from_parent_;
-  bool new_local_surface_id_request_ = false;
-  base::TimeDelta visual_properties_update_duration_;
   uint32_t defer_main_frame_update_count_ = 0;
 
-  SkColor background_color_ = SK_ColorWHITE;
-
-  // Display transform hint to tag generated compositor frames.
-  gfx::OverlayTransform display_transform_hint_ = gfx::OVERLAY_TRANSFORM_NONE;
-
-  LayerSelection selection_;
-
-  gfx::Rect device_viewport_rect_;
   gfx::Rect visual_device_viewport_intersection_rect_;
-  gfx::Size visual_device_viewport_size_;
-
-  // Set to true if viewport is mobile optimized by using meta tag
-  // <meta name="viewport" content="width=device-width">
-  // or
-  // <meta name="viewport" content="initial-scale=1.0">
-  bool is_viewport_mobile_optimized_ = false;
-
-  bool prefers_reduced_motion_ = false;
-  bool may_throttle_if_undrawn_frames_ = true;
-  bool have_scroll_event_handlers_ = false;
-  EventListenerProperties event_listener_properties_
-      [static_cast<size_t>(EventListenerClass::kLast) + 1];
-
-  std::unique_ptr<PendingPageScaleAnimation> pending_page_scale_animation_;
-
-  // Whether we have a pending request to force send RenderFrameMetadata with
-  // the next frame.
-  bool force_send_metadata_request_ = false;
 
   PropertyTrees property_trees_;
 
-  bool needs_full_tree_sync_ = true;
-
-  bool needs_surface_ranges_sync_ = false;
-
-  gfx::Vector2dF elastic_overscroll_;
-
   scoped_refptr<HeadsUpDisplayLayer> hud_layer_;
 
-  // The number of SurfaceLayers that have (fallback,primary) set to
-  // viz::SurfaceRange.
-  base::flat_map<viz::SurfaceRange, int> surface_ranges_;
-
-  // Set of layers that need to push properties.
-  base::flat_set<Layer*> layers_that_should_push_properties_;
-
   // Layer id to Layer map.
   std::unordered_map<int, Layer*> layer_id_map_;
 
@@ -982,16 +919,9 @@
 
   RasterDarkModeFilter* dark_mode_filter_;
 
-  std::vector<std::pair<PaintImage, base::OnceCallback<void(bool)>>>
-      queued_image_decodes_;
   std::unordered_map<int, base::OnceCallback<void(bool)>>
       pending_image_decodes_;
 
-  // Presentation time callbacks requested for the next frame are initially
-  // added here.
-  std::vector<PresentationTimeCallbackBuffer::MainCallback>
-      pending_presentation_time_callbacks_;
-
   struct ScrollAnimationState {
     ScrollAnimationState();
     ~ScrollAnimationState();
@@ -1003,33 +933,10 @@
     base::OnceClosure end_notification;
   } scroll_animation_;
 
-  // Latency information for work done in ProxyMain::BeginMainFrame. The
-  // unique_ptr is allocated in RequestMainFrameUpdate, and passed to Blink's
-  // LocalFrameView that fills in the fields. This object adds the timing for
-  // UpdateLayers. CC reads the data during commit, and clears the unique_ptr.
-  std::unique_ptr<BeginMainFrameMetrics> begin_main_frame_metrics_;
-
-  // The time that the impl thread started processing the most recent commit
-  // sent from the main thread. Zero if the most recent BeginMainFrame did not
-  // result in a commit (due to no change in content).
-  base::TimeTicks impl_commit_start_time_;
-  base::TimeTicks impl_commit_finish_time_;
-
   std::unique_ptr<CompletionEvent> commit_completion_event_;
 
   EventsMetricsManager events_metrics_manager_;
 
-  // Metadata required for drawing a delegated ink trail onto the end of a
-  // stroke. std::unique_ptr was specifically chosen so that it would be cleared
-  // as it is forwarded along the pipeline to avoid old information incorrectly
-  // sticking around and potentially being reused.
-  std::unique_ptr<gfx::DelegatedInkMetadata> delegated_ink_metadata_;
-
-  // A list of document transitions that need to be transported from Blink to
-  // Viz, as a CompositorFrameTransitionDirective.
-  std::vector<std::unique_ptr<DocumentTransitionRequest>>
-      document_transition_requests_;
-
   // A list of callbacks that need to be invoked when they are processed.
   base::flat_map<uint32_t, base::OnceClosure> document_transition_callbacks_;
 
diff --git a/cc/trees/layer_tree_host_client.h b/cc/trees/layer_tree_host_client.h
index 9fcde930..2c4617ad 100644
--- a/cc/trees/layer_tree_host_client.h
+++ b/cc/trees/layer_tree_host_client.h
@@ -25,6 +25,7 @@
 
 namespace cc {
 struct BeginMainFrameMetrics;
+struct CommitState;
 struct WebVitalMetrics;
 
 struct ApplyViewportChangesArgs {
@@ -151,7 +152,7 @@
   virtual void RequestNewLayerTreeFrameSink() = 0;
   virtual void DidInitializeLayerTreeFrameSink() = 0;
   virtual void DidFailToInitializeLayerTreeFrameSink() = 0;
-  virtual void WillCommit() = 0;
+  virtual void WillCommit(CommitState*) = 0;
   // Report that a commit to the impl thread has completed. The
   // commit_start_time is the time that the impl thread began processing the
   // commit, or base::TimeTicks() if the commit did not require action by the
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 28a94db..b0e3200 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -769,8 +769,7 @@
     layer_tree_impl->SetRootLayerForTesting(nullptr);
     layer_tree_impl->DetachLayers();
     layer_tree_impl->property_trees()->clear();
-    layer_tree_impl->SetViewportPropertyIds(
-        LayerTreeImpl::ViewportPropertyIds());
+    layer_tree_impl->SetViewportPropertyIds(ViewportPropertyIds());
   }
 
   void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
diff --git a/cc/trees/layer_tree_host_perftest.cc b/cc/trees/layer_tree_host_perftest.cc
index 92759e7..80c7b4d4 100644
--- a/cc/trees/layer_tree_host_perftest.cc
+++ b/cc/trees/layer_tree_host_perftest.cc
@@ -314,7 +314,7 @@
     ASSERT_TRUE(tab_contents_.get());
   }
 
-  void WillCommit() override {
+  void WillCommit(CommitState*) override {
     if (CleanUpStarted())
       return;
     gpu::Mailbox gpu_mailbox;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 4c72ec53..ad5668c 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -3634,7 +3634,7 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  void WillCommit() override {
+  void WillCommit(CommitState*) override {
     PostSetVisibleToMainThread(false);
     // This is suppressed while we're invisible.
     PostSetNeedsRedrawToMainThread();
@@ -4651,38 +4651,44 @@
 
     // The scrollbar layer always needs to be pushed.
     if (root_->layer_tree_host()) {
-      EXPECT_FALSE(base::Contains(
-          root_->layer_tree_host()->LayersThatShouldPushProperties(),
-          root_.get()));
+      EXPECT_FALSE(base::Contains(root_->layer_tree_host()
+                                      ->pending_commit_state()
+                                      ->layers_that_should_push_properties,
+                                  root_.get()));
     }
     if (child2_->layer_tree_host()) {
-      EXPECT_FALSE(base::Contains(
-          child2_->layer_tree_host()->LayersThatShouldPushProperties(),
-          child2_.get()));
+      EXPECT_FALSE(base::Contains(child2_->layer_tree_host()
+                                      ->pending_commit_state()
+                                      ->layers_that_should_push_properties,
+                                  child2_.get()));
     }
     if (leaf_always_pushing_layer_->layer_tree_host()) {
       leaf_always_pushing_layer_->SetNeedsPushProperties();
       EXPECT_TRUE(base::Contains(leaf_always_pushing_layer_->layer_tree_host()
-                                     ->LayersThatShouldPushProperties(),
+                                     ->pending_commit_state()
+                                     ->layers_that_should_push_properties,
                                  leaf_always_pushing_layer_.get()));
     }
 
     // child_ and grandchild_ don't persist their need to push properties.
     if (child_->layer_tree_host()) {
-      EXPECT_FALSE(base::Contains(
-          child_->layer_tree_host()->LayersThatShouldPushProperties(),
-          child_.get()));
+      EXPECT_FALSE(base::Contains(child_->layer_tree_host()
+                                      ->pending_commit_state()
+                                      ->layers_that_should_push_properties,
+                                  child_.get()));
     }
     if (grandchild_->layer_tree_host()) {
-      EXPECT_FALSE(base::Contains(
-          grandchild_->layer_tree_host()->LayersThatShouldPushProperties(),
-          grandchild_.get()));
+      EXPECT_FALSE(base::Contains(grandchild_->layer_tree_host()
+                                      ->pending_commit_state()
+                                      ->layers_that_should_push_properties,
+                                  grandchild_.get()));
     }
 
     if (other_root_->layer_tree_host()) {
-      EXPECT_FALSE(base::Contains(
-          other_root_->layer_tree_host()->LayersThatShouldPushProperties(),
-          other_root_.get()));
+      EXPECT_FALSE(base::Contains(other_root_->layer_tree_host()
+                                      ->pending_commit_state()
+                                      ->layers_that_should_push_properties,
+                                  other_root_.get()));
     }
 
     switch (num_commits_) {
@@ -5031,9 +5037,10 @@
 
         scrollbar_layer_->SetBounds(gfx::Size(30, 30));
 
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           scrollbar_layer_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   scrollbar_layer_.get()));
         layer_tree_host()->SetNeedsCommit();
 
         scrollbar_layer_->reset_push_properties_count();
@@ -5075,10 +5082,14 @@
         // avoid causing a second commit to be scheduled. If a property change
         // is made during this, however, it needs to be pushed in the upcoming
         // commit.
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
         EXPECT_EQ(0, root_->NumDescendantsThatDrawContent());
         root_->reset_push_properties_count();
         child_->reset_push_properties_count();
@@ -5086,19 +5097,27 @@
         EXPECT_EQ(1, root_->NumDescendantsThatDrawContent());
         EXPECT_EQ(0u, root_->push_properties_count());
         EXPECT_EQ(0u, child_->push_properties_count());
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
         break;
       }
       case 2:
         EXPECT_EQ(1u, root_->push_properties_count());
         EXPECT_EQ(1u, child_->push_properties_count());
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
         EndTest();
         break;
     }
@@ -5161,19 +5180,26 @@
       case 0:
         // All layers will need push properties as we set their layer tree host
         layer_tree_host()->SetRootLayer(root_);
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild2_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild3_.get()));
         break;
       case 1:
         EndTest();
@@ -5194,82 +5220,117 @@
         layer_tree_host()->SetRootLayer(root_);
         break;
       case 1:
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild1_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         grandchild1_->RemoveFromParent();
         grandchild1_->SetPosition(gfx::PointF(1.f, 1.f));
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         child_->AddChild(grandchild1_);
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         grandchild2_->SetPosition(gfx::PointF(1.f, 1.f));
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         // grandchild2_ will still need a push properties.
         grandchild1_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
 
         // grandchild3_ does not need a push properties, so recursing should
         // no longer be needed.
         grandchild2_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
         EndTest();
         break;
     }
@@ -5293,36 +5354,51 @@
         layer_tree_host()->SetRootLayer(root_);
         break;
       case 1:
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         // grandchild2_ will still need a push properties.
         grandchild1_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
 
         // grandchild3_ does not need a push properties, so recursing should
         // no longer be needed.
         grandchild2_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
         EndTest();
         break;
     }
@@ -5342,19 +5418,26 @@
         layer_tree_host()->SetRootLayer(root_);
         break;
       case 1:
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild1_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         // Change grandchildren while their parent is not in the tree.
         child_->RemoveFromParent();
@@ -5362,40 +5445,59 @@
         grandchild2_->SetPosition(gfx::PointF(1.f, 1.f));
         root_->AddChild(child_);
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild2_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild3_.get()));
 
         grandchild1_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         grandchild2_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         grandchild3_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         EndTest();
         break;
@@ -5416,56 +5518,80 @@
         layer_tree_host()->SetRootLayer(root_);
         break;
       case 1:
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild1_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         child_->SetPosition(gfx::PointF(1.f, 1.f));
         grandchild1_->SetPosition(gfx::PointF(1.f, 1.f));
         grandchild2_->SetPosition(gfx::PointF(1.f, 1.f));
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         grandchild1_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         grandchild2_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         child_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
 
         EndTest();
         break;
@@ -5486,56 +5612,80 @@
         layer_tree_host()->SetRootLayer(root_);
         break;
       case 1:
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild1_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         grandchild1_->SetPosition(gfx::PointF(1.f, 1.f));
         grandchild2_->SetPosition(gfx::PointF(1.f, 1.f));
         child_->SetPosition(gfx::PointF(1.f, 1.f));
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild1_.get()));
-        EXPECT_TRUE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild2_.get()));
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           grandchild3_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild1_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   grandchild2_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    grandchild3_.get()));
 
         grandchild1_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         grandchild2_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
-        EXPECT_TRUE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), child_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
+        EXPECT_TRUE(base::Contains(layer_tree_host()
+                                       ->pending_commit_state()
+                                       ->layers_that_should_push_properties,
+                                   child_.get()));
 
         child_->RemoveFromParent();
 
-        EXPECT_FALSE(base::Contains(
-            layer_tree_host()->LayersThatShouldPushProperties(), root_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    root_.get()));
 
         EndTest();
         break;
@@ -5696,9 +5846,10 @@
     switch (layer_tree_host()->SourceFrameNumber()) {
       case 1:
         // The layer type used does not need to push properties every frame.
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           child_layer_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_layer_.get()));
 
         // Change the bounds of the child layer, but make it skipped
         // by CalculateDrawProperties.
@@ -5707,9 +5858,10 @@
         break;
       case 2:
         // The bounds of the child layer were pushed to the impl side.
-        EXPECT_FALSE(
-            base::Contains(layer_tree_host()->LayersThatShouldPushProperties(),
-                           child_layer_.get()));
+        EXPECT_FALSE(base::Contains(layer_tree_host()
+                                        ->pending_commit_state()
+                                        ->layers_that_should_push_properties,
+                                    child_layer_.get()));
 
         EndTest();
         break;
@@ -7722,7 +7874,7 @@
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
-  void WillCommit() override {
+  void WillCommit(CommitState*) override {
     MainThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&LayerTreeHostTestNoTasksBetweenWillAndDidCommit::
@@ -7760,8 +7912,8 @@
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
-  void WillCommit() override {
-    switch (layer_tree_host()->SourceFrameNumber()) {
+  void WillCommit(CommitState* commit_state) override {
+    switch (commit_state->source_frame_number) {
       case 1:
         EXPECT_TRUE(LayerSubtreeHasCopyRequest(root.get()));
         break;
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc
index 536332c..b2b792b 100644
--- a/cc/trees/layer_tree_host_unittest_animation.cc
+++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1023,12 +1023,18 @@
     PostSetNeedsCommitToMainThread();
   }
 
+  void WillCommit(CommitState* commit_state) override {
+    if (commit_state->source_frame_number == 2) {
+      commit_state->pending_presentation_time_callbacks.push_back(
+          base::BindOnce(
+              &LayerTreeHostPresentationDuringAnimation::OnPresentation,
+              base::Unretained(this)));
+    }
+  }
+
   void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
     if (host_impl->active_tree()->source_frame_number() == 1) {
       request_token_ = host_impl->next_frame_token();
-      layer_tree_host()->RequestPresentationTimeForNextFrame(base::BindOnce(
-          &LayerTreeHostPresentationDuringAnimation::OnPresentation,
-          base::Unretained(this)));
       host_impl->BlockNotifyReadyToActivateForTesting(true);
     }
   }
@@ -1894,8 +1900,8 @@
       AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5);
   }
 
-  void WillCommit() override {
-    if (layer_tree_host()->SourceFrameNumber() == 2) {
+  void WillCommit(CommitState* commit_state) override {
+    if (commit_state->source_frame_number == 2) {
       // Block until the animation finishes on the compositor thread. Since
       // animations have already been ticked on the main thread, when the commit
       // happens the state on the main thread will be consistent with having a
@@ -1964,8 +1970,8 @@
       AddAnimatedTransformToAnimation(animation_child_.get(), 0.04, 5, 5);
   }
 
-  void WillCommit() override {
-    if (layer_tree_host()->SourceFrameNumber() == 2) {
+  void WillCommit(CommitState* commit_state) override {
+    if (commit_state->source_frame_number == 2) {
       // Block until the animation finishes on the compositor thread. Since
       // animations have already been ticked on the main thread, when the commit
       // happens the state on the main thread will be consistent with having a
@@ -2045,8 +2051,8 @@
     EndTest();
   }
 
-  void WillCommit() override {
-    if (layer_tree_host()->SourceFrameNumber() == 1) {
+  void WillCommit(CommitState* commit_state) override {
+    if (commit_state->source_frame_number == 1) {
       // Block until the invalidation is done after animation finishes on the
       // compositor thread. We need to make sure the pending tree has valid
       // information based on invalidation only.
diff --git a/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc b/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc
index 01a9d5a..874109f 100644
--- a/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc
+++ b/cc/trees/layer_tree_host_unittest_record_gpu_histogram.cc
@@ -20,9 +20,18 @@
   std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(
       &host_client, &task_graph_runner, animation_host.get(), settings,
       CompositorMode::SINGLE_THREADED);
+  EXPECT_FALSE(host->pending_commit_state()->needs_gpu_rasterization_histogram);
   host->CreateFakeLayerTreeHostImpl();
-  host->RecordGpuRasterizationHistogram(host->host_impl());
-  EXPECT_FALSE(host->gpu_rasterization_histogram_recorded());
+  host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/true);
+  EXPECT_FALSE(host->pending_commit_state()->needs_gpu_rasterization_histogram);
+  {
+    DebugScopedSetImplThread impl(host->GetTaskRunnerProvider());
+    EXPECT_FALSE(
+        host->active_commit_state()->needs_gpu_rasterization_histogram);
+    host->RecordGpuRasterizationHistogram(host->host_impl());
+  }
+  host->CommitComplete();
+  EXPECT_FALSE(host->pending_commit_state()->needs_gpu_rasterization_histogram);
 }
 
 TEST(LayerTreeHostRecordGpuHistogramTest, Threaded) {
@@ -33,9 +42,17 @@
   std::unique_ptr<FakeLayerTreeHost> host = FakeLayerTreeHost::Create(
       &host_client, &task_graph_runner, animation_host.get(), settings,
       CompositorMode::THREADED);
+  EXPECT_TRUE(host->pending_commit_state()->needs_gpu_rasterization_histogram);
   host->CreateFakeLayerTreeHostImpl();
-  host->RecordGpuRasterizationHistogram(host->host_impl());
-  EXPECT_TRUE(host->gpu_rasterization_histogram_recorded());
+  host->WillCommit(/*completion_event=*/nullptr, /*has_updates=*/true);
+  EXPECT_FALSE(host->pending_commit_state()->needs_gpu_rasterization_histogram);
+  {
+    DebugScopedSetImplThread impl(host->GetTaskRunnerProvider());
+    EXPECT_TRUE(host->active_commit_state()->needs_gpu_rasterization_histogram);
+    host->RecordGpuRasterizationHistogram(host->host_impl());
+  }
+  host->CommitComplete();
+  EXPECT_FALSE(host->pending_commit_state()->needs_gpu_rasterization_histogram);
 }
 
 }  // namespace
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc
index de71d52..72c1cfc 100644
--- a/cc/trees/layer_tree_host_unittest_scroll.cc
+++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -30,6 +30,7 @@
 #include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/scroll_node.h"
+#include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/transform_node.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -330,7 +331,7 @@
 
   void DidBeginMainFrame() override { num_did_begin_main_frames_++; }
 
-  void WillCommit() override { num_will_commits_++; }
+  void WillCommit(CommitState*) override { num_will_commits_++; }
 
   void DidCommit() override { num_did_commits_++; }
 
@@ -607,10 +608,10 @@
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
-  void WillCommit() override {
+  void WillCommit(CommitState* commit_state) override {
     // Keep the test committing (otherwise the early out for no update
     // will stall the test).
-    if (layer_tree_host()->SourceFrameNumber() < 2) {
+    if (commit_state->source_frame_number < 2) {
       layer_tree_host()->SetNeedsCommit();
     }
   }
@@ -923,21 +924,19 @@
     PostSetNeedsCommitToMainThread();
   }
 
-  void WillCommit() override {
+  void WillCommit(CommitState* commit_state) override {
     Layer* scroll_layer =
         layer_tree_host()->OuterViewportScrollLayerForTesting();
-    switch (layer_tree_host()->SourceFrameNumber()) {
+    switch (commit_state->source_frame_number) {
       case 0:
-        EXPECT_TRUE(base::Contains(
-            scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(),
+        EXPECT_TRUE(commit_state->layers_that_should_push_properties.contains(
             scroll_layer));
         break;
       case 1:
         // Even if this layer doesn't need push properties, it should
         // still pick up scrolls that happen on the active layer during
         // commit.
-        EXPECT_FALSE(base::Contains(
-            scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(),
+        EXPECT_FALSE(commit_state->layers_that_should_push_properties.contains(
             scroll_layer));
         break;
     }
@@ -1096,7 +1095,7 @@
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
-  void WillCommit() override {
+  void WillCommit(CommitState*) override {
     if (TestEnded())
       return;
     // Keep the test committing (otherwise the early out for no update
@@ -1841,8 +1840,7 @@
     if (scroll_destroy_whole_tree_) {
       layer_tree_host()->SetRootLayer(nullptr);
       layer_tree_host()->property_trees()->clear();
-      layer_tree_host()->RegisterViewportPropertyIds(
-          LayerTreeHost::ViewportPropertyIds());
+      layer_tree_host()->RegisterViewportPropertyIds(ViewportPropertyIds());
       EndTest();
       return;
     }
@@ -2090,7 +2088,7 @@
 
   void DidBeginMainFrame() override { num_did_begin_main_frames_++; }
 
-  void WillCommit() override { num_will_commits_++; }
+  void WillCommit(CommitState*) override { num_will_commits_++; }
 
   void DidCommit() override { num_did_commits_++; }
 
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 76ea3c12..ce4fe29 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -294,7 +294,6 @@
   // The following viewport related property nodes will only ever be set on the
   // main-frame's renderer (i.e. OOPIF and UI compositors will not have these
   // set.
-  using ViewportPropertyIds = LayerTreeHost::ViewportPropertyIds;
   void SetViewportPropertyIds(const ViewportPropertyIds& ids);
 
   const TransformNode* OverscrollElasticityTransformNode() const;
@@ -325,7 +324,7 @@
         const_cast<const LayerTreeImpl*>(this)->OuterViewportScrollNode());
   }
 
-  LayerTreeHost::ViewportPropertyIds ViewportPropertyIdsForTesting() const {
+  ViewportPropertyIds ViewportPropertyIdsForTesting() const {
     return viewport_property_ids_;
   }
   LayerImpl* InnerViewportScrollLayerForTesting() const;
@@ -517,7 +516,7 @@
 
   void AddLayerShouldPushProperties(LayerImpl* layer);
   void ClearLayersThatShouldPushProperties();
-  const base::flat_set<LayerImpl*>& LayersThatShouldPushProperties() {
+  const base::flat_set<LayerImpl*>& LayersThatShouldPushProperties() const {
     return layers_that_should_push_properties_;
   }
 
@@ -814,7 +813,7 @@
 
   int last_scrolled_scroll_node_index_;
 
-  LayerTreeHost::ViewportPropertyIds viewport_property_ids_;
+  ViewportPropertyIds viewport_property_ids_;
 
   LayerSelection selection_;
 
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc
index 2e9740e..4f02f3a 100644
--- a/cc/trees/layer_tree_impl_unittest.cc
+++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -1351,7 +1351,7 @@
       gfx::Rect(scaled_bounds_for_root));
 
   host_impl().active_tree()->SetDeviceScaleFactor(device_scale_factor);
-  LayerTreeImpl::ViewportPropertyIds viewport_property_ids;
+  ViewportPropertyIds viewport_property_ids;
   viewport_property_ids.page_scale_transform =
       page_scale_layer->transform_tree_index();
   host_impl().active_tree()->SetViewportPropertyIds(viewport_property_ids);
@@ -2004,7 +2004,7 @@
   gfx::Size scaled_bounds_for_root = gfx::ScaleToCeiledSize(
       root->bounds(), device_scale_factor * page_scale_factor);
 
-  LayerTreeImpl::ViewportPropertyIds viewport_property_ids;
+  ViewportPropertyIds viewport_property_ids;
   viewport_property_ids.page_scale_transform =
       page_scale_layer->transform_tree_index();
   host_impl().active_tree()->SetViewportPropertyIds(viewport_property_ids);
diff --git a/cc/trees/property_tree_builder_unittest.cc b/cc/trees/property_tree_builder_unittest.cc
index ecc3c4c..b7e69dd 100644
--- a/cc/trees/property_tree_builder_unittest.cc
+++ b/cc/trees/property_tree_builder_unittest.cc
@@ -53,8 +53,8 @@
     // TODO(https://crbug.com/939968) This call should be handled by
     // FakeLayerTreeHost instead of manually pushing the properties from the
     // layer tree host to the pending tree.
-    host()->PushLayerTreePropertiesTo(host_impl()->pending_tree());
-
+    LayerTreeHost::PushLayerTreePropertiesTo(host()->pending_commit_state(),
+                                             host_impl()->pending_tree());
     UpdateDrawProperties(host_impl()->pending_tree());
   }
 
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 316fbd1a..9b8501e 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -49,7 +49,6 @@
   virtual void SetNeedsUpdateLayers() = 0;
   virtual void SetNeedsCommit() = 0;
   virtual void SetNeedsRedraw(const gfx::Rect& damage_rect) = 0;
-  virtual void SetNextCommitWaitsForActivation() = 0;
   virtual void SetTargetLocalSurfaceId(
       const viz::LocalSurfaceId& target_local_surface_id) = 0;
 
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index f96afdf..97328433 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -65,7 +65,6 @@
                      LayerTreeHost* layer_tree_host,
                      TaskRunnerProvider* task_runner_provider)
     : layer_tree_host_id_(layer_tree_host->GetId()),
-      commit_completion_waits_for_activation_(false),
       next_frame_is_newly_committed_frame_(false),
       inside_draw_(false),
       task_runner_provider_(task_runner_provider),
@@ -270,47 +269,43 @@
 }
 
 void ProxyImpl::NotifyReadyToCommitOnImpl(
-    CompletionEvent* completion,
+    CompletionEvent* completion_event,
     LayerTreeHost* layer_tree_host,
     base::TimeTicks main_thread_start_time,
-    const viz::BeginFrameArgs& commit_args,
-    int source_frame_number,
-    std::vector<std::unique_ptr<SwapPromise>> swap_promises,
-    bool hold_commit_for_activation) {
+    const viz::BeginFrameArgs& commit_args) {
   TRACE_EVENT0("cc", "ProxyImpl::NotifyReadyToCommitOnImpl");
   DCHECK(!commit_completion_event_);
   DCHECK(IsImplThread() && IsMainThreadBlocked());
   DCHECK(scheduler_);
   DCHECK(scheduler_->CommitPending());
+  DCHECK(layer_tree_host->active_commit_state());
+
+  // Inform the layer tree host that the commit has started, so that metrics
+  // can determine how long we waited for thread synchronization.
+  layer_tree_host->active_commit_state()->impl_commit_start_time =
+      base::TimeTicks::Now();
 
   if (!host_impl_) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoLayerTree",
                          TRACE_EVENT_SCOPE_THREAD);
-    completion->Signal();
+    completion_event->Signal();
     return;
   }
 
-  source_frame_number_ = source_frame_number;
-  swap_promises_ = std::move(swap_promises);
-
   // Ideally, we should inform to impl thread when BeginMainFrame is started.
   // But, we can avoid a PostTask in here.
   scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
 
-  auto begin_main_frame_metrics = layer_tree_host->begin_main_frame_metrics();
+  auto& begin_main_frame_metrics =
+      layer_tree_host->active_commit_state()->begin_main_frame_metrics;
   host_impl_->ReadyToCommit(commit_args, begin_main_frame_metrics.get());
 
   commit_completion_event_ =
-      std::make_unique<ScopedCompletionEvent>(completion);
-  commit_completion_waits_for_activation_ = hold_commit_for_activation;
+      std::make_unique<ScopedCompletionEvent>(completion_event);
 
   DCHECK(!blocked_main_commit().layer_tree_host);
   blocked_main_commit().layer_tree_host = layer_tree_host;
 
-  // Inform the layer tree host that the commit has started, so that metrics
-  // can determine how long we waited for thread synchronization.
-  layer_tree_host->SetImplCommitStartTime(base::TimeTicks::Now());
-
   // Extract metrics data from the layer tree host and send them to the
   // scheduler to pass them to the compositor_timing_history object.
   scheduler_->NotifyReadyToCommit(std::move(begin_main_frame_metrics));
@@ -685,9 +680,12 @@
   base::ScopedAllowCrossThreadRefCountAccess
       allow_cross_thread_ref_count_access;
 
-  host_impl_->BeginCommit(source_frame_number_);
-  blocked_main_commit().layer_tree_host->FinishCommitOnImplThread(
-      host_impl_.get(), std::move(swap_promises_));
+  LayerTreeHost* layer_tree_host = blocked_main_commit().layer_tree_host;
+  bool commit_waits_for_activation =
+      layer_tree_host->active_commit_state()->commit_waits_for_activation;
+  host_impl_->BeginCommit(
+      layer_tree_host->active_commit_state()->source_frame_number);
+  layer_tree_host->FinishCommitOnImplThread(host_impl_.get());
 
   // Remove the LayerTreeHost reference before the completion event is signaled
   // and cleared. This is necessary since blocked_main_commit() allows access
@@ -695,12 +693,11 @@
   // blocked for a commit.
   blocked_main_commit().layer_tree_host = nullptr;
 
-  if (commit_completion_waits_for_activation_) {
+  if (commit_waits_for_activation) {
     // For some layer types in impl-side painting, the commit is held until the
     // sync tree is activated.  It's also possible that the sync tree has
     // already activated if there was no work to be done.
     TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
-    commit_completion_waits_for_activation_ = false;
     activation_completion_event_ = std::move(commit_completion_event_);
   }
   commit_completion_event_ = nullptr;
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index cfbade29..4466c573 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -64,14 +64,10 @@
   void SetVisibleOnImpl(bool visible);
   void ReleaseLayerTreeFrameSinkOnImpl(CompletionEvent* completion);
   void FinishGLOnImpl(CompletionEvent* completion);
-  void NotifyReadyToCommitOnImpl(
-      CompletionEvent* completion,
-      LayerTreeHost* layer_tree_host,
-      base::TimeTicks main_thread_start_time,
-      const viz::BeginFrameArgs& commit_args,
-      int source_frame_number,
-      std::vector<std::unique_ptr<SwapPromise>> swap_promises,
-      bool hold_commit_for_activation);
+  void NotifyReadyToCommitOnImpl(CompletionEvent* completion_event,
+                                 LayerTreeHost* layer_tree_host,
+                                 base::TimeTicks main_thread_start_time,
+                                 const viz::BeginFrameArgs& commit_args);
   void SetSourceURL(ukm::SourceId source_id, const GURL& url);
   void SetUkmSmoothnessDestination(
       base::WritableSharedMemoryMapping ukm_smoothness_data);
@@ -171,12 +167,6 @@
 
   std::unique_ptr<Scheduler> scheduler_;
 
-  int source_frame_number_ = -1;
-  std::vector<std::unique_ptr<SwapPromise>> swap_promises_;
-
-  // Set when the main thread is waiting on a pending tree activation.
-  bool commit_completion_waits_for_activation_;
-
   // Set when the main thread is waiting on a commit to complete.
   std::unique_ptr<ScopedCompletionEvent> commit_completion_event_;
 
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 7e8599f..6cf5c6ab 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -40,7 +40,6 @@
       current_pipeline_stage_(NO_PIPELINE_STAGE),
       final_pipeline_stage_(NO_PIPELINE_STAGE),
       deferred_final_pipeline_stage_(NO_PIPELINE_STAGE),
-      commit_waits_for_activation_(false),
       started_(false),
       defer_main_frame_update_(false) {
   TRACE_EVENT0("cc", "ProxyMain::ProxyMain");
@@ -122,6 +121,7 @@
     std::unique_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
   DCHECK(IsMainThread());
   DCHECK_EQ(NO_PIPELINE_STAGE, current_pipeline_stage_);
+  DCHECK(!layer_tree_host_->in_commit());
 
   base::TimeTicks begin_main_frame_start_time = base::TimeTicks::Now();
 
@@ -312,21 +312,20 @@
   if (updated)
     final_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
 
-  int source_frame_number = layer_tree_host_->SourceFrameNumber();
-
-  auto completion_event_ptr = std::make_unique<CompletionEvent>(
-      base::WaitableEvent::ResetPolicy::MANUAL);
-  auto* completion_event = completion_event_ptr.get();
-  layer_tree_host_->WillCommit(std::move(completion_event_ptr));
-
   devtools_instrumentation::ScopedCommitTrace commit_task(
       layer_tree_host_->GetId(),
       begin_main_frame_state->begin_frame_args.frame_id.sequence_number);
 
+  auto completion_event_ptr = std::make_unique<CompletionEvent>(
+      base::WaitableEvent::ResetPolicy::MANUAL);
+  auto* completion_event = completion_event_ptr.get();
+  bool has_updates = (final_pipeline_stage_ == COMMIT_PIPELINE_STAGE);
+  layer_tree_host_->WillCommit(std::move(completion_event_ptr), has_updates);
   current_pipeline_stage_ = COMMIT_PIPELINE_STAGE;
-  if (final_pipeline_stage_ < COMMIT_PIPELINE_STAGE) {
-    current_pipeline_stage_ = NO_PIPELINE_STAGE;
+
+  if (!has_updates) {
     completion_event->Signal();
+    current_pipeline_stage_ = NO_PIPELINE_STAGE;
     layer_tree_host_->DidBeginMainFrame();
     TRACE_EVENT_INSTANT0("cc,raf_investigation", "EarlyOut_NoUpdates",
                          TRACE_EVENT_SCOPE_THREAD);
@@ -351,7 +350,6 @@
     // Although the commit is internally aborted, this is because it has been
     // detected to be a no-op.  From the perspective of an embedder, this commit
     // went through, and input should no longer be throttled, etc.
-    layer_tree_host_->SetImplCommitFinishTime(base::TimeTicks::Now());
     layer_tree_host_->CommitComplete();
     layer_tree_host_->RecordEndOfFrameMetrics(
         begin_main_frame_start_time,
@@ -370,19 +368,12 @@
 
     DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
 
-    std::vector<std::unique_ptr<SwapPromise>> swap_promises =
-        layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises();
-
-    bool hold_commit_for_activation = commit_waits_for_activation_;
-    commit_waits_for_activation_ = false;
     ImplThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(&ProxyImpl::NotifyReadyToCommitOnImpl,
                        base::Unretained(proxy_impl_.get()), completion_event,
                        layer_tree_host_, begin_main_frame_start_time,
-                       begin_main_frame_state->begin_frame_args,
-                       source_frame_number, std::move(swap_promises),
-                       hold_commit_for_activation));
+                       begin_main_frame_state->begin_frame_args));
     layer_tree_host_->WaitForCommitCompletion();
   }
 
@@ -391,9 +382,7 @@
   // but *not* script-created IntersectionObserver. See
   // blink::LocalFrameView::RunPostLifecycleSteps.
   layer_tree_host_->DidBeginMainFrame();
-
   layer_tree_host_->CommitComplete();
-
   layer_tree_host_->RecordEndOfFrameMetrics(
       begin_main_frame_start_time,
       begin_main_frame_state->active_sequence_trackers);
@@ -486,11 +475,6 @@
                      base::Unretained(proxy_impl_.get()), damage_rect));
 }
 
-void ProxyMain::SetNextCommitWaitsForActivation() {
-  DCHECK(IsMainThread());
-  commit_waits_for_activation_ = true;
-}
-
 void ProxyMain::SetTargetLocalSurfaceId(
     const viz::LocalSurfaceId& target_local_surface_id) {
   DCHECK(IsMainThread());
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index 1157b1a..921a021 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -85,7 +85,6 @@
   void SetNeedsUpdateLayers() override;
   void SetNeedsCommit() override;
   void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
-  void SetNextCommitWaitsForActivation() override;
   void SetTargetLocalSurfaceId(
       const viz::LocalSurfaceId& target_local_surface_id) override;
   bool RequestedAnimatePending() override;
@@ -144,8 +143,6 @@
   // deferred.
   CommitPipelineStage deferred_final_pipeline_stage_;
 
-  bool commit_waits_for_activation_;
-
   // Set when the Proxy is started using Proxy::Start() and reset when it is
   // stopped using Proxy::Stop().
   bool started_;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 989918e..359ebf4 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -193,8 +193,19 @@
   TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
   DCHECK(task_runner_provider_->IsMainThread());
 
-  int source_frame_number = layer_tree_host_->SourceFrameNumber();
-  layer_tree_host_->WillCommit(nullptr);
+  if (host_impl_->EvictedUIResourcesExist())
+    layer_tree_host_->GetUIResourceManager()->RecreateUIResources();
+
+  // Strictly speaking, it's not necessary to pass a CompletionEvent to
+  // WillCommit, since we can't have thread contention issues. The benefit to
+  // creating one here is that it simplifies LayerTreeHost::in_commit(), which
+  // useful in DCHECKs sprinkled throughout the code.
+  auto completion_event_ptr = std::make_unique<CompletionEvent>(
+      base::WaitableEvent::ResetPolicy::MANUAL);
+  auto* completion_event = completion_event_ptr.get();
+  auto* commit_state =
+      layer_tree_host_->WillCommit(std::move(completion_event_ptr),
+                                   /*has_updates=*/true);
   devtools_instrumentation::ScopedCommitTrace commit_task(
       layer_tree_host_->GetId(), commit_args.frame_id.sequence_number);
 
@@ -203,14 +214,10 @@
     DebugScopedSetMainThreadBlocked main_thread_blocked(task_runner_provider_);
     DebugScopedSetImplThread impl(task_runner_provider_);
 
-    host_impl_->BeginCommit(source_frame_number);
+    host_impl_->BeginCommit(commit_state->source_frame_number);
 
-    if (host_impl_->EvictedUIResourcesExist())
-      layer_tree_host_->GetUIResourceManager()->RecreateUIResources();
-
-    layer_tree_host_->FinishCommitOnImplThread(
-        host_impl_.get(),
-        layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises());
+    layer_tree_host_->FinishCommitOnImplThread(host_impl_.get());
+    completion_event->Signal();
 
     if (scheduler_on_impl_thread_) {
       scheduler_on_impl_thread_->DidCommit();
@@ -269,11 +276,6 @@
   SetNeedsRedrawOnImplThread();
 }
 
-void SingleThreadProxy::SetNextCommitWaitsForActivation() {
-  // Activation always forced in commit, so nothing to do.
-  DCHECK(task_runner_provider_->IsMainThread());
-}
-
 void SingleThreadProxy::SetTargetLocalSurfaceId(
     const viz::LocalSurfaceId& target_local_surface_id) {
   if (!scheduler_on_impl_thread_)
@@ -925,7 +927,8 @@
   layer_tree_host_->UpdateLayers();
   update_layers_requested_ = false;
 
-  auto begin_main_frame_metrics = layer_tree_host_->begin_main_frame_metrics();
+  auto& begin_main_frame_metrics =
+      layer_tree_host_->pending_commit_state()->begin_main_frame_metrics;
   host_impl_->ReadyToCommit(commit_args, begin_main_frame_metrics.get());
 
   // TODO(enne): SingleThreadProxy does not support cancelling commits yet,
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 8d2fa41..ea9c09c 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -54,7 +54,6 @@
   void SetNeedsUpdateLayers() override;
   void SetNeedsCommit() override;
   void SetNeedsRedraw(const gfx::Rect& damage_rect) override;
-  void SetNextCommitWaitsForActivation() override;
   void SetTargetLocalSurfaceId(
       const viz::LocalSurfaceId& target_local_surface_id) override;
   bool RequestedAnimatePending() override;
diff --git a/cc/trees/tree_synchronizer.cc b/cc/trees/tree_synchronizer.cc
index e3d23bd..c62b3f0a 100644
--- a/cc/trees/tree_synchronizer.cc
+++ b/cc/trees/tree_synchronizer.cc
@@ -43,11 +43,13 @@
          layer->scroll_tree_index() != ScrollTree::kInvalidNodeId;
 }
 
-static bool LayerWillPushProperties(LayerTreeHost* host, Layer* layer) {
-  return base::Contains(host->LayersThatShouldPushProperties(), layer);
+static bool LayerWillPushProperties(const CommitState* commit_state,
+                                    const Layer* layer) {
+  return commit_state->layers_that_should_push_properties.contains(layer);
 }
 
-static bool LayerWillPushProperties(LayerTreeImpl* tree, LayerImpl* layer) {
+static bool LayerWillPushProperties(const LayerTreeImpl* tree,
+                                    const LayerImpl* layer) {
   return base::Contains(tree->LayersThatShouldPushProperties(), layer) ||
          // TODO(crbug.com/303943): Stop always pushing PictureLayerImpl
          // properties.
@@ -109,12 +111,12 @@
 
 }  // namespace
 
-void TreeSynchronizer::SynchronizeTrees(Layer* layer_root,
+void TreeSynchronizer::SynchronizeTrees(const CommitState* commit_state,
                                         LayerTreeImpl* tree_impl) {
-  if (!layer_root) {
+  if (!commit_state->root_layer) {
     tree_impl->DetachLayers();
   } else {
-    SynchronizeTreesInternal(layer_root->layer_tree_host(), tree_impl);
+    SynchronizeTreesInternal(commit_state, tree_impl);
   }
 }
 
@@ -152,13 +154,21 @@
   pending_tree->ClearLayersThatShouldPushProperties();
 }
 
-void TreeSynchronizer::PushLayerProperties(LayerTreeHost* host_tree,
+void TreeSynchronizer::PushLayerProperties(CommitState* commit_state,
                                            LayerTreeImpl* impl_tree) {
-  auto layers = host_tree->LayersThatShouldPushProperties();
   TRACE_EVENT1("cc", "TreeSynchronizer::PushLayerPropertiesTo.Main",
-               "layer_count", layers.size());
-  PushLayerPropertiesInternal(layers.begin(), layers.end(), impl_tree);
-  host_tree->ClearLayersThatShouldPushProperties();
+               "layer_count",
+               commit_state->layers_that_should_push_properties.size());
+  auto source_layers_begin =
+      commit_state->layers_that_should_push_properties.begin();
+  auto source_layers_end =
+      commit_state->layers_that_should_push_properties.end();
+  for (auto it = source_layers_begin; it != source_layers_end; ++it) {
+    auto* source_layer = *it;
+    LayerImpl* target_layer = impl_tree->LayerById(source_layer->id());
+    DCHECK(target_layer);
+    source_layer->PushPropertiesTo(target_layer, *commit_state);
+  }
 }
 
 }  // namespace cc
diff --git a/cc/trees/tree_synchronizer.h b/cc/trees/tree_synchronizer.h
index 560e62b..552896d 100644
--- a/cc/trees/tree_synchronizer.h
+++ b/cc/trees/tree_synchronizer.h
@@ -6,11 +6,11 @@
 #define CC_TREES_TREE_SYNCHRONIZER_H_
 
 #include "cc/cc_export.h"
+#include "cc/trees/layer_tree_host.h"
 
 namespace cc {
 
 class LayerImpl;
-class LayerTreeHost;
 class LayerTreeImpl;
 class Layer;
 
@@ -22,14 +22,15 @@
   // Accepts a Layer tree and returns a reference to a LayerImpl tree that
   // duplicates the structure of the Layer tree, reusing the LayerImpls in the
   // tree provided by old_layer_impl_root if possible.
-  static void SynchronizeTrees(Layer* layer_root, LayerTreeImpl* tree_impl);
+  static void SynchronizeTrees(const CommitState*, LayerTreeImpl* tree_impl);
+
   static void SynchronizeTrees(LayerTreeImpl* pending_tree,
                                LayerTreeImpl* active_tree);
 
+  static void PushLayerProperties(CommitState*, LayerTreeImpl* impl_tree);
+
   static void PushLayerProperties(LayerTreeImpl* pending_tree,
                                   LayerTreeImpl* active_tree);
-  static void PushLayerProperties(LayerTreeHost* host_tree,
-                                  LayerTreeImpl* impl_tree);
 };
 
 }  // namespace cc
diff --git a/cc/trees/tree_synchronizer_unittest.cc b/cc/trees/tree_synchronizer_unittest.cc
index f556fd1..3eb8cfd 100644
--- a/cc/trees/tree_synchronizer_unittest.cc
+++ b/cc/trees/tree_synchronizer_unittest.cc
@@ -78,8 +78,9 @@
     return MockLayerImpl::Create(tree_impl, id());
   }
 
-  void PushPropertiesTo(LayerImpl* layer_impl) override {
-    Layer::PushPropertiesTo(layer_impl);
+  void PushPropertiesTo(LayerImpl* layer_impl,
+                        const CommitState& commit_state) override {
+    Layer::PushPropertiesTo(layer_impl, commit_state);
 
     MockLayerImpl* mock_layer_impl = static_cast<MockLayerImpl*>(layer_impl);
     mock_layer_impl->SetLayerImplDestructionList(layer_impl_destruction_list_);
@@ -166,7 +167,7 @@
 // Attempts to synchronizes a null tree. This should not crash, and should
 // return a null tree.
 TEST_F(TreeSynchronizerTest, SyncNullTree) {
-  TreeSynchronizer::SynchronizeTrees(static_cast<Layer*>(nullptr),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->pending_tree());
   EXPECT_TRUE(!host_->pending_tree()->root_layer());
 }
@@ -181,7 +182,7 @@
   host_->SetRootLayer(layer_tree_root);
   host_->BuildPropertyTreesForTesting();
 
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->pending_tree());
 
   LayerImpl* root = host_->pending_tree()->root_layer();
@@ -204,7 +205,7 @@
   host_->SetRootLayer(layer_tree_root);
   host_->BuildPropertyTreesForTesting();
 
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->pending_tree());
 
   // First time the main thread layers are synced to pending tree, and all the
@@ -219,7 +220,8 @@
                           host_->pending_tree());
 
   // Push properties to make pending tree have valid property tree index.
-  TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree());
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
+                                        host_->pending_tree());
 
   // Now sync from pending tree to active tree. This would clear the map of
   // layers that need push properties.
@@ -232,14 +234,16 @@
 
   // Set the main thread root layer needs push properties.
   layer_tree_root->SetNeedsPushProperties();
-  EXPECT_TRUE(base::Contains(host_->LayersThatShouldPushProperties(),
-                             layer_tree_root.get()));
+  EXPECT_TRUE(base::Contains(
+      host_->pending_commit_state()->layers_that_should_push_properties,
+      layer_tree_root.get()));
 
   // When sync from main thread, the needs push properties status is carried
   // over to pending tree.
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->pending_tree());
-  TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree());
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
+                                        host_->pending_tree());
   EXPECT_TRUE(base::Contains(
       host_->pending_tree()->LayersThatShouldPushProperties(), root));
 }
@@ -258,7 +262,7 @@
   host_->SetRootLayer(layer_tree_root);
   host_->BuildPropertyTreesForTesting();
 
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->pending_tree());
   LayerImpl* layer_impl_tree_root = host_->pending_tree()->root_layer();
   EXPECT_TRUE(
@@ -269,7 +273,8 @@
                           host_->pending_tree());
 
   // We have to push properties to pick up the destruction list pointer.
-  TreeSynchronizer::PushLayerProperties(host_.get(), host_->pending_tree());
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
+                                        host_->pending_tree());
 
   // Add a new layer to the Layer side
   layer_tree_root->children()[0]->AddChild(
@@ -280,7 +285,7 @@
   // Synchronize again. After the sync the trees should be equivalent and we
   // should have created and destroyed one LayerImpl.
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->pending_tree());
   layer_impl_tree_root = host_->pending_tree()->root_layer();
 
@@ -311,23 +316,22 @@
   host_->SetRootLayer(layer_tree_root);
 
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root,
                           host_->active_tree());
 
   // We have to push properties to pick up the destruction list pointer.
-  TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(),
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
                                         host_->active_tree());
-
   host_->active_tree()->ResetAllChangeTracking();
 
   // re-insert the layer and sync again.
   child2->RemoveFromParent();
   layer_tree_root->AddChild(child2);
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root,
@@ -335,7 +339,7 @@
 
   host_->active_tree()->SetPropertyTrees(
       layer_tree_root->layer_tree_host()->property_trees());
-  TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(),
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
                                         host_->active_tree());
 
   // Check that the impl thread properly tracked the change.
@@ -370,13 +374,13 @@
   int second_child_id = layer_tree_root->children()[1]->id();
 
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root,
                           host_->active_tree());
 
-  TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(),
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
                                         host_->active_tree());
 
   // Check that the property values we set on the Layer tree are reflected in
@@ -417,14 +421,14 @@
   host_->SetRootLayer(layer_tree_root);
   host_->BuildPropertyTreesForTesting();
 
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root,
                           host_->active_tree());
 
   // We have to push properties to pick up the destruction list pointer.
-  TreeSynchronizer::PushLayerProperties(layer_tree_root->layer_tree_host(),
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
                                         host_->active_tree());
 
   // Now restructure the tree to look like this:
@@ -444,7 +448,7 @@
   // After another synchronize our trees should match and we should not have
   // destroyed any LayerImpls
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(layer_tree_root.get(), layer_impl_tree_root,
@@ -474,14 +478,14 @@
   int old_tree_second_child_layer_id = old_layer_tree_root->children()[1]->id();
 
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(old_layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   LayerImpl* layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(old_layer_tree_root.get(), layer_impl_tree_root,
                           host_->active_tree());
 
   // We have to push properties to pick up the destruction list pointer.
-  TreeSynchronizer::PushLayerProperties(old_layer_tree_root->layer_tree_host(),
+  TreeSynchronizer::PushLayerProperties(host_->pending_commit_state(),
                                         host_->active_tree());
 
   // Remove all children on the Layer side.
@@ -493,7 +497,7 @@
   host_->SetRootLayer(new_layer_tree_root);
 
   host_->BuildPropertyTreesForTesting();
-  TreeSynchronizer::SynchronizeTrees(new_layer_tree_root.get(),
+  TreeSynchronizer::SynchronizeTrees(host_->pending_commit_state(),
                                      host_->active_tree());
   layer_impl_tree_root = host_->active_tree()->root_layer();
   ExpectTreesAreIdentical(new_layer_tree_root.get(), layer_impl_tree_root,
diff --git a/cc/trees/viewport_property_ids.h b/cc/trees/viewport_property_ids.h
new file mode 100644
index 0000000..51f9866
--- /dev/null
+++ b/cc/trees/viewport_property_ids.h
@@ -0,0 +1,24 @@
+// Copyright 2021 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_TREES_VIEWPORT_PROPERTY_IDS_H_
+#define CC_TREES_VIEWPORT_PROPERTY_IDS_H_
+
+#include "cc/paint/element_id.h"
+#include "cc/trees/property_tree.h"
+
+namespace cc {
+
+struct ViewportPropertyIds {
+  int overscroll_elasticity_transform = TransformTree::kInvalidNodeId;
+  ElementId overscroll_elasticity_effect;
+  int page_scale_transform = TransformTree::kInvalidNodeId;
+  int inner_scroll = ScrollTree::kInvalidNodeId;
+  int outer_clip = ClipTree::kInvalidNodeId;
+  int outer_scroll = ScrollTree::kInvalidNodeId;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_VIEWPORT_PROPERTY_IDS_H_
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index fd9befa..d072575 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -45,6 +45,8 @@
 class AnimationHost;
 class Layer;
 class LayerTreeHost;
+
+struct CommitState;
 }
 
 namespace viz {
@@ -132,7 +134,7 @@
   void RequestNewLayerTreeFrameSink() override;
   void DidInitializeLayerTreeFrameSink() override;
   void DidFailToInitializeLayerTreeFrameSink() override;
-  void WillCommit() override {}
+  void WillCommit(cc::CommitState*) override {}
   void DidCommit(base::TimeTicks, base::TimeTicks) override;
   void DidCommitAndDrawFrame() override {}
   void DidReceiveCompositorFrameAck() override;
diff --git a/third_party/blink/renderer/core/document_transition/document_transition_test.cc b/third_party/blink/renderer/core/document_transition/document_transition_test.cc
index 541ccb7..3fa6464 100644
--- a/third_party/blink/renderer/core/document_transition/document_transition_test.cc
+++ b/third_party/blink/renderer/core/document_transition/document_transition_test.cc
@@ -68,9 +68,9 @@
   // callback directly.
   void UpdateAllLifecyclePhasesAndFinishDirectives() {
     UpdateAllLifecyclePhasesForTest();
-    for (auto& request :
-         LayerTreeHost()->TakeDocumentTransitionRequestsForTesting()) {
-      request->TakeFinishedCallback().Run();
+    for (auto& callback :
+         LayerTreeHost()->TakeDocumentTransitionCallbacksForTesting()) {
+      std::move(callback).Run();
     }
   }
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
index e93e18d..421649a 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_test.cc
@@ -134,11 +134,13 @@
   cc::LayerTreeHost* layer_tree_host =
       WebView().MainFrameViewWidget()->LayerTreeHostForTesting();
   // We should not have any force send metadata requests at start.
-  EXPECT_FALSE(layer_tree_host->TakeForceSendMetadataRequest());
+  EXPECT_FALSE(
+      layer_tree_host->pending_commit_state()->force_send_metadata_request);
   // ShowVirtualKeyboard will trigger a text input state update.
   WebView().MainFrameViewWidget()->ShowVirtualKeyboard();
   // We should now have a force send metadata request.
-  EXPECT_TRUE(layer_tree_host->TakeForceSendMetadataRequest());
+  EXPECT_TRUE(
+      layer_tree_host->pending_commit_state()->force_send_metadata_request);
 }
 #endif  // defined(OS_ANDROID)
 
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index 5724463..51d987d 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -674,19 +674,31 @@
 
   // Initially, neither a nor b should have a layer that should push properties.
   cc::LayerTreeHost& host = *Compositor().LayerTreeHost();
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          a_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          b_layer));
 
   // Modifying b should only cause the b layer to need to push properties.
   b_element->setAttribute(html_names::kStyleAttr, "opacity: 0.2");
   UpdateAllLifecyclePhases();
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
-  EXPECT_TRUE(host.LayersThatShouldPushProperties().count(b_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          a_layer));
+  EXPECT_TRUE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          b_layer));
 
   // After a frame, no layers should need to push properties again.
   Compositor().BeginFrame();
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          a_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          b_layer));
 }
 
 TEST_P(CompositingSimTest, LayerUpdatesDoNotInvalidateLaterLayers) {
@@ -716,24 +728,42 @@
 
   // Initially, no layer should need to push properties.
   cc::LayerTreeHost& host = *Compositor().LayerTreeHost();
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(c_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          a_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          b_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          c_layer));
 
   // Modifying a and b (adding opacity to a and removing opacity from b) should
   // not cause the c layer to push properties.
   a_element->setAttribute(html_names::kStyleAttr, "opacity: 0.3");
   b_element->setAttribute(html_names::kStyleAttr, "");
   UpdateAllLifecyclePhases();
-  EXPECT_TRUE(host.LayersThatShouldPushProperties().count(a_layer));
-  EXPECT_TRUE(host.LayersThatShouldPushProperties().count(b_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(c_layer));
+  EXPECT_TRUE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          a_layer));
+  EXPECT_TRUE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          b_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          c_layer));
 
   // After a frame, no layers should need to push properties again.
   Compositor().BeginFrame();
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(a_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(b_layer));
-  EXPECT_FALSE(host.LayersThatShouldPushProperties().count(c_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          a_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          b_layer));
+  EXPECT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.count(
+          c_layer));
 }
 
 TEST_P(CompositingSimTest,
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index cf44535..984f3c5 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -730,7 +730,7 @@
   DCHECK(!properties.outer_clip ||
          static_cast<bool>(properties.inner_scroll_translation));
 
-  cc::LayerTreeHost::ViewportPropertyIds ids;
+  cc::ViewportPropertyIds ids;
   if (properties.overscroll_elasticity_transform) {
     ids.overscroll_elasticity_transform =
         property_tree_manager.EnsureCompositorTransformNode(
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index 1bd0ae3..23601ab 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -3716,8 +3716,12 @@
                                     gfx::Rect(0, 0, 400, 200), Color::kBlack)
                        .Build();
   // Simluate commit to the compositor thread.
-  layer->PushPropertiesTo(
-      layer->CreateLayerImpl(host_impl.active_tree()).get());
+  // When doing a full commit, we would call
+  // layer_tree_host_->ActivateCommitState() and the second argument would come
+  // from layer_tree_host_->active_commit_state(); we use pending_commit_state()
+  // just to keep the test code simple.
+  layer->PushPropertiesTo(layer->CreateLayerImpl(host_impl.active_tree()).get(),
+                          *GetLayerTreeHost().pending_commit_state());
   Update(artifact2);
   ASSERT_EQ(1u, LayerCount());
   ASSERT_EQ(layer, LayerAt(0));
@@ -3739,8 +3743,8 @@
                        Color::kBlack)
           .Build();
   // Simluate commit to the compositor thread.
-  layer->PushPropertiesTo(
-      layer->CreateLayerImpl(host_impl.active_tree()).get());
+  layer->PushPropertiesTo(layer->CreateLayerImpl(host_impl.active_tree()).get(),
+                          *GetLayerTreeHost().pending_commit_state());
   Update(artifact3);
   ASSERT_EQ(1u, LayerCount());
   ASSERT_EQ(layer, LayerAt(0));
@@ -4520,13 +4524,17 @@
 
   auto& host = GetLayerTreeHost();
   host.CompositeForTest(base::TimeTicks::Now(), true);
-  ASSERT_FALSE(host.LayersThatShouldPushProperties().contains(scroll_layer));
+  ASSERT_FALSE(
+      host.pending_commit_state()->layers_that_should_push_properties.contains(
+          scroll_layer));
   ASSERT_FALSE(host.proxy()->CommitRequested());
   ASSERT_FALSE(transform_tree.needs_update());
 
   ASSERT_TRUE(GetPaintArtifactCompositor().DirectlySetScrollOffset(
       scroll_element_id, FloatPoint(-10, -20)));
-  EXPECT_TRUE(host.LayersThatShouldPushProperties().contains(scroll_layer));
+  EXPECT_TRUE(
+      host.pending_commit_state()->layers_that_should_push_properties.contains(
+          scroll_layer));
   EXPECT_TRUE(host.proxy()->CommitRequested());
   EXPECT_EQ(gfx::Vector2dF(-10, -20),
             scroll_tree.current_scroll_offset(scroll_element_id));
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
index 2ae5942..0092ad5 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.cc
@@ -130,6 +130,7 @@
   DCHECK(delegate_);
   // Drop compositor resources immediately, while keeping the compositor alive
   // until after this class is destroyed.
+  layer_tree_host_->WaitForCommitCompletion();
   layer_tree_host_->SetVisible(false);
   layer_tree_host_->ReleaseLayerTreeFrameSink();
   delegate_ = nullptr;
@@ -278,7 +279,7 @@
                                 weak_factory_.GetWeakPtr()));
 }
 
-void LayerTreeView::WillCommit() {
+void LayerTreeView::WillCommit(cc::CommitState*) {
   if (!delegate_)
     return;
   delegate_->WillCommitCompositorFrame();
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
index 1c1761f..77ee3cd 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_view.h
@@ -92,7 +92,7 @@
   void RequestNewLayerTreeFrameSink() override;
   void DidInitializeLayerTreeFrameSink() override;
   void DidFailToInitializeLayerTreeFrameSink() override;
-  void WillCommit() override;
+  void WillCommit(cc::CommitState*) override;
   void DidCommit(base::TimeTicks commit_start_time,
                  base::TimeTicks commit_finish_time) override;
   void DidCommitAndDrawFrame() override;
diff --git a/tools/gdb/gdb_chrome.py b/tools/gdb/gdb_chrome.py
index 46ffac2..db2a754 100644
--- a/tools/gdb/gdb_chrome.py
+++ b/tools/gdb/gdb_chrome.py
@@ -297,7 +297,7 @@
     # Python is much more complicated and this output is reasonable.
     # (Without this printer, a flat_map will output 7 lines of internal
     # template goop before the vector contents.)
-    return 'base::flat_tree with ' + str(self.val['impl_']['body_'])
+    return 'base::flat_tree with ' + str(self.val['body_'])
 
 
 pp_set.add_printer('base::flat_map', '^base::flat_map<.*>$', FlatTreePrinter)
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 9ce8225d..b7cc052 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -342,7 +342,7 @@
   void RequestNewLayerTreeFrameSink() override;
   void DidInitializeLayerTreeFrameSink() override {}
   void DidFailToInitializeLayerTreeFrameSink() override;
-  void WillCommit() override {}
+  void WillCommit(cc::CommitState*) override {}
   void DidCommit(base::TimeTicks, base::TimeTicks) override;
   void DidCommitAndDrawFrame() override {}
   void DidReceiveCompositorFrameAck() override;