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

#include <stddef.h>

#include <algorithm>

#include "cc/base/math_util.h"
#include "cc/base/region.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/trees/layer_tree_impl.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/rect_conversions.h"

namespace cc {

OcclusionTracker::OcclusionTracker(const gfx::Rect& screen_space_clip_rect)
    : screen_space_clip_rect_(screen_space_clip_rect) {
}

OcclusionTracker::~OcclusionTracker() = default;

Occlusion OcclusionTracker::GetCurrentOcclusionForLayer(
    const gfx::Transform& draw_transform) const {
  DCHECK(!stack_.empty());
  const StackObject& back = stack_.back();
  return Occlusion(draw_transform,
                   back.occlusion_from_outside_target,
                   back.occlusion_from_inside_target);
}

Occlusion OcclusionTracker::GetCurrentOcclusionForContributingSurface(
    const gfx::Transform& draw_transform) const {
  DCHECK(!stack_.empty());
  if (stack_.size() < 2)
    return Occlusion();
  // A contributing surface doesn't get occluded by things inside its own
  // surface, so only things outside the surface can occlude it. That occlusion
  // is found just below the top of the stack (if it exists).
  const StackObject& second_last = stack_[stack_.size() - 2];
  return Occlusion(draw_transform, second_last.occlusion_from_outside_target,
                   second_last.occlusion_from_inside_target);
}

const RenderSurfaceImpl*
OcclusionTracker::OcclusionSurfaceForContributingSurface() const {
  // A contributing surface doesn't get occluded by things inside its own
  // surface, so only things outside the surface can occlude it. That occlusion
  // is found just below the top of the stack (if it exists).
  return (stack_.size() < 2) ? nullptr : stack_[stack_.size() - 2].target;
}

void OcclusionTracker::EnterLayer(
    const EffectTreeLayerListIterator::Position& iterator) {
  RenderSurfaceImpl* render_target = iterator.target_render_surface;

  if (iterator.state == EffectTreeLayerListIterator::State::LAYER)
    EnterRenderTarget(render_target);
  else if (iterator.state == EffectTreeLayerListIterator::State::TARGET_SURFACE)
    FinishedRenderTarget(render_target);
}

void OcclusionTracker::LeaveLayer(
    const EffectTreeLayerListIterator::Position& iterator) {
  RenderSurfaceImpl* render_target = iterator.target_render_surface;

  if (iterator.state == EffectTreeLayerListIterator::State::LAYER)
    MarkOccludedBehindLayer(iterator.current_layer);
  // TODO(danakj): This should be done when entering the contributing surface,
  // but in a way that the surface's own occlusion won't occlude itself.
  else if (iterator.state ==
           EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE)
    LeaveToRenderTarget(render_target);
}

static gfx::Rect ScreenSpaceClipRectInTargetSurface(
    const RenderSurfaceImpl* target_surface,
    const gfx::Rect& screen_space_clip_rect) {
  gfx::Transform inverse_screen_space_transform(
      gfx::Transform::kSkipInitialization);
  if (!target_surface->screen_space_transform().GetInverse(
          &inverse_screen_space_transform))
    return target_surface->content_rect();

  return MathUtil::ProjectEnclosingClippedRect(inverse_screen_space_transform,
                                               screen_space_clip_rect);
}

static SimpleEnclosedRegion TransformSurfaceOpaqueRegion(
    const SimpleEnclosedRegion& region,
    bool have_clip_rect,
    const gfx::Rect& clip_rect_in_new_target,
    const gfx::Transform& transform) {
  if (region.IsEmpty())
    return region;

  // Verify that rects within the |surface| will remain rects in its target
  // surface after applying |transform|. If this is true, then apply |transform|
  // to each rect within |region| in order to transform the entire Region.

  // TODO(danakj): Find a rect interior to each transformed quad.
  if (!transform.Preserves2dAxisAlignment())
    return SimpleEnclosedRegion();

  SimpleEnclosedRegion transformed_region;
  for (size_t i = 0; i < region.GetRegionComplexity(); ++i) {
    gfx::Rect transformed_rect =
        MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform,
                                                            region.GetRect(i));
    if (have_clip_rect)
      transformed_rect.Intersect(clip_rect_in_new_target);
    transformed_region.Union(transformed_rect);
  }
  return transformed_region;
}

void OcclusionTracker::EnterRenderTarget(
    const RenderSurfaceImpl* new_target_surface) {
  DCHECK(new_target_surface);
  if (!stack_.empty() && stack_.back().target == new_target_surface)
    return;

  const RenderSurfaceImpl* old_target_surface = nullptr;
  const RenderSurfaceImpl* old_occlusion_immune_ancestor = nullptr;
  if (!stack_.empty()) {
    old_target_surface = stack_.back().target;
    old_occlusion_immune_ancestor =
        old_target_surface->nearest_occlusion_immune_ancestor();
  }
  const RenderSurfaceImpl* new_occlusion_immune_ancestor =
      new_target_surface->nearest_occlusion_immune_ancestor();

  stack_.emplace_back(new_target_surface);

  // We copy the screen occlusion into the new RenderSurfaceImpl subtree, but we
  // never copy in the occlusion from inside the target, since we are looking
  // at a new RenderSurfaceImpl target.

  // If entering an unoccluded subtree, do not carry forward the outside
  // occlusion calculated so far.
  bool entering_unoccluded_subtree =
      new_occlusion_immune_ancestor &&
      new_occlusion_immune_ancestor != old_occlusion_immune_ancestor;

  gfx::Transform inverse_new_target_screen_space_transform(
      // Note carefully, not used if screen space transform is uninvertible.
      gfx::Transform::kSkipInitialization);
  bool have_transform_from_screen_to_new_target =
      new_target_surface->screen_space_transform().GetInverse(
          &inverse_new_target_screen_space_transform);

  bool entering_root_target =
      new_target_surface->render_target() == new_target_surface;

  bool copy_outside_occlusion_forward =
      stack_.size() > 1 &&
      !entering_unoccluded_subtree &&
      have_transform_from_screen_to_new_target &&
      !entering_root_target;
  if (!copy_outside_occlusion_forward)
    return;

  size_t last_index = stack_.size() - 1;
  gfx::Transform old_target_to_new_target_transform(
      inverse_new_target_screen_space_transform,
      old_target_surface->screen_space_transform());
  stack_[last_index].occlusion_from_outside_target =
      TransformSurfaceOpaqueRegion(
          stack_[last_index - 1].occlusion_from_outside_target, false,
          gfx::Rect(), old_target_to_new_target_transform);
  stack_[last_index].occlusion_from_outside_target.Union(
      TransformSurfaceOpaqueRegion(
          stack_[last_index - 1].occlusion_from_inside_target, false,
          gfx::Rect(), old_target_to_new_target_transform));
}

void OcclusionTracker::FinishedRenderTarget(
    const RenderSurfaceImpl* finished_target_surface) {
  // Make sure we know about the target surface.
  EnterRenderTarget(finished_target_surface);

  bool is_hidden =
      finished_target_surface->OwningEffectNode()->screen_space_opacity == 0.f;

  // Readbacks always happen on render targets so we only need to check
  // for readbacks here.
  bool target_is_only_for_copy_request_or_force_render_surface =
      (finished_target_surface->HasCopyRequest() ||
       finished_target_surface->ShouldCacheRenderSurface()) &&
      is_hidden;

  // If the occlusion within the surface can not be applied to things outside of
  // the surface's subtree, then clear the occlusion here so it won't be used.
  if (finished_target_surface->HasMask() ||
      finished_target_surface->HasMaskingContributingSurface() ||
      finished_target_surface->draw_opacity() < 1 ||
      !finished_target_surface->UsesDefaultBlendMode() ||
      target_is_only_for_copy_request_or_force_render_surface ||
      finished_target_surface->Filters().HasFilterThatAffectsOpacity()) {
    stack_.back().occlusion_from_outside_target.Clear();
    stack_.back().occlusion_from_inside_target.Clear();
  }
}

static void ReduceOcclusionBelowSurface(
    const RenderSurfaceImpl* contributing_surface,
    const gfx::Rect& surface_rect,
    const gfx::Transform& surface_transform,
    SimpleEnclosedRegion* occlusion_from_inside_target) {
  if (surface_rect.IsEmpty())
    return;

  gfx::Rect target_rect =
      MathUtil::MapEnclosingClippedRect(surface_transform, surface_rect);
  if (contributing_surface->is_clipped()) {
    target_rect.Intersect(contributing_surface->clip_rect());
  }
  if (target_rect.IsEmpty())
    return;

  gfx::Rect affected_area_in_target =
      contributing_surface->BackdropFilters().MapRectReverse(target_rect,
                                                             SkMatrix::I());
  // Unite target_rect because we only care about positive outsets.
  affected_area_in_target.Union(target_rect);

  SimpleEnclosedRegion affected_occlusion = *occlusion_from_inside_target;
  affected_occlusion.Intersect(affected_area_in_target);

  occlusion_from_inside_target->Subtract(affected_area_in_target);
  for (size_t i = 0; i < affected_occlusion.GetRegionComplexity(); ++i) {
    gfx::Rect occlusion_rect = affected_occlusion.GetRect(i);

    // Shrink the rect by expanding the non-opaque pixels outside the rect.

    // The left outset of the filters moves pixels on the right side of
    // the occlusion_rect into it, shrinking its right edge.
    int shrink_left =
        occlusion_rect.x() == affected_area_in_target.x()
            ? 0
            : affected_area_in_target.right() - target_rect.right();
    int shrink_top =
        occlusion_rect.y() == affected_area_in_target.y()
            ? 0
            : affected_area_in_target.bottom() - target_rect.bottom();
    int shrink_right = occlusion_rect.right() == affected_area_in_target.right()
                           ? 0
                           : target_rect.x() - affected_area_in_target.x();
    int shrink_bottom =
        occlusion_rect.bottom() == affected_area_in_target.bottom()
            ? 0
            : target_rect.y() - affected_area_in_target.y();

    occlusion_rect.Inset(shrink_left, shrink_top, shrink_right, shrink_bottom);

    occlusion_from_inside_target->Union(occlusion_rect);
  }
}

void OcclusionTracker::LeaveToRenderTarget(
    const RenderSurfaceImpl* new_target_surface) {
  DCHECK(!stack_.empty());
  size_t last_index = stack_.size() - 1;
  DCHECK(new_target_surface);
  bool surface_will_be_at_top_after_pop =
      stack_.size() > 1 && stack_[last_index - 1].target == new_target_surface;

  // We merge the screen occlusion from the current RenderSurfaceImpl subtree
  // out to its parent target RenderSurfaceImpl. The target occlusion can be
  // merged out as well but needs to be transformed to the new target.

  const RenderSurfaceImpl* old_surface = stack_[last_index].target;

  SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target =
      TransformSurfaceOpaqueRegion(
          stack_[last_index].occlusion_from_inside_target,
          old_surface->is_clipped(), old_surface->clip_rect(),
          old_surface->draw_transform());

  SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target =
      TransformSurfaceOpaqueRegion(
          stack_[last_index].occlusion_from_outside_target, false, gfx::Rect(),
          old_surface->draw_transform());

  gfx::Rect unoccluded_surface_rect;
  if (old_surface->BackdropFilters().HasFilterThatMovesPixels()) {
    Occlusion surface_occlusion = GetCurrentOcclusionForContributingSurface(
        old_surface->draw_transform());
    unoccluded_surface_rect =
        surface_occlusion.GetUnoccludedContentRect(old_surface->content_rect());
  }

  bool is_root = new_target_surface->render_target() == new_target_surface;
  if (surface_will_be_at_top_after_pop) {
    // Merge the top of the stack down.
    stack_[last_index - 1].occlusion_from_inside_target.Union(
        old_occlusion_from_inside_target_in_new_target);
    // TODO(danakj): Strictly this should subtract the inside target occlusion
    // before union.
    if (!is_root) {
      stack_[last_index - 1].occlusion_from_outside_target.Union(
          old_occlusion_from_outside_target_in_new_target);
    }
    stack_.pop_back();
  } else {
    // Replace the top of the stack with the new pushed surface.
    stack_.back().target = new_target_surface;
    stack_.back().occlusion_from_inside_target =
        old_occlusion_from_inside_target_in_new_target;
    if (!is_root) {
      stack_.back().occlusion_from_outside_target =
          old_occlusion_from_outside_target_in_new_target;
    } else {
      stack_.back().occlusion_from_outside_target.Clear();
    }
  }

  if (!old_surface->BackdropFilters().HasFilterThatMovesPixels())
    return;

  ReduceOcclusionBelowSurface(old_surface, unoccluded_surface_rect,
                              old_surface->draw_transform(),
                              &stack_.back().occlusion_from_inside_target);
  ReduceOcclusionBelowSurface(old_surface, unoccluded_surface_rect,
                              old_surface->draw_transform(),
                              &stack_.back().occlusion_from_outside_target);
}

void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) {
  DCHECK(!stack_.empty());
  DCHECK_EQ(layer->render_target(), stack_.back().target);

  if (layer->draw_opacity() < 1)
    return;

  if (layer->Is3dSorted())
    return;

  SimpleEnclosedRegion opaque_layer_region = layer->VisibleOpaqueRegion();
  if (opaque_layer_region.IsEmpty())
    return;

  DCHECK(layer->visible_layer_rect().Contains(opaque_layer_region.bounds()));

  gfx::Transform draw_transform = layer->DrawTransform();
  // TODO(danakj): Find a rect interior to each transformed quad.
  if (!draw_transform.Preserves2dAxisAlignment())
    return;

  gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface(
      layer->render_target(), screen_space_clip_rect_);
  if (layer->is_clipped()) {
    clip_rect_in_target.Intersect(layer->clip_rect());
  } else {
    clip_rect_in_target.Intersect(layer->render_target()->content_rect());
  }

  for (size_t i = 0; i < opaque_layer_region.GetRegionComplexity(); ++i) {
    gfx::Rect transformed_rect =
        MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
            draw_transform, opaque_layer_region.GetRect(i));
    transformed_rect.Intersect(clip_rect_in_target);
    if (transformed_rect.width() < minimum_tracking_size_.width() &&
        transformed_rect.height() < minimum_tracking_size_.height())
      continue;
    stack_.back().occlusion_from_inside_target.Union(transformed_rect);
  }
}

Region OcclusionTracker::ComputeVisibleRegionInScreen(
    const LayerTreeImpl* layer_tree) const {
  DCHECK(layer_tree->RootRenderSurface() == stack_.back().target);
  const SimpleEnclosedRegion& occluded =
      stack_.back().occlusion_from_inside_target;
  Region visible_region(screen_space_clip_rect_);
  for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i)
    visible_region.Subtract(occluded.GetRect(i));
  return visible_region;
}

}  // namespace cc
