Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / cc / trees / layer_tree_host_impl.cc
index 2db5818..9bee07e 100644 (file)
 #include "gpu/GLES2/gl2extchromium.h"
 #include "ui/gfx/frame_time.h"
 #include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gfx/vector2d_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
 
 namespace cc {
 namespace {
 
+// Small helper class that saves the current viewport location as the user sees
+// it and resets to the same location.
+class ViewportAnchor {
+ public:
+  ViewportAnchor(LayerImpl* inner_scroll, LayerImpl* outer_scroll)
+  : inner_(inner_scroll),
+    outer_(outer_scroll) {
+    viewport_in_content_coordinates_ = inner_->TotalScrollOffset();
+
+    if (outer_)
+      viewport_in_content_coordinates_ += outer_->TotalScrollOffset();
+  }
+
+  void ResetViewportToAnchoredPosition() {
+    DCHECK(outer_);
+
+    inner_->ClampScrollToMaxScrollOffset();
+    outer_->ClampScrollToMaxScrollOffset();
+
+    gfx::ScrollOffset viewport_location = inner_->TotalScrollOffset() +
+                                          outer_->TotalScrollOffset();
+
+    gfx::Vector2dF delta =
+        viewport_in_content_coordinates_.DeltaFrom(viewport_location);
+
+    delta = outer_->ScrollBy(delta);
+    inner_->ScrollBy(delta);
+  }
+
+ private:
+  LayerImpl* inner_;
+  LayerImpl* outer_;
+  gfx::ScrollOffset viewport_in_content_coordinates_;
+};
+
+
 void DidVisibilityChange(LayerTreeHostImpl* id, bool visible) {
   if (visible) {
     TRACE_EVENT_ASYNC_BEGIN1("webkit",
@@ -116,8 +152,14 @@ size_t GetMaxTransferBufferUsageBytes(
 
 unsigned GetMapImageTextureTarget(
     const ContextProvider::Capabilities& context_capabilities) {
+// TODO(reveman): This should be a setting passed to the compositor instead
+// of hard-coded here. The target that need to be used depends on our choice
+// of GpuMemoryBuffer type. Note: SURFACE_TEXTURE needs EXTERNAL_OES,
+// IO_SURFACE needs RECTANGLE_ARB. crbug.com/431059
+#if defined(OS_ANDROID)
   if (context_capabilities.gpu.egl_image_external)
     return GL_TEXTURE_EXTERNAL_OES;
+#endif
   if (context_capabilities.gpu.texture_rectangle)
     return GL_TEXTURE_RECTANGLE_ARB;
 
@@ -140,12 +182,12 @@ class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
         new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl,
                                                time_source));
   }
-  virtual ~LayerTreeHostImplTimeSourceAdapter() {
+  ~LayerTreeHostImplTimeSourceAdapter() override {
     time_source_->SetClient(NULL);
     time_source_->SetActive(false);
   }
 
-  virtual void OnTimerTick() OVERRIDE {
+  void OnTimerTick() override {
     // In single threaded mode we attempt to simulate changing the current
     // thread by maintaining a fake thread id. When we switch from one
     // thread to another, we construct DebugScopedSetXXXThread objects that
@@ -212,10 +254,16 @@ scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create(
     LayerTreeHostImplClient* client,
     Proxy* proxy,
     RenderingStatsInstrumentation* rendering_stats_instrumentation,
-    SharedBitmapManager* manager,
+    SharedBitmapManager* shared_bitmap_manager,
+    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     int id) {
-  return make_scoped_ptr(new LayerTreeHostImpl(
-      settings, client, proxy, rendering_stats_instrumentation, manager, id));
+  return make_scoped_ptr(new LayerTreeHostImpl(settings,
+                                               client,
+                                               proxy,
+                                               rendering_stats_instrumentation,
+                                               shared_bitmap_manager,
+                                               gpu_memory_buffer_manager,
+                                               id));
 }
 
 LayerTreeHostImpl::LayerTreeHostImpl(
@@ -223,9 +271,11 @@ LayerTreeHostImpl::LayerTreeHostImpl(
     LayerTreeHostImplClient* client,
     Proxy* proxy,
     RenderingStatsInstrumentation* rendering_stats_instrumentation,
-    SharedBitmapManager* manager,
+    SharedBitmapManager* shared_bitmap_manager,
+    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
     int id)
-    : client_(client),
+    : BeginFrameSourceMixIn(),
+      client_(client),
       proxy_(proxy),
       use_gpu_rasterization_(false),
       input_handler_client_(NULL),
@@ -261,8 +311,10 @@ LayerTreeHostImpl::LayerTreeHostImpl(
       rendering_stats_instrumentation_(rendering_stats_instrumentation),
       micro_benchmark_controller_(this),
       need_to_update_visible_tiles_before_draw_(false),
-      shared_bitmap_manager_(manager),
-      id_(id) {
+      shared_bitmap_manager_(shared_bitmap_manager),
+      gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
+      id_(id),
+      requires_high_res_to_draw_(false) {
   DCHECK(proxy_->IsImplThread());
   DidVisibilityChange(this, visible_);
   animation_registrar_->set_supports_scroll_animations(
@@ -309,9 +361,9 @@ LayerTreeHostImpl::~LayerTreeHostImpl() {
   if (pending_tree_)
     pending_tree_->Shutdown();
   active_tree_->Shutdown();
-  recycle_tree_.reset();
-  pending_tree_.reset();
-  active_tree_.reset();
+  recycle_tree_ = nullptr;
+  pending_tree_ = nullptr;
+  active_tree_ = nullptr;
   DestroyTileManager();
 }
 
@@ -465,7 +517,7 @@ bool LayerTreeHostImpl::HaveTouchEventHandlersAt(
 scoped_ptr<SwapPromiseMonitor>
 LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor(
     ui::LatencyInfo* latency) {
-  return scoped_ptr<SwapPromiseMonitor>(
+  return make_scoped_ptr(
       new LatencyInfoSwapPromiseMonitor(latency, NULL, this));
 }
 
@@ -545,7 +597,10 @@ static void AppendQuadsForLayer(
     LayerImpl* layer,
     const OcclusionTracker<LayerImpl>& occlusion_tracker,
     AppendQuadsData* append_quads_data) {
-  layer->AppendQuads(target_render_pass, occlusion_tracker, append_quads_data);
+  layer->AppendQuads(
+      target_render_pass,
+      occlusion_tracker.GetCurrentOcclusionForLayer(layer->draw_transform()),
+      append_quads_data);
 }
 
 static void AppendQuadsForRenderSurfaceLayer(
@@ -848,7 +903,7 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(
     if (append_quads_data.num_incomplete_tiles ||
         append_quads_data.num_missing_tiles) {
       frame->contains_incomplete_tile = true;
-      if (active_tree()->RequiresHighResToDraw())
+      if (RequiresHighResToDraw())
         draw_result = DRAW_ABORTED_MISSING_HIGH_RES_CONTENT;
     }
 
@@ -860,13 +915,11 @@ DrawResult LayerTreeHostImpl::CalculateRenderPasses(
     draw_result = DRAW_SUCCESS;
 
 #if DCHECK_IS_ON
-  for (size_t i = 0; i < frame->render_passes.size(); ++i) {
-    for (QuadList::Iterator iter = frame->render_passes[i]->quad_list.begin();
-         iter != frame->render_passes[i]->quad_list.end();
-         ++iter)
-      DCHECK(iter->shared_quad_state);
-    DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id)
-           != frame->render_passes_by_id.end());
+  for (const auto& render_pass : frame->render_passes) {
+    for (const auto& quad : render_pass->quad_list)
+      DCHECK(quad->shared_quad_state);
+    DCHECK(frame->render_passes_by_id.find(render_pass->id) !=
+           frame->render_passes_by_id.end());
   }
 #endif
   DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin());
@@ -982,11 +1035,10 @@ static void RemoveRenderPassesRecursive(RenderPassId remove_render_pass_id,
   // Now follow up for all RenderPass quads and remove their RenderPasses
   // recursively.
   const QuadList& quad_list = removed_pass->quad_list;
-  QuadList::ConstBackToFrontIterator quad_list_iterator =
-      quad_list.BackToFrontBegin();
-  for (; quad_list_iterator != quad_list.BackToFrontEnd();
+  for (auto quad_list_iterator = quad_list.BackToFrontBegin();
+       quad_list_iterator != quad_list.BackToFrontEnd();
        ++quad_list_iterator) {
-    const DrawQuad* current_quad = &*quad_list_iterator;
+    const DrawQuad* current_quad = *quad_list_iterator;
     if (current_quad->material != DrawQuad::RENDER_PASS)
       continue;
 
@@ -1005,11 +1057,10 @@ bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass(
 
   // If any quad or RenderPass draws into this RenderPass, then keep it.
   const QuadList& quad_list = render_pass->quad_list;
-  for (QuadList::ConstBackToFrontIterator quad_list_iterator =
-           quad_list.BackToFrontBegin();
+  for (auto quad_list_iterator = quad_list.BackToFrontBegin();
        quad_list_iterator != quad_list.BackToFrontEnd();
        ++quad_list_iterator) {
-    const DrawQuad* current_quad = &*quad_list_iterator;
+    const DrawQuad* current_quad = *quad_list_iterator;
 
     if (current_quad->material != DrawQuad::RENDER_PASS)
       return false;
@@ -1036,12 +1087,11 @@ void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler,
        it = culler.RenderPassListNext(it)) {
     const RenderPass* current_pass = frame->render_passes[it];
     const QuadList& quad_list = current_pass->quad_list;
-    QuadList::ConstBackToFrontIterator quad_list_iterator =
-        quad_list.BackToFrontBegin();
 
-    for (; quad_list_iterator != quad_list.BackToFrontEnd();
+    for (auto quad_list_iterator = quad_list.BackToFrontBegin();
+         quad_list_iterator != quad_list.BackToFrontEnd();
          ++quad_list_iterator) {
-      const DrawQuad* current_quad = &*quad_list_iterator;
+      const DrawQuad* current_quad = *quad_list_iterator;
 
       if (current_quad->material != DrawQuad::RENDER_PASS)
         continue;
@@ -1130,16 +1180,10 @@ void LayerTreeHostImpl::ResetTreesForTesting() {
   active_tree_ = LayerTreeImpl::create(this);
   if (pending_tree_)
     pending_tree_->DetachLayerTree();
-  pending_tree_.reset();
+  pending_tree_ = nullptr;
   if (recycle_tree_)
     recycle_tree_->DetachLayerTree();
-  recycle_tree_.reset();
-}
-
-void LayerTreeHostImpl::ResetRecycleTreeForTesting() {
-  if (recycle_tree_)
-    recycle_tree_->DetachLayerTree();
-  recycle_tree_.reset();
+  recycle_tree_ = nullptr;
 }
 
 void LayerTreeHostImpl::EnforceManagedMemoryPolicy(
@@ -1194,7 +1238,7 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy(
       100);
 
   DCHECK(resource_pool_);
-  resource_pool_->CheckBusyResources();
+  resource_pool_->CheckBusyResources(false);
   // Soft limit is used for resource pool such that memory returns to soft
   // limit after going over.
   resource_pool_->SetResourceUsageLimits(
@@ -1204,7 +1248,7 @@ void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy(
 
   // Release all staging resources when invisible.
   if (staging_resource_pool_) {
-    staging_resource_pool_->CheckBusyResources();
+    staging_resource_pool_->CheckBusyResources(false);
     staging_resource_pool_->SetResourceUsageLimits(
         std::numeric_limits<size_t>::max(),
         std::numeric_limits<size_t>::max(),
@@ -1239,7 +1283,7 @@ void LayerTreeHostImpl::GetPictureLayerImplPairs(
     if (!layer->HasValidTilePriorities())
       continue;
 
-    PictureLayerImpl* twin_layer = layer->GetTwinLayer();
+    PictureLayerImpl* twin_layer = layer->GetPendingOrActiveTwinLayer();
 
     // Ignore the twin layer when tile priorities are invalid.
     // TODO(vmpstr): Iterators should handle this instead. crbug.com/381704
@@ -1260,6 +1304,7 @@ void LayerTreeHostImpl::GetPictureLayerImplPairs(
 
 void LayerTreeHostImpl::BuildRasterQueue(RasterTilePriorityQueue* queue,
                                          TreePriority tree_priority) {
+  TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildRasterQueue");
   picture_layer_pairs_.clear();
   GetPictureLayerImplPairs(&picture_layer_pairs_);
   queue->Build(picture_layer_pairs_, tree_priority);
@@ -1267,6 +1312,7 @@ void LayerTreeHostImpl::BuildRasterQueue(RasterTilePriorityQueue* queue,
 
 void LayerTreeHostImpl::BuildEvictionQueue(EvictionTilePriorityQueue* queue,
                                            TreePriority tree_priority) {
+  TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildEvictionQueue");
   picture_layer_pairs_.clear();
   GetPictureLayerImplPairs(&picture_layer_pairs_);
   queue->Build(picture_layer_pairs_, tree_priority);
@@ -1392,7 +1438,7 @@ void LayerTreeHostImpl::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
 }
 
 void LayerTreeHostImpl::BeginFrame(const BeginFrameArgs& args) {
-  client_->BeginFrame(args);
+  CallOnBeginFrame(args);
 }
 
 void LayerTreeHostImpl::DidSwapBuffers() {
@@ -1414,7 +1460,7 @@ void LayerTreeHostImpl::ReclaimResources(const CompositorFrameAck* ack) {
   if (tile_manager_) {
     DCHECK(resource_pool_);
 
-    resource_pool_->CheckBusyResources();
+    resource_pool_->CheckBusyResources(false);
     resource_pool_->ReduceResourceUsage();
   }
   // If we're not visible, we likely released resources, so we want to
@@ -1450,7 +1496,9 @@ CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const {
   if (!InnerViewportScrollLayer())
     return metadata;
 
-  metadata.root_scroll_offset = active_tree_->TotalScrollOffset();
+  // TODO(miletus) : Change the metadata to hold ScrollOffset.
+  metadata.root_scroll_offset = gfx::ScrollOffsetToVector2dF(
+      active_tree_->TotalScrollOffset());
 
   return metadata;
 }
@@ -1475,9 +1523,7 @@ void LayerTreeHostImpl::DrawLayers(FrameData* frame,
 
   fps_counter_->SaveTimeStamp(frame_begin_time,
                               !output_surface_->context_provider());
-  bool on_main_thread = false;
-  rendering_stats_instrumentation_->IncrementFrameCount(
-      1, on_main_thread);
+  rendering_stats_instrumentation_->IncrementFrameCount(1);
 
   if (tile_manager_) {
     memory_history_->SaveEntry(
@@ -1605,7 +1651,7 @@ void LayerTreeHostImpl::SetUseGpuRasterization(bool use_gpu) {
   // We have released tilings for both active and pending tree.
   // We would not have any content to draw until the pending tree is activated.
   // Prevent the active tree from drawing until activation.
-  active_tree_->SetRequiresHighResToDraw();
+  SetRequiresHighResToDraw();
 }
 
 const RendererCapabilitiesImpl&
@@ -1614,7 +1660,7 @@ LayerTreeHostImpl::GetRendererCapabilities() const {
 }
 
 bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
-  active_tree()->ResetRequiresHighResToDraw();
+  ResetRequiresHighResToDraw();
   if (frame.has_no_damage) {
     active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS);
     return false;
@@ -1632,7 +1678,7 @@ bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) {
   return true;
 }
 
-void LayerTreeHostImpl::SetNeedsBeginFrame(bool enable) {
+void LayerTreeHostImpl::OnNeedsBeginFramesChange(bool enable) {
   if (output_surface_)
     output_surface_->SetNeedsBeginFrame(enable);
   else
@@ -1647,16 +1693,41 @@ void LayerTreeHostImpl::WillBeginImplFrame(const BeginFrameArgs& args) {
   begin_impl_frame_interval_ = args.interval;
 }
 
-void LayerTreeHostImpl::UpdateInnerViewportContainerSize() {
-  LayerImpl* container_layer = active_tree_->InnerViewportContainerLayer();
-  if (!container_layer)
+void LayerTreeHostImpl::UpdateViewportContainerSizes() {
+  LayerImpl* inner_container = active_tree_->InnerViewportContainerLayer();
+  LayerImpl* outer_container = active_tree_->OuterViewportContainerLayer();
+
+  if (!inner_container || !top_controls_manager_)
     return;
 
-  if (top_controls_manager_) {
-    container_layer->SetBoundsDelta(
-        gfx::Vector2dF(0, active_tree_->top_controls_layout_height() -
-            active_tree_->total_top_controls_content_offset()));
-  }
+  ViewportAnchor anchor(InnerViewportScrollLayer(),
+                        OuterViewportScrollLayer());
+
+  // Adjust the inner viewport by shrinking/expanding the container to account
+  // for the change in top controls height since the last Resize from Blink.
+  inner_container->SetBoundsDelta(
+      gfx::Vector2dF(0, active_tree_->top_controls_layout_height() -
+          active_tree_->total_top_controls_content_offset()));
+
+  if (!outer_container || outer_container->BoundsForScrolling().IsEmpty())
+    return;
+
+  // Adjust the outer viewport container as well, since adjusting only the
+  // inner may cause its bounds to exceed those of the outer, causing scroll
+  // clamping. We adjust it so it maintains the same aspect ratio as the
+  // inner viewport.
+  float aspect_ratio = inner_container->BoundsForScrolling().width() /
+      inner_container->BoundsForScrolling().height();
+  float target_height = outer_container->BoundsForScrolling().width() /
+      aspect_ratio;
+  float current_outer_height = outer_container->BoundsForScrolling().height() -
+      outer_container->bounds_delta().y();
+  gfx::Vector2dF delta(0, target_height - current_outer_height);
+
+  outer_container->SetBoundsDelta(delta);
+  active_tree_->InnerViewportScrollLayer()->SetBoundsDelta(delta);
+
+  anchor.ResetViewportToAnchoredPosition();
 }
 
 void LayerTreeHostImpl::SetTopControlsLayoutHeight(float height) {
@@ -1664,10 +1735,16 @@ void LayerTreeHostImpl::SetTopControlsLayoutHeight(float height) {
     return;
 
   active_tree_->set_top_controls_layout_height(height);
-  UpdateInnerViewportContainerSize();
+  UpdateViewportContainerSizes();
   SetFullRootLayerDamage();
 }
 
+void LayerTreeHostImpl::SynchronouslyInitializeAllTiles() {
+  // Only valid for the single-threaded non-scheduled/synchronous case
+  // using the zero copy raster worker pool.
+  single_thread_synchronous_task_graph_runner_->RunUntilIdle();
+}
+
 void LayerTreeHostImpl::DidLoseOutputSurface() {
   if (resource_provider_)
     resource_provider_->DidLoseOutputSurface();
@@ -1785,7 +1862,7 @@ void LayerTreeHostImpl::ActivateSyncTree() {
           top_controls_manager_->top_controls_height());
     }
 
-    UpdateInnerViewportContainerSize();
+    UpdateViewportContainerSizes();
   } else {
     active_tree_->ProcessUIResourceRequestQueue();
   }
@@ -1803,9 +1880,11 @@ void LayerTreeHostImpl::ActivateSyncTree() {
   if (debug_state_.continuous_painting) {
     const RenderingStats& stats =
         rendering_stats_instrumentation_->GetRenderingStats();
-    paint_time_counter_->SavePaintTime(stats.main_stats.paint_time +
-                                       stats.main_stats.record_time +
-                                       stats.impl_stats.rasterize_time);
+    // TODO(hendrikw): This requires a different metric when we commit directly
+    // to the active tree.  See crbug.com/429311.
+    paint_time_counter_->SavePaintTime(
+        stats.impl_stats.commit_to_activate_duration.GetLastTimeDelta() +
+        stats.impl_stats.draw_duration.GetLastTimeDelta());
   }
 
   if (time_source_client_adapter_ && time_source_client_adapter_->Active())
@@ -1833,7 +1912,7 @@ void LayerTreeHostImpl::SetVisible(bool visible) {
   // If we just became visible, we have to ensure that we draw high res tiles,
   // to prevent checkerboard/low res flashes.
   if (visible_)
-    active_tree()->SetRequiresHighResToDraw();
+    SetRequiresHighResToDraw();
   else
     EvictAllUIResources();
 
@@ -1932,87 +2011,120 @@ void LayerTreeHostImpl::CreateAndSetTileManager() {
   DCHECK(settings_.impl_side_painting);
   DCHECK(output_surface_);
   DCHECK(resource_provider_);
-  DCHECK(proxy_->ImplThreadTaskRunner());
+
+  CreateResourceAndRasterWorkerPool(
+      &raster_worker_pool_, &resource_pool_, &staging_resource_pool_);
+  DCHECK(raster_worker_pool_);
+  DCHECK(resource_pool_);
+
+  base::SingleThreadTaskRunner* task_runner =
+      proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner()
+                              : proxy_->MainThreadTaskRunner();
+  DCHECK(task_runner);
+  size_t scheduled_raster_task_limit =
+      IsSynchronousSingleThreaded() ? std::numeric_limits<size_t>::max()
+                                    : settings_.scheduled_raster_task_limit;
+  tile_manager_ = TileManager::Create(this,
+                                      task_runner,
+                                      resource_pool_.get(),
+                                      raster_worker_pool_->AsRasterizer(),
+                                      rendering_stats_instrumentation_,
+                                      scheduled_raster_task_limit);
+
+  UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
+  need_to_update_visible_tiles_before_draw_ = false;
+}
+
+void LayerTreeHostImpl::CreateResourceAndRasterWorkerPool(
+    scoped_ptr<RasterWorkerPool>* raster_worker_pool,
+    scoped_ptr<ResourcePool>* resource_pool,
+    scoped_ptr<ResourcePool>* staging_resource_pool) {
+  base::SingleThreadTaskRunner* task_runner =
+      proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner()
+                              : proxy_->MainThreadTaskRunner();
+  DCHECK(task_runner);
 
   ContextProvider* context_provider = output_surface_->context_provider();
+  bool should_use_zero_copy_rasterizer =
+      settings_.use_zero_copy || IsSynchronousSingleThreaded();
+
   if (!context_provider) {
-    resource_pool_ =
+    *resource_pool =
         ResourcePool::Create(resource_provider_.get(),
                              GL_TEXTURE_2D,
                              resource_provider_->best_texture_format());
 
-    raster_worker_pool_ =
-        BitmapRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
+    *raster_worker_pool =
+        BitmapRasterWorkerPool::Create(task_runner,
                                        RasterWorkerPool::GetTaskGraphRunner(),
                                        resource_provider_.get());
   } else if (use_gpu_rasterization_) {
-    resource_pool_ =
+    *resource_pool =
         ResourcePool::Create(resource_provider_.get(),
                              GL_TEXTURE_2D,
                              resource_provider_->best_texture_format());
 
-    raster_worker_pool_ =
-        GpuRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
+    *raster_worker_pool =
+        GpuRasterWorkerPool::Create(task_runner,
                                     context_provider,
-                                    resource_provider_.get());
-  } else if (UseZeroCopyRasterizer()) {
-    resource_pool_ = ResourcePool::Create(
+                                    resource_provider_.get(),
+                                    settings_.use_distance_field_text);
+  } else if (should_use_zero_copy_rasterizer && CanUseZeroCopyRasterizer()) {
+    *resource_pool = ResourcePool::Create(
         resource_provider_.get(),
         GetMapImageTextureTarget(context_provider->ContextCapabilities()),
         resource_provider_->best_texture_format());
 
-    raster_worker_pool_ =
-        ZeroCopyRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
-                                         RasterWorkerPool::GetTaskGraphRunner(),
-                                         resource_provider_.get());
-  } else if (UseOneCopyRasterizer()) {
+    TaskGraphRunner* task_graph_runner;
+    if (IsSynchronousSingleThreaded()) {
+      DCHECK(!single_thread_synchronous_task_graph_runner_);
+      single_thread_synchronous_task_graph_runner_.reset(new TaskGraphRunner);
+      task_graph_runner = single_thread_synchronous_task_graph_runner_.get();
+    } else {
+      task_graph_runner = RasterWorkerPool::GetTaskGraphRunner();
+    }
+
+    *raster_worker_pool = ZeroCopyRasterWorkerPool::Create(
+        task_runner, task_graph_runner, resource_provider_.get());
+  } else if (settings_.use_one_copy && CanUseOneCopyRasterizer()) {
     // We need to create a staging resource pool when using copy rasterizer.
-    staging_resource_pool_ = ResourcePool::Create(
+    *staging_resource_pool = ResourcePool::Create(
         resource_provider_.get(),
         GetMapImageTextureTarget(context_provider->ContextCapabilities()),
         resource_provider_->best_texture_format());
-    resource_pool_ =
+    *resource_pool =
         ResourcePool::Create(resource_provider_.get(),
                              GL_TEXTURE_2D,
                              resource_provider_->best_texture_format());
 
-    raster_worker_pool_ =
-        OneCopyRasterWorkerPool::Create(proxy_->ImplThreadTaskRunner(),
+    *raster_worker_pool =
+        OneCopyRasterWorkerPool::Create(task_runner,
                                         RasterWorkerPool::GetTaskGraphRunner(),
                                         context_provider,
                                         resource_provider_.get(),
                                         staging_resource_pool_.get());
   } else {
-    resource_pool_ = ResourcePool::Create(
+    *resource_pool = ResourcePool::Create(
         resource_provider_.get(),
         GL_TEXTURE_2D,
         resource_provider_->memory_efficient_texture_format());
 
-    raster_worker_pool_ = PixelBufferRasterWorkerPool::Create(
-        proxy_->ImplThreadTaskRunner(),
+    *raster_worker_pool = PixelBufferRasterWorkerPool::Create(
+        task_runner,
         RasterWorkerPool::GetTaskGraphRunner(),
         context_provider,
         resource_provider_.get(),
         GetMaxTransferBufferUsageBytes(context_provider->ContextCapabilities(),
                                        settings_.refresh_rate));
   }
-
-  tile_manager_ =
-      TileManager::Create(this,
-                          proxy_->ImplThreadTaskRunner(),
-                          resource_pool_.get(),
-                          raster_worker_pool_->AsRasterizer(),
-                          rendering_stats_instrumentation_);
-
-  UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
-  need_to_update_visible_tiles_before_draw_ = false;
 }
 
 void LayerTreeHostImpl::DestroyTileManager() {
-  tile_manager_.reset();
-  resource_pool_.reset();
-  staging_resource_pool_.reset();
-  raster_worker_pool_.reset();
+  tile_manager_ = nullptr;
+  resource_pool_ = nullptr;
+  staging_resource_pool_ = nullptr;
+  raster_worker_pool_ = nullptr;
+  single_thread_synchronous_task_graph_runner_ = nullptr;
 }
 
 bool LayerTreeHostImpl::UsePendingTreeForSync() const {
@@ -2021,13 +2133,17 @@ bool LayerTreeHostImpl::UsePendingTreeForSync() const {
   return settings_.impl_side_painting;
 }
 
-bool LayerTreeHostImpl::UseZeroCopyRasterizer() const {
-  return settings_.use_zero_copy && GetRendererCapabilities().using_map_image;
+bool LayerTreeHostImpl::IsSynchronousSingleThreaded() const {
+  return !proxy_->HasImplThread() && !settings_.single_thread_proxy_scheduler;
+}
+
+bool LayerTreeHostImpl::CanUseZeroCopyRasterizer() const {
+  return GetRendererCapabilities().using_image;
 }
 
-bool LayerTreeHostImpl::UseOneCopyRasterizer() const {
+bool LayerTreeHostImpl::CanUseOneCopyRasterizer() const {
   // Sync query support is required by one-copy rasterizer.
-  return settings_.use_one_copy && GetRendererCapabilities().using_map_image &&
+  return GetRendererCapabilities().using_image &&
          resource_provider_->use_sync_query();
 }
 
@@ -2045,10 +2161,10 @@ bool LayerTreeHostImpl::InitializeRenderer(
   ReleaseTreeResources();
 
   // Note: order is important here.
-  renderer_.reset();
+  renderer_ = nullptr;
   DestroyTileManager();
-  resource_provider_.reset();
-  output_surface_.reset();
+  resource_provider_ = nullptr;
+  output_surface_ = nullptr;
 
   if (!output_surface->BindToClient(this))
     return false;
@@ -2057,11 +2173,11 @@ bool LayerTreeHostImpl::InitializeRenderer(
   resource_provider_ =
       ResourceProvider::Create(output_surface_.get(),
                                shared_bitmap_manager_,
+                               gpu_memory_buffer_manager_,
                                proxy_->blocking_main_thread_task_runner(),
                                settings_.highp_threshold_min,
                                settings_.use_rgba_4444_textures,
-                               settings_.texture_id_allocation_chunk_size,
-                               settings_.use_distance_field_text);
+                               settings_.texture_id_allocation_chunk_size);
 
   if (output_surface_->capabilities().deferred_gl_initialization)
     EnforceZeroBudget(true);
@@ -2094,7 +2210,7 @@ bool LayerTreeHostImpl::InitializeRenderer(
   // There will not be anything to draw here, so set high res
   // to avoid checkerboards, typically when we are recovering
   // from lost context.
-  active_tree_->SetRequiresHighResToDraw();
+  SetRequiresHighResToDraw();
 
   return true;
 }
@@ -2110,7 +2226,7 @@ void LayerTreeHostImpl::DeferredInitialize() {
   DCHECK(output_surface_->context_provider());
 
   ReleaseTreeResources();
-  renderer_.reset();
+  renderer_ = nullptr;
   DestroyTileManager();
 
   resource_provider_->InitializeGL();
@@ -2128,7 +2244,7 @@ void LayerTreeHostImpl::ReleaseGL() {
   DCHECK(output_surface_->context_provider());
 
   ReleaseTreeResources();
-  renderer_.reset();
+  renderer_ = nullptr;
   DestroyTileManager();
 
   resource_provider_->InitializeSoftware();
@@ -2150,7 +2266,7 @@ void LayerTreeHostImpl::SetViewportSize(const gfx::Size& device_viewport_size) {
 
   device_viewport_size_ = device_viewport_size;
 
-  UpdateInnerViewportContainerSize();
+  UpdateViewportContainerSizes();
   client_->OnCanDrawStateChanged(CanDraw());
   SetFullRootLayerDamage();
   active_tree_->set_needs_update_draw_properties();
@@ -2201,7 +2317,7 @@ const gfx::Transform& LayerTreeHostImpl::DrawTransform() const {
 }
 
 void LayerTreeHostImpl::DidChangeTopControlsPosition() {
-  UpdateInnerViewportContainerSize();
+  UpdateViewportContainerSizes();
   SetNeedsRedraw();
   SetNeedsAnimate();
   active_tree_->set_needs_update_draw_properties();
@@ -2351,8 +2467,9 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated(
     ScrollOffsetAnimationCurve* curve =
         animation->curve()->ToScrollOffsetAnimationCurve();
 
-    gfx::Vector2dF new_target = curve->target_value() + scroll_delta;
-    new_target.SetToMax(gfx::Vector2dF());
+    gfx::ScrollOffset new_target =
+        gfx::ScrollOffsetWithDelta(curve->target_value(), scroll_delta);
+    new_target.SetToMax(gfx::ScrollOffset());
     new_target.SetToMin(layer_impl->MaxScrollOffset());
 
     curve->UpdateTarget(animation->TrimTimeToCurrentIteration(
@@ -2372,11 +2489,12 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated(
       if (!layer_impl->scrollable())
         continue;
 
-      gfx::Vector2dF current_offset = layer_impl->TotalScrollOffset();
-      gfx::Vector2dF target_offset = current_offset + pending_delta;
-      target_offset.SetToMax(gfx::Vector2dF());
+      gfx::ScrollOffset current_offset = layer_impl->TotalScrollOffset();
+      gfx::ScrollOffset target_offset =
+          ScrollOffsetWithDelta(current_offset, pending_delta);
+      target_offset.SetToMax(gfx::ScrollOffset());
       target_offset.SetToMin(layer_impl->MaxScrollOffset());
-      gfx::Vector2dF actual_delta = target_offset - current_offset;
+      gfx::Vector2dF actual_delta = target_offset.DeltaFrom(current_offset);
 
       const float kEpsilon = 0.1f;
       bool can_layer_scroll = (std::abs(actual_delta.x()) > kEpsilon ||
@@ -2396,7 +2514,7 @@ InputHandler::ScrollStatus LayerTreeHostImpl::ScrollAnimated(
       curve->SetInitialValue(current_offset);
 
       scoped_ptr<Animation> animation =
-          Animation::Create(curve.PassAs<AnimationCurve>(),
+          Animation::Create(curve.Pass(),
                             AnimationIdProvider::NextAnimationId(),
                             AnimationIdProvider::NextGroupId(),
                             Animation::ScrollOffset);
@@ -2495,49 +2613,77 @@ static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl,
   return layer_impl->ScrollDelta() - previous_delta;
 }
 
-bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point,
-                                 const gfx::Vector2dF& scroll_delta) {
+bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll(
+    const gfx::Vector2dF& scroll_delta) const {
+  DCHECK(CurrentlyScrollingLayer());
+
+  if (!top_controls_manager_)
+    return false;
+
+  // Always consume if it's in the direction to show the top controls.
+  if (scroll_delta.y() < 0)
+    return true;
+
+  if (CurrentlyScrollingLayer() != InnerViewportScrollLayer() &&
+      CurrentlyScrollingLayer() != OuterViewportScrollLayer())
+    return false;
+
+  if (InnerViewportScrollLayer()->MaxScrollOffset().y() > 0)
+    return true;
+
+  if (OuterViewportScrollLayer() &&
+      OuterViewportScrollLayer()->MaxScrollOffset().y() > 0)
+    return true;
+
+  return false;
+}
+
+InputHandlerScrollResult LayerTreeHostImpl::ScrollBy(
+    const gfx::Point& viewport_point,
+    const gfx::Vector2dF& scroll_delta) {
   TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy");
   if (!CurrentlyScrollingLayer())
-    return false;
+    return InputHandlerScrollResult();
 
   gfx::Vector2dF pending_delta = scroll_delta;
   gfx::Vector2dF unused_root_delta;
   bool did_scroll_x = false;
   bool did_scroll_y = false;
   bool did_scroll_top_controls = false;
-  // TODO(wjmaclean) Should we guard against CurrentlyScrollingLayer() == 0
-  // here?
-  bool consume_by_top_controls =
-      top_controls_manager_ &&
-      (((CurrentlyScrollingLayer() == InnerViewportScrollLayer() ||
-         CurrentlyScrollingLayer() == OuterViewportScrollLayer()) &&
-        InnerViewportScrollLayer()->MaxScrollOffset().y() > 0) ||
-       scroll_delta.y() < 0);
 
-  for (LayerImpl* layer_impl = CurrentlyScrollingLayer();
+  bool consume_by_top_controls = ShouldTopControlsConsumeScroll(scroll_delta);
+
+  // There's an edge case where the outer viewport isn't scrollable when the
+  // scroll starts, however, as the top controls show the outer viewport becomes
+  // scrollable. Therefore, always try scrolling the outer viewport before the
+  // inner.
+  // TODO(bokan): Move the top controls logic out of the loop since the scroll
+  // that causes the outer viewport to become scrollable will still be applied
+  // to the inner viewport.
+  LayerImpl* start_layer = CurrentlyScrollingLayer();
+  if (start_layer == InnerViewportScrollLayer() && OuterViewportScrollLayer())
+      start_layer = OuterViewportScrollLayer();
+
+  for (LayerImpl* layer_impl = start_layer;
        layer_impl;
        layer_impl = layer_impl->parent()) {
     if (!layer_impl->scrollable())
       continue;
 
-    if (layer_impl == InnerViewportScrollLayer()) {
-      // Only allow bubble scrolling when the scroll is in the direction to make
-      // the top controls visible.
-      gfx::Vector2dF applied_delta;
-      gfx::Vector2dF excess_delta;
+    if (layer_impl == InnerViewportScrollLayer() ||
+        layer_impl == OuterViewportScrollLayer()) {
       if (consume_by_top_controls) {
-        excess_delta = top_controls_manager_->ScrollBy(pending_delta);
-        applied_delta = pending_delta - excess_delta;
+        gfx::Vector2dF excess_delta =
+            top_controls_manager_->ScrollBy(pending_delta);
+        gfx::Vector2dF applied_delta = pending_delta - excess_delta;
         pending_delta = excess_delta;
         // Force updating of vertical adjust values if needed.
-        if (applied_delta.y() != 0) {
+        if (applied_delta.y() != 0)
           did_scroll_top_controls = true;
-          layer_impl->ScrollbarParametersDidChange();
-        }
       }
       // Track root layer deltas for reporting overscroll.
-      unused_root_delta = pending_delta;
+      if (layer_impl == InnerViewportScrollLayer())
+        unused_root_delta = pending_delta;
     }
 
     gfx::Vector2dF applied_delta;
@@ -2564,47 +2710,58 @@ bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point,
         unused_root_delta.set_y(0.0f);
       // Disable overscroll on axes which is impossible to scroll.
       if (settings_.report_overscroll_only_for_scrollable_axes) {
-        if (std::abs(active_tree_->TotalMaxScrollOffset().x()) <= kEpsilon)
+        if (std::abs(active_tree_->TotalMaxScrollOffset().x()) <= kEpsilon ||
+            !layer_impl->user_scrollable_horizontal())
           unused_root_delta.set_x(0.0f);
-        if (std::abs(active_tree_->TotalMaxScrollOffset().y()) <= kEpsilon)
+        if (std::abs(active_tree_->TotalMaxScrollOffset().y()) <= kEpsilon ||
+            !layer_impl->user_scrollable_vertical())
           unused_root_delta.set_y(0.0f);
       }
     }
 
+    // Scrolls should bubble perfectly between the outer and inner viewports.
+    bool allow_unrestricted_bubbling_for_current_layer =
+        layer_impl == OuterViewportScrollLayer();
+    bool allow_bubbling_for_current_layer =
+        allow_unrestricted_bubbling_for_current_layer || should_bubble_scrolls_;
+
     // If the layer wasn't able to move, try the next one in the hierarchy.
     bool did_move_layer_x = std::abs(applied_delta.x()) > kEpsilon;
     bool did_move_layer_y = std::abs(applied_delta.y()) > kEpsilon;
     did_scroll_x |= did_move_layer_x;
     did_scroll_y |= did_move_layer_y;
     if (!did_move_layer_x && !did_move_layer_y) {
-      // Scrolls should always bubble between the outer and inner viewports
-      if (should_bubble_scrolls_ || !did_lock_scrolling_layer_ ||
-          layer_impl == OuterViewportScrollLayer())
+      if (allow_bubbling_for_current_layer || !did_lock_scrolling_layer_)
         continue;
       else
         break;
     }
 
     did_lock_scrolling_layer_ = true;
-    if (!should_bubble_scrolls_) {
+    if (!allow_bubbling_for_current_layer) {
       active_tree_->SetCurrentlyScrollingLayer(layer_impl);
       break;
     }
 
-    // If the applied delta is within 45 degrees of the input delta, bail out to
-    // make it easier to scroll just one layer in one direction without
-    // affecting any of its parents.
-    float angle_threshold = 45;
-    if (MathUtil::SmallestAngleBetweenVectors(
-            applied_delta, pending_delta) < angle_threshold) {
-      pending_delta = gfx::Vector2d();
-      break;
-    }
+    if (allow_unrestricted_bubbling_for_current_layer) {
+      pending_delta -= applied_delta;
+    } else {
+      // If the applied delta is within 45 degrees of the input delta, bail out
+      // to make it easier to scroll just one layer in one direction without
+      // affecting any of its parents.
+      float angle_threshold = 45;
+      if (MathUtil::SmallestAngleBetweenVectors(applied_delta, pending_delta) <
+          angle_threshold) {
+        pending_delta = gfx::Vector2dF();
+        break;
+      }
 
-    // Allow further movement only on an axis perpendicular to the direction in
-    // which the layer moved.
-    gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
-    pending_delta = MathUtil::ProjectVector(pending_delta, perpendicular_axis);
+      // Allow further movement only on an axis perpendicular to the direction
+      // in which the layer moved.
+      gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x());
+      pending_delta =
+          MathUtil::ProjectVector(pending_delta, perpendicular_axis);
+    }
 
     if (gfx::ToRoundedVector2d(pending_delta).IsZero())
       break;
@@ -2627,15 +2784,14 @@ bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point,
     accumulated_root_overscroll_.set_x(0);
   if (did_scroll_y)
     accumulated_root_overscroll_.set_y(0);
-
   accumulated_root_overscroll_ += unused_root_delta;
-  bool did_overscroll = !unused_root_delta.IsZero();
-  if (did_overscroll && input_handler_client_) {
-    input_handler_client_->DidOverscroll(
-        viewport_point, accumulated_root_overscroll_, unused_root_delta);
-  }
 
-  return did_scroll_content || did_scroll_top_controls;
+  InputHandlerScrollResult scroll_result;
+  scroll_result.did_scroll = did_scroll_content || did_scroll_top_controls;
+  scroll_result.did_overscroll_root = !unused_root_delta.IsZero();
+  scroll_result.accumulated_root_overscroll = accumulated_root_overscroll_;
+  scroll_result.unused_scroll_delta = unused_root_delta;
+  return scroll_result;
 }
 
 // This implements scrolling by page as described here:
@@ -2687,8 +2843,10 @@ void LayerTreeHostImpl::SetRootLayerScrollOffsetDelegate(
 }
 
 void LayerTreeHostImpl::OnRootLayerDelegatedScrollOffsetChanged() {
-  DCHECK(root_layer_scroll_offset_delegate_ != NULL);
+  DCHECK(root_layer_scroll_offset_delegate_);
   client_->SetNeedsCommitOnImplThread();
+  SetNeedsRedraw();
+  active_tree_->OnRootLayerDelegatedScrollOffsetChanged();
   active_tree_->set_needs_update_draw_properties();
 }
 
@@ -2937,6 +3095,15 @@ void LayerTreeHostImpl::SetFullRootLayerDamage() {
   SetViewportDamage(gfx::Rect(DrawViewportSize()));
 }
 
+void LayerTreeHostImpl::ScrollViewportInnerFirst(gfx::Vector2dF scroll_delta) {
+  DCHECK(InnerViewportScrollLayer());
+  LayerImpl* scroll_layer = InnerViewportScrollLayer();
+
+  gfx::Vector2dF unused_delta = scroll_layer->ScrollBy(scroll_delta);
+  if (!unused_delta.IsZero() && OuterViewportScrollLayer())
+    OuterViewportScrollLayer()->ScrollBy(unused_delta);
+}
+
 void LayerTreeHostImpl::ScrollViewportBy(gfx::Vector2dF scroll_delta) {
   DCHECK(InnerViewportScrollLayer());
   LayerImpl* scroll_layer = OuterViewportScrollLayer()
@@ -2953,7 +3120,7 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) {
   if (!page_scale_animation_)
     return;
 
-  gfx::Vector2dF scroll_total = active_tree_->TotalScrollOffset();
+  gfx::ScrollOffset scroll_total = active_tree_->TotalScrollOffset();
 
   if (!page_scale_animation_->IsAnimationStarted())
     page_scale_animation_->StartAnimation(monotonic_time);
@@ -2961,14 +3128,14 @@ void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) {
   active_tree_->SetPageScaleDelta(
       page_scale_animation_->PageScaleFactorAtTime(monotonic_time) /
       active_tree_->page_scale_factor());
-  gfx::Vector2dF next_scroll =
-      page_scale_animation_->ScrollOffsetAtTime(monotonic_time);
+  gfx::ScrollOffset next_scroll = gfx::ScrollOffset(
+      page_scale_animation_->ScrollOffsetAtTime(monotonic_time));
 
-  ScrollViewportBy(next_scroll - scroll_total);
+  ScrollViewportInnerFirst(next_scroll.DeltaFrom(scroll_total));
   SetNeedsRedraw();
 
   if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) {
-    page_scale_animation_.reset();
+    page_scale_animation_ = nullptr;
     client_->SetNeedsCommitOnImplThread();
     client_->RenewTreePriority();
   } else {
@@ -3112,6 +3279,10 @@ void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
   DidModifyTilePriorities();
 }
 
+TreePriority LayerTreeHostImpl::GetTreePriority() const {
+  return global_tile_state_.tree_priority;
+}
+
 void LayerTreeHostImpl::UpdateCurrentBeginFrameArgs(
     const BeginFrameArgs& args) {
   DCHECK(!current_begin_frame_args_.IsValid());
@@ -3136,6 +3307,10 @@ BeginFrameArgs LayerTreeHostImpl::CurrentBeginFrameArgs() const {
                                 BeginFrameArgs::DefaultInterval());
 }
 
+void LayerTreeHostImpl::AsValueInto(base::debug::TracedValue* value) const {
+  return AsValueWithFrameInto(NULL, value);
+}
+
 scoped_refptr<base::debug::ConvertableToTraceFormat>
 LayerTreeHostImpl::AsValue() const {
   return AsValueWithFrame(NULL);