// Copyright 2014 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/draw_property_utils.h"

#include <vector>

#include "cc/base/math_util.h"
#include "cc/layers/layer.h"
#include "cc/trees/property_tree.h"
#include "cc/trees/property_tree_builder.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {

namespace {

void CalculateVisibleRects(
    const std::vector<Layer*>& layers_that_need_visible_rects,
    const ClipTree& clip_tree,
    const TransformTree& transform_tree) {
  for (size_t i = 0; i < layers_that_need_visible_rects.size(); ++i) {
    Layer* layer = layers_that_need_visible_rects[i];

    // TODO(ajuma): Compute content_scale rather than using it. Note that for
    // PictureLayer and PictureImageLayers, content_bounds == bounds and
    // content_scale_x == content_scale_y == 1.0, so once impl painting is on
    // everywhere, this code will be unnecessary.
    gfx::Size layer_content_bounds = layer->content_bounds();
    float contents_scale_x = layer->contents_scale_x();
    float contents_scale_y = layer->contents_scale_y();
    const bool has_clip = layer->clip_tree_index() > 0;
    const TransformNode* transform_node =
        transform_tree.Node(layer->transform_tree_index());
    if (has_clip) {
      const ClipNode* clip_node = clip_tree.Node(layer->clip_tree_index());
      const TransformNode* clip_transform_node =
          transform_tree.Node(clip_node->data.transform_id);
      const TransformNode* target_node =
          transform_tree.Node(transform_node->data.target_id);

      gfx::Transform clip_to_target;
      gfx::Transform content_to_target;
      gfx::Transform target_to_content;
      gfx::Transform target_to_layer;

      bool success =
          transform_tree.ComputeTransform(clip_transform_node->id,
                                          target_node->id, &clip_to_target) &&
          transform_tree.ComputeTransform(transform_node->id, target_node->id,
                                          &content_to_target) &&
          transform_tree.ComputeTransform(target_node->id, transform_node->id,
                                          &target_to_layer);

      // This should only fail if we somehow got here with a singular ancestor.
      DCHECK(success);

      target_to_content.Scale(contents_scale_x, contents_scale_y);
      target_to_content.Translate(-layer->offset_to_transform_parent().x(),
                                  -layer->offset_to_transform_parent().y());
      target_to_content.PreconcatTransform(target_to_layer);

      content_to_target.Translate(layer->offset_to_transform_parent().x(),
                                  layer->offset_to_transform_parent().y());
      content_to_target.Scale(1.0 / contents_scale_x, 1.0 / contents_scale_y);

      gfx::Rect layer_content_rect = gfx::Rect(layer_content_bounds);
      gfx::RectF layer_content_bounds_in_target_space =
          MathUtil::MapClippedRect(content_to_target, layer_content_rect);
      gfx::RectF clip_rect_in_target_space;
      if (target_node->id > clip_node->id) {
        clip_rect_in_target_space = MathUtil::ProjectClippedRect(
            clip_to_target, clip_node->data.combined_clip);
      } else {
        clip_rect_in_target_space = MathUtil::MapClippedRect(
            clip_to_target, clip_node->data.combined_clip);
      }

      clip_rect_in_target_space.Intersect(layer_content_bounds_in_target_space);

      gfx::Rect visible_rect =
          gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
              target_to_content, clip_rect_in_target_space));

      visible_rect.Intersect(gfx::Rect(layer_content_bounds));

      layer->set_visible_rect_from_property_trees(visible_rect);
    } else {
      layer->set_visible_rect_from_property_trees(
          gfx::Rect(layer_content_bounds));
    }
  }
}

static bool IsRootLayerOfNewRenderingContext(Layer* layer) {
  if (layer->parent())
    return !layer->parent()->Is3dSorted() && layer->Is3dSorted();
  return layer->Is3dSorted();
}

static inline bool LayerIsInExisting3DRenderingContext(Layer* layer) {
  return layer->Is3dSorted() && layer->parent() &&
         layer->parent()->Is3dSorted();
}

static bool TransformToScreenIsKnown(Layer* layer, const TransformTree& tree) {
  const TransformNode* node = tree.Node(layer->transform_tree_index());
  return !node->data.to_screen_is_animated;
}

static bool IsLayerBackFaceExposed(Layer* layer, const TransformTree& tree) {
  if (!TransformToScreenIsKnown(layer, tree))
    return false;
  if (LayerIsInExisting3DRenderingContext(layer))
    return layer->draw_transform_from_property_trees(tree).IsBackFaceVisible();
  return layer->transform().IsBackFaceVisible();
}

static bool IsSurfaceBackFaceExposed(Layer* layer,
                                     const TransformTree& tree) {
  if (!TransformToScreenIsKnown(layer, tree))
    return false;
  if (LayerIsInExisting3DRenderingContext(layer))
    return layer->draw_transform_from_property_trees(tree).IsBackFaceVisible();

  if (IsRootLayerOfNewRenderingContext(layer))
    return layer->transform().IsBackFaceVisible();

  // If the render_surface is not part of a new or existing rendering context,
  // then the layers that contribute to this surface will decide back-face
  // visibility for themselves.
  return false;
}

static bool HasSingularTransform(Layer* layer, const TransformTree& tree) {
  const TransformNode* node = tree.Node(layer->transform_tree_index());
  return !node->data.is_invertible || !node->data.ancestors_are_invertible;
}

static bool IsBackFaceInvisible(Layer* layer, const TransformTree& tree) {
  Layer* backface_test_layer = layer;
  if (layer->use_parent_backface_visibility()) {
    DCHECK(layer->parent());
    DCHECK(!layer->parent()->use_parent_backface_visibility());
    backface_test_layer = layer->parent();
  }
  return !backface_test_layer->double_sided() &&
         IsLayerBackFaceExposed(backface_test_layer, tree);
}

static bool IsInvisibleDueToTransform(Layer* layer, const TransformTree& tree) {
  return HasSingularTransform(layer, tree) || IsBackFaceInvisible(layer, tree);
}

void FindLayersThatNeedVisibleRects(Layer* layer,
                                    const TransformTree& tree,
                                    bool subtree_is_visible_from_ancestor,
                                    std::vector<Layer*>* layers_to_update) {
  const bool subtree_is_invisble =
      layer->opacity() == 0.0f ||
      (layer->has_render_surface() && !layer->double_sided() &&
       IsSurfaceBackFaceExposed(layer, tree));

  if (subtree_is_invisble)
    return;

  bool layer_is_drawn =
      layer->HasCopyRequest() ||
      (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree());

  if (layer_is_drawn && layer->DrawsContent()) {
    const bool visible = !IsInvisibleDueToTransform(layer, tree);
    if (visible)
      layers_to_update->push_back(layer);
  }

  for (size_t i = 0; i < layer->children().size(); ++i) {
    FindLayersThatNeedVisibleRects(layer->children()[i].get(),
                                   tree,
                                   layer_is_drawn,
                                   layers_to_update);
  }
}

}  // namespace

void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) {
  for (int i = 0; i < static_cast<int>(clip_tree->size()); ++i) {
    ClipNode* clip_node = clip_tree->Node(i);

    // Only descendants of a real clipping layer (i.e., not 0) may have their
    // clip adjusted due to intersecting with an ancestor clip.
    const bool is_clipped = clip_node->parent_id > 0;
    if (!is_clipped) {
      clip_node->data.combined_clip = clip_node->data.clip;
      continue;
    }

    ClipNode* parent_clip_node = clip_tree->parent(clip_node);
    const TransformNode* parent_transform_node =
        transform_tree.Node(parent_clip_node->data.transform_id);
    const TransformNode* transform_node =
        transform_tree.Node(clip_node->data.transform_id);

    // Clips must be combined in target space. We cannot, for example, combine
    // clips in the space of the child clip. The reason is non-affine
    // transforms. Say we have the following tree T->A->B->C, and B clips C, but
    // draw into target T. It may be the case that A applies a perspective
    // transform, and B and C are at different z positions. When projected into
    // target space, the relative sizes and positions of B and C can shift.
    // Since it's the relationship in target space that matters, that's where we
    // must combine clips.
    gfx::Transform parent_to_target;
    gfx::Transform clip_to_target;
    gfx::Transform target_to_clip;

    bool success =
        transform_tree.ComputeTransform(parent_transform_node->id,
                                        clip_node->data.target_id,
                                        &parent_to_target) &&
        transform_tree.ComputeTransform(
            transform_node->id, clip_node->data.target_id, &clip_to_target) &&
        transform_tree.ComputeTransform(clip_node->data.target_id,
                                        transform_node->id, &target_to_clip);

    // If we can't compute a transform, it's because we had to use the inverse
    // of a singular transform. We won't draw in this case, so there's no need
    // to compute clips.
    if (!success)
      continue;

    // In order to intersect with as small a rect as possible, we do a
    // preliminary clip in target space so that when we project back, there's
    // less likelihood of intersecting the view plane.
    gfx::RectF inherited_clip_in_target_space = MathUtil::MapClippedRect(
        parent_to_target, parent_clip_node->data.combined_clip);

    gfx::RectF clip_in_target_space =
        MathUtil::MapClippedRect(clip_to_target, clip_node->data.clip);

    gfx::RectF intersected_in_target_space = gfx::IntersectRects(
        inherited_clip_in_target_space, clip_in_target_space);

    clip_node->data.combined_clip = MathUtil::ProjectClippedRect(
        target_to_clip, intersected_in_target_space);

    clip_node->data.combined_clip.Intersect(clip_node->data.clip);
  }
}

void ComputeTransforms(TransformTree* transform_tree) {
  for (int i = 1; i < static_cast<int>(transform_tree->size()); ++i)
    transform_tree->UpdateTransforms(i);
}

void ComputeVisibleRectsUsingPropertyTrees(
    Layer* root_layer,
    const Layer* page_scale_layer,
    float page_scale_factor,
    float device_scale_factor,
    const gfx::Rect& viewport,
    const gfx::Transform& device_transform,
    TransformTree* transform_tree,
    ClipTree* clip_tree) {
  PropertyTreeBuilder::BuildPropertyTrees(
      root_layer, page_scale_layer, page_scale_factor, device_scale_factor,
      viewport, device_transform, transform_tree, clip_tree);
  ComputeTransforms(transform_tree);
  ComputeClips(clip_tree, *transform_tree);

  std::vector<Layer*> layers_to_update;
  const bool subtree_is_visible_from_ancestor = true;
  FindLayersThatNeedVisibleRects(root_layer, *transform_tree,
                                 subtree_is_visible_from_ancestor,
                                 &layers_to_update);
  CalculateVisibleRects(layers_to_update, *clip_tree, *transform_tree);
}

}  // namespace cc
