// Copyright 2012 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/layers/delegated_renderer_layer_impl.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "cc/base/math_util.h"
#include "cc/layers/append_quads_data.h"
#include "cc/layers/render_pass_sink.h"
#include "cc/output/delegated_frame_data.h"
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/trees/layer_tree_impl.h"
#include "cc/trees/occlusion.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {

DelegatedRendererLayerImpl::DelegatedRendererLayerImpl(LayerTreeImpl* tree_impl,
                                                       int id)
    : LayerImpl(tree_impl, id),
      have_render_passes_to_push_(false),
      inverse_device_scale_factor_(1.0f),
      child_id_(0),
      own_child_id_(false) {
}

DelegatedRendererLayerImpl::~DelegatedRendererLayerImpl() {
  ClearRenderPasses();
  ClearChildId();
}

bool DelegatedRendererLayerImpl::HasDelegatedContent() const { return true; }

bool DelegatedRendererLayerImpl::HasContributingDelegatedRenderPasses() const {
  // The root RenderPass for the layer is merged with its target
  // RenderPass in each frame. So we only have extra RenderPasses
  // to merge when we have a non-root RenderPass present.
  return render_passes_in_draw_order_.size() > 1;
}

static ResourceProvider::ResourceId ResourceRemapHelper(
    bool* invalid_frame,
    const ResourceProvider::ResourceIdMap& child_to_parent_map,
    ResourceProvider::ResourceIdArray* resources_in_frame,
    ResourceProvider::ResourceId id) {

  ResourceProvider::ResourceIdMap::const_iterator it =
      child_to_parent_map.find(id);
  if (it == child_to_parent_map.end()) {
    *invalid_frame = true;
    return 0;
  }

  DCHECK_EQ(it->first, id);
  ResourceProvider::ResourceId remapped_id = it->second;
  resources_in_frame->push_back(id);
  return remapped_id;
}

void DelegatedRendererLayerImpl::PushPropertiesTo(LayerImpl* layer) {
  LayerImpl::PushPropertiesTo(layer);

  DelegatedRendererLayerImpl* delegated_layer =
      static_cast<DelegatedRendererLayerImpl*>(layer);

  // If we have a new child_id to give to the active layer, it should
  // have already deleted its old child_id.
  DCHECK(delegated_layer->child_id_ == 0 ||
         delegated_layer->child_id_ == child_id_);
  delegated_layer->inverse_device_scale_factor_ = inverse_device_scale_factor_;
  delegated_layer->child_id_ = child_id_;
  delegated_layer->own_child_id_ = true;
  own_child_id_ = false;

  if (have_render_passes_to_push_) {
    // This passes ownership of the render passes to the active tree.
    delegated_layer->SetRenderPasses(&render_passes_in_draw_order_);
    DCHECK(render_passes_in_draw_order_.empty());
    have_render_passes_to_push_ = false;
  }

  // This is just a copy for testing, since resources are added to the
  // ResourceProvider in the pending tree.
  delegated_layer->resources_ = resources_;
}

void DelegatedRendererLayerImpl::CreateChildIdIfNeeded(
    const ReturnCallback& return_callback) {
  if (child_id_)
    return;

  ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
  child_id_ = resource_provider->CreateChild(return_callback);
  own_child_id_ = true;
}

void DelegatedRendererLayerImpl::SetFrameData(
    const DelegatedFrameData* frame_data,
    const gfx::RectF& damage_in_frame) {
  DCHECK(child_id_) << "CreateChildIdIfNeeded must be called first.";
  DCHECK(frame_data);
  DCHECK(!frame_data->render_pass_list.empty());
  // A frame with an empty root render pass is invalid.
  DCHECK(!frame_data->render_pass_list.back()->output_rect.IsEmpty());

  ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
    const ResourceProvider::ResourceIdMap& resource_map =
        resource_provider->GetChildToParentMap(child_id_);

  resource_provider->ReceiveFromChild(child_id_, frame_data->resource_list);

  RenderPassList render_pass_list;
  RenderPass::CopyAll(frame_data->render_pass_list, &render_pass_list);

  bool invalid_frame = false;
  ResourceProvider::ResourceIdArray resources_in_frame;
  DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
      base::Bind(&ResourceRemapHelper,
                 &invalid_frame,
                 resource_map,
                 &resources_in_frame);
  for (const auto& pass : render_pass_list) {
    for (const auto& quad : pass->quad_list)
      quad->IterateResources(remap_resources_to_parent_callback);
  }

  if (invalid_frame) {
    // Declare we are still using the last frame's resources.
    resource_provider->DeclareUsedResourcesFromChild(child_id_, resources_);
    return;
  }

  // Declare we are using the new frame's resources.
  resources_.swap(resources_in_frame);
  resource_provider->DeclareUsedResourcesFromChild(child_id_, resources_);

  inverse_device_scale_factor_ = 1.0f / frame_data->device_scale_factor;
  // Display size is already set so we can compute what the damage rect
  // will be in layer space. The damage may exceed the visible portion of
  // the frame, so intersect the damage to the layer's bounds.
  RenderPass* new_root_pass = render_pass_list.back();
  gfx::Size frame_size = new_root_pass->output_rect.size();
  gfx::RectF damage_in_layer = damage_in_frame;
  damage_in_layer.Scale(inverse_device_scale_factor_);
  SetUpdateRect(gfx::IntersectRects(
      gfx::UnionRects(update_rect(), gfx::ToEnclosingRect(damage_in_layer)),
      gfx::Rect(bounds())));

  SetRenderPasses(&render_pass_list);
  have_render_passes_to_push_ = true;
}

void DelegatedRendererLayerImpl::SetRenderPasses(
    RenderPassList* render_passes_in_draw_order) {
  ClearRenderPasses();

  for (size_t i = 0; i < render_passes_in_draw_order->size(); ++i) {
    RenderPassList::iterator to_take =
        render_passes_in_draw_order->begin() + i;
    render_passes_index_by_id_.insert(
        std::pair<RenderPassId, int>((*to_take)->id, i));
    scoped_ptr<RenderPass> taken_render_pass =
        render_passes_in_draw_order->take(to_take);
    render_passes_in_draw_order_.push_back(taken_render_pass.Pass());
  }

  // Give back an empty array instead of nulls.
  render_passes_in_draw_order->clear();
}

void DelegatedRendererLayerImpl::ClearRenderPasses() {
  render_passes_index_by_id_.clear();
  render_passes_in_draw_order_.clear();
}

scoped_ptr<LayerImpl> DelegatedRendererLayerImpl::CreateLayerImpl(
    LayerTreeImpl* tree_impl) {
  return DelegatedRendererLayerImpl::Create(tree_impl, id());
}

void DelegatedRendererLayerImpl::ReleaseResources() {
  ClearRenderPasses();
  ClearChildId();
}

static inline int IndexToId(int index) { return index + 1; }
static inline int IdToIndex(int id) { return id - 1; }

RenderPassId DelegatedRendererLayerImpl::FirstContributingRenderPassId() const {
  return RenderPassId(id(), IndexToId(0));
}

RenderPassId DelegatedRendererLayerImpl::NextContributingRenderPassId(
    RenderPassId previous) const {
  return RenderPassId(previous.layer_id, previous.index + 1);
}

bool DelegatedRendererLayerImpl::ConvertDelegatedRenderPassId(
    RenderPassId delegated_render_pass_id,
    RenderPassId* output_render_pass_id) const {
  base::hash_map<RenderPassId, int>::const_iterator found =
      render_passes_index_by_id_.find(delegated_render_pass_id);
  if (found == render_passes_index_by_id_.end()) {
    // Be robust against a RenderPass id that isn't part of the frame.
    return false;
  }
  unsigned delegated_render_pass_index = found->second;
  *output_render_pass_id =
      RenderPassId(id(), IndexToId(delegated_render_pass_index));
  return true;
}

void DelegatedRendererLayerImpl::AppendContributingRenderPasses(
    RenderPassSink* render_pass_sink) {
  DCHECK(HasContributingDelegatedRenderPasses());

  const RenderPass* root_delegated_render_pass =
      render_passes_in_draw_order_.back();
  gfx::Size frame_size = root_delegated_render_pass->output_rect.size();
  gfx::Transform delegated_frame_to_root_transform = screen_space_transform();
  delegated_frame_to_root_transform.Scale(inverse_device_scale_factor_,
                                          inverse_device_scale_factor_);

  for (size_t i = 0; i < render_passes_in_draw_order_.size() - 1; ++i) {
    RenderPassId output_render_pass_id(-1, -1);
    bool present =
        ConvertDelegatedRenderPassId(render_passes_in_draw_order_[i]->id,
                                     &output_render_pass_id);

    // Don't clash with the RenderPass we generate if we own a RenderSurface.
    DCHECK(present) << render_passes_in_draw_order_[i]->id.layer_id << ", "
                    << render_passes_in_draw_order_[i]->id.index;
    DCHECK_GT(output_render_pass_id.index, 0);

    scoped_ptr<RenderPass> copy_pass =
        render_passes_in_draw_order_[i]->Copy(output_render_pass_id);
    copy_pass->transform_to_root_target.ConcatTransform(
        delegated_frame_to_root_transform);
    render_pass_sink->AppendRenderPass(copy_pass.Pass());
  }
}

bool DelegatedRendererLayerImpl::WillDraw(DrawMode draw_mode,
                                          ResourceProvider* resource_provider) {
  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
    return false;
  return LayerImpl::WillDraw(draw_mode, resource_provider);
}

void DelegatedRendererLayerImpl::AppendQuads(
    RenderPass* render_pass,
    AppendQuadsData* append_quads_data) {
  AppendRainbowDebugBorder(render_pass);

  // This list will be empty after a lost context until a new frame arrives.
  if (render_passes_in_draw_order_.empty())
    return;

  RenderPassId target_render_pass_id = render_pass->id;

  const RenderPass* root_delegated_render_pass =
      render_passes_in_draw_order_.back();

  DCHECK(root_delegated_render_pass->output_rect.origin().IsOrigin());
  gfx::Size frame_size = root_delegated_render_pass->output_rect.size();

  // If the index of the RenderPassId is 0, then it is a RenderPass generated
  // for a layer in this compositor, not the delegating renderer. Then we want
  // to merge our root RenderPass with the target RenderPass. Otherwise, it is
  // some RenderPass which we added from the delegating renderer.
  bool should_merge_root_render_pass_with_target = !target_render_pass_id.index;
  if (should_merge_root_render_pass_with_target) {
    // Verify that the RenderPass we are appending to is created by our
    // render_target.
    DCHECK(target_render_pass_id.layer_id == render_target()->id());

    AppendRenderPassQuads(render_pass,
                          root_delegated_render_pass,
                          frame_size);
  } else {
    // Verify that the RenderPass we are appending to was created by us.
    DCHECK(target_render_pass_id.layer_id == id());

    int render_pass_index = IdToIndex(target_render_pass_id.index);
    const RenderPass* delegated_render_pass =
        render_passes_in_draw_order_[render_pass_index];
    AppendRenderPassQuads(render_pass,
                          delegated_render_pass,
                          frame_size);
  }
}

void DelegatedRendererLayerImpl::AppendRainbowDebugBorder(
    RenderPass* render_pass) {
  if (!ShowDebugBorders())
    return;

  SharedQuadState* shared_quad_state =
      render_pass->CreateAndAppendSharedQuadState();
  PopulateSharedQuadState(shared_quad_state);

  SkColor color;
  float border_width;
  GetDebugBorderProperties(&color, &border_width);

  SkColor colors[] = {
    0x80ff0000,  // Red.
    0x80ffa500,  // Orange.
    0x80ffff00,  // Yellow.
    0x80008000,  // Green.
    0x800000ff,  // Blue.
    0x80ee82ee,  // Violet.
  };
  const int kNumColors = arraysize(colors);

  const int kStripeWidth = 300;
  const int kStripeHeight = 300;

  for (size_t i = 0; ; ++i) {
    // For horizontal lines.
    int x =  kStripeWidth * i;
    int width = std::min(kStripeWidth, content_bounds().width() - x - 1);

    // For vertical lines.
    int y = kStripeHeight * i;
    int height = std::min(kStripeHeight, content_bounds().height() - y - 1);

    gfx::Rect top(x, 0, width, border_width);
    gfx::Rect bottom(x,
                     content_bounds().height() - border_width,
                     width,
                     border_width);
    gfx::Rect left(0, y, border_width, height);
    gfx::Rect right(content_bounds().width() - border_width,
                    y,
                    border_width,
                    height);

    if (top.IsEmpty() && left.IsEmpty())
      break;

    if (!top.IsEmpty()) {
      bool force_anti_aliasing_off = false;
      SolidColorDrawQuad* top_quad =
          render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
      top_quad->SetNew(shared_quad_state, top, top, colors[i % kNumColors],
                       force_anti_aliasing_off);

      SolidColorDrawQuad* bottom_quad =
          render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
      bottom_quad->SetNew(shared_quad_state, bottom, bottom,
                          colors[kNumColors - 1 - (i % kNumColors)],
                          force_anti_aliasing_off);

      if (contents_opaque()) {
        // Draws a stripe filling the layer vertically with the same color and
        // width as the horizontal stipes along the layer's top border.
        SolidColorDrawQuad* solid_quad =
            render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
        // The inner fill is more transparent then the border.
        static const float kFillOpacity = 0.1f;
        SkColor fill_color = SkColorSetA(
            colors[i % kNumColors],
            static_cast<uint8_t>(SkColorGetA(colors[i % kNumColors]) *
                                 kFillOpacity));
        gfx::Rect fill_rect(x, 0, width, content_bounds().height());
        solid_quad->SetNew(shared_quad_state, fill_rect, fill_rect, fill_color,
                           force_anti_aliasing_off);
      }
    }
    if (!left.IsEmpty()) {
      bool force_anti_aliasing_off = false;
      SolidColorDrawQuad* left_quad =
          render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
      left_quad->SetNew(shared_quad_state, left, left,
                        colors[kNumColors - 1 - (i % kNumColors)],
                        force_anti_aliasing_off);

      SolidColorDrawQuad* right_quad =
          render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
      right_quad->SetNew(shared_quad_state, right, right,
                         colors[i % kNumColors], force_anti_aliasing_off);
    }
  }
}

void DelegatedRendererLayerImpl::AppendRenderPassQuads(
    RenderPass* render_pass,
    const RenderPass* delegated_render_pass,
    const gfx::Size& frame_size) const {
  const SharedQuadState* delegated_shared_quad_state = nullptr;
  SharedQuadState* output_shared_quad_state = nullptr;

  for (const auto& delegated_quad : delegated_render_pass->quad_list) {
    bool is_root_delegated_render_pass =
        delegated_render_pass == render_passes_in_draw_order_.back();

    if (delegated_quad->shared_quad_state != delegated_shared_quad_state) {
      delegated_shared_quad_state = delegated_quad->shared_quad_state;
      output_shared_quad_state = render_pass->CreateAndAppendSharedQuadState();
      output_shared_quad_state->CopyFrom(delegated_shared_quad_state);

      if (is_root_delegated_render_pass) {
        gfx::Transform delegated_frame_to_target_transform = draw_transform();
        delegated_frame_to_target_transform.Scale(inverse_device_scale_factor_,
                                                  inverse_device_scale_factor_);

        output_shared_quad_state->content_to_target_transform.ConcatTransform(
            delegated_frame_to_target_transform);

        if (render_target() == this) {
          DCHECK(!is_clipped());
          DCHECK(render_surface());
          DCHECK_EQ(0, num_unclipped_descendants());
          output_shared_quad_state->clip_rect =
              MathUtil::MapEnclosingClippedRect(
                  delegated_frame_to_target_transform,
                  output_shared_quad_state->clip_rect);
        } else {
          gfx::Rect clip_rect = drawable_content_rect();
          if (output_shared_quad_state->is_clipped) {
            clip_rect.Intersect(MathUtil::MapEnclosingClippedRect(
                delegated_frame_to_target_transform,
                output_shared_quad_state->clip_rect));
          }
          output_shared_quad_state->clip_rect = clip_rect;
          output_shared_quad_state->is_clipped = true;
        }

        output_shared_quad_state->opacity *= draw_opacity();
      }
    }
    DCHECK(output_shared_quad_state);

    gfx::Transform quad_content_to_delegated_target_space =
        output_shared_quad_state->content_to_target_transform;
    if (!is_root_delegated_render_pass) {
      quad_content_to_delegated_target_space.ConcatTransform(
          delegated_render_pass->transform_to_root_target);
      quad_content_to_delegated_target_space.ConcatTransform(draw_transform());
    }

    Occlusion occlusion_in_quad_space =
        draw_properties()
            .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
                quad_content_to_delegated_target_space);

    gfx::Rect quad_visible_rect =
        occlusion_in_quad_space.GetUnoccludedContentRect(
            delegated_quad->visible_rect);

    if (quad_visible_rect.IsEmpty())
      continue;

    if (delegated_quad->material != DrawQuad::RENDER_PASS) {
      DrawQuad* output_quad = render_pass->CopyFromAndAppendDrawQuad(
          delegated_quad, output_shared_quad_state);
      output_quad->visible_rect = quad_visible_rect;
    } else {
      RenderPassId delegated_contributing_render_pass_id =
          RenderPassDrawQuad::MaterialCast(delegated_quad)->render_pass_id;
      RenderPassId output_contributing_render_pass_id(-1, -1);

      bool present =
          ConvertDelegatedRenderPassId(delegated_contributing_render_pass_id,
                                       &output_contributing_render_pass_id);

      // The frame may have a RenderPassDrawQuad that points to a RenderPass not
      // part of the frame. Just ignore these quads.
      if (present) {
        DCHECK(output_contributing_render_pass_id != render_pass->id);

        RenderPassDrawQuad* output_quad =
            render_pass->CopyFromAndAppendRenderPassDrawQuad(
                RenderPassDrawQuad::MaterialCast(delegated_quad),
                output_shared_quad_state,
                output_contributing_render_pass_id);
        output_quad->visible_rect = quad_visible_rect;
      }
    }
  }
}

const char* DelegatedRendererLayerImpl::LayerTypeAsString() const {
  return "cc::DelegatedRendererLayerImpl";
}

void DelegatedRendererLayerImpl::ClearChildId() {
  if (!child_id_)
    return;

  if (own_child_id_) {
    ResourceProvider* provider = layer_tree_impl()->resource_provider();
    provider->DestroyChild(child_id_);
  }

  resources_.clear();
  child_id_ = 0;
}

}  // namespace cc
