// Copyright 2015 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/platform/graphics/compositing/paint_artifact_compositor.h"

#include <memory>
#include <utility>

#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/layer_tree_host.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "ui/gfx/geometry/rect.h"

namespace blink {

namespace {

// Inserts the element ids of the given node and all of its ancestors into the
// given |composited_element_ids| set. Returns once it finds an id which already
// exists as this implies that all of those ancestor nodes have already been
// inserted.
template <typename NodeType>
void InsertAncestorElementIds(const NodeType* node,
                              CompositorElementIdSet& composited_element_ids) {
  while (node) {
    const CompositorElementId& element_id = node->GetCompositorElementId();
    if (element_id) {
      if (composited_element_ids.count(element_id)) {
        // Once we reach a node already counted we can stop traversing the
        // parent chain.
        return;
      }
      composited_element_ids.insert(element_id);
    }
    node = node->Parent() ? node->Parent()->Unalias() : nullptr;
  }
}

}  // namespace

// cc property trees make use of a sequence number to identify when tree
// topology changes. For now we naively increment the sequence number each time
// we update the property trees. We should explore optimizing our management of
// the sequence number through the use of a dirty bit or similar. See
// http://crbug.com/692842#c4.
static int g_s_property_tree_sequence_number = 1;

PaintArtifactCompositor::PaintArtifactCompositor(
    base::RepeatingCallback<void(const gfx::ScrollOffset&,
                                 const cc::ElementId&)> scroll_callback)
    : scroll_callback_(std::move(scroll_callback)),
      tracks_raster_invalidations_(false) {
  if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
      !RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
    return;
  root_layer_ = cc::Layer::Create();
}

PaintArtifactCompositor::~PaintArtifactCompositor() {
  // TODO(crbug.com/836897, crbug.com/836912):
  // In BlinkGenPropertyTrees mode, some of the layers passed from Blink core
  // have pre-filled element ID. Need to figure out what is the best place to
  // setup them.
  if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
    return;
  for (auto child : root_layer_->children())
    DCHECK(!child->element_id());
}

void PaintArtifactCompositor::EnableExtraDataForTesting() {
  extra_data_for_testing_enabled_ = true;
  extra_data_for_testing_ = std::make_unique<ExtraDataForTesting>();
}

void PaintArtifactCompositor::SetTracksRasterInvalidations(bool should_track) {
  for (auto& client : content_layer_clients_)
    client->GetRasterInvalidator().SetTracksRasterInvalidations(should_track);
}

void PaintArtifactCompositor::WillBeRemovedFromFrame() {
  root_layer_->RemoveAllChildren();
  if (extra_data_for_testing_enabled_) {
    extra_data_for_testing_->content_layers.clear();
    extra_data_for_testing_->synthesized_clip_layers.clear();
    extra_data_for_testing_->scroll_hit_test_layers.clear();
  }
}

std::unique_ptr<JSONObject> PaintArtifactCompositor::LayersAsJSON(
    LayerTreeFlags flags) const {
  ContentLayerClientImpl::LayerAsJSONContext context(flags);
  std::unique_ptr<JSONArray> layers_json = JSONArray::Create();
  for (const auto& client : content_layer_clients_) {
    layers_json->PushObject(client->LayerAsJSON(context));
  }
  std::unique_ptr<JSONObject> json = JSONObject::Create();
  json->SetArray("layers", std::move(layers_json));
  if (context.transforms_json)
    json->SetArray("transforms", std::move(context.transforms_json));
  return json;
}

static scoped_refptr<cc::Layer> ForeignLayerForPaintChunk(
    const PaintArtifact& paint_artifact,
    const PaintChunk& paint_chunk,
    gfx::Vector2dF& layer_offset) {
  if (paint_chunk.size() != 1)
    return nullptr;

  const auto& display_item =
      paint_artifact.GetDisplayItemList()[paint_chunk.begin_index];
  if (!display_item.IsForeignLayer())
    return nullptr;

  const auto& foreign_layer_display_item =
      static_cast<const ForeignLayerDisplayItem&>(display_item);
  auto* layer = foreign_layer_display_item.GetLayer();
  layer_offset = layer->offset_to_transform_parent();
  return layer;
}

const TransformPaintPropertyNode&
PaintArtifactCompositor::ScrollTranslationForPendingLayer(
    const PaintArtifact& paint_artifact,
    const PendingLayer& pending_layer) {
  if (const auto* scroll_translation = ScrollTranslationForScrollHitTestLayer(
          paint_artifact, pending_layer)) {
    return *scroll_translation;
  }
  const auto* transform = pending_layer.property_tree_state.Transform();
  // TODO(pdr): This could be a performance issue because it crawls up the
  // transform tree for each pending layer. If this is on profiles, we should
  // cache a lookup of transform node to scroll translation transform node.
  return transform->NearestScrollTranslationNode();
}

const TransformPaintPropertyNode*
PaintArtifactCompositor::ScrollTranslationForScrollHitTestLayer(
    const PaintArtifact& paint_artifact,
    const PendingLayer& pending_layer) {
  auto paint_chunks =
      paint_artifact.GetPaintChunkSubset(pending_layer.paint_chunk_indices);
  DCHECK(paint_chunks.size());
  const auto& first_paint_chunk = paint_chunks[0];
  if (first_paint_chunk.size() != 1)
    return nullptr;

  const auto& display_item =
      paint_artifact.GetDisplayItemList()[first_paint_chunk.begin_index];
  if (!display_item.IsScrollHitTest())
    return nullptr;

  const auto& scroll_hit_test_display_item =
      static_cast<const ScrollHitTestDisplayItem&>(display_item);
  return &scroll_hit_test_display_item.scroll_offset_node();
}

scoped_refptr<cc::Layer>
PaintArtifactCompositor::ScrollHitTestLayerForPendingLayer(
    const PaintArtifact& paint_artifact,
    const PendingLayer& pending_layer,
    gfx::Vector2dF& layer_offset) {
  const auto* scroll_offset_node =
      ScrollTranslationForScrollHitTestLayer(paint_artifact, pending_layer);
  if (!scroll_offset_node)
    return nullptr;

  const auto& scroll_node = *scroll_offset_node->ScrollNode();
  auto scroll_element_id = scroll_node.GetCompositorElementId();

  scoped_refptr<cc::Layer> scroll_layer;
  for (auto& existing_layer : scroll_hit_test_layers_) {
    if (existing_layer && existing_layer->element_id() == scroll_element_id)
      scroll_layer = existing_layer;
  }
  if (!scroll_layer) {
    scroll_layer = cc::Layer::Create();
    scroll_layer->SetElementId(scroll_element_id);
  }

  // TODO(pdr): Add a helper for blink::FloatPoint to gfx::Vector2dF.
  auto offset = scroll_node.ContainerRect().Location();
  layer_offset = gfx::Vector2dF(offset.X(), offset.Y());
  // TODO(pdr): The scroll layer's bounds are currently set to the clipped
  // container bounds but this does not include the border. We may want to
  // change this behavior to make non-composited and composited hit testing
  // match (see: crbug.com/753124).
  auto bounds = scroll_node.ContainerRect().Size();
  // Mark the layer as scrollable.
  // TODO(pdr): When CAP launches this parameter for bounds will not be needed.
  scroll_layer->SetScrollable(static_cast<gfx::Size>(bounds));
  // Set the layer's bounds equal to the container because the scroll layer
  // does not scroll.
  scroll_layer->SetBounds(static_cast<gfx::Size>(bounds));
  scroll_layer->set_did_scroll_callback(scroll_callback_);
  return scroll_layer;
}

std::unique_ptr<ContentLayerClientImpl>
PaintArtifactCompositor::ClientForPaintChunk(const PaintChunk& paint_chunk) {
  // TODO(chrishtr): for now, just using a linear walk. In the future we can
  // optimize this by using the same techniques used in PaintController for
  // display lists.
  for (auto& client : content_layer_clients_) {
    if (client && client->Matches(paint_chunk))
      return std::move(client);
  }

  auto client = std::make_unique<ContentLayerClientImpl>();
  client->GetRasterInvalidator().SetTracksRasterInvalidations(
      tracks_raster_invalidations_);
  return client;
}

scoped_refptr<cc::Layer>
PaintArtifactCompositor::CompositedLayerForPendingLayer(
    scoped_refptr<const PaintArtifact> paint_artifact,
    const PendingLayer& pending_layer,
    gfx::Vector2dF& layer_offset,
    Vector<std::unique_ptr<ContentLayerClientImpl>>& new_content_layer_clients,
    Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers) {
  auto paint_chunks =
      paint_artifact->GetPaintChunkSubset(pending_layer.paint_chunk_indices);
  DCHECK(paint_chunks.size());
  const PaintChunk& first_paint_chunk = paint_chunks[0];
  DCHECK(first_paint_chunk.size());

  // If the paint chunk is a foreign layer, just return that layer.
  if (scoped_refptr<cc::Layer> foreign_layer = ForeignLayerForPaintChunk(
          *paint_artifact, first_paint_chunk, layer_offset)) {
    DCHECK_EQ(paint_chunks.size(), 1u);
    if (extra_data_for_testing_enabled_)
      extra_data_for_testing_->content_layers.push_back(foreign_layer);
    return foreign_layer;
  }

  // If the paint chunk is a scroll hit test layer, lookup/create the layer.
  if (scoped_refptr<cc::Layer> scroll_layer = ScrollHitTestLayerForPendingLayer(
          *paint_artifact, pending_layer, layer_offset)) {
    new_scroll_hit_test_layers.push_back(scroll_layer);
    if (extra_data_for_testing_enabled_)
      extra_data_for_testing_->scroll_hit_test_layers.push_back(scroll_layer);
    return scroll_layer;
  }

  // The common case: create or reuse a PictureLayer for painted content.
  std::unique_ptr<ContentLayerClientImpl> content_layer_client =
      ClientForPaintChunk(first_paint_chunk);

  gfx::Rect cc_combined_bounds(EnclosingIntRect(pending_layer.bounds));
  layer_offset = cc_combined_bounds.OffsetFromOrigin();

  auto cc_layer = content_layer_client->UpdateCcPictureLayer(
      paint_artifact, paint_chunks, cc_combined_bounds,
      pending_layer.property_tree_state);
  new_content_layer_clients.push_back(std::move(content_layer_client));
  if (extra_data_for_testing_enabled_)
    extra_data_for_testing_->content_layers.push_back(cc_layer);

  // Set properties that foreign layers would normally control for themselves
  // here to avoid changing foreign layers. This includes things set by
  // GraphicsLayer on the ContentsLayer() or by video clients etc.
  cc_layer->SetContentsOpaque(pending_layer.rect_known_to_be_opaque.Contains(
      FloatRect(EnclosingIntRect(pending_layer.bounds))));

  return cc_layer;
}

void PaintArtifactCompositor::UpdateTouchActionRects(
    cc::Layer* layer,
    const gfx::Vector2dF& layer_offset,
    const PropertyTreeState& layer_state,
    const PaintChunkSubset& paint_chunks) {
  Vector<HitTestRect> touch_action_rects_in_layer_space;
  for (const auto& chunk : paint_chunks) {
    const auto* hit_test_data = chunk.hit_test_data.get();
    if (!hit_test_data || hit_test_data->touch_action_rects.IsEmpty())
      continue;

    const auto& chunk_state = chunk.properties.GetPropertyTreeState();
    for (auto touch_action_rect : hit_test_data->touch_action_rects) {
      auto rect =
          FloatClipRect(FloatRect(PixelSnappedIntRect(touch_action_rect.rect)));
      if (!GeometryMapper::LocalToAncestorVisualRect(chunk_state, layer_state,
                                                     rect)) {
        continue;
      }
      LayoutRect layout_rect = LayoutRect(rect.Rect());
      layout_rect.MoveBy(
          LayoutPoint(FloatPoint(-layer_offset.x(), -layer_offset.y())));
      touch_action_rects_in_layer_space.emplace_back(
          HitTestRect(layout_rect, touch_action_rect.whitelisted_touch_action));
    }
  }
  layer->SetTouchActionRegion(
      HitTestRect::BuildRegion(touch_action_rects_in_layer_space));
}

bool PaintArtifactCompositor::PropertyTreeStateChanged(
    const PropertyTreeState& state) const {
  const PropertyTreeState root = PropertyTreeState::Root();
  bool changed = false;
  changed = changed || state.Transform()->Changed(*root.Transform());
  changed = changed || state.Clip()->Changed(root, state.Transform());
  changed = changed || state.Effect()->Changed(root, state.Transform());
  return changed;
}

PaintArtifactCompositor::PendingLayer::PendingLayer(
    const PaintChunk& first_paint_chunk,
    wtf_size_t chunk_index,
    bool chunk_requires_own_layer)
    : bounds(first_paint_chunk.bounds),
      rect_known_to_be_opaque(
          first_paint_chunk.known_to_be_opaque ? bounds : FloatRect()),
      property_tree_state(
          first_paint_chunk.properties.GetPropertyTreeState().Unalias()),
      requires_own_layer(chunk_requires_own_layer) {
  paint_chunk_indices.push_back(chunk_index);
}

void PaintArtifactCompositor::PendingLayer::Merge(const PendingLayer& guest) {
  DCHECK(!requires_own_layer && !guest.requires_own_layer);

  paint_chunk_indices.AppendVector(guest.paint_chunk_indices);
  FloatClipRect guest_bounds_in_home(guest.bounds);
  GeometryMapper::LocalToAncestorVisualRect(
      guest.property_tree_state, property_tree_state, guest_bounds_in_home);
  bounds.Unite(guest_bounds_in_home.Rect());
  // TODO(crbug.com/701991): Upgrade GeometryMapper.
  // If we knew the new bounds is enclosed by the mapped opaque region of
  // the guest layer, we can deduce the merged layer being opaque too, and
  // update rect_known_to_be_opaque accordingly.
}

static bool CanUpcastTo(const PropertyTreeState& guest,
                        const PropertyTreeState& home);
bool PaintArtifactCompositor::PendingLayer::CanMerge(
    const PendingLayer& guest) const {
  if (requires_own_layer || guest.requires_own_layer)
    return false;
  if (property_tree_state.Effect()->Unalias() !=
      guest.property_tree_state.Effect()->Unalias()) {
    return false;
  }
  return CanUpcastTo(guest.property_tree_state, property_tree_state);
}

void PaintArtifactCompositor::PendingLayer::Upcast(
    const PropertyTreeState& new_state) {
  DCHECK(!requires_own_layer);
  FloatClipRect float_clip_rect(bounds);
  GeometryMapper::LocalToAncestorVisualRect(property_tree_state, new_state,
                                            float_clip_rect);
  bounds = float_clip_rect.Rect();

  property_tree_state = new_state;
  // TODO(crbug.com/701991): Upgrade GeometryMapper.
  // A local visual rect mapped to an ancestor space may become a polygon
  // (e.g. consider transformed clip), also effects may affect the opaque
  // region. To determine whether the layer is still opaque, we need to
  // query conservative opaque rect after mapping to an ancestor space,
  // which is not supported by GeometryMapper yet.
  rect_known_to_be_opaque = FloatRect();
}

static bool IsNonCompositingAncestorOf(
    const TransformPaintPropertyNode* unaliased_ancestor,
    const TransformPaintPropertyNode* node) {
  for (; node != unaliased_ancestor; node = SafeUnalias(node->Parent())) {
    if (!node || node->HasDirectCompositingReasons())
      return false;
  }
  return true;
}

// Determines whether drawings based on the 'guest' state can be painted into
// a layer with the 'home' state. A number of criteria need to be met:
// 1. The guest effect must be a descendant of the home effect. However this
//    check is enforced by the layerization recursion. Here we assume the guest
//    has already been upcasted to the same effect.
// 2. The guest transform and the home transform have compatible backface
//    visibility.
// 3. The guest clip must be a descendant of the home clip.
// 4. The local space of each clip and effect node on the ancestor chain must
//    be within compositing boundary of the home transform space.
// 5. The guest transform space must be within compositing boundary of the home
//    transform space.
static bool CanUpcastTo(const PropertyTreeState& guest,
                        const PropertyTreeState& home) {
  DCHECK_EQ(home.Effect()->Unalias(), guest.Effect()->Unalias());

  if (home.Transform()->IsBackfaceHidden() !=
      guest.Transform()->IsBackfaceHidden())
    return false;

  auto* home_clip = home.Clip()->Unalias();
  for (const ClipPaintPropertyNode* current_clip = guest.Clip()->Unalias();
       current_clip != home_clip;
       current_clip = current_clip->Parent() ? current_clip->Parent()->Unalias()
                                             : nullptr) {
    if (!current_clip || current_clip->HasDirectCompositingReasons())
      return false;
    if (!IsNonCompositingAncestorOf(
            home.Transform()->Unalias(),
            current_clip->LocalTransformSpace()->Unalias())) {
      return false;
    }
  }

  return IsNonCompositingAncestorOf(home.Transform()->Unalias(),
                                    guest.Transform()->Unalias());
}

// Returns nullptr if 'ancestor' is not a strict ancestor of 'node'.
// Otherwise, return the child of 'ancestor' that is an ancestor of 'node' or
// 'node' itself.
static const EffectPaintPropertyNode* StrictUnaliasedChildOfAlongPath(
    const EffectPaintPropertyNode* unaliased_ancestor,
    const EffectPaintPropertyNode* node) {
  node = node->Unalias();
  while (node) {
    auto* parent = SafeUnalias(node->Parent());
    if (parent == unaliased_ancestor)
      return node;
    node = parent;
  }
  return nullptr;
}

bool PaintArtifactCompositor::MightOverlap(const PendingLayer& layer_a,
                                           const PendingLayer& layer_b) {
  FloatClipRect bounds_a(layer_a.bounds);
  GeometryMapper::LocalToAncestorVisualRect(
      layer_a.property_tree_state, PropertyTreeState::Root(), bounds_a);
  FloatClipRect bounds_b(layer_b.bounds);
  GeometryMapper::LocalToAncestorVisualRect(
      layer_b.property_tree_state, PropertyTreeState::Root(), bounds_b);

  return bounds_a.Rect().Intersects(bounds_b.Rect());
}

bool PaintArtifactCompositor::CanDecompositeEffect(
    const EffectPaintPropertyNode* unaliased_effect,
    const PendingLayer& layer) {
  // If the effect associated with the layer is deeper than than the effect
  // we are attempting to decomposite, than implies some previous decision
  // did not allow to decomposite intermediate effects.
  if (layer.property_tree_state.Effect()->Unalias() != unaliased_effect)
    return false;
  if (layer.requires_own_layer)
    return false;
  // TODO(trchen): Exotic blending layer may be decomposited only if it could
  // be merged into the first layer of the current group.
  if (unaliased_effect->BlendMode() != SkBlendMode::kSrcOver)
    return false;
  if (unaliased_effect->HasDirectCompositingReasons())
    return false;
  if (!CanUpcastTo(layer.property_tree_state,
                   PropertyTreeState(unaliased_effect->LocalTransformSpace(),
                                     unaliased_effect->OutputClip()
                                         ? unaliased_effect->OutputClip()
                                         : layer.property_tree_state.Clip(),
                                     unaliased_effect)))
    return false;
  return true;
}

static bool EffectGroupContainsChunk(
    const EffectPaintPropertyNode& unaliased_group_effect,
    const PaintChunk& chunk) {
  const auto* effect = SafeUnalias(chunk.properties.Effect());
  return effect == &unaliased_group_effect ||
         StrictUnaliasedChildOfAlongPath(&unaliased_group_effect, effect);
}

static bool SkipGroupIfEffectivelyInvisible(
    const PaintArtifact& paint_artifact,
    const EffectPaintPropertyNode& unaliased_group,
    Vector<PaintChunk>::const_iterator& chunk_it) {
  // The lower bound of visibility is considered to be 0.0004f < 1/2048. With
  // 10-bit color channels (only available on the newest Macs as of 2016;
  // otherwise it's 8-bit), we see that an alpha of 1/2048 or less leads to a
  // color output of less than 0.5 in all channels, hence not visible.
  static const float kMinimumVisibleOpacity = 0.0004f;
  if (unaliased_group.Opacity() >= kMinimumVisibleOpacity ||
      unaliased_group.HasDirectCompositingReasons()) {
    return false;
  }

  // Fast-forward to just past the end of the chunk sequence within this
  // effect group.
  DCHECK(EffectGroupContainsChunk(unaliased_group, *chunk_it));
  while (++chunk_it != paint_artifact.PaintChunks().end()) {
    if (!EffectGroupContainsChunk(unaliased_group, *chunk_it))
      break;
  }
  return true;
}

void PaintArtifactCompositor::LayerizeGroup(
    const PaintArtifact& paint_artifact,
    Vector<PendingLayer>& pending_layers,
    const EffectPaintPropertyNode& current_group,
    Vector<PaintChunk>::const_iterator& chunk_it) {
  // Skip paint chunks that are effectively invisible due to opacity and don't
  // have a direct compositing reason.
  const auto& unaliased_group = *current_group.Unalias();
  if (SkipGroupIfEffectivelyInvisible(paint_artifact, unaliased_group,
                                      chunk_it))
    return;

  wtf_size_t first_layer_in_current_group = pending_layers.size();
  // The worst case time complexity of the algorithm is O(pqd), where
  // p = the number of paint chunks.
  // q = average number of trials to find a squash layer or rejected
  //     for overlapping.
  // d = (sum of) the depth of property trees.
  // The analysis as follows:
  // Every paint chunk will be visited by the main loop below for exactly once,
  // except for chunks that enter or exit groups (case B & C below).
  // For normal chunk visit (case A), the only cost is determining squash,
  // which costs O(qd), where d came from "canUpcastTo" and geometry mapping.
  // Subtotal: O(pqd)
  // For group entering and exiting, it could cost O(d) for each group, for
  // searching the shallowest subgroup (strictChildOfAlongPath), thus O(d^2)
  // in total.
  // Also when exiting group, the group may be decomposited and squashed to a
  // previous layer. Again finding the host costs O(qd). Merging would cost O(p)
  // due to copying the chunk list. Subtotal: O((qd + p)d) = O(qd^2 + pd)
  // Assuming p > d, the total complexity would be O(pqd + qd^2 + pd) = O(pqd)
  while (chunk_it != paint_artifact.PaintChunks().end()) {
    // Look at the effect node of the next chunk. There are 3 possible cases:
    // A. The next chunk belongs to the current group but no subgroup.
    // B. The next chunk does not belong to the current group.
    // C. The next chunk belongs to some subgroup of the current group.
    DCHECK(chunk_it->properties.Effect());
    const auto* chunk_effect = chunk_it->properties.Effect()->Unalias();
    if (chunk_effect == &unaliased_group) {
      // Case A: The next chunk belongs to the current group but no subgroup.
      const auto& last_display_item =
          paint_artifact.GetDisplayItemList()[chunk_it->begin_index];
      bool requires_own_layer = last_display_item.IsForeignLayer() ||
                                // TODO(pdr): This should require a direct
                                // compositing reason.
                                last_display_item.IsScrollHitTest();
      pending_layers.push_back(PendingLayer(
          *chunk_it, chunk_it - paint_artifact.PaintChunks().begin(),
          requires_own_layer));
      chunk_it++;
      if (requires_own_layer)
        continue;
    } else {
      const EffectPaintPropertyNode* unaliased_subgroup =
          StrictUnaliasedChildOfAlongPath(&unaliased_group, chunk_effect);
      // Case B: This means we need to close the current group without
      //         processing the next chunk.
      if (!unaliased_subgroup)
        break;
      // Case C: The following chunks belong to a subgroup. Process them by
      //         a recursion call.
      wtf_size_t first_layer_in_subgroup = pending_layers.size();
      LayerizeGroup(paint_artifact, pending_layers, *unaliased_subgroup,
                    chunk_it);
      // Now the chunk iterator stepped over the subgroup we just saw.
      // If the subgroup generated 2 or more layers then the subgroup must be
      // composited to satisfy grouping requirement.
      // i.e. Grouping effects generally must be applied atomically,
      // for example,  Opacity(A+B) != Opacity(A) + Opacity(B), thus an effect
      // either applied 100% within a layer, or not at all applied within layer
      // (i.e. applied by compositor render surface instead).
      if (pending_layers.size() != first_layer_in_subgroup + 1)
        continue;
      // Now attempt to "decomposite" subgroup.
      PendingLayer& subgroup_layer = pending_layers[first_layer_in_subgroup];
      if (!CanDecompositeEffect(unaliased_subgroup, subgroup_layer))
        continue;
      subgroup_layer.Upcast(
          PropertyTreeState(unaliased_subgroup->LocalTransformSpace(),
                            unaliased_subgroup->OutputClip()
                                ? unaliased_subgroup->OutputClip()
                                : subgroup_layer.property_tree_state.Clip(),
                            &unaliased_group));
    }
    // At this point pending_layers.back() is the either a layer from a
    // "decomposited" subgroup or a layer created from a chunk we just
    // processed. Now determine whether it could be merged into a previous
    // layer.
    const PendingLayer& new_layer = pending_layers.back();
    DCHECK(!new_layer.requires_own_layer);
    DCHECK_EQ(&unaliased_group, new_layer.property_tree_state.Effect());
    // This iterates pending_layers[first_layer_in_current_group:-1] in reverse.
    for (wtf_size_t candidate_index = pending_layers.size() - 1;
         candidate_index-- > first_layer_in_current_group;) {
      PendingLayer& candidate_layer = pending_layers[candidate_index];
      if (candidate_layer.CanMerge(new_layer)) {
        candidate_layer.Merge(new_layer);
        pending_layers.pop_back();
        break;
      }
      if (MightOverlap(new_layer, candidate_layer))
        break;
    }
  }
}

void PaintArtifactCompositor::CollectPendingLayers(
    const PaintArtifact& paint_artifact,
    Vector<PendingLayer>& pending_layers) {
  Vector<PaintChunk>::const_iterator cursor =
      paint_artifact.PaintChunks().begin();
  LayerizeGroup(paint_artifact, pending_layers, EffectPaintPropertyNode::Root(),
                cursor);
  DCHECK_EQ(paint_artifact.PaintChunks().end(), cursor);
}

// This class maintains a persistent mask layer and unique stable cc effect IDs
// for reuse across compositing cycles. The mask layer paints a rounded rect,
// which is an updatable parameter of the class. The caller is responsible for
// inserting the layer into layer list and associating with property nodes.
//
// The typical application of the mask layer is to create an isolating effect
// node to paint the clipped contents, and at the end draw the mask layer with
// a kDstIn blend effect. This is why two stable cc effect IDs are provided for
// the convenience of the caller, although they are not directly related to the
// class functionality.
class SynthesizedClip : private cc::ContentLayerClient {
 public:
  SynthesizedClip() : layer_(cc::PictureLayer::Create(this)) {
    mask_isolation_id_ =
        CompositorElementIdFromUniqueObjectId(NewUniqueObjectId());
    mask_effect_id_ =
        CompositorElementIdFromUniqueObjectId(NewUniqueObjectId());
    layer_->SetIsDrawable(true);
  }

  void Update(const FloatRoundedRect& rrect,
              scoped_refptr<const RefCountedPath> path) {
    IntRect layer_bounds = EnclosingIntRect(rrect.Rect());
    gfx::Vector2dF new_layer_origin(layer_bounds.X(), layer_bounds.Y());

    SkRRect new_local_rrect = rrect;
    new_local_rrect.offset(-new_layer_origin.x(), -new_layer_origin.y());

    bool path_in_layer_changed = false;
    if (path_ == path) {
      path_in_layer_changed = path && layer_origin_ != new_layer_origin;
    } else if (!path_ || !path) {
      path_in_layer_changed = true;
    } else {
      SkPath new_path = path->GetSkPath();
      new_path.offset(layer_origin_.x() - new_layer_origin.x(),
                      layer_origin_.y() - new_layer_origin.y());
      path_in_layer_changed = path_->GetSkPath() != new_path;
    }

    if (local_rrect_ != new_local_rrect || path_in_layer_changed) {
      layer_->SetNeedsDisplay();
    }
    layer_->SetOffsetToTransformParent(new_layer_origin);
    layer_->SetBounds(gfx::Size(layer_bounds.Width(), layer_bounds.Height()));

    layer_origin_ = new_layer_origin;
    local_rrect_ = new_local_rrect;
    path_ = std::move(path);
  }

  cc::Layer* GetLayer() const { return layer_.get(); }
  CompositorElementId GetMaskIsolationId() const { return mask_isolation_id_; }
  CompositorElementId GetMaskEffectId() const { return mask_effect_id_; }

 private:
  // ContentLayerClient implementation.
  gfx::Rect PaintableRegion() final { return gfx::Rect(layer_->bounds()); }
  bool FillsBoundsCompletely() const final { return false; }
  size_t GetApproximateUnsharedMemoryUsage() const final { return 0; }

  scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList(
      PaintingControlSetting) final {
    auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
        cc::DisplayItemList::kTopLevelDisplayItemList);
    PaintFlags flags;
    flags.setAntiAlias(true);
    cc_list->StartPaint();
    if (!path_) {
      cc_list->push<cc::DrawRRectOp>(local_rrect_, flags);
    } else {
      cc_list->push<cc::SaveOp>();
      cc_list->push<cc::TranslateOp>(-layer_origin_.x(), -layer_origin_.x());
      cc_list->push<cc::ClipPathOp>(path_->GetSkPath(), SkClipOp::kIntersect,
                                    true);
      SkRRect rrect = local_rrect_;
      rrect.offset(layer_origin_.x(), layer_origin_.y());
      cc_list->push<cc::DrawRRectOp>(rrect, flags);
      cc_list->push<cc::RestoreOp>();
    }
    cc_list->EndPaintOfUnpaired(gfx::Rect(layer_->bounds()));
    cc_list->Finalize();
    return cc_list;
  }

 private:
  scoped_refptr<cc::PictureLayer> layer_;
  gfx::Vector2dF layer_origin_;
  SkRRect local_rrect_ = SkRRect::MakeEmpty();
  scoped_refptr<const RefCountedPath> path_;
  CompositorElementId mask_isolation_id_;
  CompositorElementId mask_effect_id_;
};

// TODO(pdr): There is no test that synthetic clip layers are re-used.
cc::Layer* PaintArtifactCompositor::CreateOrReuseSynthesizedClipLayer(
    const ClipPaintPropertyNode* node,
    CompositorElementId& mask_isolation_id,
    CompositorElementId& mask_effect_id) {
  auto entry = std::find_if(
      synthesized_clip_cache_.begin(), synthesized_clip_cache_.end(),
      [node](const auto& entry) { return entry.key == node && !entry.in_use; });
  if (entry == synthesized_clip_cache_.end()) {
    auto clip = std::make_unique<SynthesizedClip>();
    clip->GetLayer()->SetLayerTreeHost(root_layer_->layer_tree_host());
    entry = synthesized_clip_cache_.insert(
        entry, SynthesizedClipEntry{node, std::move(clip), false});
  }

  entry->in_use = true;
  SynthesizedClip& synthesized_clip = *entry->synthesized_clip;
  synthesized_clip.Update(node->ClipRect(), node->ClipPath());
  mask_isolation_id = synthesized_clip.GetMaskIsolationId();
  mask_effect_id = synthesized_clip.GetMaskEffectId();
  return synthesized_clip.GetLayer();
}

void PaintArtifactCompositor::Update(
    scoped_refptr<const PaintArtifact> paint_artifact,
    CompositorElementIdSet& composited_element_ids,
    TransformPaintPropertyNode* viewport_scale_node) {
  DCHECK(root_layer_);

  // The tree will be null after detaching and this update can be ignored.
  // See: WebViewImpl::detachPaintArtifactCompositor().
  cc::LayerTreeHost* host = root_layer_->layer_tree_host();
  if (!host)
    return;

  // When using BlinkGenPropertyTrees, the compositor accepts a list of layers
  // and property trees instead of building property trees. This DCHECK ensures
  // we have not forgotten to set |use_layer_lists|.
  DCHECK(!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
         host->GetSettings().use_layer_lists);

  if (extra_data_for_testing_enabled_)
    extra_data_for_testing_.reset(new ExtraDataForTesting);

  root_layer_->set_property_tree_sequence_number(
      g_s_property_tree_sequence_number);

  LayerListBuilder layer_list_builder;

  PropertyTreeManager property_tree_manager(
      *this, *host->property_trees(), root_layer_.get(), &layer_list_builder);
  Vector<PendingLayer, 0> pending_layers;
  CollectPendingLayers(*paint_artifact, pending_layers);

  cc::LayerTreeHost::ViewportPropertyIds viewport_property_ids;
  if (viewport_scale_node) {
    viewport_property_ids.page_scale_transform =
        property_tree_manager.EnsureCompositorPageScaleTransformNode(
            viewport_scale_node);
  }
  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
    host->RegisterViewportPropertyIds(viewport_property_ids);

  Vector<std::unique_ptr<ContentLayerClientImpl>> new_content_layer_clients;
  new_content_layer_clients.ReserveCapacity(pending_layers.size());
  Vector<scoped_refptr<cc::Layer>> new_scroll_hit_test_layers;

  for (auto& entry : synthesized_clip_cache_)
    entry.in_use = false;

  for (auto& pending_layer : pending_layers) {
    const auto& property_state = pending_layer.property_tree_state;
    const auto* transform = property_state.Transform();
    const auto* clip = property_state.Clip();

    if (clip->LocalTransformSpace() == transform) {
      // Limit layer bounds to hide the areas that will be never visible because
      // of the clip.
      pending_layer.bounds.Intersect(clip->ClipRect().Rect());
    } else if (const auto* scroll = transform->ScrollNode()) {
      // Limit layer bounds to the scroll range to hide the areas that will
      // never be scrolled into the visible area.
      pending_layer.bounds.Intersect(FloatRect(
          IntRect(scroll->ContainerRect().Location(), scroll->ContentsSize())));
    }

    gfx::Vector2dF layer_offset;
    scoped_refptr<cc::Layer> layer = CompositedLayerForPendingLayer(
        paint_artifact, pending_layer, layer_offset, new_content_layer_clients,
        new_scroll_hit_test_layers);

    // Pre-CompositeAfterPaint, touch action rects are updated through
    // ScrollingCoordinator::UpdateLayerTouchActionRects.
    if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
      auto paint_chunks = paint_artifact->GetPaintChunkSubset(
          pending_layer.paint_chunk_indices);
      UpdateTouchActionRects(layer.get(), layer_offset, property_state,
                             paint_chunks);
    }

    layer->SetLayerTreeHost(root_layer_->layer_tree_host());

    int transform_id =
        property_tree_manager.EnsureCompositorTransformNode(transform);
    int clip_id = property_tree_manager.EnsureCompositorClipNode(clip);
    int effect_id = property_tree_manager.SwitchToEffectNodeWithSynthesizedClip(
        *property_state.Effect(), *clip);
    // The compositor scroll node is not directly stored in the property tree
    // state but can be created via the scroll offset translation node.
    const auto& scroll_translation =
        ScrollTranslationForPendingLayer(*paint_artifact, pending_layer);
    int scroll_id =
        property_tree_manager.EnsureCompositorScrollNode(&scroll_translation);

    layer->SetOffsetToTransformParent(layer_offset);

    layer_list_builder.Add(layer);

    layer->set_property_tree_sequence_number(
        root_layer_->property_tree_sequence_number());
    layer->SetTransformTreeIndex(transform_id);
    layer->SetScrollTreeIndex(scroll_id);
    layer->SetClipTreeIndex(clip_id);
    layer->SetEffectTreeIndex(effect_id);
    bool backface_hidden = property_state.Transform()->IsBackfaceHidden();
    layer->SetDoubleSided(!backface_hidden);
    // TODO(wangxianzhu): cc::PropertyTreeBuilder has a more sophisticated
    // condition for this. Do we need to do the same here?
    layer->SetShouldCheckBackfaceVisibility(backface_hidden);

    InsertAncestorElementIds(property_state.Effect(), composited_element_ids);
    InsertAncestorElementIds(transform, composited_element_ids);
    if (layer->scrollable())
      composited_element_ids.insert(layer->element_id());

    // If the property tree state has changed between the layer and the root, we
    // need to inform the compositor so damage can be calculated.
    // Calling |PropertyTreeStateChanged| for every pending layer is
    // O(|property nodes|^2) and could be optimized by caching the lookup of
    // nodes known to be changed/unchanged.
    if (PropertyTreeStateChanged(property_state))
      layer->SetSubtreePropertyChanged();
  }
  property_tree_manager.Finalize();
  content_layer_clients_.swap(new_content_layer_clients);
  scroll_hit_test_layers_.swap(new_scroll_hit_test_layers);

  synthesized_clip_cache_.erase(
      std::remove_if(synthesized_clip_cache_.begin(),
                     synthesized_clip_cache_.end(),
                     [](const auto& entry) { return !entry.in_use; }),
      synthesized_clip_cache_.end());
  if (extra_data_for_testing_enabled_) {
    for (const auto& entry : synthesized_clip_cache_) {
      extra_data_for_testing_->synthesized_clip_layers.push_back(
          entry.synthesized_clip->GetLayer());
    }
  }

  // This should be done before UpdateRenderSurfaceForEffects() for which to
  // get property tree node ids from the layers.
  host->property_trees()->sequence_number = g_s_property_tree_sequence_number;

  auto layers = layer_list_builder.Finalize();
  UpdateRenderSurfaceForEffects(*host, layers);
  root_layer_->SetChildLayerList(std::move(layers));

  // Update the host's active registered element ids.
  host->SetActiveRegisteredElementIds(composited_element_ids);

  // Mark the property trees as having been rebuilt.
  host->property_trees()->needs_rebuild = false;
  host->property_trees()->ResetCachedData();

  g_s_property_tree_sequence_number++;

#if DCHECK_IS_ON()
  if (VLOG_IS_ON(2)) {
    static String s_previous_output;
    LayerTreeFlags flags = VLOG_IS_ON(3) ? 0xffffffff : 0;
    String new_output = LayersAsJSON(flags)->ToPrettyJSONString();
    if (new_output != s_previous_output) {
      LOG(ERROR) << "PaintArtifactCompositor::Update() done\n"
                 << "Composited layers:\n"
                 << new_output.Utf8().data();
      s_previous_output = new_output;
    }
  }
#endif
}

// Every effect is supposed to have render surface enabled for grouping, but we
// can omit one if the effect is opacity-only, render surface is not forced,
// and the effect has only one compositing child. This is both for optimization
// and not introducing sub-pixel differences in layout tests.
// TODO(crbug.com/504464): There is ongoing work in cc to delay render surface
// decision until later phase of the pipeline. Remove premature optimization
// here once the work is ready.
void PaintArtifactCompositor::UpdateRenderSurfaceForEffects(
    cc::LayerTreeHost& host,
    const cc::LayerList& layers) {
  HashSet<int> pending_render_surfaces;
  auto& effect_tree = host.property_trees()->effect_tree;
  for (const auto& layer : layers) {
    for (auto* effect = effect_tree.Node(layer->effect_tree_index());
         !effect->has_render_surface;
         effect = effect_tree.Node(effect->parent_id)) {
      if (effect->opacity != 1.f &&
          !pending_render_surfaces.insert(effect->id).is_new_entry) {
        // The opacity-only effect is seen the second time, which means that it
        // has more than one compositing child and needs a render surface.
        effect->has_render_surface = true;
        break;
      }
    }
  }
}

void LayerListBuilder::Add(scoped_refptr<cc::Layer> layer) {
  DCHECK(list_valid_);
  list_.push_back(layer);
}

cc::LayerList LayerListBuilder::Finalize() {
  DCHECK(list_valid_);
  list_valid_ = false;
  return std::move(list_);
}

cc::Layer*
PaintArtifactCompositor::ExtraDataForTesting::ScrollHitTestWebLayerAt(
    unsigned index) {
  return scroll_hit_test_layers[index].get();
}

#if DCHECK_IS_ON()
void PaintArtifactCompositor::ShowDebugData() {
  LOG(ERROR) << LayersAsJSON(kLayerTreeIncludesDebugInfo |
                             kLayerTreeIncludesPaintInvalidations)
                    ->ToPrettyJSONString()
                    .Utf8()
                    .data();
}
#endif

}  // namespace blink
