// 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 "third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h"

#include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"

namespace blink {
static const LayoutBoxModelObject* ClippingContainerFromClipChainParent(
    const PaintLayer* clip_chain_parent) {
  return clip_chain_parent->GetLayoutObject().HasClipRelatedProperty()
             ? &clip_chain_parent->GetLayoutObject()
             : clip_chain_parent->ClippingContainer();
}

CompositingInputsUpdater::CompositingInputsUpdater(
    PaintLayer* root_layer,
    PaintLayer* compositing_inputs_root)
    : root_layer_(root_layer),
      compositing_inputs_root_(compositing_inputs_root) {
  if (!RuntimeEnabledFeatures::CompositingOptimizationsEnabled())
    geometry_map_.emplace();
}

CompositingInputsUpdater::~CompositingInputsUpdater() = default;

bool CompositingInputsUpdater::LayerOrDescendantShouldBeComposited(
    PaintLayer* layer) {
  if (auto* layout_view = DynamicTo<LayoutView>(layer->GetLayoutObject())) {
    if (layout_view->AdditionalCompositingReasons())
      return true;
    // The containing frame may call this function for the root layer of a
    // throttled frame. In that case, look for a pre-existing root GraphicsLayer
    // in the iframe's compositor.
    if (layout_view->GetFrameView()->ShouldThrottleRendering()) {
      DisableCompositingQueryAsserts disabler;
      if (auto* inner_compositor = layout_view->Compositor()) {
        if (inner_compositor->RootGraphicsLayer())
          return true;
      }
      return false;
    }
  }
  DCHECK(!layer->GetLayoutObject().GetFrameView()->ShouldThrottleRendering());
  PaintLayerCompositor* compositor =
      layer->GetLayoutObject().View()->Compositor();
  return layer->DescendantHasDirectOrScrollingCompositingReason() ||
         layer->NeedsCompositedScrolling() ||
         (compositor->CanBeComposited(layer) &&
          layer->DirectCompositingReasons());
}

void CompositingInputsUpdater::Update() {
  TRACE_EVENT0("blink", "CompositingInputsUpdater::update");

  AncestorInfo info;
  UpdateType update_type = kDoNotForceUpdate;
  PaintLayer* layer =
      compositing_inputs_root_ ? compositing_inputs_root_ : root_layer_;

  // We don't need to do anything if the layer is under a locked display lock
  // that prevents updates.
  if (DisplayLockUtilities::LockedAncestorPreventingPrePaint(
          layer->GetLayoutObject())) {
    return;
  }

  CompositingReasons initial_compositing_reasons =
      layer->DirectCompositingReasons();
  ApplyAncestorInfoToSelfAndAncestorsRecursively(layer, update_type, info);
  UpdateSelfAndDescendantsRecursively(layer, update_type, info);

  // The layer has changed from non-compositing to compositing
  if (initial_compositing_reasons == CompositingReason::kNone &&
      LayerOrDescendantShouldBeComposited(layer)) {
    // Update all parent layers
    PaintLayer* parent_layer = layer->Parent();
    while (parent_layer) {
      parent_layer->SetDescendantHasDirectOrScrollingCompositingReason(true);
      parent_layer = parent_layer->Parent();
    }
  }
}

void CompositingInputsUpdater::ApplyAncestorInfoToSelfAndAncestorsRecursively(
    PaintLayer* layer,
    UpdateType& update_type,
    AncestorInfo& info) {
  if (!layer)
    return;

  // We first recursively call ApplyAncestorInfoToSelfAndAncestorsRecursively()
  // to ensure that we start to compute the geometry_map_ and AncestorInfo from
  // the root layer (as we need to do a top-down tree walk to incrementally
  // update this information).
  ApplyAncestorInfoToSelfAndAncestorsRecursively(layer->Parent(), update_type,
                                                 info);
  if (!RuntimeEnabledFeatures::CompositingOptimizationsEnabled())
    geometry_map_->PushMappingsToAncestor(layer, layer->Parent());
  UpdateAncestorInfo(layer, update_type, info);
}

void CompositingInputsUpdater::UpdateSelfAndDescendantsRecursively(
    PaintLayer* layer,
    UpdateType update_type,
    AncestorInfo info) {
  LayoutBoxModelObject& layout_object = layer->GetLayoutObject();

  // geometry_map_ has been already updated in ApplyAncestorInfo() and
  // UpdateAncestorInfo has been already computed in ApplyAncestorInfo() for
  // layers from root_layer_ down to compositing_inputs_root_ both included.
  if (layer != root_layer_ && layer != compositing_inputs_root_) {
    if (!RuntimeEnabledFeatures::CompositingOptimizationsEnabled())
      geometry_map_->PushMappingsToAncestor(layer, layer->Parent());
    UpdateAncestorInfo(layer, update_type, info);
  }

  PaintLayerCompositor* compositor =
      layer->GetLayoutObject().View()->Compositor();

  // The sequence of updates to compositing triggers goes like this:
  // 1. Apply all triggers from kComboAllDirectNonStyleDeterminedReasons for
  //    |layer|. This may depend on ancestor composited scrolling (i.e. step
  //    2 for an ancestor PaintLayer).
  // 2. Put |layer| in composited scrolling mode if needed.
  // 3. Reset DescendantHasDirectCompositingReason to false for |layer|.
  // 4. Recurse into child PaintLayers.
  // 5. Set DescendantHasDirectCompositingReason to true if it was for any
  //    child.
  // 6. If |layer| is the root, composite if
  //    DescendantHasDirectCompositingReason is true for |layer|.

  layer->SetPotentialCompositingReasonsFromNonStyle(
      CompositingReasonFinder::NonStyleDeterminedDirectReasons(*layer));

  if (layer->GetScrollableArea()) {
    layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(
        compositor->CanBeComposited(layer) &&
        layer->DirectCompositingReasons());
  }

  // Note that prepaint may use the compositing information, so only skip
  // recursing it if we're skipping prepaint.
  bool recursion_blocked_by_display_lock =
      layer->GetLayoutObject().ChildPrePaintBlockedByDisplayLock();

  bool should_recurse = (layer->ChildNeedsCompositingInputsUpdate() ||
                         update_type == kForceUpdate);

  layer->SetDescendantHasDirectOrScrollingCompositingReason(false);
  bool descendant_has_direct_compositing_reason = false;

  auto* first_child =
      recursion_blocked_by_display_lock ? nullptr : layer->FirstChild();
  for (PaintLayer* child = first_child; child; child = child->NextSibling()) {
    if (should_recurse)
      UpdateSelfAndDescendantsRecursively(child, update_type, info);
    descendant_has_direct_compositing_reason |=
        LayerOrDescendantShouldBeComposited(child);
  }
  if (!descendant_has_direct_compositing_reason &&
      layer->GetLayoutObject().IsLayoutEmbeddedContent()) {
    if (LayoutView* embedded_layout_view =
            To<LayoutEmbeddedContent>(layer->GetLayoutObject())
                .ChildLayoutView()) {
      descendant_has_direct_compositing_reason |=
          LayerOrDescendantShouldBeComposited(embedded_layout_view->Layer());
    }
  }
  layer->SetDescendantHasDirectOrScrollingCompositingReason(
      descendant_has_direct_compositing_reason);

  if ((layer->IsRootLayer() || layer->NeedsReorderOverlayOverflowControls()) &&
      layer->ScrollsOverflow() &&
      layer->DescendantHasDirectOrScrollingCompositingReason() &&
      !layer->NeedsCompositedScrolling())
    layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(true);

  // If display lock blocked this recursion, then keep the dirty bit around
  // since it is a breadcrumb that will allow us to recurse later when we unlock
  // the element.
  if (!recursion_blocked_by_display_lock)
    layer->ClearChildNeedsCompositingInputsUpdate();

  if (!RuntimeEnabledFeatures::CompositingOptimizationsEnabled())
    geometry_map_->PopMappingsToAncestor(layer->Parent());

  if (layer->SelfPaintingStatusChanged()) {
    layer->ClearSelfPaintingStatusChanged();
    // If the floating object becomes non-self-painting, so some ancestor should
    // paint it; if it becomes self-painting, it should paint itself and no
    // ancestor should paint it.
    if (layout_object.IsFloating()) {
      LayoutBlockFlow::UpdateAncestorShouldPaintFloatingObject(
          *layer->GetLayoutBox());
    }
  }

  compositor->ClearCompositingInputsRoot();

  DisableCompositingQueryAsserts disabler;

  bool previously_needed_paint_offset_translation =
      layer->NeedsPaintOffsetTranslationForCompositing();

  layer->SetNeedsPaintOffsetTranslationForCompositing(
      NeedsPaintOffsetTranslationForCompositing(layer));

  // Invalidate if needed to affect NeedsPaintOffsetTranslation().
  if (previously_needed_paint_offset_translation !=
      layer->NeedsPaintOffsetTranslationForCompositing())
    layout_object.SetNeedsPaintPropertyUpdate();
}

bool CompositingInputsUpdater::NeedsPaintOffsetTranslationForCompositing(
    PaintLayer* layer) {
  PaintLayerCompositor* compositor =
      layer->GetLayoutObject().View()->Compositor();

  /// Allocate when the developer indicated compositing via a direct
  // method.
  if ((compositor->CanBeComposited(layer) &&
       layer->DirectCompositingReasons()) ||
      layer->NeedsCompositedScrolling())
    return true;

  // Allocate when there is a need for a cc effect that applies to
  // descendants.
  // TODO(chrishtr): this should not be necessary, but currently at least
  // cc mask layers don't apply correctly otherwise.
  // compositing/clip-path-with-composited-descendants.html is one test
  // that demonstrates this.
  if ((layer->PotentialCompositingReasonsFromStyle() &
       CompositingReason::kComboCompositedDescendants) &&
      layer->DescendantHasDirectOrScrollingCompositingReason())
    return true;

  return false;
}

void CompositingInputsUpdater::UpdateAncestorInfo(PaintLayer* const layer,
                                                  UpdateType& update_type,
                                                  AncestorInfo& info) {
  LayoutBoxModelObject& layout_object = layer->GetLayoutObject();
  const ComputedStyle& style = layout_object.StyleRef();

  PaintLayer* enclosing_stacking_composited_layer =
      info.enclosing_stacking_composited_layer;
  PaintLayer* enclosing_squashing_composited_layer =
      info.enclosing_squashing_composited_layer;

  DisableCompositingQueryAsserts disabler;

  if (layer->NeedsCompositingInputsUpdate()) {
    if (enclosing_stacking_composited_layer) {
      enclosing_stacking_composited_layer->GetCompositedLayerMapping()
          ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
    }

    if (enclosing_squashing_composited_layer) {
      enclosing_squashing_composited_layer->GetCompositedLayerMapping()
          ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
    }

    update_type = kForceUpdate;
  }

  switch (layer->GetCompositingState()) {
    case kNotComposited:
      break;
    case kPaintsIntoOwnBacking:
      if (layout_object.IsStackingContext())
        enclosing_stacking_composited_layer = layer;
      break;
    case kPaintsIntoGroupedBacking:
      enclosing_squashing_composited_layer =
          &layer->GroupedMapping()->OwningLayer();
      break;
  }

  // invalidate again after the switch, in case
  // enclosing_stacking_composited_layer or
  // enclosing_squashing_composited_layer was previously null.
  if (layer->NeedsCompositingInputsUpdate()) {
    if (enclosing_stacking_composited_layer) {
      enclosing_stacking_composited_layer->GetCompositedLayerMapping()
          ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
    }

    if (enclosing_squashing_composited_layer) {
      enclosing_squashing_composited_layer->GetCompositedLayerMapping()
          ->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
    }
  }

  if (style.GetPosition() == EPosition::kAbsolute) {
    info.escape_clip_to = info.escape_clip_to_for_absolute;
    info.scrolling_ancestor = info.scrolling_ancestor_for_absolute;
    info.needs_reparent_scroll = info.needs_reparent_scroll_for_absolute;
  } else if (style.GetPosition() == EPosition::kFixed) {
    info.escape_clip_to = info.escape_clip_to_for_fixed;
    info.scrolling_ancestor = info.scrolling_ancestor_for_fixed;
    info.needs_reparent_scroll = info.needs_reparent_scroll_for_fixed;
  }

  if (layout_object.ShouldApplyLayoutContainment())
    info.nearest_contained_layout_layer = layer;

  if (update_type == kForceUpdate)
    UpdateAncestorDependentCompositingInputs(layer, info);

  info.enclosing_stacking_composited_layer =
      enclosing_stacking_composited_layer;
  info.enclosing_squashing_composited_layer =
      enclosing_squashing_composited_layer;

  // Handles sibling scroll problem, i.e. a non-stacking context scroller
  // needs to propagate scroll to its descendants that are siblings in
  // paint order. For example:
  // <div style="overflow:scroll;">
  //   <div style="position:relative;">Paint sibling.</div>
  // </div>
  if (layer->ScrollsOverflow()) {
    info.scrolling_ancestor = layer;
    info.needs_reparent_scroll = true;
  }
  if (layout_object.CanContainAbsolutePositionObjects()) {
    info.clip_chain_parent_for_absolute = layer;
    info.escape_clip_to_for_absolute = info.escape_clip_to;
    info.scrolling_ancestor_for_absolute = info.scrolling_ancestor;
    info.needs_reparent_scroll_for_absolute = info.needs_reparent_scroll;
  }

  // LayoutView isn't really the containing block for fixed-pos descendants
  // in the sense that they don't scroll along with its in-flow contents.
  // However LayoutView does clip them.
  if (layout_object.CanContainFixedPositionObjects() &&
      !IsA<LayoutView>(layout_object)) {
    info.clip_chain_parent_for_fixed = layer;
    info.escape_clip_to_for_fixed = info.escape_clip_to;
    info.scrolling_ancestor_for_fixed = info.scrolling_ancestor;
    info.needs_reparent_scroll_for_fixed = info.needs_reparent_scroll;
  }
  if (IsA<LayoutView>(layout_object))
    info.clip_chain_parent_for_fixed = layer;

  // CSS clip affects all descendants, not just containing-block descendants.
  // We don't have to set clip_chain_parent_for_absolute here because CSS clip
  // requires position:absolute, so the element must contain absolute-positioned
  // descendants.
  // However it is incorrect to let fixed-positioned descendants to inherit the
  // clip state from this element either, because the overflow clip and the
  // inherited clip of the current element shouldn't apply to them if the
  // current element is not a fixed-pos container. This is a known bug but too
  // difficult to fix in SPv1 compositing.
  if (layout_object.HasClip())
    info.clip_chain_parent_for_fixed = layer;

  if (layout_object.IsStackingContext()) {
    info.escape_clip_to = nullptr;
    const LayoutBoxModelObject* clipping_container =
        ClippingContainerFromClipChainParent(layer);
    info.escape_clip_to_for_absolute =
        ClippingContainerFromClipChainParent(
            info.clip_chain_parent_for_absolute) != clipping_container
            ? info.clip_chain_parent_for_absolute
            : nullptr;
    info.escape_clip_to_for_fixed =
        ClippingContainerFromClipChainParent(
            info.clip_chain_parent_for_fixed) != clipping_container
            ? info.clip_chain_parent_for_fixed
            : nullptr;
    // Workaround crbug.com/817175
    // We can't escape clip to a layer that paints after us, because in SPv1
    // cc needs to reverse engineer clip tree from the layer tree, and we
    // can't refer to a clip node that hasn't been built yet.
    // This will result in wrong clip in some rare cases, for example:
    // <div style="display:grid;">
    //   <div style="z-index:-1; overflow:hidden;">
    //     <div style="position:absolute;"></div>
    //   </div>
    // </div>
    if (info.escape_clip_to_for_absolute && style.EffectiveZIndex() < 0 &&
        !info.escape_clip_to_for_absolute->GetLayoutObject()
             .IsStackingContext())
      info.escape_clip_to_for_absolute = nullptr;
    if (info.escape_clip_to_for_fixed && style.EffectiveZIndex() < 0 &&
        !info.escape_clip_to_for_fixed->GetLayoutObject().IsStackingContext())
      info.escape_clip_to_for_fixed = nullptr;

    info.needs_reparent_scroll = info.needs_reparent_scroll_for_absolute =
        info.needs_reparent_scroll_for_fixed = false;
  }

  if (layout_object.IsStickyPositioned())
    info.is_under_position_sticky = true;
}

void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs(
    PaintLayer* layer,
    const AncestorInfo& info) {
  if (layer->IsRootLayer()) {
    layer->UpdateAncestorDependentCompositingInputs(
        PaintLayer::AncestorDependentCompositingInputs());
    return;
  }

  PaintLayer::AncestorDependentCompositingInputs properties;
  LayoutBoxModelObject& layout_object = layer->GetLayoutObject();

  if (!RuntimeEnabledFeatures::CompositingOptimizationsEnabled()) {
    // The final value for |unclipped_absolute_bounding_box| needs to be
    // in absolute, unscrolled space, without any scroll applied.

    properties.unclipped_absolute_bounding_box =
        EnclosingIntRect(geometry_map_->AbsoluteRect(
            layer->LocalBoundingBoxForCompositingOverlapTest()));

    bool affected_by_scroll = root_layer_->GetScrollableArea() &&
                              layer->IsAffectedByScrollOf(root_layer_);

    // At this point, |unclipped_absolute_bounding_box| is in viewport space.
    // To convert to absolute space, add scroll offset for non-fixed layers.
    // Content that is not affected by scroll, e.g. fixed-pos content and
    // children of that content, stays in viewport space so we can expand its
    // bounds during overlap testing without having a dependency on the scroll
    // offset at the time these properties are calculated.
    if (affected_by_scroll) {
      properties.unclipped_absolute_bounding_box.Move(
          RoundedIntSize(root_layer_->GetScrollableArea()->GetScrollOffset()));
    }

    // For sticky-positioned elements, the scroll offset is sometimes included
    // and sometimes not, depending on whether the sticky element is affixed or
    // still scrolling. This makes caching difficult, as compared to Fixed
    // position elements which have consistent behavior. So we disable caching
    // for sticky-positioned subtrees.
    ClipRectsCacheSlot cache_slot =
        info.is_under_position_sticky ? kUncachedClipRects
                                      : kAbsoluteClipRectsIgnoringViewportClip;

    ClipRect clip_rect;
    layer->Clipper(PaintLayer::GeometryMapperOption::kDoNotUseGeometryMapper)
        .CalculateBackgroundClipRect(
            ClipRectsContext(root_layer_,
                             &root_layer_->GetLayoutObject().FirstFragment(),
                             cache_slot, kIgnoreOverlayScrollbarSize,
                             kIgnoreOverflowClipAndScroll),
            clip_rect);
    IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
    // |snapped_clip_rect| is in absolute space space, but with scroll applied.
    // To convert to absolute, unscrolled space, subtract scroll offsets for
    // fixed layers.
    if (root_layer_->GetScrollableArea() && !affected_by_scroll) {
      snapped_clip_rect.Move(
          RoundedIntSize(-root_layer_->GetScrollableArea()->GetScrollOffset()));
    }

    properties.clipped_absolute_bounding_box =
        properties.unclipped_absolute_bounding_box;
    properties.clipped_absolute_bounding_box.Intersect(snapped_clip_rect);
  }

  const PaintLayer* parent = layer->Parent();
  properties.opacity_ancestor =
      parent->IsTransparent() ? parent : parent->OpacityAncestor();
  properties.transform_ancestor =
      parent->Transform() ? parent : parent->TransformAncestor();
  properties.filter_ancestor =
      parent->HasFilterInducingProperty() ? parent : parent->FilterAncestor();
  properties.clip_path_ancestor = parent->GetLayoutObject().HasClipPath()
                                      ? parent
                                      : parent->ClipPathAncestor();
  properties.mask_ancestor =
      parent->GetLayoutObject().HasMask() ? parent : parent->MaskAncestor();

  EPosition position = layout_object.StyleRef().GetPosition();
  properties.nearest_fixed_position_layer =
      position == EPosition::kFixed ? layer
                                    : parent->NearestFixedPositionLayer();

  PaintLayer* clip_chain_parent = layer->Parent();
  if (position == EPosition::kAbsolute)
    clip_chain_parent = info.clip_chain_parent_for_absolute;
  else if (position == EPosition::kFixed)
    clip_chain_parent = info.clip_chain_parent_for_fixed;
  properties.clipping_container =
      ClippingContainerFromClipChainParent(clip_chain_parent);
  properties.clip_parent = info.escape_clip_to;

  properties.ancestor_scrolling_layer = info.scrolling_ancestor;
  if (info.needs_reparent_scroll && layout_object.IsStacked())
    properties.scroll_parent = info.scrolling_ancestor;

  properties.nearest_contained_layout_layer =
      info.nearest_contained_layout_layer;

  layer->UpdateAncestorDependentCompositingInputs(properties);
}

#if DCHECK_IS_ON()

void CompositingInputsUpdater::AssertNeedsCompositingInputsUpdateBitsCleared(
    PaintLayer* layer) {
  bool recursion_blocked_by_display_lock =
      layer->GetLayoutObject().ChildPrePaintBlockedByDisplayLock();

  DCHECK(recursion_blocked_by_display_lock ||
         !layer->ChildNeedsCompositingInputsUpdate());
  DCHECK(!layer->NeedsCompositingInputsUpdate());

  if (recursion_blocked_by_display_lock)
    return;

  for (PaintLayer* child = layer->FirstChild(); child;
       child = child->NextSibling())
    AssertNeedsCompositingInputsUpdateBitsCleared(child);
}

#endif

}  // namespace blink
