// 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 <stddef.h>
#include <stdint.h>

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

#include "base/atomic_sequence_num.h"
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/metrics/histogram.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "cc/animation/animation_events.h"
#include "cc/animation/animation_host.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/frame_viewer_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/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/layer_proto_converter.h"
#include "cc/layers/layer_settings.h"
#include "cc/layers/painted_scrollbar_layer.h"
#include "cc/proto/gfx_conversions.h"
#include "cc/proto/layer_tree_host.pb.h"
#include "cc/resources/ui_resource_request.h"
#include "cc/scheduler/begin_frame_source.h"
#include "cc/trees/draw_property_utils.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/proxy_main.h"
#include "cc/trees/remote_channel_impl.h"
#include "cc/trees/single_thread_proxy.h"
#include "cc/trees/tree_synchronizer.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d_conversions.h"

namespace {
static base::StaticAtomicSequenceNumber s_layer_tree_host_sequence_number;
}

namespace cc {
namespace {

Layer* UpdateAndGetLayer(Layer* current_layer,
                         int layer_id,
                         const std::unordered_map<int, Layer*>& layer_id_map) {
  if (layer_id == Layer::INVALID_ID) {
    if (current_layer)
      current_layer->SetLayerTreeHost(nullptr);

    return nullptr;
  }

  auto layer_it = layer_id_map.find(layer_id);
  DCHECK(layer_it != layer_id_map.end());
  if (current_layer && current_layer != layer_it->second)
    current_layer->SetLayerTreeHost(nullptr);

  return layer_it->second;
}

}  // namespace

LayerTreeHost::InitParams::InitParams() {
}

LayerTreeHost::InitParams::~InitParams() {
}

scoped_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
    InitParams* params) {
  DCHECK(params->main_task_runner.get());
  DCHECK(impl_task_runner.get());
  DCHECK(params->settings);
  scoped_ptr<LayerTreeHost> layer_tree_host(
      new LayerTreeHost(params, CompositorMode::THREADED));
  layer_tree_host->InitializeThreaded(
      params->main_task_runner, impl_task_runner,
      std::move(params->external_begin_frame_source));
  return layer_tree_host;
}

scoped_ptr<LayerTreeHost> LayerTreeHost::CreateSingleThreaded(
    LayerTreeHostSingleThreadClient* single_thread_client,
    InitParams* params) {
  DCHECK(params->settings);
  scoped_ptr<LayerTreeHost> layer_tree_host(
      new LayerTreeHost(params, CompositorMode::SINGLE_THREADED));
  layer_tree_host->InitializeSingleThreaded(
      single_thread_client, params->main_task_runner,
      std::move(params->external_begin_frame_source));
  return layer_tree_host;
}

scoped_ptr<LayerTreeHost> LayerTreeHost::CreateRemoteServer(
    RemoteProtoChannel* remote_proto_channel,
    InitParams* params) {
  DCHECK(params->main_task_runner.get());
  DCHECK(params->settings);
  DCHECK(remote_proto_channel);

  // Using an external begin frame source is not supported on the server in
  // remote mode.
  DCHECK(!params->settings->use_external_begin_frame_source);
  DCHECK(!params->external_begin_frame_source);

  scoped_ptr<LayerTreeHost> layer_tree_host(
      new LayerTreeHost(params, CompositorMode::REMOTE));
  layer_tree_host->InitializeRemoteServer(remote_proto_channel,
                                          params->main_task_runner);
  return layer_tree_host;
}

scoped_ptr<LayerTreeHost> LayerTreeHost::CreateRemoteClient(
    RemoteProtoChannel* remote_proto_channel,
    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
    InitParams* params) {
  DCHECK(params->main_task_runner.get());
  DCHECK(params->settings);
  DCHECK(remote_proto_channel);

  // Using an external begin frame source is not supported in remote mode.
  // TODO(khushalsagar): Add support for providing an external begin frame
  // source on the client LayerTreeHost. crbug/576962
  DCHECK(!params->settings->use_external_begin_frame_source);
  DCHECK(!params->external_begin_frame_source);

  scoped_ptr<LayerTreeHost> layer_tree_host(
      new LayerTreeHost(params, CompositorMode::REMOTE));
  layer_tree_host->InitializeRemoteClient(
      remote_proto_channel, params->main_task_runner, impl_task_runner);
  return layer_tree_host;
}

LayerTreeHost::LayerTreeHost(InitParams* params, CompositorMode mode)
    : micro_benchmark_controller_(this),
      next_ui_resource_id_(1),
      compositor_mode_(mode),
      needs_full_tree_sync_(true),
      needs_meta_info_recomputation_(true),
      client_(params->client),
      source_frame_number_(0),
      meta_information_sequence_number_(1),
      rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
      output_surface_lost_(true),
      settings_(*params->settings),
      debug_state_(settings_.initial_debug_state),
      top_controls_shrink_blink_size_(false),
      top_controls_height_(0.f),
      top_controls_shown_ratio_(0.f),
      device_scale_factor_(1.f),
      painted_device_scale_factor_(1.f),
      visible_(false),
      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),
      have_wheel_event_handlers_(false),
      did_complete_scale_animation_(false),
      in_paint_layer_contents_(false),
      id_(s_layer_tree_host_sequence_number.GetNext() + 1),
      next_commit_forces_redraw_(false),
      shared_bitmap_manager_(params->shared_bitmap_manager),
      gpu_memory_buffer_manager_(params->gpu_memory_buffer_manager),
      task_graph_runner_(params->task_graph_runner),
      surface_id_namespace_(0u),
      next_surface_sequence_(1u) {
  DCHECK(task_graph_runner_);

  if (settings_.accelerated_animation_enabled) {
    if (settings_.use_compositor_animation_timelines) {
      animation_host_ = AnimationHost::Create(ThreadInstance::MAIN);
      animation_host_->SetMutatorHostClient(this);
    } else {
      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) {
  task_runner_provider_ =
      TaskRunnerProvider::Create(main_task_runner, impl_task_runner);
  scoped_ptr<ProxyMain> proxy_main =
      ProxyMain::CreateThreaded(this, task_runner_provider_.get());
  InitializeProxy(std::move(proxy_main),
                  std::move(external_begin_frame_source));
}

void LayerTreeHost::InitializeSingleThreaded(
    LayerTreeHostSingleThreadClient* single_thread_client,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
  task_runner_provider_ = TaskRunnerProvider::Create(main_task_runner, nullptr);
  InitializeProxy(SingleThreadProxy::Create(this, single_thread_client,
                                            task_runner_provider_.get()),
                  std::move(external_begin_frame_source));
}

void LayerTreeHost::InitializeRemoteServer(
    RemoteProtoChannel* remote_proto_channel,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
  task_runner_provider_ = TaskRunnerProvider::Create(main_task_runner, nullptr);
  InitializeProxy(ProxyMain::CreateRemote(remote_proto_channel, this,
                                          task_runner_provider_.get()),
                  nullptr);
}

void LayerTreeHost::InitializeRemoteClient(
    RemoteProtoChannel* remote_proto_channel,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
  task_runner_provider_ =
      TaskRunnerProvider::Create(main_task_runner, impl_task_runner);

  // For the remote mode, the RemoteChannelImpl implements the Proxy, which is
  // owned by the LayerTreeHost. The RemoteChannelImpl pipes requests which need
  // to handled locally, for instance the Output Surface creation to the
  // LayerTreeHost on the client, while the other requests are sent to the
  // RemoteChannelMain on the server which directs them to ProxyMain and the
  // remote server LayerTreeHost.
  InitializeProxy(RemoteChannelImpl::Create(this, remote_proto_channel,
                                            task_runner_provider_.get()),
                  nullptr);
}

void LayerTreeHost::InitializeForTesting(
    scoped_ptr<TaskRunnerProvider> task_runner_provider,
    scoped_ptr<Proxy> proxy_for_testing,
    scoped_ptr<BeginFrameSource> external_begin_frame_source) {
  task_runner_provider_ = std::move(task_runner_provider);
  InitializeProxy(std::move(proxy_for_testing),
                  std::move(external_begin_frame_source));
}

void LayerTreeHost::SetTaskRunnerProviderForTesting(
    scoped_ptr<TaskRunnerProvider> task_runner_provider) {
  DCHECK(!task_runner_provider_);
  task_runner_provider_ = std::move(task_runner_provider);
}

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

  proxy_ = std::move(proxy);
  proxy_->Start(std::move(external_begin_frame_source));
  if (settings_.accelerated_animation_enabled) {
    if (animation_host_)
      animation_host_->SetSupportsScrollAnimations(
          proxy_->SupportsImplScrolling());
    else
      animation_registrar_->set_supports_scroll_animations(
          proxy_->SupportsImplScrolling());
  }
}

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

  if (animation_host_)
    animation_host_->SetMutatorHostClient(nullptr);

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

  DCHECK(swap_promise_monitor_.empty());

  BreakSwapPromises(SwapPromise::COMMIT_FAILS);

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

    // Proxy must be destroyed before the Task Runner Provider.
    proxy_ = nullptr;
  }

  // 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::WillBeginMainFrame() {
  devtools_instrumentation::WillBeginMainThreadFrame(id(),
                                                     source_frame_number());
  client_->WillBeginMainFrame();
}

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

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

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

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

void LayerTreeHost::RequestMainFrameUpdate() {
  client_->UpdateLayerTreeHost();
}

// 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(!IsRemoteServer());
  DCHECK(task_runner_provider_->IsImplThread());

  bool is_new_trace;
  TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
  if (is_new_trace &&
      frame_viewer_instrumentation::IsTracingLayerTreeSnapshots() &&
      root_layer()) {
    LayerTreeHostCommon::CallFunctionForSubtree(
        root_layer(), [](Layer* layer) { layer->DidBeginTracing(); });
  }

  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_);
  sync_tree->set_have_wheel_event_handlers(have_wheel_event_handlers_);

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

  // Setting property trees must happen before pushing the page scale.
  sync_tree->SetPropertyTrees(property_trees_);

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

  sync_tree->set_top_controls_shrink_blink_size(
      top_controls_shrink_blink_size_);
  sync_tree->set_top_controls_height(top_controls_height_);
  sync_tree->PushTopControlsFromMainThread(top_controls_shown_ratio_);

  host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_);
  host_impl->SetContentIsSuitableForGpuRasterization(
      content_is_suitable_for_gpu_rasterization_);
  RecordGpuRasterizationHistogram();

  host_impl->SetViewportSize(device_viewport_size_);
  // TODO(senorblanco): Move this up so that it happens before GPU rasterization
  // properties are set, since those trigger an update of GPU rasterization
  // status, which depends on the device scale factor. (crbug.com/535700)
  sync_tree->SetDeviceScaleFactor(device_scale_factor_);
  sync_tree->set_painted_device_scale_factor(painted_device_scale_factor_);
  host_impl->SetDebugState(debug_state_);
  if (pending_page_scale_animation_) {
    sync_tree->SetPendingPageScaleAnimation(
        std::move(pending_page_scale_animation_));
  }

  if (!ui_resource_request_queue_.empty()) {
    sync_tree->set_ui_resource_request_queue(ui_resource_request_queue_);
    ui_resource_request_queue_.clear();
  }

  DCHECK(!sync_tree->ViewportSizeInvalid());

  sync_tree->set_has_ever_been_drawn(false);

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

    if (animation_host_) {
      TRACE_EVENT0("cc", "LayerTreeHost::AnimationHost::PushProperties");
      DCHECK(host_impl->animation_host());
      animation_host_->PushPropertiesTo(host_impl->animation_host());
    }
  }

  // This must happen after synchronizing property trees and after push
  // properties, which updates property tree indices.
  sync_tree->UpdatePropertyTreeScrollingAndAnimationFromMainThread();

  micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl);
}

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

void LayerTreeHost::UpdateHudLayer() {
  if (debug_state_.ShowHudInfo()) {
    if (!hud_layer_.get()) {
      LayerSettings hud_layer_settings;
      hud_layer_settings.use_compositor_animation_timelines =
          settings_.use_compositor_animation_timelines;
      hud_layer_ = HeadsUpDisplayLayer::Create(hud_layer_settings);
    }

    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();
  if (did_complete_scale_animation_) {
    client_->DidCompletePageScaleAnimation();
    did_complete_scale_animation_ = false;
  }
}

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

  DCHECK(!new_output_surface_);
  new_output_surface_ = std::move(surface);
  proxy_->SetOutputSurface(new_output_surface_.get());
}

scoped_ptr<OutputSurface> LayerTreeHost::ReleaseOutputSurface() {
  DCHECK(!visible_);
  DCHECK(!output_surface_lost_);

  DidLoseOutputSurface();
  proxy_->ReleaseOutputSurface();
  return std::move(current_output_surface_);
}

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

void LayerTreeHost::DidInitializeOutputSurface() {
  DCHECK(new_output_surface_);
  output_surface_lost_ = false;
  current_output_surface_ = std::move(new_output_surface_);
  client_->DidInitializeOutputSurface();
}

void LayerTreeHost::DidFailToInitializeOutputSurface() {
  DCHECK(output_surface_lost_);
  DCHECK(new_output_surface_);
  // Note: It is safe to drop all output surface references here as
  // LayerTreeHostImpl will not keep a pointer to either the old or
  // new output surface after failing to initialize the new one.
  current_output_surface_ = nullptr;
  new_output_surface_ = nullptr;
  client_->DidFailToInitializeOutputSurface();
}

scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl(
    LayerTreeHostImplClient* client) {
  DCHECK(!IsRemoteServer());
  DCHECK(task_runner_provider_->IsImplThread());
  scoped_ptr<LayerTreeHostImpl> host_impl = LayerTreeHostImpl::Create(
      settings_, client, task_runner_provider_.get(),
      rendering_stats_instrumentation_.get(), shared_bitmap_manager_,
      gpu_memory_buffer_manager_, task_graph_runner_, id_);
  host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_);
  host_impl->SetContentIsSuitableForGpuRasterization(
      content_is_suitable_for_gpu_rasterization_);
  shared_bitmap_manager_ = NULL;
  gpu_memory_buffer_manager_ = NULL;
  task_graph_runner_ = NULL;
  input_handler_weak_ptr_ = host_impl->AsWeakPtr();
  return host_impl;
}

void LayerTreeHost::DidLoseOutputSurface() {
  TRACE_EVENT0("cc", "LayerTreeHost::DidLoseOutputSurface");
  DCHECK(task_runner_provider_->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::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::SetPropertyTreesNeedRebuild() {
  property_trees_.needs_rebuild = true;
  SetNeedsUpdateLayers();
}

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

void LayerTreeHost::SetNeedsFullTreeSync() {
  needs_full_tree_sync_ = true;
  needs_meta_info_recomputation_ = true;

  property_trees_.needs_rebuild = true;
  SetNeedsCommit();
}

void LayerTreeHost::SetNeedsMetaInfoRecomputation(bool needs_recomputation) {
  needs_meta_info_recomputation_ = needs_recomputation;
}

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;
  proxy_->SetNeedsUpdateLayers();
}

void LayerTreeHost::SetAnimationEvents(scoped_ptr<AnimationEvents> events) {
  DCHECK(task_runner_provider_->IsMainThread());
  if (animation_host_)
    animation_host_->SetAnimationEvents(std::move(events));
  else
    animation_registrar_->SetAnimationEvents(std::move(events));
}

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();
}

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;

  SetPropertyTreesNeedRebuild();
  SetNeedsCommit();
}

void LayerTreeHost::SetTopControlsHeight(float height, bool shrink) {
  if (top_controls_height_ == height &&
      top_controls_shrink_blink_size_ == shrink)
    return;

  top_controls_height_ = height;
  top_controls_shrink_blink_size_ = shrink;
  SetNeedsCommit();
}

void LayerTreeHost::SetTopControlsShownRatio(float ratio) {
  if (top_controls_shown_ratio_ == ratio)
    return;

  top_controls_shown_ratio_ = ratio;
  SetNeedsCommit();
}

void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(float page_scale_delta) {
  DCHECK(CommitRequested());
  if (page_scale_delta == 1.f)
    return;
  page_scale_factor_ *= page_scale_delta;
  SetPropertyTreesNeedRebuild();
}

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;
  SetPropertyTreesNeedRebuild();
  SetNeedsCommit();
}

void LayerTreeHost::SetVisible(bool visible) {
  if (visible_ == visible)
    return;
  visible_ = visible;
  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::LayoutAndUpdateLayers() {
  DCHECK(IsSingleThreaded());
  // This function is only valid when not using the scheduler.
  DCHECK(!settings_.single_thread_proxy_scheduler);
  SingleThreadProxy* proxy = static_cast<SingleThreadProxy*>(proxy_.get());

  if (output_surface_lost()) {
    proxy->RequestNewOutputSurface();
    // RequestNewOutputSurface could have synchronously created an output
    // surface, so check again before returning.
    if (output_surface_lost())
      return;
  }

  RequestMainFrameUpdate();
  UpdateLayers();
}

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

  proxy->CompositeImmediately(frame_begin_time);
}

bool LayerTreeHost::UpdateLayers() {
  DCHECK(!output_surface_lost_);
  if (!root_layer())
    return false;
  DCHECK(!root_layer()->parent());
  bool result = DoUpdateLayers(root_layer());
  micro_benchmark_controller_.DidUpdateLayers();
  return result || next_commit_forces_redraw_;
}

void LayerTreeHost::DidCompletePageScaleAnimation() {
  did_complete_scale_animation_ = true;
}

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 for Renderer compositors.
  // Checking for IsSingleThreaded() to exclude Browser compositors.
  if (gpu_rasterization_histogram_recorded_ || IsSingleThreaded())
    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;
}

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

bool LayerTreeHost::DoUpdateLayers(Layer* root_layer) {
  TRACE_EVENT1("cc", "LayerTreeHost::DoUpdateLayers", "source_frame_number",
               source_frame_number());

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

  gfx::Transform identity_transform;
  LayerList update_layer_list;

  {
    TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::BuildPropertyTrees");
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.cdp-perf"),
                 "LayerTreeHostCommon::ComputeVisibleRectsWithPropertyTrees");
    LayerTreeHostCommon::PreCalculateMetaInformation(root_layer);
    bool can_render_to_separate_surface = true;
    BuildPropertyTreesAndComputeVisibleRects(
        root_layer, page_scale_layer, inner_viewport_scroll_layer_.get(),
        outer_viewport_scroll_layer_.get(), overscroll_elasticity_layer_.get(),
        elastic_overscroll_, page_scale_factor_, device_scale_factor_,
        gfx::Rect(device_viewport_size_), identity_transform,
        can_render_to_separate_surface, &property_trees_, &update_layer_list);
  }

  for (const auto& layer : update_layer_list)
    layer->SavePaintProperties();

  base::AutoReset<bool> painting(&in_paint_layer_contents_, true);
  bool did_paint_content = false;
  for (const auto& layer : update_layer_list) {
    did_paint_content |= layer->Update();
    content_is_suitable_for_gpu_rasterization_ &=
        layer->IsSuitableForGpuRasterization();
  }
  return did_paint_content;
}

void LayerTreeHost::ApplyScrollAndScale(ScrollAndScaleSet* info) {
  for (auto& swap_promise : info->swap_promises) {
    TRACE_EVENT_WITH_FLOW1("input,benchmark",
                           "LatencyInfo.Flow",
                           TRACE_ID_DONT_MANGLE(swap_promise->TraceId()),
                           TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                           "step", "Main thread scroll update");
    QueueSwapPromise(std::move(swap_promise));
  }

  gfx::Vector2dF inner_viewport_scroll_delta;
  gfx::Vector2dF 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));
      }
      SetNeedsUpdateLayers();
    }
  }

  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;
    // 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);
    SetNeedsUpdateLayers();
  }
}

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

  property_trees_.needs_rebuild = true;
  SetNeedsCommit();
}

void LayerTreeHost::SetPaintedDeviceScaleFactor(
    float painted_device_scale_factor) {
  if (painted_device_scale_factor == painted_device_scale_factor_)
    return;
  painted_device_scale_factor_ = painted_device_scale_factor;

  SetNeedsCommit();
}

void LayerTreeHost::UpdateTopControlsState(TopControlsState constraints,
                                           TopControlsState current,
                                           bool animate) {
  // Top controls are only used in threaded or remote mode.
  DCHECK(IsThreaded() || IsRemoteServer());
  proxy_->UpdateTopControlsState(constraints, current, animate);
}

void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) {
  if (!settings_.accelerated_animation_enabled)
    return;

  scoped_ptr<AnimationEvents> events;
  if (animation_host_) {
    events = animation_host_->CreateEvents();
    if (animation_host_->AnimateLayers(monotonic_time))
      animation_host_->UpdateAnimationState(true, events.get());
  } else {
    events = animation_registrar_->CreateEvents();
    if (animation_registrar_->AnimateLayers(monotonic_time))
      animation_registrar_->UpdateAnimationState(true, events.get());
  }

  if (!events->events_.empty())
    property_trees_.needs_rebuild = true;
}

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::UI_RESOURCE_CREATE, 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::UI_RESOURCE_DELETE, 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::UI_RESOURCE_CREATE, 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) {
  DCHECK(!inner_viewport_scroll_layer ||
         inner_viewport_scroll_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 LayerSelection& selection) {
  if (selection_ == selection)
    return;

  selection_ = selection;
  SetNeedsCommit();
}

void LayerTreeHost::SetHaveWheelEventHandlers(bool have_event_handlers) {
  if (have_wheel_event_handlers_ == have_event_handlers)
    return;

  have_wheel_event_handlers_ = have_event_handlers;
  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,
                                                 std::move(value), callback);
}

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

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(std::move(swap_promise));
}

void LayerTreeHost::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
  for (const auto& swap_promise : swap_promise_list_)
    swap_promise->DidNotSwap(reason);
  swap_promise_list_.clear();
}

void LayerTreeHost::OnCommitForSwapPromises() {
  for (const auto& swap_promise : swap_promise_list_)
    swap_promise->OnCommit();
}

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);
}

void LayerTreeHost::SetAuthoritativeVSyncInterval(
    const base::TimeDelta& interval) {
  proxy_->SetAuthoritativeVSyncInterval(interval);
}

void LayerTreeHost::RecordFrameTimingEvents(
    scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
    scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
  client_->RecordFrameTimingEvents(std::move(composite_events),
                                   std::move(main_frame_events));
}

Layer* LayerTreeHost::LayerById(int id) const {
  LayerIdMap::const_iterator iter = layer_id_map_.find(id);
  return iter != layer_id_map_.end() ? iter->second : NULL;
}

void LayerTreeHost::RegisterLayer(Layer* layer) {
  DCHECK(!LayerById(layer->id()));
  DCHECK(!in_paint_layer_contents_);
  layer_id_map_[layer->id()] = layer;
  if (animation_host_)
    animation_host_->RegisterLayer(layer->id(), LayerTreeType::ACTIVE);
}

void LayerTreeHost::UnregisterLayer(Layer* layer) {
  DCHECK(LayerById(layer->id()));
  DCHECK(!in_paint_layer_contents_);
  if (animation_host_)
    animation_host_->UnregisterLayer(layer->id(), LayerTreeType::ACTIVE);
  layer_id_map_.erase(layer->id());
}

bool LayerTreeHost::IsLayerInTree(int layer_id, LayerTreeType tree_type) const {
  return tree_type == LayerTreeType::ACTIVE && LayerById(layer_id);
}

void LayerTreeHost::SetMutatorsNeedCommit() {
  SetNeedsCommit();
}

void LayerTreeHost::SetMutatorsNeedRebuildPropertyTrees() {
  property_trees_.needs_rebuild = true;
}

void LayerTreeHost::SetLayerFilterMutated(int layer_id,
                                          LayerTreeType tree_type,
                                          const FilterOperations& filters) {
  LayerAnimationValueObserver* layer = LayerById(layer_id);
  DCHECK(layer);
  layer->OnFilterAnimated(filters);
}

void LayerTreeHost::SetLayerOpacityMutated(int layer_id,
                                           LayerTreeType tree_type,
                                           float opacity) {
  LayerAnimationValueObserver* layer = LayerById(layer_id);
  DCHECK(layer);
  layer->OnOpacityAnimated(opacity);
}

void LayerTreeHost::SetLayerTransformMutated(int layer_id,
                                             LayerTreeType tree_type,
                                             const gfx::Transform& transform) {
  LayerAnimationValueObserver* layer = LayerById(layer_id);
  DCHECK(layer);
  layer->OnTransformAnimated(transform);
}

void LayerTreeHost::SetLayerScrollOffsetMutated(
    int layer_id,
    LayerTreeType tree_type,
    const gfx::ScrollOffset& scroll_offset) {
  LayerAnimationValueObserver* layer = LayerById(layer_id);
  DCHECK(layer);
  layer->OnScrollOffsetAnimated(scroll_offset);
}

void LayerTreeHost::LayerTransformIsPotentiallyAnimatingChanged(
    int layer_id,
    LayerTreeType tree_type,
    bool is_animating) {
  LayerAnimationValueObserver* layer = LayerById(layer_id);
  DCHECK(layer);
  layer->OnTransformIsPotentiallyAnimatingChanged(is_animating);
}

gfx::ScrollOffset LayerTreeHost::GetScrollOffsetForAnimation(
    int layer_id) const {
  LayerAnimationValueProvider* layer = LayerById(layer_id);
  DCHECK(layer);
  return layer->ScrollOffsetForAnimation();
}

bool LayerTreeHost::ScrollOffsetAnimationWasInterrupted(
    const Layer* layer) const {
  return animation_host_
             ? animation_host_->ScrollOffsetAnimationWasInterrupted(layer->id())
             : false;
}

bool LayerTreeHost::IsAnimatingFilterProperty(const Layer* layer) const {
  return animation_host_
             ? animation_host_->IsAnimatingFilterProperty(layer->id(),
                                                          LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::IsAnimatingOpacityProperty(const Layer* layer) const {
  return animation_host_
             ? animation_host_->IsAnimatingOpacityProperty(
                   layer->id(), LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::IsAnimatingTransformProperty(const Layer* layer) const {
  return animation_host_
             ? animation_host_->IsAnimatingTransformProperty(
                   layer->id(), LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::HasPotentiallyRunningFilterAnimation(
    const Layer* layer) const {
  return animation_host_
             ? animation_host_->HasPotentiallyRunningFilterAnimation(
                   layer->id(), LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::HasPotentiallyRunningOpacityAnimation(
    const Layer* layer) const {
  return animation_host_
             ? animation_host_->HasPotentiallyRunningOpacityAnimation(
                   layer->id(), LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::HasPotentiallyRunningTransformAnimation(
    const Layer* layer) const {
  return animation_host_
             ? animation_host_->HasPotentiallyRunningTransformAnimation(
                   layer->id(), LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::HasOnlyTranslationTransforms(const Layer* layer) const {
  return animation_host_
             ? animation_host_->HasOnlyTranslationTransforms(
                   layer->id(), LayerTreeType::ACTIVE)
             : false;
}

bool LayerTreeHost::MaximumTargetScale(const Layer* layer,
                                       float* max_scale) const {
  return animation_host_
             ? animation_host_->MaximumTargetScale(
                   layer->id(), LayerTreeType::ACTIVE, max_scale)
             : false;
}

bool LayerTreeHost::AnimationStartScale(const Layer* layer,
                                        float* start_scale) const {
  return animation_host_
             ? animation_host_->AnimationStartScale(
                   layer->id(), LayerTreeType::ACTIVE, start_scale)
             : false;
}

bool LayerTreeHost::HasAnyAnimationTargetingProperty(
    const Layer* layer,
    Animation::TargetProperty property) const {
  return animation_host_
             ? animation_host_->HasAnyAnimationTargetingProperty(layer->id(),
                                                                 property)
             : false;
}

bool LayerTreeHost::AnimationsPreserveAxisAlignment(const Layer* layer) const {
  return animation_host_
             ? animation_host_->AnimationsPreserveAxisAlignment(layer->id())
             : true;
}

bool LayerTreeHost::HasAnyAnimation(const Layer* layer) const {
  return animation_host_ ? animation_host_->HasAnyAnimation(layer->id())
                         : false;
}

bool LayerTreeHost::HasActiveAnimation(const Layer* layer) const {
  return animation_host_ ? animation_host_->HasActiveAnimation(layer->id())
                         : false;
}

bool LayerTreeHost::IsSingleThreaded() const {
  DCHECK(compositor_mode_ != CompositorMode::SINGLE_THREADED ||
         !task_runner_provider_->HasImplThread());
  return compositor_mode_ == CompositorMode::SINGLE_THREADED;
}

bool LayerTreeHost::IsThreaded() const {
  DCHECK(compositor_mode_ != CompositorMode::THREADED ||
         task_runner_provider_->HasImplThread());
  return compositor_mode_ == CompositorMode::THREADED;
}

bool LayerTreeHost::IsRemoteServer() const {
  // The LayerTreeHost on the server does not have an impl task runner.
  return compositor_mode_ == CompositorMode::REMOTE &&
         !task_runner_provider_->HasImplThread();
}

bool LayerTreeHost::IsRemoteClient() const {
  return compositor_mode_ == CompositorMode::REMOTE &&
         task_runner_provider_->HasImplThread();
}

void LayerTreeHost::ToProtobufForCommit(proto::LayerTreeHost* proto) const {
  // Not all fields are serialized, as they are eiher not needed for a commit,
  // or implementation isn't ready yet.
  // Unsupported items:
  // - animations
  // - UI resources
  // - instrumentation of stats
  // - histograms
  // Skipped items:
  // - SwapPromise as they are mostly used for perf measurements.
  // - The bitmap and GPU memory related items.
  // Other notes:
  // - The output surfaces are only valid on the client-side so they are
  //   therefore not serialized.
  // - LayerTreeSettings are needed only during construction of the
  //   LayerTreeHost, so they are serialized outside of the LayerTreeHost
  //   serialization.
  // - The |visible_| flag will be controlled from the client separately and
  //   will need special handling outside of the serialization of the
  //   LayerTreeHost.
  // TODO(nyquist): Figure out how to support animations. See crbug.com/570376.
  proto->set_needs_full_tree_sync(needs_full_tree_sync_);
  proto->set_needs_meta_info_recomputation(needs_meta_info_recomputation_);
  proto->set_source_frame_number(source_frame_number_);
  proto->set_meta_information_sequence_number(
      meta_information_sequence_number_);
  LayerProtoConverter::SerializeLayerHierarchy(root_layer_,
                                               proto->mutable_root_layer());
  LayerProtoConverter::SerializeLayerProperties(root_layer_.get(),
                                                proto->mutable_layer_updates());
  proto->set_hud_layer_id(hud_layer_ ? hud_layer_->id() : Layer::INVALID_ID);
  debug_state_.ToProtobuf(proto->mutable_debug_state());
  SizeToProto(device_viewport_size_, proto->mutable_device_viewport_size());
  proto->set_top_controls_shrink_blink_size(top_controls_shrink_blink_size_);
  proto->set_top_controls_height(top_controls_height_);
  proto->set_top_controls_shown_ratio(top_controls_shown_ratio_);
  proto->set_device_scale_factor(device_scale_factor_);
  proto->set_painted_device_scale_factor(painted_device_scale_factor_);
  proto->set_page_scale_factor(page_scale_factor_);
  proto->set_min_page_scale_factor(min_page_scale_factor_);
  proto->set_max_page_scale_factor(max_page_scale_factor_);
  Vector2dFToProto(elastic_overscroll_, proto->mutable_elastic_overscroll());
  proto->set_has_gpu_rasterization_trigger(has_gpu_rasterization_trigger_);
  proto->set_content_is_suitable_for_gpu_rasterization(
      content_is_suitable_for_gpu_rasterization_);
  proto->set_background_color(background_color_);
  proto->set_has_transparent_background(has_transparent_background_);
  proto->set_have_wheel_event_handlers(have_wheel_event_handlers_);
  proto->set_in_paint_layer_contents(in_paint_layer_contents_);
  proto->set_id(id_);
  proto->set_next_commit_forces_redraw(next_commit_forces_redraw_);

  // Viewport layers.
  proto->set_overscroll_elasticity_layer_id(
      overscroll_elasticity_layer_ ? overscroll_elasticity_layer_->id()
                                   : Layer::INVALID_ID);
  proto->set_page_scale_layer_id(page_scale_layer_ ? page_scale_layer_->id()
                                                   : Layer::INVALID_ID);
  proto->set_inner_viewport_scroll_layer_id(
      inner_viewport_scroll_layer_ ? inner_viewport_scroll_layer_->id()
                                   : Layer::INVALID_ID);
  proto->set_outer_viewport_scroll_layer_id(
      outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
                                   : Layer::INVALID_ID);

  LayerSelectionToProtobuf(selection_, proto->mutable_selection());
  property_trees_.ToProtobuf(proto->mutable_property_trees());
  proto->set_surface_id_namespace(surface_id_namespace_);
  proto->set_next_surface_sequence(next_surface_sequence_);
}

void LayerTreeHost::FromProtobufForCommit(const proto::LayerTreeHost& proto) {
  needs_full_tree_sync_ = proto.needs_full_tree_sync();
  needs_meta_info_recomputation_ = proto.needs_meta_info_recomputation();
  source_frame_number_ = proto.source_frame_number();
  meta_information_sequence_number_ = proto.meta_information_sequence_number();

  // Layer hierarchy.
  scoped_refptr<Layer> new_root_layer =
      LayerProtoConverter::DeserializeLayerHierarchy(root_layer_,
                                                     proto.root_layer());
  if (root_layer_ != new_root_layer) {
    root_layer_->SetLayerTreeHost(nullptr);
    root_layer_ = new_root_layer;
    root_layer_->SetLayerTreeHost(this);
  }

  // Populate layer_id_map_ with the new layers.
  layer_id_map_.clear();
  LayerTreeHostCommon::CallFunctionForSubtree(
      root_layer(),
      [this](Layer* layer) { layer_id_map_[layer->id()] = layer; });

  LayerProtoConverter::DeserializeLayerProperties(root_layer_.get(),
                                                  proto.layer_updates());

  debug_state_.FromProtobuf(proto.debug_state());
  device_viewport_size_ = ProtoToSize(proto.device_viewport_size());
  top_controls_shrink_blink_size_ = proto.top_controls_shrink_blink_size();
  top_controls_height_ = proto.top_controls_height();
  top_controls_shown_ratio_ = proto.top_controls_shown_ratio();
  device_scale_factor_ = proto.device_scale_factor();
  painted_device_scale_factor_ = proto.painted_device_scale_factor();
  page_scale_factor_ = proto.page_scale_factor();
  min_page_scale_factor_ = proto.min_page_scale_factor();
  max_page_scale_factor_ = proto.max_page_scale_factor();
  elastic_overscroll_ = ProtoToVector2dF(proto.elastic_overscroll());
  has_gpu_rasterization_trigger_ = proto.has_gpu_rasterization_trigger();
  content_is_suitable_for_gpu_rasterization_ =
      proto.content_is_suitable_for_gpu_rasterization();
  background_color_ = proto.background_color();
  has_transparent_background_ = proto.has_transparent_background();
  have_wheel_event_handlers_ = proto.have_wheel_event_handlers();
  in_paint_layer_contents_ = proto.in_paint_layer_contents();
  id_ = proto.id();
  next_commit_forces_redraw_ = proto.next_commit_forces_redraw();

  hud_layer_ = static_cast<HeadsUpDisplayLayer*>(
      UpdateAndGetLayer(hud_layer_.get(), proto.hud_layer_id(), layer_id_map_));
  overscroll_elasticity_layer_ =
      UpdateAndGetLayer(overscroll_elasticity_layer_.get(),
                        proto.overscroll_elasticity_layer_id(), layer_id_map_);
  page_scale_layer_ = UpdateAndGetLayer(
      page_scale_layer_.get(), proto.page_scale_layer_id(), layer_id_map_);
  inner_viewport_scroll_layer_ =
      UpdateAndGetLayer(inner_viewport_scroll_layer_.get(),
                        proto.inner_viewport_scroll_layer_id(), layer_id_map_);
  outer_viewport_scroll_layer_ =
      UpdateAndGetLayer(outer_viewport_scroll_layer_.get(),
                        proto.outer_viewport_scroll_layer_id(), layer_id_map_);

  LayerSelectionFromProtobuf(&selection_, proto.selection());

  // It is required to create new PropertyTrees before deserializing it.
  property_trees_ = PropertyTrees();
  property_trees_.FromProtobuf(proto.property_trees());

  // Forcefully override the sequence number of all layers in the tree to have
  // a valid sequence number. Changing the sequence number for a layer does not
  // need a commit, so the value will become out of date for layers that are not
  // updated for other reasons. All layers that at this point are part of the
  // layer tree are valid, so it is OK that they have a valid sequence number.
  int seq_num = property_trees_.sequence_number;
  LayerTreeHostCommon::CallFunctionForSubtree(
      root_layer(), [seq_num](Layer* layer) {
        layer->set_property_tree_sequence_number(seq_num);
      });

  surface_id_namespace_ = proto.surface_id_namespace();
  next_surface_sequence_ = proto.next_surface_sequence();
}

}  // namespace cc
