// 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_scroll_event_handlers_(false),
      event_listener_properties_(),
      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);

  // The LayerTreeHost on the server never requests the output surface since
  // it is only needed on the client. Since ProxyMain aborts commits if
  // output_surface_lost() is true, always assume we have the output surface
  // on the server.
  output_surface_lost_ = false;

  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_scroll_event_handlers(have_scroll_event_handlers_);
  sync_tree->set_event_listener_properties(
      EventListenerClass::kTouch,
      event_listener_properties(EventListenerClass::kTouch));
  sync_tree->set_event_listener_properties(
      EventListenerClass::kMouseWheel,
      event_listener_properties(EventListenerClass::kMouseWheel));

  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::SetHaveScrollEventHandlers(bool have_event_handlers) {
  if (have_scroll_event_handlers_ == have_event_handlers)
    return;

  have_scroll_event_handlers_ = have_event_handlers;
  SetNeedsCommit();
}

void LayerTreeHost::SetEventListenerProperties(
    EventListenerClass event_class,
    EventListenerProperties properties) {
  const size_t index = static_cast<size_t>(event_class);
  if (event_listener_properties_[index] == properties)
    return;

  event_listener_properties_[index] = properties;
  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_scroll_event_handlers(have_scroll_event_handlers_);
  proto->set_wheel_event_listener_properties(static_cast<uint32_t>(
      event_listener_properties(EventListenerClass::kMouseWheel)));
  proto->set_touch_event_listener_properties(static_cast<uint32_t>(
      event_listener_properties(EventListenerClass::kTouch)));
  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) {
    if (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_scroll_event_handlers_ = proto.have_scroll_event_handlers();
  event_listener_properties_[static_cast<size_t>(
      EventListenerClass::kMouseWheel)] =
      static_cast<EventListenerProperties>(
          proto.wheel_event_listener_properties());
  event_listener_properties_[static_cast<size_t>(EventListenerClass::kTouch)] =
      static_cast<EventListenerProperties>(
          proto.touch_event_listener_properties());
  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
