// 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_impl.h"

#include "base/debug/trace_event.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/scrollbar_animation_controller.h"
#include "cc/debug/traced_value.h"
#include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/painted_scrollbar_layer_impl.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_host_impl.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/vector2d_conversions.h"

namespace cc {

LayerTreeImpl::LayerTreeImpl(LayerTreeHostImpl* layer_tree_host_impl)
    : layer_tree_host_impl_(layer_tree_host_impl),
      source_frame_number_(-1),
      hud_layer_(0),
      root_scroll_layer_(NULL),
      currently_scrolling_layer_(NULL),
      root_layer_scroll_offset_delegate_(NULL),
      background_color_(0),
      has_transparent_background_(false),
      page_scale_factor_(1),
      page_scale_delta_(1),
      sent_page_scale_delta_(1),
      min_page_scale_factor_(0),
      max_page_scale_factor_(0),
      scrolling_layer_id_from_previous_tree_(0),
      contents_textures_purged_(false),
      viewport_size_invalid_(false),
      needs_update_draw_properties_(true),
      needs_full_tree_sync_(true) {
}

LayerTreeImpl::~LayerTreeImpl() {
  // Need to explicitly clear the tree prior to destroying this so that
  // the LayerTreeImpl pointer is still valid in the LayerImpl dtor.
  root_layer_.reset();
}

static LayerImpl* FindRootScrollLayerRecursive(LayerImpl* layer) {
  if (!layer)
    return NULL;

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

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

  return NULL;
}

void LayerTreeImpl::SetRootLayer(scoped_ptr<LayerImpl> layer) {
  if (root_scroll_layer_)
    root_scroll_layer_->SetScrollOffsetDelegate(NULL);
  root_layer_ = layer.Pass();
  currently_scrolling_layer_ = NULL;
  root_scroll_layer_ = NULL;

  layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}

void LayerTreeImpl::FindRootScrollLayer() {
  root_scroll_layer_ = FindRootScrollLayerRecursive(root_layer_.get());

  if (root_scroll_layer_) {
    UpdateMaxScrollOffset();
    root_scroll_layer_->SetScrollOffsetDelegate(
        root_layer_scroll_offset_delegate_);
  }

  if (scrolling_layer_id_from_previous_tree_) {
    currently_scrolling_layer_ = LayerTreeHostCommon::FindLayerInSubtree(
        root_layer_.get(),
        scrolling_layer_id_from_previous_tree_);
  }

  scrolling_layer_id_from_previous_tree_ = 0;
}

scoped_ptr<LayerImpl> LayerTreeImpl::DetachLayerTree() {
  // Clear all data structures that have direct references to the layer tree.
  scrolling_layer_id_from_previous_tree_ =
    currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0;
  if (root_scroll_layer_)
    root_scroll_layer_->SetScrollOffsetDelegate(NULL);
  root_scroll_layer_ = NULL;
  currently_scrolling_layer_ = NULL;

  render_surface_layer_list_.clear();
  set_needs_update_draw_properties();
  return root_layer_.Pass();
}

void LayerTreeImpl::PushPropertiesTo(LayerTreeImpl* target_tree) {
  // The request queue should have been processed and does not require a push.
  DCHECK_EQ(ui_resource_request_queue_.size(), 0u);

  target_tree->SetLatencyInfo(latency_info_);
  latency_info_.Clear();
  target_tree->SetPageScaleFactorAndLimits(
      page_scale_factor(), min_page_scale_factor(), max_page_scale_factor());
  target_tree->SetPageScaleDelta(
      target_tree->page_scale_delta() / target_tree->sent_page_scale_delta());
  target_tree->set_sent_page_scale_delta(1);

  // This should match the property synchronization in
  // LayerTreeHost::finishCommitOnImplThread().
  target_tree->set_source_frame_number(source_frame_number());
  target_tree->set_background_color(background_color());
  target_tree->set_has_transparent_background(has_transparent_background());

  if (ContentsTexturesPurged())
    target_tree->SetContentsTexturesPurged();
  else
    target_tree->ResetContentsTexturesPurged();

  if (ViewportSizeInvalid())
    target_tree->SetViewportSizeInvalid();
  else
    target_tree->ResetViewportSizeInvalid();

  if (hud_layer())
    target_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(
        LayerTreeHostCommon::FindLayerInSubtree(
            target_tree->root_layer(), hud_layer()->id())));
  else
    target_tree->set_hud_layer(NULL);
}

LayerImpl* LayerTreeImpl::RootScrollLayer() const {
  return root_scroll_layer_;
}

LayerImpl* LayerTreeImpl::RootContainerLayer() const {
  return root_scroll_layer_ ? root_scroll_layer_->parent() : NULL;
}

LayerImpl* LayerTreeImpl::CurrentlyScrollingLayer() const {
  DCHECK(IsActiveTree());
  return currently_scrolling_layer_;
}

void LayerTreeImpl::SetCurrentlyScrollingLayer(LayerImpl* layer) {
  if (currently_scrolling_layer_ == layer)
    return;

  if (currently_scrolling_layer_ &&
      currently_scrolling_layer_->scrollbar_animation_controller())
    currently_scrolling_layer_->scrollbar_animation_controller()->
        DidScrollGestureEnd(CurrentPhysicalTimeTicks());
  currently_scrolling_layer_ = layer;
  if (layer && layer->scrollbar_animation_controller())
    layer->scrollbar_animation_controller()->DidScrollGestureBegin();
}

void LayerTreeImpl::ClearCurrentlyScrollingLayer() {
  SetCurrentlyScrollingLayer(NULL);
  scrolling_layer_id_from_previous_tree_ = 0;
}

void LayerTreeImpl::SetPageScaleFactorAndLimits(float page_scale_factor,
    float min_page_scale_factor, float max_page_scale_factor) {
  if (!page_scale_factor)
    return;

  min_page_scale_factor_ = min_page_scale_factor;
  max_page_scale_factor_ = max_page_scale_factor;
  page_scale_factor_ = page_scale_factor;
}

void LayerTreeImpl::SetPageScaleDelta(float delta) {
  // Clamp to the current min/max limits.
  float total = page_scale_factor_ * delta;
  if (min_page_scale_factor_ && total < min_page_scale_factor_)
    delta = min_page_scale_factor_ / page_scale_factor_;
  else if (max_page_scale_factor_ && total > max_page_scale_factor_)
    delta = max_page_scale_factor_ / page_scale_factor_;

  if (delta == page_scale_delta_)
    return;

  page_scale_delta_ = delta;

  if (IsActiveTree()) {
    LayerTreeImpl* pending_tree = layer_tree_host_impl_->pending_tree();
    if (pending_tree) {
      DCHECK_EQ(1, pending_tree->sent_page_scale_delta());
      pending_tree->SetPageScaleDelta(
          page_scale_delta_ / sent_page_scale_delta_);
    }
  }

  UpdateMaxScrollOffset();
  set_needs_update_draw_properties();
}

gfx::SizeF LayerTreeImpl::ScrollableViewportSize() const {
  return gfx::ScaleSize(layer_tree_host_impl_->VisibleViewportSize(),
                        1.0f / total_page_scale_factor());
}

void LayerTreeImpl::UpdateMaxScrollOffset() {
  LayerImpl* root_scroll = RootScrollLayer();
  if (!root_scroll || !root_scroll->children().size())
    return;

  gfx::Vector2dF max_scroll = gfx::Rect(ScrollableSize()).bottom_right() -
      gfx::RectF(ScrollableViewportSize()).bottom_right();

  // The viewport may be larger than the contents in some cases, such as
  // having a vertical scrollbar but no horizontal overflow.
  max_scroll.SetToMax(gfx::Vector2dF());

  root_scroll_layer_->SetMaxScrollOffset(gfx::ToFlooredVector2d(max_scroll));
}

static void ApplySentScrollDeltasFromAbortedCommitTo(LayerImpl* layer) {
  layer->ApplySentScrollDeltasFromAbortedCommit();
}

void LayerTreeImpl::ApplySentScrollAndScaleDeltasFromAbortedCommit() {
  DCHECK(IsActiveTree());

  page_scale_factor_ *= sent_page_scale_delta_;
  page_scale_delta_ /= sent_page_scale_delta_;
  sent_page_scale_delta_ = 1.f;

  if (!root_layer())
    return;

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

static void ApplyScrollDeltasSinceBeginFrameTo(LayerImpl* layer) {
  layer->ApplyScrollDeltasSinceBeginFrame();
}

void LayerTreeImpl::ApplyScrollDeltasSinceBeginFrame() {
  DCHECK(IsPendingTree());
  if (!root_layer())
    return;

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

void LayerTreeImpl::UpdateSolidColorScrollbars() {
  DCHECK(settings().solid_color_scrollbars);

  LayerImpl* root_scroll = RootScrollLayer();
  DCHECK(root_scroll);
  DCHECK(IsActiveTree());

  gfx::RectF scrollable_viewport(
      gfx::PointAtOffsetFromOrigin(root_scroll->TotalScrollOffset()),
      ScrollableViewportSize());
  float vertical_adjust = 0.0f;
  if (RootContainerLayer())
    vertical_adjust = layer_tree_host_impl_->VisibleViewportSize().height() -
                      RootContainerLayer()->bounds().height();
  if (PaintedScrollbarLayerImpl* horiz =
          root_scroll->horizontal_scrollbar_layer()) {
    horiz->SetVerticalAdjust(vertical_adjust);
    horiz->SetVisibleToTotalLengthRatio(
        scrollable_viewport.width() / ScrollableSize().width());
  }
  if (PaintedScrollbarLayerImpl* vertical =
          root_scroll->vertical_scrollbar_layer()) {
    vertical->SetVerticalAdjust(vertical_adjust);
    vertical->SetVisibleToTotalLengthRatio(
        scrollable_viewport.height() / ScrollableSize().height());
  }
}

void LayerTreeImpl::UpdateDrawProperties() {
  if (IsActiveTree() && RootScrollLayer() && RootContainerLayer())
    UpdateRootScrollLayerSizeDelta();

  if (settings().solid_color_scrollbars &&
      IsActiveTree() &&
      RootScrollLayer()) {
    UpdateSolidColorScrollbars();
  }

  needs_update_draw_properties_ = false;
  render_surface_layer_list_.clear();

  // For max_texture_size.
  if (!layer_tree_host_impl_->renderer())
    return;

  if (!root_layer())
    return;

  {
    TRACE_EVENT2("cc",
                 "LayerTreeImpl::UpdateDrawProperties",
                 "IsActive",
                 IsActiveTree(),
                 "SourceFrameNumber",
                 source_frame_number_);
    LayerTreeHostCommon::CalcDrawPropsImplInputs inputs(
        root_layer(),
        layer_tree_host_impl_->DeviceViewport().size(),
        layer_tree_host_impl_->DeviceTransform(),
        device_scale_factor(),
        total_page_scale_factor(),
        root_scroll_layer_ ? root_scroll_layer_->parent() : NULL,
        MaxTextureSize(),
        settings().can_use_lcd_text,
        settings().layer_transforms_should_scale_layer_contents,
        &render_surface_layer_list_);
    LayerTreeHostCommon::CalculateDrawProperties(&inputs);
  }

  DCHECK(!needs_update_draw_properties_) <<
      "CalcDrawProperties should not set_needs_update_draw_properties()";
}

const LayerImplList& LayerTreeImpl::RenderSurfaceLayerList() const {
  // If this assert triggers, then the list is dirty.
  DCHECK(!needs_update_draw_properties_);
  return render_surface_layer_list_;
}

gfx::Size LayerTreeImpl::ScrollableSize() const {
  if (!root_scroll_layer_ || root_scroll_layer_->children().empty())
    return gfx::Size();
  return root_scroll_layer_->children()[0]->bounds();
}

LayerImpl* LayerTreeImpl::LayerById(int id) {
  LayerIdMap::iterator iter = layer_id_map_.find(id);
  return iter != layer_id_map_.end() ? iter->second : NULL;
}

void LayerTreeImpl::RegisterLayer(LayerImpl* layer) {
  DCHECK(!LayerById(layer->id()));
  layer_id_map_[layer->id()] = layer;
}

void LayerTreeImpl::UnregisterLayer(LayerImpl* layer) {
  DCHECK(LayerById(layer->id()));
  layer_id_map_.erase(layer->id());
}

void LayerTreeImpl::PushPersistedState(LayerTreeImpl* pending_tree) {
  pending_tree->SetCurrentlyScrollingLayer(
      LayerTreeHostCommon::FindLayerInSubtree(pending_tree->root_layer(),
          currently_scrolling_layer_ ? currently_scrolling_layer_->id() : 0));
  pending_tree->SetLatencyInfo(latency_info_);
  latency_info_.Clear();
}

static void DidBecomeActiveRecursive(LayerImpl* layer) {
  layer->DidBecomeActive();
  for (size_t i = 0; i < layer->children().size(); ++i)
    DidBecomeActiveRecursive(layer->children()[i]);
}

void LayerTreeImpl::DidBecomeActive() {
  if (!root_layer())
    return;

  DidBecomeActiveRecursive(root_layer());
  FindRootScrollLayer();
}

bool LayerTreeImpl::ContentsTexturesPurged() const {
  return contents_textures_purged_;
}

void LayerTreeImpl::SetContentsTexturesPurged() {
  if (contents_textures_purged_)
    return;
  contents_textures_purged_ = true;
  layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}

void LayerTreeImpl::ResetContentsTexturesPurged() {
  if (!contents_textures_purged_)
    return;
  contents_textures_purged_ = false;
  layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}

bool LayerTreeImpl::ViewportSizeInvalid() const {
  return viewport_size_invalid_;
}

void LayerTreeImpl::SetViewportSizeInvalid() {
  viewport_size_invalid_ = true;
  layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}

void LayerTreeImpl::ResetViewportSizeInvalid() {
  viewport_size_invalid_ = false;
  layer_tree_host_impl_->OnCanDrawStateChangedForTree();
}

Proxy* LayerTreeImpl::proxy() const {
  return layer_tree_host_impl_->proxy();
}

const LayerTreeSettings& LayerTreeImpl::settings() const {
  return layer_tree_host_impl_->settings();
}

const RendererCapabilities& LayerTreeImpl::GetRendererCapabilities() const {
  return layer_tree_host_impl_->GetRendererCapabilities();
}

ContextProvider* LayerTreeImpl::context_provider() const {
  return output_surface()->context_provider();
}

OutputSurface* LayerTreeImpl::output_surface() const {
  return layer_tree_host_impl_->output_surface();
}

ResourceProvider* LayerTreeImpl::resource_provider() const {
  return layer_tree_host_impl_->resource_provider();
}

TileManager* LayerTreeImpl::tile_manager() const {
  return layer_tree_host_impl_->tile_manager();
}

FrameRateCounter* LayerTreeImpl::frame_rate_counter() const {
  return layer_tree_host_impl_->fps_counter();
}

PaintTimeCounter* LayerTreeImpl::paint_time_counter() const {
  return layer_tree_host_impl_->paint_time_counter();
}

MemoryHistory* LayerTreeImpl::memory_history() const {
  return layer_tree_host_impl_->memory_history();
}

bool LayerTreeImpl::IsActiveTree() const {
  return layer_tree_host_impl_->active_tree() == this;
}

bool LayerTreeImpl::IsPendingTree() const {
  return layer_tree_host_impl_->pending_tree() == this;
}

bool LayerTreeImpl::IsRecycleTree() const {
  return layer_tree_host_impl_->recycle_tree() == this;
}

LayerImpl* LayerTreeImpl::FindActiveTreeLayerById(int id) {
  LayerTreeImpl* tree = layer_tree_host_impl_->active_tree();
  if (!tree)
    return NULL;
  return tree->LayerById(id);
}

LayerImpl* LayerTreeImpl::FindPendingTreeLayerById(int id) {
  LayerTreeImpl* tree = layer_tree_host_impl_->pending_tree();
  if (!tree)
    return NULL;
  return tree->LayerById(id);
}

int LayerTreeImpl::MaxTextureSize() const {
  return layer_tree_host_impl_->GetRendererCapabilities().max_texture_size;
}

bool LayerTreeImpl::PinchGestureActive() const {
  return layer_tree_host_impl_->pinch_gesture_active();
}

base::TimeTicks LayerTreeImpl::CurrentFrameTimeTicks() const {
  return layer_tree_host_impl_->CurrentFrameTimeTicks();
}

base::Time LayerTreeImpl::CurrentFrameTime() const {
  return layer_tree_host_impl_->CurrentFrameTime();
}

base::TimeTicks LayerTreeImpl::CurrentPhysicalTimeTicks() const {
  return layer_tree_host_impl_->CurrentPhysicalTimeTicks();
}

void LayerTreeImpl::SetNeedsCommit() {
  layer_tree_host_impl_->SetNeedsCommit();
}

void LayerTreeImpl::SetNeedsRedraw() {
  layer_tree_host_impl_->SetNeedsRedraw();
}

const LayerTreeDebugState& LayerTreeImpl::debug_state() const {
  return layer_tree_host_impl_->debug_state();
}

float LayerTreeImpl::device_scale_factor() const {
  return layer_tree_host_impl_->device_scale_factor();
}

gfx::Size LayerTreeImpl::device_viewport_size() const {
  return layer_tree_host_impl_->device_viewport_size();
}

DebugRectHistory* LayerTreeImpl::debug_rect_history() const {
  return layer_tree_host_impl_->debug_rect_history();
}

AnimationRegistrar* LayerTreeImpl::animationRegistrar() const {
  return layer_tree_host_impl_->animation_registrar();
}

scoped_ptr<base::Value> LayerTreeImpl::AsValue() const {
  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
  TracedValue::MakeDictIntoImplicitSnapshot(
      state.get(), "cc::LayerTreeImpl", this);

  state->Set("root_layer", root_layer_->AsValue().release());

  scoped_ptr<base::ListValue> render_surface_layer_list(new base::ListValue());
  typedef LayerIterator<LayerImpl,
                        LayerImplList,
                        RenderSurfaceImpl,
                        LayerIteratorActions::BackToFront> LayerIteratorType;
  LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
  for (LayerIteratorType it = LayerIteratorType::Begin(
           &render_surface_layer_list_); it != end; ++it) {
    if (!it.represents_itself())
      continue;
    render_surface_layer_list->Append(TracedValue::CreateIDRef(*it).release());
  }

  state->Set("render_surface_layer_list",
             render_surface_layer_list.release());
  return state.PassAs<base::Value>();
}

void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
    LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) {
  root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate;
  if (root_scroll_layer_) {
    root_scroll_layer_->SetScrollOffsetDelegate(
        root_layer_scroll_offset_delegate_);
  }
}

void LayerTreeImpl::UpdateRootScrollLayerSizeDelta() {
  LayerImpl* root_scroll = RootScrollLayer();
  LayerImpl* root_container = RootContainerLayer();
  DCHECK(root_scroll);
  DCHECK(root_container);
  DCHECK(IsActiveTree());

  gfx::Vector2dF scrollable_viewport_size =
      gfx::RectF(ScrollableViewportSize()).bottom_right() - gfx::PointF();

  gfx::Vector2dF original_viewport_size =
      gfx::RectF(root_container->bounds()).bottom_right() -
      gfx::PointF();
  original_viewport_size.Scale(1 / page_scale_factor());

  root_scroll->SetFixedContainerSizeDelta(
      scrollable_viewport_size - original_viewport_size);
}

void LayerTreeImpl::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
  latency_info_.MergeWith(latency_info);
}

const ui::LatencyInfo& LayerTreeImpl::GetLatencyInfo() {
  return latency_info_;
}

void LayerTreeImpl::ClearLatencyInfo() {
  latency_info_.Clear();
}

void LayerTreeImpl::WillModifyTilePriorities() {
  layer_tree_host_impl_->SetNeedsManageTiles();
}

void LayerTreeImpl::set_ui_resource_request_queue(
    const UIResourceRequestQueue& queue) {
  ui_resource_request_queue_ = queue;
}

ResourceProvider::ResourceId LayerTreeImpl::ResourceIdForUIResource(
    UIResourceId uid) const {
  return layer_tree_host_impl_->ResourceIdForUIResource(uid);
}

void LayerTreeImpl::ProcessUIResourceRequestQueue() {
  while (ui_resource_request_queue_.size() > 0) {
    UIResourceRequest req = ui_resource_request_queue_.front();
    ui_resource_request_queue_.pop_front();

    switch (req.type) {
      case UIResourceRequest::UIResourceCreate:
        layer_tree_host_impl_->CreateUIResource(req.id, req.bitmap);
        break;
      case UIResourceRequest::UIResourceDelete:
        layer_tree_host_impl_->DeleteUIResource(req.id);
        break;
      default:
        NOTREACHED();
        break;
    }
  }
}

void LayerTreeImpl::AddLayerWithCopyOutputRequest(LayerImpl* layer) {
  // Only the active tree needs to know about layers with copy requests, as
  // they are aborted if not serviced during draw.
  DCHECK(IsActiveTree());

  DCHECK(std::find(layers_with_copy_output_request_.begin(),
                   layers_with_copy_output_request_.end(),
                   layer) == layers_with_copy_output_request_.end());
  layers_with_copy_output_request_.push_back(layer);
}

void LayerTreeImpl::RemoveLayerWithCopyOutputRequest(LayerImpl* layer) {
  // Only the active tree needs to know about layers with copy requests, as
  // they are aborted if not serviced during draw.
  DCHECK(IsActiveTree());

  std::vector<LayerImpl*>::iterator it = std::find(
      layers_with_copy_output_request_.begin(),
      layers_with_copy_output_request_.end(),
      layer);
  DCHECK(it != layers_with_copy_output_request_.end());
  layers_with_copy_output_request_.erase(it);
}

const std::vector<LayerImpl*> LayerTreeImpl::LayersWithCopyOutputRequest()
    const {
  // Only the active tree needs to know about layers with copy requests, as
  // they are aborted if not serviced during draw.
  DCHECK(IsActiveTree());

  return layers_with_copy_output_request_;
}

}  // namespace cc
