// Copyright 2011 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/layer_tree_host.h"

#include <algorithm>
#include <stack>
#include <string>

#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_argument.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "cc/animation/animation_registrar.h"
#include "cc/animation/layer_animation_controller.h"
#include "cc/base/math_util.h"
#include "cc/debug/devtools_instrumentation.h"
#include "cc/debug/rendering_stats_instrumentation.h"
#include "cc/input/layer_selection_bound.h"
#include "cc/input/page_scale_animation.h"
#include "cc/input/top_controls_manager.h"
#include "cc/layers/heads_up_display_layer.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_iterator.h"
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/layers/render_surface.h"
#include "cc/resources/prioritized_resource_manager.h"
#include "cc/resources/ui_resource_request.h"
#include "cc/scheduler/begin_frame_source.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/occlusion_tracker.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
#include "ui/gfx/geometry/size_conversions.h"

namespace {
static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
}

namespace cc {

RendererCapabilities::RendererCapabilities(ResourceFormat best_texture_format,
                                           bool allow_partial_texture_updates,
                                           int max_texture_size,
                                           bool using_shared_memory_resources)
    : best_texture_format(best_texture_format),
      allow_partial_texture_updates(allow_partial_texture_updates),
      max_texture_size(max_texture_size),
      using_shared_memory_resources(using_shared_memory_resources) {}

RendererCapabilities::RendererCapabilities()
    : best_texture_format(RGBA_8888),
      allow_partial_texture_updates(false),
      max_texture_size(0),
      using_shared_memory_resources(false) {}

RendererCapabilities::~RendererCapabilities() {}

scoped_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
    LayerTreeHostClient* client,
    SharedBitmapManager* shared_bitmap_manager,
    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
    const LayerTreeSettings& settings,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
  DCHECK(main_task_runner.get());
  DCHECK(impl_task_runner.get());
  scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost(
      client, shared_bitmap_manager, gpu_memory_buffer_manager, settings));
  layer_tree_host->InitializeThreaded(main_task_runner,
                                      impl_task_runner,
                                      external_begin_frame_source.Pass());
  return layer_tree_host.Pass();
}

scoped_ptr<LayerTreeHost> LayerTreeHost::CreateSingleThreaded(
    LayerTreeHostClient* client,
    LayerTreeHostSingleThreadClient* single_thread_client,
    SharedBitmapManager* shared_bitmap_manager,
    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
    const LayerTreeSettings& settings,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
  scoped_ptr<LayerTreeHost> layer_tree_host(new LayerTreeHost(
      client, shared_bitmap_manager, gpu_memory_buffer_manager, settings));
  layer_tree_host->InitializeSingleThreaded(single_thread_client,
                                            main_task_runner,
                                            external_begin_frame_source.Pass());
  return layer_tree_host.Pass();
}

LayerTreeHost::LayerTreeHost(
    LayerTreeHostClient* client,
    SharedBitmapManager* shared_bitmap_manager,
    gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
    const LayerTreeSettings& settings)
    : micro_benchmark_controller_(this),
      next_ui_resource_id_(1),
      inside_begin_main_frame_(false),
      needs_full_tree_sync_(true),
      client_(client),
      source_frame_number_(0),
      rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
      output_surface_lost_(true),
      settings_(settings),
      debug_state_(settings.initial_debug_state),
      top_controls_shrink_blink_size_(false),
      top_controls_height_(0.f),
      top_controls_content_offset_(0.f),
      device_scale_factor_(1.f),
      visible_(true),
      page_scale_factor_(1.f),
      min_page_scale_factor_(1.f),
      max_page_scale_factor_(1.f),
      has_gpu_rasterization_trigger_(false),
      content_is_suitable_for_gpu_rasterization_(true),
      gpu_rasterization_histogram_recorded_(false),
      background_color_(SK_ColorWHITE),
      has_transparent_background_(false),
      partial_texture_update_requests_(0),
      in_paint_layer_contents_(false),
      total_frames_used_for_lcd_text_metrics_(0),
      id_(s_layer_tree_host_sequence_number.GetNext() + 1),
      next_commit_forces_redraw_(false),
      shared_bitmap_manager_(shared_bitmap_manager),
      gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
      surface_id_namespace_(0u),
      next_surface_sequence_(1u) {
  if (settings_.accelerated_animation_enabled)
    animation_registrar_ = AnimationRegistrar::Create();
  rendering_stats_instrumentation_->set_record_rendering_stats(
      debug_state_.RecordRenderingStats());
}

void LayerTreeHost::InitializeThreaded(
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
  InitializeProxy(ThreadProxy::Create(this,
                                      main_task_runner,
                                      impl_task_runner,
                                      external_begin_frame_source.Pass()));
}

void LayerTreeHost::InitializeSingleThreaded(
    LayerTreeHostSingleThreadClient* single_thread_client,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
  InitializeProxy(
      SingleThreadProxy::Create(this,
                                single_thread_client,
                                main_task_runner,
                                external_begin_frame_source.Pass()));
}

void LayerTreeHost::InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing) {
  InitializeProxy(proxy_for_testing.Pass());
}

void LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) {
  TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal");

  proxy_ = proxy.Pass();
  proxy_->Start();
  if (settings_.accelerated_animation_enabled) {
    animation_registrar_->set_supports_scroll_animations(
        proxy_->SupportsImplScrolling());
  }
}

LayerTreeHost::~LayerTreeHost() {
  TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");

  overhang_ui_resource_ = nullptr;

  if (root_layer_.get())
    root_layer_->SetLayerTreeHost(NULL);

  DCHECK(swap_promise_monitor_.empty());

  BreakSwapPromises(SwapPromise::COMMIT_FAILS);

  if (proxy_) {
    DCHECK(proxy_->IsMainThread());
    proxy_->Stop();
  }

  // We must clear any pointers into the layer tree prior to destroying it.
  RegisterViewportLayers(NULL, NULL, NULL, NULL);

  if (root_layer_.get()) {
    // The layer tree must be destroyed before the layer tree host. We've
    // made a contract with our animation controllers that the registrar
    // will outlive them, and we must make good.
    root_layer_ = NULL;
  }
}

void LayerTreeHost::SetLayerTreeHostClientReady() {
  proxy_->SetLayerTreeHostClientReady();
}

static void LayerTreeHostOnOutputSurfaceCreatedCallback(Layer* layer) {
  layer->OnOutputSurfaceCreated();
}

void LayerTreeHost::DeleteContentsTexturesOnImplThread(
    ResourceProvider* resource_provider) {
  DCHECK(proxy_->IsImplThread());
  if (contents_texture_manager_)
    contents_texture_manager_->ClearAllMemory(resource_provider);
}

void LayerTreeHost::DidBeginMainFrame() {
  client_->DidBeginMainFrame();
}

void LayerTreeHost::BeginMainFrame(const BeginFrameArgs& args) {
  inside_begin_main_frame_ = true;
  client_->BeginMainFrame(args);
  inside_begin_main_frame_ = false;
}

void LayerTreeHost::DidStopFlinging() {
  proxy_->MainThreadHasStoppedFlinging();
}

void LayerTreeHost::Layout() {
  client_->Layout();
}

void LayerTreeHost::BeginCommitOnImplThread(LayerTreeHostImpl* host_impl) {
  DCHECK(proxy_->IsImplThread());
  TRACE_EVENT0("cc", "LayerTreeHost::CommitTo");
}

// This function commits the LayerTreeHost to an impl tree. When modifying
// this function, keep in mind that the function *runs* on the impl thread! Any
// 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) {
  DCHECK(proxy_->IsImplThread());

  // If there are linked evicted backings, these backings' resources may be put
  // into the impl tree, so we can't draw yet. Determine this before clearing
  // all evicted backings.
  bool new_impl_tree_has_no_evicted_resources = false;
  if (contents_texture_manager_) {
    new_impl_tree_has_no_evicted_resources =
        !contents_texture_manager_->LinkedEvictedBackingsExist();

    // If the memory limit has been increased since this now-finishing
    // commit began, and the extra now-available memory would have been used,
    // then request another commit.
    if (contents_texture_manager_->MaxMemoryLimitBytes() <
            host_impl->memory_allocation_limit_bytes() &&
        contents_texture_manager_->MaxMemoryLimitBytes() <
            contents_texture_manager_->MaxMemoryNeededBytes()) {
      host_impl->SetNeedsCommit();
    }

    host_impl->set_max_memory_needed_bytes(
        contents_texture_manager_->MaxMemoryNeededBytes());

    contents_texture_manager_->UpdateBackingsState(
        host_impl->resource_provider());
    contents_texture_manager_->ReduceMemory(host_impl->resource_provider());
  }

  LayerTreeImpl* sync_tree = host_impl->sync_tree();

  if (next_commit_forces_redraw_) {
    sync_tree->ForceRedrawNextActivation();
    next_commit_forces_redraw_ = false;
  }

  sync_tree->set_source_frame_number(source_frame_number());

  if (needs_full_tree_sync_) {
    sync_tree->SetRootLayer(TreeSynchronizer::SynchronizeTrees(
        root_layer(), sync_tree->DetachLayerTree(), sync_tree));
  }
  sync_tree->set_needs_full_tree_sync(needs_full_tree_sync_);
  needs_full_tree_sync_ = false;

  if (hud_layer_.get()) {
    LayerImpl* hud_impl = LayerTreeHostCommon::FindLayerInSubtree(
        sync_tree->root_layer(), hud_layer_->id());
    sync_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl));
  } else {
    sync_tree->set_hud_layer(NULL);
  }

  sync_tree->set_background_color(background_color_);
  sync_tree->set_has_transparent_background(has_transparent_background_);

  if (page_scale_layer_.get() && inner_viewport_scroll_layer_.get()) {
    sync_tree->SetViewportLayersFromIds(
        overscroll_elasticity_layer_.get() ? overscroll_elasticity_layer_->id()
                                           : Layer::INVALID_ID,
        page_scale_layer_->id(), inner_viewport_scroll_layer_->id(),
        outer_viewport_scroll_layer_.get() ? outer_viewport_scroll_layer_->id()
                                           : Layer::INVALID_ID);
    DCHECK(inner_viewport_scroll_layer_->IsContainerForFixedPositionLayers());
  } else {
    sync_tree->ClearViewportLayers();
  }

  sync_tree->RegisterSelection(selection_start_, selection_end_);

  sync_tree->PushPageScaleFromMainThread(
      page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_);
  sync_tree->elastic_overscroll()->PushFromMainThread(elastic_overscroll_);
  if (sync_tree->IsActiveTree())
    sync_tree->elastic_overscroll()->PushPendingToActive();

  sync_tree->PassSwapPromises(&swap_promise_list_);

  // Track the change in top controls height to offset the top_controls_delta
  // properly.  This is so that the top controls offset will be maintained
  // across height changes.
  float top_controls_height_delta =
      sync_tree->top_controls_height() - top_controls_height_;

  sync_tree->set_top_controls_shrink_blink_size(
      top_controls_shrink_blink_size_);
  sync_tree->set_top_controls_height(top_controls_height_);
  sync_tree->set_top_controls_content_offset(top_controls_content_offset_);
  sync_tree->set_top_controls_delta(sync_tree->top_controls_delta() -
                                    sync_tree->sent_top_controls_delta() -
                                    top_controls_height_delta);
  sync_tree->set_sent_top_controls_delta(0.f);

  host_impl->SetUseGpuRasterization(UseGpuRasterization());
  host_impl->set_gpu_rasterization_status(GetGpuRasterizationStatus());
  RecordGpuRasterizationHistogram();

  host_impl->SetViewportSize(device_viewport_size_);
  host_impl->SetDeviceScaleFactor(device_scale_factor_);
  host_impl->SetDebugState(debug_state_);
  if (pending_page_scale_animation_) {
    sync_tree->SetPendingPageScaleAnimation(
        pending_page_scale_animation_.Pass());
  }

  if (!ui_resource_request_queue_.empty()) {
    sync_tree->set_ui_resource_request_queue(ui_resource_request_queue_);
    ui_resource_request_queue_.clear();
  }
  if (overhang_ui_resource_) {
    host_impl->SetOverhangUIResource(
        overhang_ui_resource_->id(),
        GetUIResourceSize(overhang_ui_resource_->id()));
  }

  DCHECK(!sync_tree->ViewportSizeInvalid());

  if (new_impl_tree_has_no_evicted_resources) {
    if (sync_tree->ContentsTexturesPurged())
      sync_tree->ResetContentsTexturesPurged();
  }

  sync_tree->set_has_ever_been_drawn(false);

  {
    TRACE_EVENT0("cc", "LayerTreeHost::PushProperties");
    TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer());
  }

  micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl);
}

void LayerTreeHost::WillCommit() {
  client_->WillCommit();
}

void LayerTreeHost::UpdateHudLayer() {
  if (debug_state_.ShowHudInfo()) {
    if (!hud_layer_.get())
      hud_layer_ = HeadsUpDisplayLayer::Create();

    if (root_layer_.get() && !hud_layer_->parent())
      root_layer_->AddChild(hud_layer_);
  } else if (hud_layer_.get()) {
    hud_layer_->RemoveFromParent();
    hud_layer_ = NULL;
  }
}

void LayerTreeHost::CommitComplete() {
  source_frame_number_++;
  client_->DidCommit();
}

void LayerTreeHost::SetOutputSurface(scoped_ptr<OutputSurface> surface) {
  TRACE_EVENT0("cc", "LayerTreeHost::SetOutputSurface");
  DCHECK(output_surface_lost_);
  DCHECK(surface);

  proxy_->SetOutputSurface(surface.Pass());
}

void LayerTreeHost::RequestNewOutputSurface() {
  client_->RequestNewOutputSurface();
}

void LayerTreeHost::DidInitializeOutputSurface() {
  output_surface_lost_ = false;

  if (!contents_texture_manager_ && !settings_.impl_side_painting) {
    contents_texture_manager_ =
        PrioritizedResourceManager::Create(proxy_.get());
    surface_memory_placeholder_ =
        contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888);
  }

  if (root_layer()) {
    LayerTreeHostCommon::CallFunctionForSubtree(
        root_layer(), base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback));
  }

  client_->DidInitializeOutputSurface();
}

void LayerTreeHost::DidFailToInitializeOutputSurface() {
  DCHECK(output_surface_lost_);
  client_->DidFailToInitializeOutputSurface();
}

scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl(
    LayerTreeHostImplClient* client) {
  DCHECK(proxy_->IsImplThread());
  scoped_ptr<LayerTreeHostImpl> host_impl =
      LayerTreeHostImpl::Create(settings_,
                                client,
                                proxy_.get(),
                                rendering_stats_instrumentation_.get(),
                                shared_bitmap_manager_,
                                gpu_memory_buffer_manager_,
                                id_);
  host_impl->SetUseGpuRasterization(UseGpuRasterization());
  shared_bitmap_manager_ = NULL;
  gpu_memory_buffer_manager_ = NULL;
  if (settings_.calculate_top_controls_position &&
      host_impl->top_controls_manager()) {
    top_controls_manager_weak_ptr_ =
        host_impl->top_controls_manager()->AsWeakPtr();
  }
  input_handler_weak_ptr_ = host_impl->AsWeakPtr();
  return host_impl.Pass();
}

void LayerTreeHost::DidLoseOutputSurface() {
  TRACE_EVENT0("cc", "LayerTreeHost::DidLoseOutputSurface");
  DCHECK(proxy_->IsMainThread());

  if (output_surface_lost_)
    return;

  output_surface_lost_ = true;
  SetNeedsCommit();
}

void LayerTreeHost::FinishAllRendering() {
  proxy_->FinishAllRendering();
}

void LayerTreeHost::SetDeferCommits(bool defer_commits) {
  proxy_->SetDeferCommits(defer_commits);
}

void LayerTreeHost::DidDeferCommit() {}

void LayerTreeHost::SetNeedsDisplayOnAllLayers() {
  std::stack<Layer*> layer_stack;
  layer_stack.push(root_layer());
  while (!layer_stack.empty()) {
    Layer* current_layer = layer_stack.top();
    layer_stack.pop();
    current_layer->SetNeedsDisplay();
    for (unsigned int i = 0; i < current_layer->children().size(); i++) {
      layer_stack.push(current_layer->child_at(i));
    }
  }
}

const RendererCapabilities& LayerTreeHost::GetRendererCapabilities() const {
  return proxy_->GetRendererCapabilities();
}

void LayerTreeHost::SetNeedsAnimate() {
  proxy_->SetNeedsAnimate();
  NotifySwapPromiseMonitorsOfSetNeedsCommit();
}

void LayerTreeHost::SetNeedsUpdateLayers() {
  proxy_->SetNeedsUpdateLayers();
  NotifySwapPromiseMonitorsOfSetNeedsCommit();
}

void LayerTreeHost::SetNeedsCommit() {
  if (!prepaint_callback_.IsCancelled()) {
    TRACE_EVENT_INSTANT0("cc",
                         "LayerTreeHost::SetNeedsCommit::cancel prepaint",
                         TRACE_EVENT_SCOPE_THREAD);
    prepaint_callback_.Cancel();
  }
  proxy_->SetNeedsCommit();
  NotifySwapPromiseMonitorsOfSetNeedsCommit();
}

void LayerTreeHost::SetNeedsFullTreeSync() {
  needs_full_tree_sync_ = true;
  SetNeedsCommit();
}

void LayerTreeHost::SetNeedsRedraw() {
  SetNeedsRedrawRect(gfx::Rect(device_viewport_size_));
}

void LayerTreeHost::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
  proxy_->SetNeedsRedraw(damage_rect);
}

bool LayerTreeHost::CommitRequested() const {
  return proxy_->CommitRequested();
}

bool LayerTreeHost::BeginMainFrameRequested() const {
  return proxy_->BeginMainFrameRequested();
}


void LayerTreeHost::SetNextCommitWaitsForActivation() {
  proxy_->SetNextCommitWaitsForActivation();
}

void LayerTreeHost::SetNextCommitForcesRedraw() {
  next_commit_forces_redraw_ = true;
}

void LayerTreeHost::SetAnimationEvents(
    scoped_ptr<AnimationEventsVector> events) {
  DCHECK(proxy_->IsMainThread());
  for (size_t event_index = 0; event_index < events->size(); ++event_index) {
    int event_layer_id = (*events)[event_index].layer_id;

    // Use the map of all controllers, not just active ones, since non-active
    // controllers may still receive events for impl-only animations.
    const AnimationRegistrar::AnimationControllerMap& animation_controllers =
        animation_registrar_->all_animation_controllers();
    AnimationRegistrar::AnimationControllerMap::const_iterator iter =
        animation_controllers.find(event_layer_id);
    if (iter != animation_controllers.end()) {
      switch ((*events)[event_index].type) {
        case AnimationEvent::Started:
          (*iter).second->NotifyAnimationStarted((*events)[event_index]);
          break;

        case AnimationEvent::Finished:
          (*iter).second->NotifyAnimationFinished((*events)[event_index]);
          break;

        case AnimationEvent::Aborted:
          (*iter).second->NotifyAnimationAborted((*events)[event_index]);
          break;

        case AnimationEvent::PropertyUpdate:
          (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
          break;
      }
    }
  }
}

void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
  if (root_layer_.get() == root_layer.get())
    return;

  if (root_layer_.get())
    root_layer_->SetLayerTreeHost(NULL);
  root_layer_ = root_layer;
  if (root_layer_.get()) {
    DCHECK(!root_layer_->parent());
    root_layer_->SetLayerTreeHost(this);
  }

  if (hud_layer_.get())
    hud_layer_->RemoveFromParent();

  // Reset gpu rasterization flag.
  // This flag is sticky until a new tree comes along.
  content_is_suitable_for_gpu_rasterization_ = true;
  gpu_rasterization_histogram_recorded_ = false;

  SetNeedsFullTreeSync();
}

void LayerTreeHost::SetDebugState(const LayerTreeDebugState& debug_state) {
  LayerTreeDebugState new_debug_state =
      LayerTreeDebugState::Unite(settings_.initial_debug_state, debug_state);

  if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
    return;

  debug_state_ = new_debug_state;

  rendering_stats_instrumentation_->set_record_rendering_stats(
      debug_state_.RecordRenderingStats());

  SetNeedsCommit();
  proxy_->SetDebugState(debug_state);
}

bool LayerTreeHost::UseGpuRasterization() const {
  if (settings_.gpu_rasterization_forced) {
    return true;
  } else if (settings_.gpu_rasterization_enabled) {
    return has_gpu_rasterization_trigger_ &&
           content_is_suitable_for_gpu_rasterization_;
  } else {
    return false;
  }
}

GpuRasterizationStatus LayerTreeHost::GetGpuRasterizationStatus() const {
  if (settings_.gpu_rasterization_forced) {
    return GpuRasterizationStatus::ON_FORCED;
  } else if (settings_.gpu_rasterization_enabled) {
    if (!has_gpu_rasterization_trigger_) {
      return GpuRasterizationStatus::OFF_VIEWPORT;
    } else if (!content_is_suitable_for_gpu_rasterization_) {
      return GpuRasterizationStatus::OFF_CONTENT;
    } else {
      return GpuRasterizationStatus::ON;
    }
  }
  return GpuRasterizationStatus::OFF_DEVICE;
}

void LayerTreeHost::SetHasGpuRasterizationTrigger(bool has_trigger) {
  if (has_trigger == has_gpu_rasterization_trigger_)
    return;

  has_gpu_rasterization_trigger_ = has_trigger;
  TRACE_EVENT_INSTANT1("cc",
                       "LayerTreeHost::SetHasGpuRasterizationTrigger",
                       TRACE_EVENT_SCOPE_THREAD,
                       "has_trigger",
                       has_gpu_rasterization_trigger_);
}

void LayerTreeHost::SetViewportSize(const gfx::Size& device_viewport_size) {
  if (device_viewport_size == device_viewport_size_)
    return;

  device_viewport_size_ = device_viewport_size;

  SetNeedsCommit();
}

void LayerTreeHost::SetTopControlsShrinkBlinkSize(bool shrink) {
  if (top_controls_shrink_blink_size_ == shrink)
    return;

  top_controls_shrink_blink_size_ = shrink;
  SetNeedsCommit();
}

void LayerTreeHost::SetTopControlsHeight(float height) {
  if (top_controls_height_ == height)
    return;

  top_controls_height_ = height;
  SetNeedsCommit();
}

void LayerTreeHost::SetTopControlsContentOffset(float offset) {
  if (top_controls_content_offset_ == offset)
    return;

  top_controls_content_offset_ = offset;
  SetNeedsCommit();
}

void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(float page_scale_delta) {
  DCHECK(CommitRequested());
  page_scale_factor_ *= page_scale_delta;
}

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_)
    return;

  page_scale_factor_ = page_scale_factor;
  min_page_scale_factor_ = min_page_scale_factor;
  max_page_scale_factor_ = max_page_scale_factor;
  SetNeedsCommit();
}

void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) {
  DCHECK(bitmap.width() && bitmap.height());
  DCHECK_EQ(bitmap.bytesPerPixel(), 4);

  SkBitmap bitmap_copy;
  if (bitmap.isImmutable()) {
    bitmap_copy = bitmap;
  } else {
    bitmap.copyTo(&bitmap_copy);
    bitmap_copy.setImmutable();
  }

  UIResourceBitmap overhang_bitmap(bitmap_copy);
  overhang_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
  overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_bitmap);
}

void LayerTreeHost::SetVisible(bool visible) {
  if (visible_ == visible)
    return;
  visible_ = visible;
  if (!visible)
    ReduceMemoryUsage();
  proxy_->SetVisible(visible);
}

void LayerTreeHost::SetThrottleFrameProduction(bool throttle) {
  proxy_->SetThrottleFrameProduction(throttle);
}

void LayerTreeHost::StartPageScaleAnimation(const gfx::Vector2d& target_offset,
                                            bool use_anchor,
                                            float scale,
                                            base::TimeDelta duration) {
  pending_page_scale_animation_.reset(
      new PendingPageScaleAnimation(
          target_offset,
          use_anchor,
          scale,
          duration));

  SetNeedsCommit();
}

void LayerTreeHost::NotifyInputThrottledUntilCommit() {
  proxy_->NotifyInputThrottledUntilCommit();
}

void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
  DCHECK(!proxy_->HasImplThread());
  // This function is only valid when not using the scheduler.
  DCHECK(!settings_.single_thread_proxy_scheduler);
  SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get());

  SetLayerTreeHostClientReady();
  proxy->CompositeImmediately(frame_begin_time);
}

bool LayerTreeHost::UpdateLayers(ResourceUpdateQueue* queue) {
  DCHECK(!output_surface_lost_);

  if (!root_layer())
    return false;

  DCHECK(!root_layer()->parent());

  bool result = UpdateLayers(root_layer(), queue);

  micro_benchmark_controller_.DidUpdateLayers();

  return result || next_commit_forces_redraw_;
}

static Layer* FindFirstScrollableLayer(Layer* layer) {
  if (!layer)
    return NULL;

  if (layer->scrollable())
    return layer;

  for (size_t i = 0; i < layer->children().size(); ++i) {
    Layer* found = FindFirstScrollableLayer(layer->children()[i].get());
    if (found)
      return found;
  }

  return NULL;
}

void LayerTreeHost::RecordGpuRasterizationHistogram() {
  // Gpu rasterization is only supported when impl-side painting is enabled.
  if (gpu_rasterization_histogram_recorded_ || !settings_.impl_side_painting)
    return;

  // Record how widely gpu rasterization is enabled.
  // This number takes device/gpu whitelisting/backlisting into account.
  // Note that we do not consider the forced gpu rasterization mode, which is
  // mostly used for debugging purposes.
  UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationEnabled",
                        settings_.gpu_rasterization_enabled);
  if (settings_.gpu_rasterization_enabled) {
    UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationTriggered",
                          has_gpu_rasterization_trigger_);
    UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationSuitableContent",
                          content_is_suitable_for_gpu_rasterization_);
    // Record how many pages actually get gpu rasterization when enabled.
    UMA_HISTOGRAM_BOOLEAN("Renderer4.GpuRasterizationUsed",
                          (has_gpu_rasterization_trigger_ &&
                           content_is_suitable_for_gpu_rasterization_));
  }

  gpu_rasterization_histogram_recorded_ = true;
}

void LayerTreeHost::CalculateLCDTextMetricsCallback(Layer* layer) {
  if (!layer->SupportsLCDText())
    return;

  lcd_text_metrics_.total_num_cc_layers++;
  if (layer->draw_properties().can_use_lcd_text) {
    lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text++;
    if (layer->contents_opaque())
      lcd_text_metrics_.total_num_cc_layers_will_use_lcd_text++;
  }
}

bool LayerTreeHost::UsingSharedMemoryResources() {
  return GetRendererCapabilities().using_shared_memory_resources;
}

bool LayerTreeHost::UpdateLayers(Layer* root_layer,
                                 ResourceUpdateQueue* queue) {
  TRACE_EVENT1("cc", "LayerTreeHost::UpdateLayers",
               "source_frame_number", source_frame_number());

  RenderSurfaceLayerList update_list;
  {
    UpdateHudLayer();

    Layer* root_scroll = FindFirstScrollableLayer(root_layer);
    Layer* page_scale_layer = page_scale_layer_.get();
    if (!page_scale_layer && root_scroll)
      page_scale_layer = root_scroll->parent();

    if (hud_layer_.get()) {
      hud_layer_->PrepareForCalculateDrawProperties(
          device_viewport_size(), device_scale_factor_);
    }

    TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
    bool can_render_to_separate_surface = true;
    // TODO(vmpstr): Passing 0 as the current render surface layer list id means
    // that we won't be able to detect if a layer is part of |update_list|.
    // Change this if this information is required.
    int render_surface_layer_list_id = 0;
    LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
        root_layer, device_viewport_size(), gfx::Transform(),
        device_scale_factor_, page_scale_factor_, page_scale_layer,
        elastic_overscroll_, overscroll_elasticity_layer_.get(),
        GetRendererCapabilities().max_texture_size, settings_.can_use_lcd_text,
        settings_.layers_always_allowed_lcd_text,
        can_render_to_separate_surface,
        settings_.layer_transforms_should_scale_layer_contents,
        settings_.verify_property_trees, &update_list,
        render_surface_layer_list_id);
    LayerTreeHostCommon::CalculateDrawProperties(&inputs);

    if (total_frames_used_for_lcd_text_metrics_ <=
        kTotalFramesToUseForLCDTextMetrics) {
      LayerTreeHostCommon::CallFunctionForSubtree(
          root_layer,
          base::Bind(&LayerTreeHost::CalculateLCDTextMetricsCallback,
                     base::Unretained(this)));
      total_frames_used_for_lcd_text_metrics_++;
    }

    if (total_frames_used_for_lcd_text_metrics_ ==
        kTotalFramesToUseForLCDTextMetrics) {
      total_frames_used_for_lcd_text_metrics_++;

      UMA_HISTOGRAM_PERCENTAGE(
          "Renderer4.LCDText.PercentageOfCandidateLayers",
          lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text * 100.0 /
          lcd_text_metrics_.total_num_cc_layers);
      UMA_HISTOGRAM_PERCENTAGE(
          "Renderer4.LCDText.PercentageOfAALayers",
          lcd_text_metrics_.total_num_cc_layers_will_use_lcd_text * 100.0 /
          lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text);
    }
  }

  // Reset partial texture update requests.
  partial_texture_update_requests_ = 0;

  bool did_paint_content = false;
  bool need_more_updates = false;
  PaintLayerContents(
      update_list, queue, &did_paint_content, &need_more_updates);
  if (need_more_updates) {
    TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::posting prepaint task");
    prepaint_callback_.Reset(base::Bind(&LayerTreeHost::TriggerPrepaint,
                                        base::Unretained(this)));
    static base::TimeDelta prepaint_delay =
        base::TimeDelta::FromMilliseconds(100);
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, prepaint_callback_.callback(), prepaint_delay);
  }

  return did_paint_content;
}

void LayerTreeHost::TriggerPrepaint() {
  prepaint_callback_.Cancel();
  TRACE_EVENT0("cc", "LayerTreeHost::TriggerPrepaint");
  SetNeedsCommit();
}

static void LayerTreeHostReduceMemoryCallback(Layer* layer) {
  layer->ReduceMemoryUsage();
}

void LayerTreeHost::ReduceMemoryUsage() {
  if (!root_layer())
    return;

  LayerTreeHostCommon::CallFunctionForSubtree(
      root_layer(),
      base::Bind(&LayerTreeHostReduceMemoryCallback));
}

void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes) {
  DCHECK(surface_memory_placeholder_);

  // Surfaces have a place holder for their memory since they are managed
  // independantly but should still be tracked and reduce other memory usage.
  surface_memory_placeholder_->SetTextureManager(
      contents_texture_manager_.get());
  surface_memory_placeholder_->set_request_priority(
      PriorityCalculator::RenderSurfacePriority());
  surface_memory_placeholder_->SetToSelfManagedMemoryPlaceholder(
      surface_memory_bytes);
}

void LayerTreeHost::SetPrioritiesForLayers(
    const RenderSurfaceLayerList& update_list) {
  PriorityCalculator calculator;
  typedef LayerIterator<Layer> LayerIteratorType;
  LayerIteratorType end = LayerIteratorType::End(&update_list);
  for (LayerIteratorType it = LayerIteratorType::Begin(&update_list);
       it != end;
       ++it) {
    if (it.represents_itself()) {
      it->SetTexturePriorities(calculator);
    } else if (it.represents_target_render_surface()) {
      if (it->mask_layer())
        it->mask_layer()->SetTexturePriorities(calculator);
      if (it->replica_layer() && it->replica_layer()->mask_layer())
        it->replica_layer()->mask_layer()->SetTexturePriorities(calculator);
    }
  }
}

void LayerTreeHost::PrioritizeTextures(
    const RenderSurfaceLayerList& render_surface_layer_list) {
  if (!contents_texture_manager_)
    return;

  contents_texture_manager_->ClearPriorities();

  size_t memory_for_render_surfaces_metric =
      CalculateMemoryForRenderSurfaces(render_surface_layer_list);

  SetPrioritiesForLayers(render_surface_layer_list);
  SetPrioritiesForSurfaces(memory_for_render_surfaces_metric);

  contents_texture_manager_->PrioritizeTextures();
}

size_t LayerTreeHost::CalculateMemoryForRenderSurfaces(
    const RenderSurfaceLayerList& update_list) {
  size_t readback_bytes = 0;
  size_t contents_texture_bytes = 0;

  // Start iteration at 1 to skip the root surface as it does not have a texture
  // cost.
  for (size_t i = 1; i < update_list.size(); ++i) {
    Layer* render_surface_layer = update_list.at(i);
    RenderSurface* render_surface = render_surface_layer->render_surface();

    size_t bytes =
        Resource::MemorySizeBytes(render_surface->content_rect().size(),
                                  RGBA_8888);
    contents_texture_bytes += bytes;

    if (render_surface_layer->background_filters().IsEmpty() &&
        render_surface_layer->uses_default_blend_mode())
      continue;

    if (!readback_bytes) {
      readback_bytes = Resource::MemorySizeBytes(device_viewport_size_,
                                                 RGBA_8888);
    }
  }
  return readback_bytes + contents_texture_bytes;
}

void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer,
                                               ResourceUpdateQueue* queue,
                                               bool* did_paint_content,
                                               bool* need_more_updates) {
  // Note: Masks and replicas only exist for layers that own render surfaces. If
  // we reach this point in code, we already know that at least something will
  // be drawn into this render surface, so the mask and replica should be
  // painted.

  Layer* mask_layer = render_surface_layer->mask_layer();
  if (mask_layer) {
    *did_paint_content |= mask_layer->Update(queue, NULL);
    *need_more_updates |= mask_layer->NeedMoreUpdates();
  }

  Layer* replica_mask_layer =
      render_surface_layer->replica_layer() ?
      render_surface_layer->replica_layer()->mask_layer() : NULL;
  if (replica_mask_layer) {
    *did_paint_content |= replica_mask_layer->Update(queue, NULL);
    *need_more_updates |= replica_mask_layer->NeedMoreUpdates();
  }
}

void LayerTreeHost::PaintLayerContents(
    const RenderSurfaceLayerList& render_surface_layer_list,
    ResourceUpdateQueue* queue,
    bool* did_paint_content,
    bool* need_more_updates) {
  OcclusionTracker<Layer> occlusion_tracker(
      root_layer_->render_surface()->content_rect());
  occlusion_tracker.set_minimum_tracking_size(
      settings_.minimum_occlusion_tracking_size);

  PrioritizeTextures(render_surface_layer_list);

  in_paint_layer_contents_ = true;

  // Iterates front-to-back to allow for testing occlusion and performing
  // culling during the tree walk.
  typedef LayerIterator<Layer> LayerIteratorType;
  LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
  for (LayerIteratorType it =
           LayerIteratorType::Begin(&render_surface_layer_list);
       it != end;
       ++it) {
    occlusion_tracker.EnterLayer(it);

    if (it.represents_target_render_surface()) {
      PaintMasksForRenderSurface(
          *it, queue, did_paint_content, need_more_updates);
    } else if (it.represents_itself()) {
      DCHECK(!it->paint_properties().bounds.IsEmpty());
      *did_paint_content |= it->Update(queue, &occlusion_tracker);
      *need_more_updates |= it->NeedMoreUpdates();
      // Note the '&&' with previous is-suitable state.
      // This means that once the layer-tree becomes unsuitable for gpu
      // rasterization due to some content, it will continue to be unsuitable
      // even if that content is replaced by gpu-friendly content.
      // This is to avoid switching back-and-forth between gpu and sw
      // rasterization which may be both bad for performance and visually
      // jarring.
      content_is_suitable_for_gpu_rasterization_ &=
          it->IsSuitableForGpuRasterization();
    }

    occlusion_tracker.LeaveLayer(it);
  }

  in_paint_layer_contents_ = false;
}

void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) {
  ScopedPtrVector<SwapPromise>::iterator it = info->swap_promises.begin();
  for (; it != info->swap_promises.end(); ++it) {
    scoped_ptr<SwapPromise> swap_promise(info->swap_promises.take(it));
    TRACE_EVENT_FLOW_STEP0("input",
                           "LatencyInfo.Flow",
                           TRACE_ID_DONT_MANGLE(swap_promise->TraceId()),
                           "Main thread scroll update");
    QueueSwapPromise(swap_promise.Pass());
  }

  gfx::Vector2d inner_viewport_scroll_delta;
  gfx::Vector2d outer_viewport_scroll_delta;

  if (root_layer_.get()) {
    for (size_t i = 0; i < info->scrolls.size(); ++i) {
      Layer* layer = LayerTreeHostCommon::FindLayerInSubtree(
          root_layer_.get(), info->scrolls[i].layer_id);
      if (!layer)
        continue;
      if (layer == outer_viewport_scroll_layer_.get()) {
        outer_viewport_scroll_delta += info->scrolls[i].scroll_delta;
      } else if (layer == inner_viewport_scroll_layer_.get()) {
        inner_viewport_scroll_delta += info->scrolls[i].scroll_delta;
      } else {
        layer->SetScrollOffsetFromImplSide(
            gfx::ScrollOffsetWithDelta(layer->scroll_offset(),
                                       info->scrolls[i].scroll_delta));
      }
    }
  }

  if (!inner_viewport_scroll_delta.IsZero() ||
      !outer_viewport_scroll_delta.IsZero() || info->page_scale_delta != 1.f ||
      !info->elastic_overscroll_delta.IsZero() || info->top_controls_delta) {
    // Preemptively apply the scroll offset and scale delta here before sending
    // it to the client.  If the client comes back and sets it to the same
    // value, then the layer can early out without needing a full commit.
    if (inner_viewport_scroll_layer_.get()) {
      inner_viewport_scroll_layer_->SetScrollOffsetFromImplSide(
          gfx::ScrollOffsetWithDelta(
              inner_viewport_scroll_layer_->scroll_offset(),
              inner_viewport_scroll_delta));
    }

    if (outer_viewport_scroll_layer_.get()) {
      outer_viewport_scroll_layer_->SetScrollOffsetFromImplSide(
          gfx::ScrollOffsetWithDelta(
              outer_viewport_scroll_layer_->scroll_offset(),
              outer_viewport_scroll_delta));
    }

    ApplyPageScaleDeltaFromImplSide(info->page_scale_delta);
    elastic_overscroll_ += info->elastic_overscroll_delta;
    if (!settings_.use_pinch_virtual_viewport) {
      client_->ApplyViewportDeltas(
          inner_viewport_scroll_delta + outer_viewport_scroll_delta,
          info->page_scale_delta,
          info->top_controls_delta);
    } else {
      // TODO(ccameron): pass the elastic overscroll here so that input events
      // may be translated appropriately.
      client_->ApplyViewportDeltas(
          inner_viewport_scroll_delta, outer_viewport_scroll_delta,
          info->elastic_overscroll_delta, info->page_scale_delta,
          info->top_controls_delta);
    }
  }
}

void LayerTreeHost::StartRateLimiter() {
  if (inside_begin_main_frame_)
    return;

  if (!rate_limit_timer_.IsRunning()) {
    rate_limit_timer_.Start(FROM_HERE,
                            base::TimeDelta(),
                            this,
                            &LayerTreeHost::RateLimit);
  }
}

void LayerTreeHost::StopRateLimiter() {
  rate_limit_timer_.Stop();
}

void LayerTreeHost::RateLimit() {
  // Force a no-op command on the compositor context, so that any ratelimiting
  // commands will wait for the compositing context, and therefore for the
  // SwapBuffers.
  proxy_->ForceSerializeOnSwapBuffers();
  client_->RateLimitSharedMainThreadContext();
}

bool LayerTreeHost::AlwaysUsePartialTextureUpdates() {
  if (!proxy_->GetRendererCapabilities().allow_partial_texture_updates)
    return false;
  return !proxy_->HasImplThread();
}

size_t LayerTreeHost::MaxPartialTextureUpdates() const {
  size_t max_partial_texture_updates = 0;
  if (proxy_->GetRendererCapabilities().allow_partial_texture_updates &&
      !settings_.impl_side_painting) {
    max_partial_texture_updates =
        std::min(settings_.max_partial_texture_updates,
                 proxy_->MaxPartialTextureUpdates());
  }
  return max_partial_texture_updates;
}

bool LayerTreeHost::RequestPartialTextureUpdate() {
  if (partial_texture_update_requests_ >= MaxPartialTextureUpdates())
    return false;

  partial_texture_update_requests_++;
  return true;
}

void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) {
  if (device_scale_factor == device_scale_factor_)
    return;
  device_scale_factor_ = device_scale_factor;

  SetNeedsCommit();
}

void LayerTreeHost::UpdateTopControlsState(TopControlsState constraints,
                                           TopControlsState current,
                                           bool animate) {
  if (!settings_.calculate_top_controls_position)
    return;

  // Top controls are only used in threaded mode.
  proxy_->ImplThreadTaskRunner()->PostTask(
      FROM_HERE,
      base::Bind(&TopControlsManager::UpdateTopControlsState,
                 top_controls_manager_weak_ptr_,
                 constraints,
                 current,
                 animate));
}

void LayerTreeHost::AsValueInto(base::debug::TracedValue* state) const {
  state->BeginDictionary("proxy");
  proxy_->AsValueInto(state);
  state->EndDictionary();
}

void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) {
  if (!settings_.accelerated_animation_enabled ||
      animation_registrar_->active_animation_controllers().empty())
    return;

  TRACE_EVENT0("cc", "LayerTreeHost::AnimateLayers");

  AnimationRegistrar::AnimationControllerMap copy =
      animation_registrar_->active_animation_controllers();
  for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
       iter != copy.end();
       ++iter) {
    (*iter).second->Animate(monotonic_time);
    bool start_ready_animations = true;
    (*iter).second->UpdateState(start_ready_animations, NULL);
  }
}

UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) {
  DCHECK(client);

  UIResourceId next_id = next_ui_resource_id_++;
  DCHECK(ui_resource_client_map_.find(next_id) ==
         ui_resource_client_map_.end());

  bool resource_lost = false;
  UIResourceRequest request(UIResourceRequest::UIResourceCreate,
                            next_id,
                            client->GetBitmap(next_id, resource_lost));
  ui_resource_request_queue_.push_back(request);

  UIResourceClientData data;
  data.client = client;
  data.size = request.GetBitmap().GetSize();

  ui_resource_client_map_[request.GetId()] = data;
  return request.GetId();
}

// Deletes a UI resource.  May safely be called more than once.
void LayerTreeHost::DeleteUIResource(UIResourceId uid) {
  UIResourceClientMap::iterator iter = ui_resource_client_map_.find(uid);
  if (iter == ui_resource_client_map_.end())
    return;

  UIResourceRequest request(UIResourceRequest::UIResourceDelete, uid);
  ui_resource_request_queue_.push_back(request);
  ui_resource_client_map_.erase(iter);
}

void LayerTreeHost::RecreateUIResources() {
  for (UIResourceClientMap::iterator iter = ui_resource_client_map_.begin();
       iter != ui_resource_client_map_.end();
       ++iter) {
    UIResourceId uid = iter->first;
    const UIResourceClientData& data = iter->second;
    bool resource_lost = true;
    UIResourceRequest request(UIResourceRequest::UIResourceCreate,
                              uid,
                              data.client->GetBitmap(uid, resource_lost));
    ui_resource_request_queue_.push_back(request);
  }
}

// Returns the size of a resource given its id.
gfx::Size LayerTreeHost::GetUIResourceSize(UIResourceId uid) const {
  UIResourceClientMap::const_iterator 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;
}

void LayerTreeHost::RegisterViewportLayers(
    scoped_refptr<Layer> overscroll_elasticity_layer,
    scoped_refptr<Layer> page_scale_layer,
    scoped_refptr<Layer> inner_viewport_scroll_layer,
    scoped_refptr<Layer> outer_viewport_scroll_layer) {
  overscroll_elasticity_layer_ = overscroll_elasticity_layer;
  page_scale_layer_ = page_scale_layer;
  inner_viewport_scroll_layer_ = inner_viewport_scroll_layer;
  outer_viewport_scroll_layer_ = outer_viewport_scroll_layer;
}

void LayerTreeHost::RegisterSelection(const LayerSelectionBound& start,
                                      const LayerSelectionBound& end) {
  if (selection_start_ == start && selection_end_ == end)
    return;

  selection_start_ = start;
  selection_end_ = end;
  SetNeedsCommit();
}

int LayerTreeHost::ScheduleMicroBenchmark(
    const std::string& benchmark_name,
    scoped_ptr<base::Value> value,
    const MicroBenchmark::DoneCallback& callback) {
  return micro_benchmark_controller_.ScheduleRun(
      benchmark_name, value.Pass(), callback);
}

bool LayerTreeHost::SendMessageToMicroBenchmark(int id,
                                                scoped_ptr<base::Value> value) {
  return micro_benchmark_controller_.SendMessage(id, value.Pass());
}

void LayerTreeHost::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
  swap_promise_monitor_.insert(monitor);
}

void LayerTreeHost::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) {
  swap_promise_monitor_.erase(monitor);
}

void LayerTreeHost::NotifySwapPromiseMonitorsOfSetNeedsCommit() {
  std::set<SwapPromiseMonitor*>::iterator it = swap_promise_monitor_.begin();
  for (; it != swap_promise_monitor_.end(); it++)
    (*it)->OnSetNeedsCommitOnMain();
}

void LayerTreeHost::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
  DCHECK(swap_promise);
  swap_promise_list_.push_back(swap_promise.Pass());
}

void LayerTreeHost::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
  for (size_t i = 0; i < swap_promise_list_.size(); i++)
    swap_promise_list_[i]->DidNotSwap(reason);
  swap_promise_list_.clear();
}

void LayerTreeHost::set_surface_id_namespace(uint32_t id_namespace) {
  surface_id_namespace_ = id_namespace;
}

SurfaceSequence LayerTreeHost::CreateSurfaceSequence() {
  return SurfaceSequence(surface_id_namespace_, next_surface_sequence_++);
}

void LayerTreeHost::SetChildrenNeedBeginFrames(
    bool children_need_begin_frames) const {
  proxy_->SetChildrenNeedBeginFrames(children_need_begin_frames);
}

void LayerTreeHost::SendBeginFramesToChildren(
    const BeginFrameArgs& args) const {
  client_->SendBeginFramesToChildren(args);
}

}  // namespace cc
