diff --git a/DEPS b/DEPS
index 2fe64aab..15bbef4 100644
--- a/DEPS
+++ b/DEPS
@@ -43,7 +43,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '827aa6dcd1f531e61dd06cd83760eddf8a0019b5',
+  'v8_revision': '3b908bc4ca42e23f57c293e4980841b6f160dae3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index c530815..933b28c 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -244,10 +244,7 @@
   if (!frame.frame.get()) {
     TRACE_EVENT_INSTANT0("android_webview", "NoNewFrame",
                          TRACE_EVENT_SCOPE_THREAD);
-    hardware_enabled_ = compositor_frame_consumer_->HasFrameOnUI();
-    if (!hardware_enabled_)
-      UpdateMemoryPolicy();
-    return hardware_enabled_;
+    return compositor_frame_consumer_->HasFrameOnUI();
   }
 
   std::unique_ptr<ChildFrame> child_frame = base::WrapUnique(new ChildFrame(
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 5108875..d367c46 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -99,7 +99,6 @@
   bool IsVisible() const;
   gfx::Rect GetScreenRect() const;
   bool attached_to_window() const { return attached_to_window_; }
-  bool hardware_enabled() const { return hardware_enabled_; }
   gfx::Size size() const { return size_; }
 
   bool IsClientVisible() const;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 56e76da..dd9af8d1 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -720,25 +720,46 @@
 
   void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
     PropertyTrees* property_trees = impl->sync_tree()->property_trees();
+    auto root_transform_id_to_index =
+        property_trees->transform_id_to_index_map.find(root_->id());
+    auto child_transform_id_to_index =
+        property_trees->transform_id_to_index_map.find(child_->id());
+    auto root_effect_id_to_index =
+        property_trees->effect_id_to_index_map.find(root_->id());
+    auto child_effect_id_to_index =
+        property_trees->effect_id_to_index_map.find(child_->id());
+    auto root_clip_id_to_index =
+        property_trees->clip_id_to_index_map.find(root_->id());
+    auto child_clip_id_to_index =
+        property_trees->clip_id_to_index_map.find(child_->id());
+    auto root_scroll_id_to_index =
+        property_trees->scroll_id_to_index_map.find(root_->id());
+    auto child_scroll_id_to_index =
+        property_trees->scroll_id_to_index_map.find(child_->id());
     switch (impl->sync_tree()->source_frame_number()) {
       case 0:
         // root_ should create every property tree node and child_ should not
         // create any.
-        EXPECT_NE(property_trees->transform_id_to_index_map.find(root_->id()),
+        EXPECT_NE(root_transform_id_to_index,
                   property_trees->transform_id_to_index_map.end());
-        EXPECT_NE(property_trees->effect_id_to_index_map.find(root_->id()),
+        EXPECT_EQ(root_transform_id_to_index->second,
+                  root_->transform_tree_index());
+        EXPECT_NE(root_effect_id_to_index,
                   property_trees->effect_id_to_index_map.end());
-        EXPECT_NE(property_trees->clip_id_to_index_map.find(root_->id()),
+        EXPECT_EQ(root_effect_id_to_index->second, root_->effect_tree_index());
+        EXPECT_NE(root_clip_id_to_index,
                   property_trees->clip_id_to_index_map.end());
-        EXPECT_NE(property_trees->scroll_id_to_index_map.find(root_->id()),
+        EXPECT_EQ(root_clip_id_to_index->second, root_->clip_tree_index());
+        EXPECT_NE(root_scroll_id_to_index,
                   property_trees->scroll_id_to_index_map.end());
-        EXPECT_EQ(property_trees->transform_id_to_index_map.find(child_->id()),
+        EXPECT_EQ(root_scroll_id_to_index->second, root_->scroll_tree_index());
+        EXPECT_EQ(child_transform_id_to_index,
                   property_trees->transform_id_to_index_map.end());
-        EXPECT_EQ(property_trees->effect_id_to_index_map.find(child_->id()),
+        EXPECT_EQ(child_effect_id_to_index,
                   property_trees->effect_id_to_index_map.end());
-        EXPECT_EQ(property_trees->clip_id_to_index_map.find(child_->id()),
+        EXPECT_EQ(child_clip_id_to_index,
                   property_trees->clip_id_to_index_map.end());
-        EXPECT_EQ(property_trees->scroll_id_to_index_map.find(child_->id()),
+        EXPECT_EQ(child_scroll_id_to_index,
                   property_trees->scroll_id_to_index_map.end());
         break;
       case 1:
@@ -746,10 +767,15 @@
         // node.
         EXPECT_NE(property_trees->transform_id_to_index_map.find(child_->id()),
                   property_trees->transform_id_to_index_map.end());
+        EXPECT_EQ(child_transform_id_to_index->second,
+                  child_->transform_tree_index());
         EXPECT_NE(property_trees->effect_id_to_index_map.find(child_->id()),
                   property_trees->effect_id_to_index_map.end());
+        EXPECT_EQ(child_effect_id_to_index->second,
+                  child_->effect_tree_index());
         EXPECT_NE(property_trees->clip_id_to_index_map.find(child_->id()),
                   property_trees->clip_id_to_index_map.end());
+        EXPECT_EQ(child_clip_id_to_index->second, child_->clip_tree_index());
         EXPECT_EQ(property_trees->scroll_id_to_index_map.find(child_->id()),
                   property_trees->scroll_id_to_index_map.end());
         break;
@@ -757,6 +783,8 @@
         // child_ should create a scroll node.
         EXPECT_NE(property_trees->scroll_id_to_index_map.find(child_->id()),
                   property_trees->scroll_id_to_index_map.end());
+        EXPECT_EQ(child_scroll_id_to_index->second,
+                  child_->scroll_tree_index());
         break;
       case 3:
         // child_ should not create any property tree nodes.
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index 1371dea..4bd62d1b 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -329,7 +329,7 @@
     data_for_children->clip_tree_parent =
         data_for_children->property_trees->clip_tree.Insert(node, parent_id);
     data_for_children->property_trees->clip_id_to_index_map[layer->id()] =
-        node.id;
+        data_for_children->clip_tree_parent;
   }
 
   layer->SetClipTreeIndex(data_for_children->clip_tree_parent);
@@ -845,7 +845,7 @@
       data_for_children->property_trees->effect_tree.Insert(node, parent_id);
   layer->SetEffectTreeIndex(data_for_children->effect_tree_parent);
   data_for_children->property_trees->effect_id_to_index_map[layer->id()] =
-      node.id;
+      data_for_children->effect_tree_parent;
   if (should_create_render_surface) {
     data_for_children->compound_transform_since_render_target =
         gfx::Transform();
@@ -925,7 +925,7 @@
     data_for_children->scroll_tree_parent_created_by_uninheritable_criteria =
         scroll_node_uninheritable_criteria;
     data_for_children->property_trees->scroll_id_to_index_map[layer->id()] =
-        node.id;
+        data_for_children->scroll_tree_parent;
 
     if (node.data.scrollable) {
       data_for_children->property_trees->scroll_tree.SetBaseScrollOffset(
diff --git a/chrome/VERSION b/chrome/VERSION
index dcb16aa..e16e153 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=52
 MINOR=0
-BUILD=2736
+BUILD=2737
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
index 0c7663c..559e12b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/physicalweb/UrlManager.java
@@ -261,6 +261,7 @@
     public void clearUrls() {
         mNearbyUrls.clear();
         mResolvedUrls.clear();
+        mUrlsSortedByTimestamp.clear();
         mUrlInfoMap.clear();
         putCachedNearbyUrls();
         putCachedResolvedUrls();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/UrlManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/UrlManagerTest.java
index 8a159cb..b8f6a91f3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/UrlManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/physicalweb/UrlManagerTest.java
@@ -69,6 +69,23 @@
     }
 
     @SmallTest
+    public void testAddUrlAfterClearUrlsWorks() {
+        addPwsResult1();
+        addPwsResult2();
+        addPwsResult1();
+        addPwsResult2();
+        mUrlManager.addUrl(URL1);
+        mUrlManager.addUrl(URL2);
+        getInstrumentation().waitForIdleSync();
+        mUrlManager.clearUrls();
+
+        // Add some more URLs...this should not crash if we cleared correctly.
+        mUrlManager.addUrl(URL1);
+        mUrlManager.addUrl(URL2);
+        getInstrumentation().waitForIdleSync();
+    }
+
+    @SmallTest
     public void testAddUrlWhileOnboardingMakesNotification() throws Exception {
         setOnboarding();
         addPwsResult1();
diff --git a/components/mus/surfaces/BUILD.gn b/components/mus/surfaces/BUILD.gn
index 1806907a..aa5e657c 100644
--- a/components/mus/surfaces/BUILD.gn
+++ b/components/mus/surfaces/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "direct_output_surface.cc",
     "direct_output_surface.h",
+    "display_compositor.cc",
+    "display_compositor.h",
     "surfaces_context_provider.cc",
     "surfaces_context_provider.h",
     "surfaces_context_provider_delegate.h",
diff --git a/components/mus/surfaces/display_compositor.cc b/components/mus/surfaces/display_compositor.cc
new file mode 100644
index 0000000..113ac6dc
--- /dev/null
+++ b/components/mus/surfaces/display_compositor.cc
@@ -0,0 +1,103 @@
+// Copyright 2016 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 "components/mus/surfaces/display_compositor.h"
+
+#include "cc/output/copy_output_request.h"
+#include "cc/output/output_surface.h"
+#include "cc/output/renderer_settings.h"
+#include "cc/surfaces/display.h"
+#include "components/mus/surfaces/direct_output_surface.h"
+#include "components/mus/surfaces/surfaces_context_provider.h"
+#include "components/mus/surfaces/top_level_display_client.h"
+
+#if defined(USE_OZONE)
+#include "components/mus/surfaces/direct_output_surface_ozone.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#endif
+
+namespace mus {
+
+DisplayCompositor::DisplayCompositor(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    gfx::AcceleratedWidget widget,
+    const scoped_refptr<GpuState>& gpu_state,
+    const scoped_refptr<SurfacesState>& surfaces_state)
+    : task_runner_(task_runner),
+      surfaces_state_(surfaces_state),
+      factory_(surfaces_state->manager(), this),
+      allocator_(surfaces_state->next_id_namespace()) {
+  allocator_.RegisterSurfaceIdNamespace(surfaces_state_->manager());
+  surfaces_state_->manager()->RegisterSurfaceFactoryClient(
+      allocator_.id_namespace(), this);
+
+  scoped_refptr<SurfacesContextProvider> surfaces_context_provider(
+      new SurfacesContextProvider(widget, gpu_state));
+  // TODO(rjkroege): If there is something better to do than CHECK, add it.
+  CHECK(surfaces_context_provider->BindToCurrentThread());
+
+  std::unique_ptr<cc::OutputSurface> output_surface;
+  if (surfaces_context_provider->ContextCapabilities().surfaceless) {
+#if defined(USE_OZONE)
+    output_surface = base::WrapUnique(new DirectOutputSurfaceOzone(
+        surfaces_context_provider, widget, task_runner_.get(), GL_TEXTURE_2D,
+        GL_RGB));
+#else
+    NOTREACHED();
+#endif
+  } else {
+    output_surface = base::WrapUnique(
+        new DirectOutputSurface(surfaces_context_provider, task_runner_.get()));
+  }
+
+  int max_frames_pending = output_surface->capabilities().max_frames_pending;
+  DCHECK_GT(max_frames_pending, 0);
+
+  display_client_.reset(new TopLevelDisplayClient(
+      std::move(output_surface), surfaces_state_->manager(),
+      nullptr /* bitmap_manager */, nullptr /* gpu_memory_buffer_manager */,
+      cc::RendererSettings(), task_runner_, allocator_.id_namespace()));
+
+  display_client_->Initialize();
+}
+
+DisplayCompositor::~DisplayCompositor() {
+  surfaces_state_->manager()->UnregisterSurfaceFactoryClient(
+      allocator_.id_namespace());
+}
+
+void DisplayCompositor::SubmitCompositorFrame(
+    std::unique_ptr<cc::CompositorFrame> frame,
+    const base::Callback<void(cc::SurfaceDrawStatus)>& callback) {
+  gfx::Size frame_size =
+      frame->delegated_frame_data->render_pass_list.back()->output_rect.size();
+  if (frame_size.IsEmpty() || frame_size != display_size_) {
+    if (!surface_id_.is_null())
+      factory_.Destroy(surface_id_);
+    surface_id_ = allocator_.GenerateId();
+    factory_.Create(surface_id_);
+    display_size_ = frame_size;
+    display_client_->display()->Resize(display_size_);
+  }
+  display_client_->display()->SetSurfaceId(surface_id_,
+                                           frame->metadata.device_scale_factor);
+  factory_.SubmitCompositorFrame(surface_id_, std::move(frame), callback);
+}
+
+void DisplayCompositor::RequestCopyOfOutput(
+    std::unique_ptr<cc::CopyOutputRequest> output_request) {
+  factory_.RequestCopyOfSurface(surface_id_, std::move(output_request));
+}
+
+void DisplayCompositor::ReturnResources(
+    const cc::ReturnedResourceArray& resources) {
+  // TODO(fsamuel): Implement this.
+}
+
+void DisplayCompositor::SetBeginFrameSource(
+    cc::BeginFrameSource* begin_frame_source) {
+  // TODO(fsamuel): Implement this.
+}
+
+}  // namespace mus
diff --git a/components/mus/surfaces/display_compositor.h b/components/mus/surfaces/display_compositor.h
new file mode 100644
index 0000000..fc54e71
--- /dev/null
+++ b/components/mus/surfaces/display_compositor.h
@@ -0,0 +1,72 @@
+// Copyright 2016 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 COMPONENTS_MUS_SURFACES_DISPLAY_COMPOSITOR_H_
+#define COMPONENTS_MUS_SURFACES_DISPLAY_COMPOSITOR_H_
+
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_id_allocator.h"
+#include "components/mus/gles2/gpu_state.h"
+#include "components/mus/surfaces/surfaces_state.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace mus {
+
+class TopLevelDisplayClient;
+
+// TODO(fsamuel): This should become a mojo interface for the mus-gpu split.
+// TODO(fsamuel): This should not be a SurfaceFactoryClient.
+// The DisplayCompositor receives CompositorFrames from all sources,
+// creates a top-level CompositorFrame once per tick, and generates graphical
+// output.
+class DisplayCompositor : public cc::SurfaceFactoryClient {
+ public:
+  DisplayCompositor(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                    gfx::AcceleratedWidget widget,
+                    const scoped_refptr<GpuState>& gpu_state,
+                    const scoped_refptr<SurfacesState>& surfaces_state);
+  ~DisplayCompositor() override;
+
+  // DisplayCompositor embedders submit a CompositorFrame when content on the
+  // display should be changed. A well-behaving embedder should only submit
+  // a CompositorFrame once per BeginFrame tick. The callback is called the
+  // first time this frame is used to draw, or if the frame is discarded.
+  void SubmitCompositorFrame(
+      std::unique_ptr<cc::CompositorFrame> frame,
+      const base::Callback<void(cc::SurfaceDrawStatus)>& callback);
+
+  // TODO(fsamuel): This is used for surface hittesting and should not be
+  // exposed outside of DisplayCompositor.
+  const cc::SurfaceId& surface_id() const { return surface_id_; }
+
+  // This requests the display CompositorFrame be rendered and given to the
+  // callback within CopyOutputRequest.
+  void RequestCopyOfOutput(
+      std::unique_ptr<cc::CopyOutputRequest> output_request);
+
+  // TODO(fsamuel): Invent an async way to create a SurfaceNamespace
+  // A SurfaceNamespace can create CompositorFrameSinks where the client can
+  // make up the ID.
+
+ private:
+  // SurfaceFactoryClient implementation.
+  void ReturnResources(const cc::ReturnedResourceArray& resources) override;
+  void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
+
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+  scoped_refptr<SurfacesState> surfaces_state_;
+  cc::SurfaceFactory factory_;
+  cc::SurfaceIdAllocator allocator_;
+  cc::SurfaceId surface_id_;
+
+  gfx::Size display_size_;
+  std::unique_ptr<TopLevelDisplayClient> display_client_;
+  DISALLOW_COPY_AND_ASSIGN(DisplayCompositor);
+};
+
+}  // namespace mus
+
+#endif  // COMPONENTS_MUS_SURFACES_DISPLAY_COMPOSITOR_H_
diff --git a/components/mus/surfaces/top_level_display_client.cc b/components/mus/surfaces/top_level_display_client.cc
index 4029542..b2f6f16 100644
--- a/components/mus/surfaces/top_level_display_client.cc
+++ b/components/mus/surfaces/top_level_display_client.cc
@@ -5,104 +5,34 @@
 #include "components/mus/surfaces/top_level_display_client.h"
 
 #include "base/memory/ptr_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "cc/output/output_surface.h"
 #include "cc/surfaces/display.h"
-#include "cc/surfaces/display_scheduler.h"
-#include "cc/surfaces/surface.h"
-#include "components/mus/gles2/gpu_state.h"
-#include "components/mus/surfaces/direct_output_surface.h"
-#include "components/mus/surfaces/surfaces_context_provider.h"
-#include "components/mus/surfaces/surfaces_state.h"
-
-#if defined(USE_OZONE)
-#include "components/mus/surfaces/direct_output_surface_ozone.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#endif
-
-namespace base {
-class SingleThreadTaskRunner;
-}
 
 namespace mus {
-namespace {
-void CallCallback(const base::Closure& callback, cc::SurfaceDrawStatus status) {
-  callback.Run();
-}
-}
 
 TopLevelDisplayClient::TopLevelDisplayClient(
-    gfx::AcceleratedWidget widget,
-    const scoped_refptr<GpuState>& gpu_state,
-    const scoped_refptr<SurfacesState>& surfaces_state)
-    : task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      surfaces_state_(surfaces_state),
-      factory_(surfaces_state->manager(), this),
-      cc_id_(static_cast<uint64_t>(surfaces_state->next_id_namespace()) << 32) {
-  factory_.Create(cc_id_);
-  surfaces_state_->manager()->RegisterSurfaceIdNamespace(cc_id_.id_namespace());
-
-  display_.reset(new cc::Display(this, surfaces_state_->manager(), nullptr,
-                                 nullptr, cc::RendererSettings(),
-                                 cc_id_.id_namespace()));
-
-  scoped_refptr<SurfacesContextProvider> surfaces_context_provider(
-      new SurfacesContextProvider(widget, gpu_state));
-  // TODO(rjkroege): If there is something better to do than CHECK, add it.
-  CHECK(surfaces_context_provider->BindToCurrentThread());
-
-  std::unique_ptr<cc::OutputSurface> output_surface;
-  if (surfaces_context_provider->ContextCapabilities().surfaceless) {
-#if defined(USE_OZONE)
-    output_surface = base::WrapUnique(new DirectOutputSurfaceOzone(
-        surfaces_context_provider, widget, task_runner_.get(), GL_TEXTURE_2D,
-        GL_RGB));
-#else
-    NOTREACHED();
-#endif
-  } else {
-    output_surface = base::WrapUnique(
-        new DirectOutputSurface(surfaces_context_provider, task_runner_.get()));
-  }
-
-  int max_frames_pending = output_surface->capabilities().max_frames_pending;
-  DCHECK_GT(max_frames_pending, 0);
-
-  if (gpu_state->HardwareRenderingAvailable()) {
-    display_->Initialize(std::move(output_surface), task_runner_.get());
-  } else {
-    // TODO(rjkroege): Implement software compositing.
-  }
-  display_->Resize(last_submitted_frame_size_);
-
-  // TODO(fsamuel): Plumb the proper device scale factor.
-  display_->SetSurfaceId(cc_id_, 1.f /* device_scale_factor */);
-}
+    std::unique_ptr<cc::OutputSurface> output_surface,
+    cc::SurfaceManager* surface_manager,
+    cc::SharedBitmapManager* bitmap_manager,
+    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+    const cc::RendererSettings& settings,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    uint32_t compositor_surface_namespace)
+    : output_surface_(std::move(output_surface)),
+      task_runner_(task_runner),
+      display_(new cc::Display(this,
+                               surface_manager,
+                               bitmap_manager,
+                               gpu_memory_buffer_manager,
+                               settings,
+                               compositor_surface_namespace)) {}
 
 TopLevelDisplayClient::~TopLevelDisplayClient() {
-  surfaces_state_->manager()->InvalidateSurfaceIdNamespace(
-      cc_id_.id_namespace());
-  factory_.Destroy(cc_id_);
 }
 
-void TopLevelDisplayClient::SubmitCompositorFrame(
-    std::unique_ptr<cc::CompositorFrame> frame,
-    const base::Closure& callback) {
-  pending_frame_ = std::move(frame);
-
-  last_submitted_frame_size_ =
-      pending_frame_->delegated_frame_data->render_pass_list.back()
-          ->output_rect.size();
-  display_->Resize(last_submitted_frame_size_);
-  factory_.SubmitCompositorFrame(cc_id_, std::move(pending_frame_),
-                                 base::Bind(&CallCallback, callback));
-}
-
-void TopLevelDisplayClient::RequestCopyOfOutput(
-    std::unique_ptr<cc::CopyOutputRequest> output_request) {
-  factory_.RequestCopyOfSurface(cc_id_, std::move(output_request));
+bool TopLevelDisplayClient::Initialize() {
+  DCHECK(output_surface_);
+  return display_->Initialize(std::move(output_surface_), task_runner_.get());
 }
 
 void TopLevelDisplayClient::OutputSurfaceLost() {
@@ -114,14 +44,4 @@
 void TopLevelDisplayClient::SetMemoryPolicy(
     const cc::ManagedMemoryPolicy& policy) {}
 
-void TopLevelDisplayClient::ReturnResources(
-    const cc::ReturnedResourceArray& resources) {
-  // TODO(fsamuel): Implement this.
-}
-
-void TopLevelDisplayClient::SetBeginFrameSource(
-    cc::BeginFrameSource* begin_frame_source) {
-  // TODO(tansell): Implement this.
-}
-
 }  // namespace mus
diff --git a/components/mus/surfaces/top_level_display_client.h b/components/mus/surfaces/top_level_display_client.h
index 9dfeb0a0..ea042bf 100644
--- a/components/mus/surfaces/top_level_display_client.h
+++ b/components/mus/surfaces/top_level_display_client.h
@@ -5,68 +5,47 @@
 #ifndef COMPONENTS_MUS_SURFACES_TOP_LEVEL_DISPLAY_CLIENT_H_
 #define COMPONENTS_MUS_SURFACES_TOP_LEVEL_DISPLAY_CLIENT_H_
 
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
 #include "cc/surfaces/display_client.h"
-#include "cc/surfaces/surface_factory.h"
-#include "cc/surfaces/surface_factory_client.h"
-#include "components/mus/gles2/gpu_state.h"
-#include "components/mus/public/interfaces/window_manager.mojom.h"
-#include "components/mus/surfaces/surfaces_state.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "ui/gfx/native_widget_types.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
 
 namespace cc {
-class CopyOutputResult;
 class Display;
-class DisplayScheduler;
-class SurfaceFactory;
+class OutputSurface;
+class RendererSettings;
+class SharedBitmapManager;
+class SurfaceManager;
+}
+
+namespace gpu {
+class GpuMemoryBufferManager;
 }
 
 namespace mus {
 
-class DisplayDelegate;
-class SurfacesState;
-
-// A TopLevelDisplayClient manages the top level surface that is rendered into a
-// provided AcceleratedWidget. Frames are submitted here. New frames are
-// scheduled to be generated here based on VSync.
-class TopLevelDisplayClient : public cc::DisplayClient,
-                              public cc::SurfaceFactoryClient {
+class TopLevelDisplayClient : public cc::DisplayClient {
  public:
-  TopLevelDisplayClient(gfx::AcceleratedWidget widget,
-                        const scoped_refptr<GpuState>& gpu_state,
-                        const scoped_refptr<SurfacesState>& surfaces_state);
+  TopLevelDisplayClient(std::unique_ptr<cc::OutputSurface> output_surface,
+                        cc::SurfaceManager* surface_manager,
+                        cc::SharedBitmapManager* bitmap_manager,
+                        gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+                        const cc::RendererSettings& settings,
+                        scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                        uint32_t compositor_surface_namespace);
   ~TopLevelDisplayClient() override;
 
-  void SubmitCompositorFrame(std::unique_ptr<cc::CompositorFrame> frame,
-                             const base::Closure& callback);
-  const cc::SurfaceId& surface_id() const { return cc_id_; }
+  bool Initialize();
 
-  void RequestCopyOfOutput(
-      std::unique_ptr<cc::CopyOutputRequest> output_request);
+  cc::Display* display() { return display_.get(); }
 
  private:
   // DisplayClient implementation.
   void OutputSurfaceLost() override;
   void SetMemoryPolicy(const cc::ManagedMemoryPolicy& policy) override;
 
-  // SurfaceFactoryClient implementation.
-  void ReturnResources(const cc::ReturnedResourceArray& resources) override;
-  void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
-
+  std::unique_ptr<cc::OutputSurface> output_surface_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  scoped_refptr<SurfacesState> surfaces_state_;
-  cc::SurfaceFactory factory_;
-  cc::SurfaceId cc_id_;
-
-  gfx::Size last_submitted_frame_size_;
-  std::unique_ptr<cc::CompositorFrame> pending_frame_;
-
   std::unique_ptr<cc::Display> display_;
 
   DISALLOW_COPY_AND_ASSIGN(TopLevelDisplayClient);
diff --git a/components/mus/ws/platform_display.cc b/components/mus/ws/platform_display.cc
index 410ac19..e0a1e2ab 100644
--- a/components/mus/ws/platform_display.cc
+++ b/components/mus/ws/platform_display.cc
@@ -15,8 +15,8 @@
 #include "components/mus/gles2/gpu_state.h"
 #include "components/mus/public/interfaces/gpu.mojom.h"
 #include "components/mus/public/interfaces/quads.mojom.h"
+#include "components/mus/surfaces/display_compositor.h"
 #include "components/mus/surfaces/surfaces_state.h"
-#include "components/mus/surfaces/top_level_display_client.h"
 #include "components/mus/ws/platform_display_factory.h"
 #include "components/mus/ws/server_window.h"
 #include "components/mus/ws/server_window_surface.h"
@@ -207,9 +207,9 @@
   delegate_ = nullptr;
 
   // Invalidate WeakPtrs now to avoid callbacks back into the
-  // DefaultPlatformDisplay during destruction of |top_level_display_client_|.
+  // DefaultPlatformDisplay during destruction of |display_compositor_|.
   weak_factory_.InvalidateWeakPtrs();
-  top_level_display_client_.reset();
+  display_compositor_.reset();
   // Destroy the PlatformWindow early on as it may call us back during
   // destruction and we want to be in a known state. But destroy the surface
   // first because it can still be using the platform window.
@@ -287,15 +287,15 @@
   // TODO(fsamuel): We should add a trace for generating a top level frame.
   std::unique_ptr<cc::CompositorFrame> frame(GenerateCompositorFrame());
   frame_pending_ = true;
-  if (top_level_display_client_) {
-    top_level_display_client_->SubmitCompositorFrame(
+  if (display_compositor_) {
+    display_compositor_->SubmitCompositorFrame(
         std::move(frame), base::Bind(&DefaultPlatformDisplay::DidDraw,
                                      weak_factory_.GetWeakPtr()));
   }
   dirty_rect_ = gfx::Rect();
 }
 
-void DefaultPlatformDisplay::DidDraw() {
+void DefaultPlatformDisplay::DidDraw(cc::SurfaceDrawStatus status) {
   frame_pending_ = false;
   delegate_->OnCompositorFrameDrawn();
   if (!dirty_rect_.IsEmpty())
@@ -420,10 +420,10 @@
     gfx::AcceleratedWidget widget,
     float device_pixel_ratio) {
   if (widget != gfx::kNullAcceleratedWidget) {
-    top_level_display_client_.reset(
-        new TopLevelDisplayClient(widget, gpu_state_, surfaces_state_));
-    delegate_->OnTopLevelSurfaceChanged(
-        top_level_display_client_->surface_id());
+    display_compositor_.reset(
+        new DisplayCompositor(base::ThreadTaskRunnerHandle::Get(), widget,
+                              gpu_state_, surfaces_state_));
+    delegate_->OnTopLevelSurfaceChanged(display_compositor_->surface_id());
   }
   UpdateMetrics(metrics_.size_in_pixels.To<gfx::Size>(), device_pixel_ratio);
 }
@@ -436,8 +436,8 @@
 
 void DefaultPlatformDisplay::RequestCopyOfOutput(
     std::unique_ptr<cc::CopyOutputRequest> output_request) {
-  if (top_level_display_client_)
-    top_level_display_client_->RequestCopyOfOutput(std::move(output_request));
+  if (display_compositor_)
+    display_compositor_->RequestCopyOfOutput(std::move(output_request));
 }
 
 }  // namespace ws
diff --git a/components/mus/ws/platform_display.h b/components/mus/ws/platform_display.h
index 8aba25b..744e722 100644
--- a/components/mus/ws/platform_display.h
+++ b/components/mus/ws/platform_display.h
@@ -15,6 +15,7 @@
 #include "base/strings/string16.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "cc/surfaces/surface.h"
 #include "components/mus/public/interfaces/window_manager.mojom.h"
 #include "components/mus/public/interfaces/window_manager_constants.mojom.h"
 #include "components/mus/public/interfaces/window_tree.mojom.h"
@@ -49,7 +50,7 @@
 
 class GpuState;
 class SurfacesState;
-class TopLevelDisplayClient;
+class DisplayCompositor;
 
 namespace ws {
 
@@ -140,7 +141,7 @@
   // This is called after cc::Display has completed generating a new frame
   // for the display. TODO(fsamuel): Idle time processing should happen here
   // if there is budget for it.
-  void DidDraw();
+  void DidDraw(cc::SurfaceDrawStatus status);
   void UpdateMetrics(const gfx::Size& size, float device_pixel_ratio);
   std::unique_ptr<cc::CompositorFrame> GenerateCompositorFrame();
 
@@ -167,7 +168,7 @@
   base::Timer draw_timer_;
   bool frame_pending_;
 
-  std::unique_ptr<TopLevelDisplayClient> top_level_display_client_;
+  std::unique_ptr<DisplayCompositor> display_compositor_;
   std::unique_ptr<ui::PlatformWindow> platform_window_;
 
 #if !defined(OS_ANDROID)
diff --git a/components/mus/ws/server_window_surface_manager.cc b/components/mus/ws/server_window_surface_manager.cc
index eb00272..23c259f 100644
--- a/components/mus/ws/server_window_surface_manager.cc
+++ b/components/mus/ws/server_window_surface_manager.cc
@@ -14,7 +14,8 @@
 
 ServerWindowSurfaceManager::ServerWindowSurfaceManager(ServerWindow* window)
     : window_(window),
-      surface_id_allocator_(WindowIdToTransportId(window->id())),
+      surface_id_allocator_(
+          window->delegate()->GetSurfacesState()->next_id_namespace()),
       waiting_for_initial_frames_(
           window_->properties().count(mus::mojom::kWaitForUnderlay_Property) >
           0) {
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
index 9e49343..18e0d52e 100644
--- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
+++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
@@ -25,7 +25,6 @@
 ThreadDebugger::ThreadDebugger(v8::Isolate* isolate)
     : m_isolate(isolate)
     , m_debugger(V8Debugger::create(isolate, this))
-    , m_lastTimerId(0)
 {
 }
 
@@ -156,31 +155,38 @@
     TRACE_EVENT_INSTANT1("devtools.timeline", "TimeStamp", TRACE_EVENT_SCOPE_THREAD, "data", InspectorTimeStampEvent::data(currentExecutionContext(isolate), title));
 }
 
-int ThreadDebugger::startRepeatingTimer(double interval, std::unique_ptr<V8DebuggerClient::TimerCallback> callback)
+void ThreadDebugger::startRepeatingTimer(double interval, V8DebuggerClient::TimerCallback callback, void* data)
 {
-    int id = ++m_lastTimerId;
+    m_timerData.append(data);
+    m_timerCallbacks.append(callback);
+
     OwnPtr<Timer<ThreadDebugger>> timer = adoptPtr(new Timer<ThreadDebugger>(this, &ThreadDebugger::onTimer));
     Timer<ThreadDebugger>* timerPtr = timer.get();
-    m_timerCallbacks.set(timerPtr, std::move(callback));
-    m_timers.set(id, timer.release());
+    m_timers.append(timer.release());
     timerPtr->startRepeating(interval, BLINK_FROM_HERE);
-    return id;
 }
 
-void ThreadDebugger::cancelTimer(int id)
+void ThreadDebugger::cancelTimer(void* data)
 {
-    if (!m_timers.contains(id))
-        return;
-    Timer<ThreadDebugger>* timer = m_timers.get(id);
-    timer->stop();
-    m_timerCallbacks.remove(timer);
-    m_timers.remove(id);
+    for (size_t index = 0; index < m_timerData.size(); ++index) {
+        if (m_timerData[index] == data) {
+            m_timers[index]->stop();
+            m_timerCallbacks.remove(index);
+            m_timers.remove(index);
+            m_timerData.remove(index);
+            return;
+        }
+    }
 }
 
 void ThreadDebugger::onTimer(Timer<ThreadDebugger>* timer)
 {
-    ASSERT(m_timerCallbacks.contains(timer));
-    (*m_timerCallbacks.get(timer))();
+    for (size_t index = 0; index < m_timers.size(); ++index) {
+        if (m_timers[index] == timer) {
+            m_timerCallbacks[index](m_timerData[index]);
+            return;
+        }
+    }
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.h b/third_party/WebKit/Source/core/inspector/ThreadDebugger.h
index 927826d..40f2ae2 100644
--- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.h
+++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.h
@@ -11,7 +11,7 @@
 #include "platform/v8_inspector/public/V8Debugger.h"
 #include "platform/v8_inspector/public/V8DebuggerClient.h"
 #include "wtf/Forward.h"
-#include "wtf/HashMap.h"
+#include "wtf/Vector.h"
 
 #include <v8.h>
 
@@ -44,8 +44,8 @@
     void consoleTime(const String16& title) override;
     void consoleTimeEnd(const String16& title) override;
     void consoleTimeStamp(const String16& title) override;
-    int startRepeatingTimer(double, std::unique_ptr<V8DebuggerClient::TimerCallback>) override;
-    void cancelTimer(int) override;
+    void startRepeatingTimer(double, V8DebuggerClient::TimerCallback, void* data) override;
+    void cancelTimer(void* data) override;
 
     V8Debugger* debugger() const { return m_debugger.get(); }
     virtual bool isWorker() { return true; }
@@ -55,9 +55,9 @@
 
     v8::Isolate* m_isolate;
     OwnPtr<V8Debugger> m_debugger;
-    HashMap<int, OwnPtr<Timer<ThreadDebugger>>> m_timers;
-    HashMap<Timer<ThreadDebugger>*, std::unique_ptr<V8DebuggerClient::TimerCallback>> m_timerCallbacks;
-    int m_lastTimerId;
+    Vector<OwnPtr<Timer<ThreadDebugger>>> m_timers;
+    Vector<V8DebuggerClient::TimerCallback> m_timerCallbacks;
+    Vector<void*> m_timerData;
     OwnPtr<UserGestureIndicator> m_userGestureIndicator;
 };
 
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp
index ab97c9cb..f5bc036b 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp
@@ -152,7 +152,7 @@
 V8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl(V8InspectorSessionImpl* session)
     : m_session(session)
     , m_isolate(session->debugger()->isolate())
-    , m_timerId(0)
+    , m_hasTimer(false)
 {
 }
 
@@ -315,18 +315,26 @@
     m_frontend->lastSeenObjectId(lastSeenObjectId, m_session->debugger()->client()->currentTimeMS());
 }
 
+// static
+void V8HeapProfilerAgentImpl::onTimer(void* data)
+{
+    reinterpret_cast<V8HeapProfilerAgentImpl*>(data)->requestHeapStatsUpdate();
+}
+
 void V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal(bool trackAllocations)
 {
     m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations);
-    if (!m_timerId)
-        m_timerId = m_session->debugger()->client()->startRepeatingTimer(0.05, bind<>(&V8HeapProfilerAgentImpl::requestHeapStatsUpdate, this));
+    if (!m_hasTimer) {
+        m_hasTimer = true;
+        m_session->debugger()->client()->startRepeatingTimer(0.05, &V8HeapProfilerAgentImpl::onTimer, reinterpret_cast<void*>(this));
+    }
 }
 
 void V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal()
 {
-    if (m_timerId) {
-        m_session->debugger()->client()->cancelTimer(m_timerId);
-        m_timerId = 0;
+    if (m_hasTimer) {
+        m_session->debugger()->client()->cancelTimer(reinterpret_cast<void*>(this));
+        m_hasTimer = false;
     }
     m_isolate->GetHeapProfiler()->StopTrackingHeapObjects();
     m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, false);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h
index b0fafe7..e3aed9abd 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.h
@@ -46,12 +46,13 @@
     void startTrackingHeapObjectsInternal(bool trackAllocations);
     void stopTrackingHeapObjectsInternal();
     void requestHeapStatsUpdate();
+    static void onTimer(void*);
 
     V8InspectorSessionImpl* m_session;
     v8::Isolate* m_isolate;
     protocol::Frontend::HeapProfiler* m_frontend;
     protocol::DictionaryValue* m_state;
-    int m_timerId;
+    bool m_hasTimer;
 };
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
index 7cbb6a48..29b041ce 100644
--- a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
+++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
@@ -10,7 +10,6 @@
 #include "platform/v8_inspector/public/ConsoleTypes.h"
 #include "platform/v8_inspector/public/V8ContextInfo.h"
 #include "platform/v8_inspector/public/V8EventListenerInfo.h"
-#include "wtf/Functional.h"
 
 #include <v8.h>
 
@@ -44,9 +43,9 @@
 
     virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Object> creationContext) = 0;
 
-    using TimerCallback = Function<void()>;
-    virtual int startRepeatingTimer(double, std::unique_ptr<TimerCallback>) = 0;
-    virtual void cancelTimer(int) = 0;
+    typedef void (*TimerCallback)(void*);
+    virtual void startRepeatingTimer(double, TimerCallback, void* data) = 0;
+    virtual void cancelTimer(void* data) = 0;
 };
 
 } // namespace blink