/*
 * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"

#include <memory>

#include "cc/input/overscroll_behavior.h"
#include "cc/layers/picture_layer.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_object.h"
#include "third_party/blink/renderer/core/layout/layout_html_canvas.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_video.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/css_mask_painter.h"
#include "third_party/blink/renderer/core/paint/frame_paint_timing.h"
#include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/time.h"

namespace blink {

using namespace HTMLNames;

static IntRect ContentsRect(const LayoutObject& layout_object) {
  if (!layout_object.IsBox())
    return IntRect();
  if (layout_object.IsCanvas()) {
    return PixelSnappedIntRect(
        ToLayoutHTMLCanvas(layout_object).ReplacedContentRect());
  }
  if (layout_object.IsVideo()) {
    return PixelSnappedIntRect(
        ToLayoutVideo(layout_object).ReplacedContentRect());
  }

  return PixelSnappedIntRect(ToLayoutBox(layout_object).ContentBoxRect());
}

static IntRect BackgroundRect(const LayoutObject& layout_object) {
  if (!layout_object.IsBox())
    return IntRect();

  LayoutRect rect;
  const LayoutBox& box = ToLayoutBox(layout_object);
  return PixelSnappedIntRect(box.BackgroundRect(kBackgroundClipRect));
}

static inline bool IsTextureLayerCanvas(const LayoutObject& layout_object) {
  if (layout_object.IsCanvas()) {
    HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode());
    if (canvas->SurfaceLayerBridge())
      return false;
    if (CanvasRenderingContext* context = canvas->RenderingContext())
      return context->IsComposited();
  }
  return false;
}

static inline bool IsSurfaceLayerCanvas(const LayoutObject& layout_object) {
  if (layout_object.IsCanvas()) {
    HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode());
    return canvas->SurfaceLayerBridge();
  }
  return false;
}

static inline bool IsCompositedCanvas(const LayoutObject& layout_object) {
  if (layout_object.IsCanvas()) {
    HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode());
    if (canvas->SurfaceLayerBridge())
      return true;
    if (CanvasRenderingContext* context = canvas->RenderingContext())
      return context->IsComposited();
  }
  return false;
}

static bool HasBoxDecorationsOrBackgroundImage(const ComputedStyle& style) {
  return style.HasBoxDecorations() || style.HasBackgroundImage();
}

static bool ContentLayerSupportsDirectBackgroundComposition(
    const LayoutObject& layout_object) {
  // No support for decorations - border, border-radius or outline.
  // Only simple background - solid color or transparent.
  if (HasBoxDecorationsOrBackgroundImage(layout_object.StyleRef()))
    return false;

  // If there is no background, there is nothing to support.
  if (!layout_object.Style()->HasBackground())
    return true;

  // Simple background that is contained within the contents rect.
  return ContentsRect(layout_object).Contains(BackgroundRect(layout_object));
}

static WebPluginContainerImpl* GetPluginContainer(LayoutObject& layout_object) {
  if (!layout_object.IsEmbeddedObject())
    return nullptr;
  return ToLayoutEmbeddedObject(layout_object).Plugin();
}

static inline bool IsAcceleratedContents(LayoutObject& layout_object) {
  return IsCompositedCanvas(layout_object) ||
         (layout_object.IsEmbeddedObject() &&
          ToLayoutEmbeddedObject(layout_object)
              .RequiresAcceleratedCompositing()) ||
         layout_object.IsVideo();
}

// Returns true if the compositor will be responsible for applying the sticky
// position offset for this composited layer.
static bool UsesCompositedStickyPosition(PaintLayer& layer) {
  return layer.GetLayoutObject().Style()->HasStickyConstrainedPosition() &&
         (layer.AncestorOverflowLayer()->IsRootLayer()
              ? layer.GetLayoutObject().View()->GetFrameView()->IsScrollable()
              : layer.AncestorOverflowLayer()->NeedsCompositedScrolling());
}

// Returns the sticky position offset that should be removed from a given layer
// for use in CompositedLayerMapping.
//
// If the layer is not using composited sticky position, this will return
// FloatPoint().
static FloatPoint StickyPositionOffsetForLayer(PaintLayer& layer) {
  if (!UsesCompositedStickyPosition(layer))
    return FloatPoint();

  const StickyConstraintsMap& constraints_map = layer.AncestorOverflowLayer()
                                                    ->GetScrollableArea()
                                                    ->GetStickyConstraintsMap();
  const StickyPositionScrollingConstraints& constraints =
      constraints_map.at(&layer);

  return FloatPoint(constraints.GetOffsetForStickyPosition(constraints_map));
}

CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
    : owning_layer_(layer),
      content_offset_in_compositing_layer_dirty_(false),
      pending_update_scope_(kGraphicsLayerUpdateNone),
      is_main_frame_layout_view_layer_(false),
      scrolling_contents_are_empty_(false),
      background_paints_onto_scrolling_contents_layer_(false),
      background_paints_onto_graphics_layer_(false),
      draws_background_onto_content_layer_(false) {
  if (layer.IsRootLayer() && GetLayoutObject().GetFrame()->IsMainFrame())
    is_main_frame_layout_view_layer_ = true;

  CreatePrimaryGraphicsLayer();
}

CompositedLayerMapping::~CompositedLayerMapping() {
  // Hits in compositing/squashing/squash-onto-nephew.html.
  DisableCompositingQueryAsserts disabler;

  // Do not leave the destroyed pointer dangling on any Layers that painted to
  // this mapping's squashing layer.
  for (size_t i = 0; i < squashed_layers_.size(); ++i) {
    PaintLayer* old_squashed_layer = squashed_layers_[i].paint_layer;
    // Assert on incorrect mappings between layers and groups
    DCHECK_EQ(old_squashed_layer->GroupedMapping(), this);
    if (old_squashed_layer->GroupedMapping() == this) {
      old_squashed_layer->SetGroupedMapping(
          nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
      old_squashed_layer->SetLostGroupedMapping(true);
    }
  }

  UpdateClippingLayers(false, false, false);
  UpdateOverflowControlsLayers(false, false, false, false);
  UpdateChildTransformLayer(false);
  UpdateForegroundLayer(false);
  UpdateMaskLayer(false);
  UpdateChildClippingMaskLayer(false);
  UpdateScrollingLayers(false);
  UpdateSquashingLayers(false);
  DestroyGraphicsLayers();
}

std::unique_ptr<GraphicsLayer> CompositedLayerMapping::CreateGraphicsLayer(
    CompositingReasons reasons,
    SquashingDisallowedReasons squashing_disallowed_reasons) {
  std::unique_ptr<GraphicsLayer> graphics_layer = GraphicsLayer::Create(*this);

  graphics_layer->SetCompositingReasons(reasons);
  graphics_layer->SetSquashingDisallowedReasons(squashing_disallowed_reasons);
  if (Node* owning_node = owning_layer_.GetLayoutObject().GetNode())
    graphics_layer->SetOwnerNodeId(DOMNodeIds::IdForNode(owning_node));

  return graphics_layer;
}

void CompositedLayerMapping::CreatePrimaryGraphicsLayer() {
  graphics_layer_ =
      CreateGraphicsLayer(owning_layer_.GetCompositingReasons(),
                          owning_layer_.GetSquashingDisallowedReasons());

  UpdateHitTestableWithoutDrawsContent(true);
  UpdateOpacity(GetLayoutObject().StyleRef());
  UpdateTransform(GetLayoutObject().StyleRef());
  UpdateFilters();
  UpdateBackdropFilters();
  UpdateLayerBlendMode(GetLayoutObject().StyleRef());
  UpdateIsRootForIsolatedGroup();
}

void CompositedLayerMapping::DestroyGraphicsLayers() {
  if (graphics_layer_)
    graphics_layer_->RemoveFromParent();

  ancestor_clipping_layer_ = nullptr;
  ancestor_clipping_mask_layer_ = nullptr;
  graphics_layer_ = nullptr;
  foreground_layer_ = nullptr;
  child_containment_layer_ = nullptr;
  child_transform_layer_ = nullptr;
  mask_layer_ = nullptr;
  child_clipping_mask_layer_ = nullptr;

  scrolling_layer_ = nullptr;
  scrolling_contents_layer_ = nullptr;
}

void CompositedLayerMapping::UpdateHitTestableWithoutDrawsContent(
    const bool& should_hit_test) {
  graphics_layer_->SetHitTestableWithoutDrawsContent(should_hit_test);
}

void CompositedLayerMapping::UpdateOpacity(const ComputedStyle& style) {
  graphics_layer_->SetOpacity(CompositingOpacity(style.Opacity()));
}

void CompositedLayerMapping::UpdateTransform(const ComputedStyle& style) {
  // FIXME: This could use m_owningLayer.transform(), but that currently has
  // transform-origin baked into it, and we don't want that.
  TransformationMatrix t;
  if (owning_layer_.HasTransformRelatedProperty()) {
    style.ApplyTransform(
        t, LayoutSize(ToLayoutBox(GetLayoutObject()).PixelSnappedSize()),
        ComputedStyle::kExcludeTransformOrigin,
        ComputedStyle::kIncludeMotionPath,
        ComputedStyle::kIncludeIndependentTransformProperties);
    MakeMatrixRenderable(t, Compositor()->HasAcceleratedCompositing());
  }

  graphics_layer_->SetTransform(t);
}

void CompositedLayerMapping::UpdateFilters() {
  CompositorFilterOperations operations;
  OwningLayer().UpdateCompositorFilterOperationsForFilter(operations);

  // If the image violates some feature policy optimized image policies, render
  // with inverted color.
  if (GetLayoutObject().IsLayoutImage() &&
      ToLayoutImage(GetLayoutObject()).ShouldInvertColor())
    operations.AppendInvertFilter(1.0f);

  graphics_layer_->SetFilters(std::move(operations));
}

void CompositedLayerMapping::UpdateBackdropFilters() {
  graphics_layer_->SetBackdropFilters(
      OwningLayer().CreateCompositorFilterOperationsForBackdropFilter());
}

void CompositedLayerMapping::UpdateStickyConstraints(
    const ComputedStyle& style) {
  cc::LayerStickyPositionConstraint constraint;
  if (!UsesCompositedStickyPosition(owning_layer_)) {
    // Clear the previous sticky position constraint - if set.
    graphics_layer_->SetStickyPositionConstraint(constraint);
    return;
  }

  const PaintLayer* ancestor_overflow_layer =
      owning_layer_.AncestorOverflowLayer();
  const StickyConstraintsMap& constraints_map =
      ancestor_overflow_layer->GetScrollableArea()->GetStickyConstraintsMap();
  const StickyPositionScrollingConstraints& constraints =
      constraints_map.at(&owning_layer_);

  constraint.is_sticky = true;
  constraint.is_anchored_left =
      constraints.GetAnchorEdges() &
      StickyPositionScrollingConstraints::kAnchorEdgeLeft;
  constraint.is_anchored_right =
      constraints.GetAnchorEdges() &
      StickyPositionScrollingConstraints::kAnchorEdgeRight;
  constraint.is_anchored_top =
      constraints.GetAnchorEdges() &
      StickyPositionScrollingConstraints::kAnchorEdgeTop;
  constraint.is_anchored_bottom =
      constraints.GetAnchorEdges() &
      StickyPositionScrollingConstraints::kAnchorEdgeBottom;
  constraint.left_offset = constraints.LeftOffset();
  constraint.right_offset = constraints.RightOffset();
  constraint.top_offset = constraints.TopOffset();
  constraint.bottom_offset = constraints.BottomOffset();
  constraint.scroll_container_relative_sticky_box_rect =
      EnclosingIntRect(constraints.ScrollContainerRelativeStickyBoxRect());
  constraint.scroll_container_relative_containing_block_rect = EnclosingIntRect(
      constraints.ScrollContainerRelativeContainingBlockRect());
  PaintLayer* sticky_box_shifting_ancestor =
      constraints.NearestStickyLayerShiftingStickyBox();
  if (sticky_box_shifting_ancestor &&
      sticky_box_shifting_ancestor->GetCompositedLayerMapping()) {
    constraint.nearest_element_shifting_sticky_box =
        sticky_box_shifting_ancestor->GetCompositedLayerMapping()
            ->MainGraphicsLayer()
            ->GetElementId();
  }
  PaintLayer* containing_block_shifting_ancestor =
      constraints.NearestStickyLayerShiftingContainingBlock();
  if (containing_block_shifting_ancestor &&
      containing_block_shifting_ancestor->GetCompositedLayerMapping()) {
    constraint.nearest_element_shifting_containing_block =
        containing_block_shifting_ancestor->GetCompositedLayerMapping()
            ->MainGraphicsLayer()
            ->GetElementId();
  }

  graphics_layer_->SetStickyPositionConstraint(constraint);
}

void CompositedLayerMapping::UpdateLayerBlendMode(const ComputedStyle& style) {
  SetBlendMode(style.GetBlendMode());
}

void CompositedLayerMapping::UpdateIsRootForIsolatedGroup() {
  bool isolate = owning_layer_.ShouldIsolateCompositedDescendants();

  // non stacking context layers should never isolate
  DCHECK(owning_layer_.StackingNode()->IsStackingContext() || !isolate);

  graphics_layer_->SetIsRootForIsolatedGroup(isolate);
}

void CompositedLayerMapping::UpdateBackgroundPaintsOntoScrollingContentsLayer(
    bool& invalidate_graphics_layer,
    bool& invalidate_scrolling_contents_layer) {
  invalidate_graphics_layer = false;
  invalidate_scrolling_contents_layer = false;
  // We can only paint the background onto the scrolling contents layer if
  // it would be visually correct and we are using composited scrolling meaning
  // we have a scrolling contents layer to paint it into.
  BackgroundPaintLocation paint_location =
      owning_layer_.GetBackgroundPaintLocation();
  bool should_paint_onto_scrolling_contents_layer =
      paint_location & kBackgroundPaintInScrollingContents &&
      owning_layer_.GetScrollableArea()->UsesCompositedScrolling();
  if (should_paint_onto_scrolling_contents_layer !=
      BackgroundPaintsOntoScrollingContentsLayer()) {
    background_paints_onto_scrolling_contents_layer_ =
        should_paint_onto_scrolling_contents_layer;
    // The scrolling contents layer needs to be updated for changed
    // m_backgroundPaintsOntoScrollingContentsLayer.
    if (HasScrollingLayer())
      invalidate_scrolling_contents_layer = true;
  }
  bool should_paint_onto_graphics_layer =
      !background_paints_onto_scrolling_contents_layer_ ||
      paint_location & kBackgroundPaintInGraphicsLayer;
  if (should_paint_onto_graphics_layer !=
      !!background_paints_onto_graphics_layer_) {
    background_paints_onto_graphics_layer_ = should_paint_onto_graphics_layer;
    // The graphics layer needs to be updated for changed
    // m_backgroundPaintsOntoGraphicsLayer.
    invalidate_graphics_layer = true;
  }
}

void CompositedLayerMapping::UpdateContentsOpaque() {
  if (IsTextureLayerCanvas(GetLayoutObject())) {
    CanvasRenderingContext* context =
        ToHTMLCanvasElement(GetLayoutObject().GetNode())->RenderingContext();
    cc::Layer* layer = context ? context->CcLayer() : nullptr;
    // Determine whether the external texture layer covers the whole graphics
    // layer. This may not be the case if there are box decorations or
    // shadows.
    if (layer && layer->bounds() == graphics_layer_->CcLayer()->bounds()) {
      // Determine whether the rendering context's external texture layer is
      // opaque.
      if (!context->CreationAttributes().alpha) {
        graphics_layer_->SetContentsOpaque(true);
      } else {
        graphics_layer_->SetContentsOpaque(
            !Color(layer->background_color()).HasAlpha());
      }
    } else {
      graphics_layer_->SetContentsOpaque(false);
    }
  } else if (IsSurfaceLayerCanvas(GetLayoutObject())) {
    // TODO(crbug.com/705019): Contents could be opaque, but that cannot be
    // determined from the main thread. Or can it?
    graphics_layer_->SetContentsOpaque(false);
  } else {
    // For non-root layers, background is painted by the scrolling contents
    // layer if all backgrounds are background attachment local, otherwise
    // background is painted by the primary graphics layer.
    if (HasScrollingLayer() &&
        background_paints_onto_scrolling_contents_layer_) {
      // Backgrounds painted onto the foreground are clipped by the padding box
      // rect.
      // TODO(flackr): This should actually check the entire overflow rect
      // within the scrolling contents layer but since we currently only trigger
      // this for solid color backgrounds the answer will be the same.
      scrolling_contents_layer_->SetContentsOpaque(
          owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
              ToLayoutBox(GetLayoutObject()).PaddingBoxRect()));

      if (owning_layer_.GetBackgroundPaintLocation() &
          kBackgroundPaintInGraphicsLayer) {
        graphics_layer_->SetContentsOpaque(
            owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
                CompositedBounds()));
      } else {
        // If we only paint the background onto the scrolling contents layer we
        // are going to leave a hole in the m_graphicsLayer where the background
        // is so it is not opaque.
        graphics_layer_->SetContentsOpaque(false);
      }
    } else {
      if (HasScrollingLayer())
        scrolling_contents_layer_->SetContentsOpaque(false);
      graphics_layer_->SetContentsOpaque(
          owning_layer_.BackgroundIsKnownToBeOpaqueInRect(CompositedBounds()));
    }
  }
}

void CompositedLayerMapping::UpdateRasterizationPolicy() {
  bool transformed_rasterization_allowed =
      !(owning_layer_.GetCompositingReasons() &
        CompositingReason::kComboAllDirectReasons);
  graphics_layer_->ContentLayer()->SetTransformedRasterizationAllowed(
      transformed_rasterization_allowed);
  if (squashing_layer_)
    squashing_layer_->ContentLayer()->SetTransformedRasterizationAllowed(true);
}

void CompositedLayerMapping::UpdateCompositedBounds() {
  DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
            DocumentLifecycle::kInCompositingUpdate);
  // FIXME: if this is really needed for performance, it would be better to
  // store it on Layer.
  composited_bounds_ = owning_layer_.BoundingBoxForCompositing();
  content_offset_in_compositing_layer_dirty_ = true;
}

GraphicsLayer* CompositedLayerMapping::FrameContentsGraphicsLayer() const {
  Node* node = GetLayoutObject().GetNode();
  if (!node->IsFrameOwnerElement())
    return nullptr;

  Document* document = ToHTMLFrameOwnerElement(node)->contentDocument();
  if (!document)
    return nullptr;

  LayoutView* layoutView = document->GetLayoutView();
  if (!layoutView)
    return nullptr;

  DCHECK(layoutView->HasLayer());
  PaintLayer* layer = layoutView->Layer();

  // PaintLayerCompositor updates child frames before parents, so in general
  // it is safe to read the child's compositing state here, and to position its
  // main GraphicsLayer in UpdateAfterPartResize.

  // If the child is not yet in compositing mode, there's nothing to do for now.
  // If it becomes composited later, it will mark the parent frame for another
  // compositing update (see PaintLayerCompositor::AttachRootLayer).

  // If the child's rendering is throttled, its lifecycle state may not permit
  // compositing queries.  But in that case, it has not yet entered compositing
  // mode (see above).

  if (layoutView->GetFrameView()->ShouldThrottleRendering())
    return nullptr;
  DCHECK(layer->IsAllowedToQueryCompositingState());
  if (!layer->HasCompositedLayerMapping())
    return nullptr;

  return layer->GetCompositedLayerMapping()->MainGraphicsLayer();
}

void CompositedLayerMapping::UpdateAfterPartResize() {
  if (GetLayoutObject().IsLayoutEmbeddedContent()) {
    FloatPoint parent_posn = child_containment_layer_
                                 ? child_containment_layer_->GetPosition()
                                 : FloatPoint();
    if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
      if (GraphicsLayer* document_layer = FrameContentsGraphicsLayer()) {
        document_layer->SetPosition(FlooredIntPoint(
            FloatPoint(ContentsBox().Location()) - parent_posn));
      }
    } else if (PaintLayerCompositor* inner_compositor =
                   PaintLayerCompositor::FrameContentsCompositor(
                       ToLayoutEmbeddedContent(GetLayoutObject()))) {
      inner_compositor->FrameViewDidChangeSize();
      FloatSize offset = FloatPoint(ContentsBox().Location()) - parent_posn;
      // Assert our frameviews are always aligned to pixel boundaries.
      DCHECK(offset.Width() == floor(offset.Width()) &&
             offset.Height() == floor(offset.Height()));
      inner_compositor->FrameViewDidChangeLocation(
          IntPoint(floor(offset.Width()), floor(offset.Height())));
    }
  }
}

void CompositedLayerMapping::UpdateCompositingReasons() {
  // All other layers owned by this mapping will have the same compositing
  // reason for their lifetime, so they are initialized only when created.
  graphics_layer_->SetCompositingReasons(owning_layer_.GetCompositingReasons());
  graphics_layer_->SetSquashingDisallowedReasons(
      owning_layer_.GetSquashingDisallowedReasons());
}

bool CompositedLayerMapping::AncestorRoundedCornersWillClip(
    const FloatRect& bounds_in_ancestor_space) const {
  // Collect all border-radius clips between us and the state we inherited.
  LayoutPoint zero_offset;
  Vector<FloatRoundedRect> rounded_rect_clips;
  LayerClipRecorder::CollectRoundedRectClips(
      owning_layer_, clip_inheritance_ancestor_, zero_offset, true,
      LayerClipRecorder::kDoNotIncludeSelfForBorderRadius, rounded_rect_clips);

  for (auto clip_rect : rounded_rect_clips) {
    FloatRect inner_clip_rect = clip_rect.RadiusCenterRect();
    // The first condition catches cases where the child is certainly inside
    // the rounded corner portion of the border, and cannot be clipped by
    // the rounded portion. The second catches cases where the child is
    // entirely outside the rectangular border (ignoring rounded corners) so
    // is also unaffected by the rounded corners. In both cases the existing
    // rectangular clip is adequate and the mask is unnecessary.
    if (!inner_clip_rect.Contains(bounds_in_ancestor_space) &&
        bounds_in_ancestor_space.Intersects(clip_rect.Rect())) {
      return true;
    }
  }
  return false;
}

void CompositedLayerMapping::
    OwningLayerClippedOrMaskedByLayerNotAboveCompositedAncestor(
        bool& owning_layer_is_clipped,
        bool& owning_layer_is_masked) const {
  owning_layer_is_clipped = false;
  owning_layer_is_masked = false;

  if (!clip_inheritance_ancestor_)
    return;

  // Compute the clips below the layer we inherit clip state from.
  // Ignore the clips of the inherited layer, because they are already a part
  // of the inherited state.
  // FIXME: this should use cached clip rects, but this sometimes give
  // inaccurate results (and trips the ASSERTS in PaintLayerClipper).
  ClipRectsContext clip_rects_context(
      clip_inheritance_ancestor_, kUncachedClipRects,
      kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClip);

  ClipRect clip_rect;
  owning_layer_.Clipper(PaintLayer::kDoNotUseGeometryMapper)
      .CalculateBackgroundClipRect(clip_rects_context, clip_rect);
  if (clip_rect.Rect() == LayoutRect(LayoutRect::InfiniteIntRect()))
    return;

  owning_layer_is_clipped = true;

  // TODO(schenney): CSS clips are not applied to composited children, and
  // should be via mask or by compositing the parent too.
  // https://bugs.chromium.org/p/chromium/issues/detail?id=615870
  if (!clip_rect.HasRadius())
    return;

  // If there are any rounded corners we must use a mask in the presence of
  // composited descendants because we have no efficient way to determine the
  // bounds of those children for optimizing the mask.
  if (owning_layer_.HasCompositingDescendant()) {
    owning_layer_is_masked = true;
    return;
  }

  FloatRect bounds_in_ancestor_space =
      GetLayoutObject()
          .LocalToAncestorQuad(FloatRect(composited_bounds_),
                               &clip_inheritance_ancestor_->GetLayoutObject(),
                               kUseTransforms)
          .BoundingBox();
  owning_layer_is_masked =
      AncestorRoundedCornersWillClip(bounds_in_ancestor_space);
}

const PaintLayer* CompositedLayerMapping::ScrollParent() const {
  const PaintLayer* scroll_parent = owning_layer_.ScrollParent();
  if (scroll_parent && !scroll_parent->NeedsCompositedScrolling())
    return nullptr;
  return scroll_parent;
}

const PaintLayer* CompositedLayerMapping::CompositedClipParent() const {
  const PaintLayer* clip_parent = owning_layer_.ClipParent();
  return clip_parent ? clip_parent->EnclosingLayerWithCompositedLayerMapping(
                           kIncludeSelf)
                     : nullptr;
}

void CompositedLayerMapping::UpdateClipInheritanceAncestor(
    const PaintLayer* compositing_container) {
  // Determine the clip state we are going to inherit.
  // There are three sources a layer inherits its clip state from, in the
  // order of priority (see cc/trees/property_tree_builder.cc):
  // 1. Clip parent
  // 2. Scroll parent
  // 3. Parent layer
  if (const PaintLayer* clip_parent = CompositedClipParent())
    clip_inheritance_ancestor_ = clip_parent;
  else if (const PaintLayer* scroll_parent = ScrollParent())
    clip_inheritance_ancestor_ = scroll_parent;
  else
    clip_inheritance_ancestor_ = compositing_container;
}

bool CompositedLayerMapping::UpdateGraphicsLayerConfiguration(
    const PaintLayer* compositing_container) {
  DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
            DocumentLifecycle::kInCompositingUpdate);

  // Note carefully: here we assume that the compositing state of all
  // descendants have been updated already, so it is legitimate to compute and
  // cache the composited bounds for this layer.
  UpdateCompositedBounds();

  PaintLayerCompositor* compositor = Compositor();
  LayoutObject& layout_object = GetLayoutObject();
  const ComputedStyle& style = layout_object.StyleRef();

  bool layer_config_changed = false;

  if (UpdateForegroundLayer(
          compositor->NeedsContentsCompositingLayer(&owning_layer_)))
    layer_config_changed = true;

  bool needs_descendants_clipping_layer =
      compositor->ClipsCompositingDescendants(&owning_layer_);

  // Our scrolling layer will clip.
  if (owning_layer_.NeedsCompositedScrolling())
    needs_descendants_clipping_layer = false;

  const PaintLayer* scroll_parent = ScrollParent();

  // This is required because compositing layers are parented according to the
  // z-order hierarchy, yet clipping goes down the layoutObject hierarchy. Thus,
  // a PaintLayer can be clipped by a PaintLayer that is an ancestor in the
  // layoutObject hierarchy, but a sibling in the z-order hierarchy. Further,
  // that sibling need not be composited at all. In such scenarios, an ancestor
  // clipping layer is necessary to apply the composited clip for this layer.
  bool needs_ancestor_clip = false;
  if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
    bool needs_ancestor_clipping_mask = false;
    UpdateClipInheritanceAncestor(compositing_container);
    OwningLayerClippedOrMaskedByLayerNotAboveCompositedAncestor(
        needs_ancestor_clip, needs_ancestor_clipping_mask);
    if (UpdateClippingLayers(needs_ancestor_clip, needs_ancestor_clipping_mask,
                             needs_descendants_clipping_layer))
      layer_config_changed = true;
  }

  if (UpdateScrollingLayers(owning_layer_.NeedsCompositedScrolling()))
    layer_config_changed = true;

  // If the outline needs to draw over the composited scrolling contents layer
  // or scrollbar layers it needs to be drawn into a separate layer.
  int min_border_width =
      std::min(layout_object.Style()->BorderTopWidth(),
               std::min(layout_object.Style()->BorderLeftWidth(),
                        std::min(layout_object.Style()->BorderRightWidth(),
                                 layout_object.Style()->BorderBottomWidth())));
  bool needs_decoration_outline_layer =
      owning_layer_.GetScrollableArea() &&
      owning_layer_.GetScrollableArea()->UsesCompositedScrolling() &&
      layout_object.Style()->HasOutline() &&
      layout_object.Style()->OutlineOffset() < -min_border_width;

  if (UpdateDecorationOutlineLayer(needs_decoration_outline_layer))
    layer_config_changed = true;

  if (UpdateOverflowControlsLayers(
          RequiresHorizontalScrollbarLayer(), RequiresVerticalScrollbarLayer(),
          RequiresScrollCornerLayer(), needs_ancestor_clip))
    layer_config_changed = true;

  bool has_perspective = style.HasPerspective();
  bool needs_child_transform_layer = has_perspective && layout_object.IsBox();
  if (UpdateChildTransformLayer(needs_child_transform_layer))
    layer_config_changed = true;

  if (UpdateSquashingLayers(!squashed_layers_.IsEmpty()))
    layer_config_changed = true;

  UpdateScrollParent(scroll_parent);
  UpdateClipParent(scroll_parent);

  if (layer_config_changed)
    UpdateInternalHierarchy();

  // A mask layer is not part of the hierarchy proper, it's an auxiliary layer
  // that's plugged into another GraphicsLayer that is part of the hierarchy.
  // It has no parent or child GraphicsLayer. For that reason, we process it
  // here, after the hierarchy has been updated.
  bool has_mask =
      CSSMaskPainter::MaskBoundingBox(GetLayoutObject(), LayoutPoint())
          .has_value();
  bool has_clip_path =
      ClipPathClipper::LocalClipPathBoundingBox(GetLayoutObject()).has_value();
  if (UpdateMaskLayer(has_mask || has_clip_path)) {
    graphics_layer_->SetMaskLayer(mask_layer_.get());
    layer_config_changed = true;
  }

  // If we have a border radius on a scrolling layer, we need a clipping mask
  // to properly clip the scrolled contents, even if there are no composited
  // descendants.
  if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
    bool is_accelerated_contents = IsAcceleratedContents(layout_object);
    bool has_children_subject_to_overflow_clip =
        HasClippingLayer() || HasScrollingLayer() || is_accelerated_contents;
    bool needs_child_clipping_mask =
        style.HasBorderRadius() && has_children_subject_to_overflow_clip;
    if (UpdateChildClippingMaskLayer(needs_child_clipping_mask))
      layer_config_changed = true;
    {
      // Attach child clipping mask layer to the first layer that can be applied
      // and clear the rest.
      // TODO(trchen): Verify if the 3 cases are mutually exclusive.
      GraphicsLayer* first_come_first_served = child_clipping_mask_layer_.get();
      if (HasClippingLayer()) {
        ClippingLayer()->SetMaskLayer(first_come_first_served);
        first_come_first_served = nullptr;
      }
      if (HasScrollingLayer()) {
        ScrollingLayer()->SetMaskLayer(first_come_first_served);
        first_come_first_served = nullptr;
      }
      graphics_layer_->SetContentsClippingMaskLayer(first_come_first_served);
    }
  }

  UpdateBackgroundColor();

  if (layout_object.IsImage()) {
    if (IsDirectlyCompositedImage()) {
      UpdateImageContents();
    } else if (graphics_layer_->HasContentsLayer()) {
      graphics_layer_->SetContentsToImage(nullptr, Image::kUnspecifiedDecode);
    }
  }

  if (WebPluginContainerImpl* plugin = GetPluginContainer(layout_object)) {
    graphics_layer_->SetContentsToCcLayer(
        plugin->CcLayer(), plugin->PreventContentsOpaqueChangesToCcLayer());
  } else if (layout_object.GetNode() &&
             layout_object.GetNode()->IsFrameOwnerElement() &&
             ToHTMLFrameOwnerElement(layout_object.GetNode())->ContentFrame()) {
    Frame* frame =
        ToHTMLFrameOwnerElement(layout_object.GetNode())->ContentFrame();
    if (frame->IsRemoteFrame()) {
      RemoteFrame* remote = ToRemoteFrame(frame);
      cc::Layer* layer = remote->GetCcLayer();
      graphics_layer_->SetContentsToCcLayer(
          layer, remote->WebLayerHasFixedContentsOpaque());
    }
  } else if (layout_object.IsVideo()) {
    HTMLMediaElement* media_element =
        ToHTMLMediaElement(layout_object.GetNode());
    graphics_layer_->SetContentsToCcLayer(
        media_element->CcLayer(),
        /*prevent_contents_opaque_changes=*/true);
  } else if (IsSurfaceLayerCanvas(layout_object)) {
    HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode());
    graphics_layer_->SetContentsToCcLayer(
        canvas->SurfaceLayerBridge()->GetCcLayer(),
        /*prevent_contents_opaque_changes=*/false);
    layer_config_changed = true;
  } else if (IsTextureLayerCanvas(layout_object)) {
    HTMLCanvasElement* canvas = ToHTMLCanvasElement(layout_object.GetNode());
    if (CanvasRenderingContext* context = canvas->RenderingContext()) {
      graphics_layer_->SetContentsToCcLayer(
          context->CcLayer(), /*prevent_contents_opaque_changes=*/false);
    }
    layer_config_changed = true;
  }
  if (layout_object.IsLayoutEmbeddedContent()) {
    if (PaintLayerCompositor::AttachFrameContentLayersToIframeLayer(
            ToLayoutEmbeddedContent(layout_object)))
      layer_config_changed = true;
  }

  if (layer_config_changed) {
    // Changes to either the internal hierarchy or the mask layer have an impact
    // on painting phases, so we need to update when either are updated.
    UpdatePaintingPhases();
    // Need to update paint property states of the changed GraphicsLayers.
    layout_object.SetNeedsPaintPropertyUpdate();
  }

  UpdateElementId();

  graphics_layer_->SetHasWillChangeTransformHint(
      style.HasWillChangeTransformHint());

  if (style.Preserves3D() && style.HasOpacity() &&
      owning_layer_.Has3DTransformedDescendant()) {
    UseCounter::Count(layout_object.GetDocument(),
                      WebFeature::kOpacityWithPreserve3DQuirk);
  }

  return layer_config_changed;
}

static LayoutPoint ComputeOffsetFromCompositedAncestor(
    const PaintLayer* layer,
    const PaintLayer* composited_ancestor,
    const LayoutPoint& local_representative_point_for_fragmentation,
    const FloatPoint& offset_for_sticky_position) {
  // Add in the offset of the composited bounds from the coordinate space of
  // the PaintLayer, since visualOffsetFromAncestor() requires the pre-offset
  // input to be in the space of the PaintLayer. We also need to add in this
  // offset before computation of visualOffsetFromAncestor(), because it affects
  // fragmentation offset if compositedAncestor crosses a pagination boundary.
  //
  // Currently, visual fragmentation for composited layers is not implemented.
  // For fragmented contents, we paint in the logical coordinates of the flow
  // thread, then split the result by fragment boundary and paste each part
  // into each fragment's physical position.
  // Since composited layers don't support visual fragmentation, we have to
  // choose a "representative" fragment to position the painted contents. This
  // is where localRepresentativePointForFragmentation comes into play.
  // The fragment that the representative point resides in will be chosen as
  // the representative fragment for layer position purpose.
  // For layers that are not fragmented, the point doesn't affect behavior as
  // there is one and only one fragment.
  LayoutPoint offset = layer->VisualOffsetFromAncestor(
      composited_ancestor, local_representative_point_for_fragmentation);
  if (composited_ancestor)
    offset.Move(composited_ancestor->SubpixelAccumulation());
  offset.MoveBy(-local_representative_point_for_fragmentation);
  offset.MoveBy(-LayoutPoint(offset_for_sticky_position));
  return offset;
}

void CompositedLayerMapping::ComputeBoundsOfOwningLayer(
    const PaintLayer* composited_ancestor,
    IntRect& local_bounds,
    IntRect& compositing_bounds_relative_to_composited_ancestor,
    LayoutPoint& offset_from_composited_ancestor,
    IntPoint& snapped_offset_from_composited_ancestor) {
  // HACK(chrishtr): adjust for position of inlines.
  LayoutPoint local_representative_point_for_fragmentation;
  if (owning_layer_.GetLayoutObject().IsLayoutInline()) {
    local_representative_point_for_fragmentation =
        ToLayoutInline(owning_layer_.GetLayoutObject()).FirstLineBoxTopLeft();
  }
  // Blink will already have applied any necessary offset for sticky positioned
  // elements. If the compositor is handling sticky offsets for this layer, we
  // need to remove the Blink-side offset to avoid double-counting.
  FloatPoint offset_for_sticky_position =
      StickyPositionOffsetForLayer(owning_layer_);
  offset_from_composited_ancestor = ComputeOffsetFromCompositedAncestor(
      &owning_layer_, composited_ancestor,
      local_representative_point_for_fragmentation, offset_for_sticky_position);
  snapped_offset_from_composited_ancestor =
      IntPoint(offset_from_composited_ancestor.X().Round(),
               offset_from_composited_ancestor.Y().Round());

  LayoutSize subpixel_accumulation;
  if (!owning_layer_.Transform() ||
      owning_layer_.Transform()->IsIdentityOrTranslation()) {
    subpixel_accumulation = offset_from_composited_ancestor -
                            snapped_offset_from_composited_ancestor;
  }

  // Invalidate the whole layer when subpixel accumulation changes, since
  // the previous subpixel accumulation is baked into the dispay list.
  // However, don't do so for directly composited layers, to avoid impacting
  // performance.
  if (subpixel_accumulation != owning_layer_.SubpixelAccumulation()) {
    // Always invalidate if under-invalidation checking is on, to avoid
    // false positives.
    if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
      SetContentsNeedDisplay();
    else if (!(owning_layer_.GetCompositingReasons() &
               CompositingReason::kComboAllDirectReasons))
      SetContentsNeedDisplay();
  }

  // Otherwise discard the sub-pixel remainder because paint offset can't be
  // transformed by a non-translation transform.
  owning_layer_.SetSubpixelAccumulation(subpixel_accumulation);

  base::Optional<IntRect> mask_bounding_box = CSSMaskPainter::MaskBoundingBox(
      GetLayoutObject(), LayoutPoint(subpixel_accumulation));
  base::Optional<FloatRect> clip_path_bounding_box =
      ClipPathClipper::LocalClipPathBoundingBox(GetLayoutObject());
  if (clip_path_bounding_box)
    clip_path_bounding_box->MoveBy(FloatPoint(subpixel_accumulation));

  // Override graphics layer size to the bound of mask layer, this is because
  // the compositor implementation requires mask layer bound to match its
  // host layer.
  if (mask_bounding_box) {
    local_bounds = *mask_bounding_box;
    if (clip_path_bounding_box)
      local_bounds.Intersect(EnclosingIntRect(*clip_path_bounding_box));
  } else if (clip_path_bounding_box) {
    local_bounds = EnclosingIntRect(*clip_path_bounding_box);
  } else {
    // Move the bounds by the subpixel accumulation so that it pixel-snaps
    // relative to absolute pixels instead of local coordinates.
    LayoutRect local_raw_compositing_bounds = CompositedBounds();
    local_raw_compositing_bounds.Move(subpixel_accumulation);
    local_bounds = PixelSnappedIntRect(local_raw_compositing_bounds);
  }

  compositing_bounds_relative_to_composited_ancestor = local_bounds;
  compositing_bounds_relative_to_composited_ancestor.MoveBy(
      snapped_offset_from_composited_ancestor);
}

void CompositedLayerMapping::UpdateSquashingLayerGeometry(
    const IntPoint& graphics_layer_parent_location,
    const PaintLayer* compositing_container,
    const IntPoint& snapped_offset_from_composited_ancestor,
    Vector<GraphicsLayerPaintInfo>& layers,
    LayoutPoint* offset_from_transformed_ancestor,
    Vector<PaintLayer*>& layers_needing_paint_invalidation) {
  if (!squashing_layer_)
    return;

  LayoutPoint compositing_container_offset_from_parent_graphics_layer =
      -graphics_layer_parent_location;
  if (compositing_container) {
    compositing_container_offset_from_parent_graphics_layer +=
        compositing_container->SubpixelAccumulation();
  }

  const PaintLayer* common_transform_ancestor = nullptr;
  if (compositing_container && compositing_container->Transform()) {
    common_transform_ancestor = compositing_container;
  } else if (compositing_container) {
    common_transform_ancestor =
        &compositing_container->TransformAncestorOrRoot();
  }

  // What about a null compositing container?

  // FIXME: Cache these offsets.
  LayoutPoint compositing_container_offset_from_transformed_ancestor;
  if (compositing_container) {
    compositing_container_offset_from_transformed_ancestor =
        compositing_container->ComputeOffsetFromAncestor(
            *common_transform_ancestor);
  }

  LayoutRect total_squash_bounds;
  for (size_t i = 0; i < layers.size(); ++i) {
    LayoutRect squashed_bounds =
        layers[i].paint_layer->BoundingBoxForCompositing();

    // Store the local bounds of the Layer subtree before applying the offset.
    layers[i].composited_bounds = squashed_bounds;

    DCHECK(&layers[i].paint_layer->TransformAncestorOrRoot() ==
           common_transform_ancestor);

    LayoutPoint squashed_layer_offset_from_transformed_ancestor =
        layers[i].paint_layer->ComputeOffsetFromAncestor(
            *common_transform_ancestor);
    LayoutSize squashed_layer_offset_from_compositing_container =
        squashed_layer_offset_from_transformed_ancestor -
        compositing_container_offset_from_transformed_ancestor;

    squashed_bounds.Move(squashed_layer_offset_from_compositing_container);
    total_squash_bounds.Unite(squashed_bounds);
  }

  // The totalSquashBounds is positioned with respect to compositingContainer.
  // But the squashingLayer needs to be positioned with respect to the
  // graphicsLayerParent.  The conversion between compositingContainer and the
  // graphicsLayerParent is already computed as
  // compositingContainerOffsetFromParentGraphicsLayer.
  total_squash_bounds.MoveBy(
      compositing_container_offset_from_parent_graphics_layer);
  const IntRect squash_layer_bounds = EnclosingIntRect(total_squash_bounds);
  const IntPoint squash_layer_origin = squash_layer_bounds.Location();
  const LayoutSize squash_layer_origin_in_compositing_container_space =
      squash_layer_origin -
      compositing_container_offset_from_parent_graphics_layer;

  // Now that the squashing bounds are known, we can convert the PaintLayer
  // painting offsets from compositingContainer space to the squashing layer
  // space.
  //
  // The painting offset we want to compute for each squashed PaintLayer is
  // essentially the position of the squashed PaintLayer described w.r.t.
  // compositingContainer's origin.  So we just need to convert that point from
  // compositingContainer space to the squashing layer's space. This is done by
  // subtracting squashLayerOriginInCompositingContainerSpace, but then the
  // offset overall needs to be negated because that's the direction that the
  // painting code expects the offset to be.
  for (size_t i = 0; i < layers.size(); ++i) {
    const LayoutPoint squashed_layer_offset_from_transformed_ancestor =
        layers[i].paint_layer->ComputeOffsetFromAncestor(
            *common_transform_ancestor);
    const LayoutSize offset_from_squash_layer_origin =
        (squashed_layer_offset_from_transformed_ancestor -
         compositing_container_offset_from_transformed_ancestor) -
        squash_layer_origin_in_compositing_container_space;

    IntSize new_offset_from_layout_object =
        -IntSize(offset_from_squash_layer_origin.Width().Round(),
                 offset_from_squash_layer_origin.Height().Round());
    LayoutSize subpixel_accumulation =
        offset_from_squash_layer_origin + new_offset_from_layout_object;
    if (layers[i].offset_from_layout_object_set &&
        layers[i].offset_from_layout_object != new_offset_from_layout_object) {
      // It is ok to issue paint invalidation here, because all of the geometry
      // needed to correctly invalidate paint is computed by this point.
      DisablePaintInvalidationStateAsserts disabler;
      ObjectPaintInvalidator(layers[i].paint_layer->GetLayoutObject())
          .InvalidatePaintIncludingNonCompositingDescendants();

      TRACE_LAYER_INVALIDATION(layers[i].paint_layer,
                               InspectorLayerInvalidationTrackingEvent::
                                   kSquashingLayerGeometryWasUpdated);
      layers_needing_paint_invalidation.push_back(layers[i].paint_layer);
    }
    layers[i].offset_from_layout_object = new_offset_from_layout_object;
    layers[i].offset_from_layout_object_set = true;

    layers[i].paint_layer->SetSubpixelAccumulation(subpixel_accumulation);
  }

  squashing_layer_->SetPosition(squash_layer_bounds.Location());
  squashing_layer_->SetSize(squash_layer_bounds.Size());
  // We can't squashing_layer_->SetOffsetFromLayoutObject().
  // Squashing layer has special paint and invalidation logic that already
  // compensated for compositing bounds, setting it here would end up
  // double adjustment. The value is stored to be used by SPv175.
  auto new_offset = squash_layer_bounds.Location() -
                    snapped_offset_from_composited_ancestor +
                    ToIntSize(graphics_layer_parent_location);
  if (new_offset != squashing_layer_offset_from_layout_object_) {
    squashing_layer_offset_from_layout_object_ = new_offset;
    // Need to update squashing layer state according to the new offset.
    OwningLayer().GetLayoutObject().SetNeedsPaintPropertyUpdate();
  }

  *offset_from_transformed_ancestor =
      compositing_container_offset_from_transformed_ancestor;
  offset_from_transformed_ancestor->Move(
      squash_layer_origin_in_compositing_container_space);

  for (size_t i = 0; i < layers.size(); ++i) {
    LocalClipRectForSquashedLayer(owning_layer_, layers, layers[i]);
  }
}

void CompositedLayerMapping::UpdateGraphicsLayerGeometry(
    const PaintLayer* compositing_container,
    const PaintLayer* compositing_stacking_context,
    Vector<PaintLayer*>& layers_needing_paint_invalidation) {
  DCHECK_EQ(owning_layer_.Compositor()->Lifecycle().GetState(),
            DocumentLifecycle::kInCompositingUpdate);

  // Set transform property, if it is not animating. We have to do this here
  // because the transform is affected by the layer dimensions.
  if (!GetLayoutObject().Style()->IsRunningTransformAnimationOnCompositor())
    UpdateTransform(GetLayoutObject().StyleRef());

  // Set opacity, if it is not animating.
  if (!GetLayoutObject().Style()->IsRunningOpacityAnimationOnCompositor())
    UpdateOpacity(GetLayoutObject().StyleRef());

  if (!GetLayoutObject().Style()->IsRunningFilterAnimationOnCompositor())
    UpdateFilters();

  if (!GetLayoutObject()
           .Style()
           ->IsRunningBackdropFilterAnimationOnCompositor())
    UpdateBackdropFilters();

  IntRect local_compositing_bounds;
  IntRect relative_compositing_bounds;
  LayoutPoint offset_from_composited_ancestor;
  IntPoint snapped_offset_from_composited_ancestor;
  ComputeBoundsOfOwningLayer(compositing_container, local_compositing_bounds,
                             relative_compositing_bounds,
                             offset_from_composited_ancestor,
                             snapped_offset_from_composited_ancestor);

  IntPoint graphics_layer_parent_location;
  ComputeGraphicsLayerParentLocation(compositing_container,
                                     graphics_layer_parent_location);

  // Might update graphicsLayerParentLocation.
  UpdateAncestorClippingLayerGeometry(compositing_container,
                                      snapped_offset_from_composited_ancestor,
                                      graphics_layer_parent_location);

  IntSize contents_size(relative_compositing_bounds.Size());

  UpdateMainGraphicsLayerGeometry(relative_compositing_bounds,
                                  local_compositing_bounds,
                                  graphics_layer_parent_location);
  UpdateOverflowControlsHostLayerGeometry(compositing_stacking_context,
                                          compositing_container,
                                          graphics_layer_parent_location);
  UpdateContentsOffsetInCompositingLayer(
      snapped_offset_from_composited_ancestor, graphics_layer_parent_location);
  UpdateStickyConstraints(GetLayoutObject().StyleRef());
  UpdateSquashingLayerGeometry(
      graphics_layer_parent_location, compositing_container,
      snapped_offset_from_composited_ancestor, squashed_layers_,
      &squashing_layer_offset_from_transformed_ancestor_,
      layers_needing_paint_invalidation);

  UpdateChildTransformLayerGeometry();
  UpdateChildContainmentLayerGeometry();

  UpdateMaskLayerGeometry();
  UpdateTransformGeometry(snapped_offset_from_composited_ancestor,
                          relative_compositing_bounds);
  // TODO(yigu): Currently the decoration layer uses the same contentSize
  // as the foreground layer. There are scenarios where the sizes could be
  // different so the decoration layer size should be calculated separately.
  UpdateDecorationOutlineLayerGeometry(contents_size);
  UpdateScrollingLayerGeometry(local_compositing_bounds);
  UpdateForegroundLayerGeometry();
  UpdateChildClippingMaskLayerGeometry();

  if (owning_layer_.GetScrollableArea() &&
      owning_layer_.GetScrollableArea()->ScrollsOverflow())
    owning_layer_.GetScrollableArea()->PositionOverflowControls();

  UpdateLayerBlendMode(GetLayoutObject().StyleRef());
  UpdateIsRootForIsolatedGroup();
  UpdateContentsRect();
  UpdateBackgroundColor();

  bool invalidate_graphics_layer;
  bool invalidate_scrolling_contents_layer;
  UpdateBackgroundPaintsOntoScrollingContentsLayer(
      invalidate_graphics_layer, invalidate_scrolling_contents_layer);

  // This depends on background_paints_onto_graphics_layer_.
  UpdateDrawsContent();

  // These invalidations need to happen after UpdateDrawsContent.
  if (invalidate_graphics_layer)
    graphics_layer_->SetNeedsDisplay();
  if (invalidate_scrolling_contents_layer)
    scrolling_contents_layer_->SetNeedsDisplay();

  UpdateElementId();
  UpdateContentsOpaque();
  UpdateRasterizationPolicy();
  UpdateAfterPartResize();
  UpdateRenderingContext();
  UpdateShouldFlattenTransform();
  UpdateChildrenTransform();
  UpdateScrollParent(ScrollParent());
  UpdateOverscrollBehavior();
  UpdateSnapContainerData();
  RegisterScrollingLayers();

  UpdateCompositingReasons();
}

void CompositedLayerMapping::UpdateOverscrollBehavior() {
  EOverscrollBehavior behavior_x =
      GetLayoutObject().StyleRef().OverscrollBehaviorX();
  EOverscrollBehavior behavior_y =
      GetLayoutObject().StyleRef().OverscrollBehaviorY();
  if (scrolling_contents_layer_) {
    scrolling_contents_layer_->SetOverscrollBehavior(cc::OverscrollBehavior(
        static_cast<cc::OverscrollBehavior::OverscrollBehaviorType>(behavior_x),
        static_cast<cc::OverscrollBehavior::OverscrollBehaviorType>(
            behavior_y)));
  }
}

void CompositedLayerMapping::UpdateSnapContainerData() {
  if (!GetLayoutObject().IsBox() || !scrolling_contents_layer_)
    return;

  SnapCoordinator* snap_coordinator =
      GetLayoutObject().GetDocument().GetSnapCoordinator();
  if (!snap_coordinator)
    return;

  scrolling_contents_layer_->SetSnapContainerData(
      snap_coordinator->GetSnapContainerData(ToLayoutBox(GetLayoutObject())));
}

void CompositedLayerMapping::UpdateMainGraphicsLayerGeometry(
    const IntRect& relative_compositing_bounds,
    const IntRect& local_compositing_bounds,
    const IntPoint& graphics_layer_parent_location) {
  // In RLS mode, an iframe's main GraphicsLayer is positioned by the CLM for
  // the <iframe> element in the parent frame's DOM.
  bool is_iframe_doc = GetLayoutObject().IsLayoutView() &&
                       !GetLayoutObject().GetFrame()->IsLocalRoot();
  if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled() || !is_iframe_doc) {
    graphics_layer_->SetPosition(
        FloatPoint(relative_compositing_bounds.Location() -
                   graphics_layer_parent_location));
  }
  graphics_layer_->SetOffsetFromLayoutObject(
      ToIntSize(local_compositing_bounds.Location()));

  if (graphics_layer_->Size() != relative_compositing_bounds.Size())
    graphics_layer_->SetSize(relative_compositing_bounds.Size());

  // m_graphicsLayer is the corresponding GraphicsLayer for this PaintLayer and
  // its non-compositing descendants. So, the visibility flag for
  // m_graphicsLayer should be true if there are any non-compositing visible
  // layers.
  bool contents_visible = owning_layer_.HasVisibleContent() ||
                          HasVisibleNonCompositingDescendant(&owning_layer_);
  graphics_layer_->SetContentsVisible(contents_visible);

  graphics_layer_->SetBackfaceVisibility(
      GetLayoutObject().Style()->BackfaceVisibility() ==
      EBackfaceVisibility::kVisible);
}

void CompositedLayerMapping::ComputeGraphicsLayerParentLocation(
    const PaintLayer* compositing_container,
    IntPoint& graphics_layer_parent_location) {
  if (compositing_container) {
    graphics_layer_parent_location =
        IntPoint(compositing_container->GetCompositedLayerMapping()
                     ->ParentForSublayers()
                     ->OffsetFromLayoutObject());
  } else if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
    graphics_layer_parent_location =
        GetLayoutObject().View()->DocumentRect().Location();
  } else if (!GetLayoutObject().GetFrame()->IsLocalRoot()) {  // TODO(oopif)
    DCHECK(RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
           !compositing_container);
    graphics_layer_parent_location = IntPoint();
  }

  if (compositing_container &&
      compositing_container->NeedsCompositedScrolling()) {
    LayoutBox& layout_box =
        ToLayoutBox(compositing_container->GetLayoutObject());
    IntSize scroll_offset = layout_box.ScrolledContentOffset();
    IntPoint scroll_origin =
        compositing_container->GetScrollableArea()->ScrollOrigin();
    scroll_origin.Move(-layout_box.BorderLeft().ToInt(),
                       -layout_box.BorderTop().ToInt());
    graphics_layer_parent_location = -(scroll_origin + scroll_offset);
  }
}

void CompositedLayerMapping::UpdateAncestorClippingLayerGeometry(
    const PaintLayer* compositing_container,
    const IntPoint& snapped_offset_from_composited_ancestor,
    IntPoint& graphics_layer_parent_location) {
  if (!compositing_container || !ancestor_clipping_layer_)
    return;

  ClipRectsContext clip_rects_context(
      clip_inheritance_ancestor_, kPaintingClipRectsIgnoringOverflowClip,
      kIgnorePlatformOverlayScrollbarSize, kIgnoreOverflowClipAndScroll);

  ClipRect clip_rect;
  owning_layer_.Clipper(PaintLayer::kDoNotUseGeometryMapper)
      .CalculateBackgroundClipRect(clip_rects_context, clip_rect);
  // Scroll offset is not included in the clip rect returned above
  // (see kIgnoreOverflowClipAndScroll), so we need to add it in
  // now. Scroll offset is excluded so that we do not need to invalidate
  // the clip rect cache on scroll.
  if (clip_inheritance_ancestor_->GetScrollableArea()) {
    clip_rect.Move(LayoutSize(
        -clip_inheritance_ancestor_->GetScrollableArea()->GetScrollOffset()));
  }

  DCHECK(clip_rect.Rect() != LayoutRect(LayoutRect::InfiniteIntRect()));

  // The accumulated clip rect is in the space of clip_inheritance_ancestor_.
  // It needs to be converted to the space of our compositing container because
  // our layer position is based on that.
  LayoutRect clip_rect_in_compositing_container_space = clip_rect.Rect();
  // The following two branches are doing exact the same conversion, but
  // ConvertToLayerCoords can only handle descendant-to-ancestor conversion.
  // Inversion needs to be done manually if clip_inheritance_container is not
  // a descendant of compositing_container.
  if (clip_inheritance_ancestor_ == compositing_container) {
    // No needs to convert.
  } else if (clip_inheritance_ancestor_ == ScrollParent()) {
    // Having a scroll parent implies that the inherited clip is a sibling to
    // us in paint order, thus our compositing container must be an ancestor
    // of the scroll parent.
    // See CompositingInputsUpdater::UpdateRecursive().
    DCHECK(clip_inheritance_ancestor_->GetLayoutObject().IsDescendantOf(
        &compositing_container->GetLayoutObject()));
    clip_inheritance_ancestor_->ConvertToLayerCoords(
        compositing_container, clip_rect_in_compositing_container_space);
  } else {
    // Inherits from clip parent. The clip parent is set only when we need to
    // escape some clip that was applied to our compositing container. As such,
    // the clip parent must be some ancestor of our compositing container.
    DCHECK(compositing_container->GetLayoutObject().IsDescendantOf(
        &clip_inheritance_ancestor_->GetLayoutObject()));
    LayoutPoint compositing_container_origin_in_clip_ancestor_space;
    compositing_container->ConvertToLayerCoords(
        clip_inheritance_ancestor_,
        compositing_container_origin_in_clip_ancestor_space);
    clip_rect_in_compositing_container_space.MoveBy(
        -compositing_container_origin_in_clip_ancestor_space);
  }
  clip_rect_in_compositing_container_space.Move(
      compositing_container->SubpixelAccumulation());

  IntRect snapped_clip_rect =
      PixelSnappedIntRect(clip_rect_in_compositing_container_space);

  ancestor_clipping_layer_->SetPosition(FloatPoint(
      snapped_clip_rect.Location() - graphics_layer_parent_location));
  ancestor_clipping_layer_->SetSize(snapped_clip_rect.Size());

  // backgroundRect is relative to compositingContainer, so subtract
  // snappedOffsetFromCompositedAncestor.X/snappedOffsetFromCompositedAncestor.Y
  // to get back to local coords.
  ancestor_clipping_layer_->SetOffsetFromLayoutObject(
      snapped_clip_rect.Location() - snapped_offset_from_composited_ancestor);

  if (ancestor_clipping_mask_layer_) {
    ancestor_clipping_mask_layer_->SetOffsetFromLayoutObject(
        ancestor_clipping_layer_->OffsetFromLayoutObject());
    ancestor_clipping_mask_layer_->SetSize(ancestor_clipping_layer_->Size());
    ancestor_clipping_mask_layer_->SetNeedsDisplay();
  }

  // The primary layer is then parented in, and positioned relative to this
  // clipping layer.
  graphics_layer_parent_location = snapped_clip_rect.Location();
}

void CompositedLayerMapping::UpdateOverflowControlsHostLayerGeometry(
    const PaintLayer* compositing_stacking_context,
    const PaintLayer* compositing_container,
    IntPoint graphics_layer_parent_location) {
  if (!overflow_controls_host_layer_)
    return;

  // To position and clip the scrollbars correctly, m_overflowControlsHostLayer
  // should match our border box rect, which is at the origin of our
  // LayoutObject. Its position is computed in various ways depending on who its
  // parent GraphicsLayer is going to be.
  LayoutPoint host_layer_position;

  if (NeedsToReparentOverflowControls()) {
    CompositedLayerMapping* stacking_clm =
        compositing_stacking_context->GetCompositedLayerMapping();
    DCHECK(stacking_clm);

    // Either m_overflowControlsHostLayer or
    // m_overflowControlsAncestorClippingLayer (if it exists) will be a child of
    // the main GraphicsLayer of the compositing stacking context.
    IntSize stacking_offset_from_layout_object =
        stacking_clm->MainGraphicsLayer()->OffsetFromLayoutObject();

    if (overflow_controls_ancestor_clipping_layer_) {
      overflow_controls_ancestor_clipping_layer_->SetSize(
          ancestor_clipping_layer_->Size());
      overflow_controls_ancestor_clipping_layer_->SetOffsetFromLayoutObject(
          ancestor_clipping_layer_->OffsetFromLayoutObject());
      overflow_controls_ancestor_clipping_layer_->SetMasksToBounds(true);

      FloatPoint position;
      if (compositing_stacking_context == compositing_container) {
        position = ancestor_clipping_layer_->GetPosition();
      } else {
        // graphicsLayerParentLocation is the location of
        // m_ancestorClippingLayer relative to compositingContainer (including
        // any offset from compositingContainer's m_childContainmentLayer).
        LayoutPoint offset = LayoutPoint(graphics_layer_parent_location);
        compositing_container->ConvertToLayerCoords(
            compositing_stacking_context, offset);
        position =
            FloatPoint(offset) - FloatSize(stacking_offset_from_layout_object);
      }

      overflow_controls_ancestor_clipping_layer_->SetPosition(position);
      host_layer_position.Move(
          -ancestor_clipping_layer_->OffsetFromLayoutObject());
    } else {
      // The controls are in the same 2D space as the compositing container, so
      // we can map them into the space of the container.
      TransformState transform_state(TransformState::kApplyTransformDirection,
                                     FloatPoint());
      owning_layer_.GetLayoutObject().MapLocalToAncestor(
          &compositing_stacking_context->GetLayoutObject(), transform_state,
          kApplyContainerFlip);
      transform_state.Flatten();
      host_layer_position = LayoutPoint(transform_state.LastPlanarPoint());
      if (PaintLayerScrollableArea* scrollable_area =
              compositing_stacking_context->GetScrollableArea()) {
        host_layer_position.Move(
            LayoutSize(ToFloatSize(scrollable_area->ScrollPosition())));
      }
      host_layer_position.Move(-stacking_offset_from_layout_object);
    }
  } else {
    host_layer_position.Move(-graphics_layer_->OffsetFromLayoutObject());
  }

  overflow_controls_host_layer_->SetPosition(FloatPoint(host_layer_position));

  const IntRect border_box =
      owning_layer_.GetLayoutBox()->PixelSnappedBorderBoxRect(
          owning_layer_.SubpixelAccumulation());
  overflow_controls_host_layer_->SetSize(border_box.Size());
  overflow_controls_host_layer_->SetMasksToBounds(true);
  overflow_controls_host_layer_->SetBackfaceVisibility(
      owning_layer_.GetLayoutObject().Style()->BackfaceVisibility() ==
      EBackfaceVisibility::kVisible);
}

void CompositedLayerMapping::UpdateChildContainmentLayerGeometry() {
  if (!child_containment_layer_)
    return;
  DCHECK(GetLayoutObject().IsBox());

  if (GetLayoutObject().IsLayoutEmbeddedContent()) {
    // Embedded content layers do not have a clipping rect defined,
    // so use the PaddingBoxRect.
    IntRect clipping_box =
        PixelSnappedIntRect(ToLayoutBox(GetLayoutObject()).PaddingBoxRect());
    child_containment_layer_->SetSize(clipping_box.Size());
    child_containment_layer_->SetOffsetFromLayoutObject(
        ToIntSize(clipping_box.Location()));
    IntPoint parent_location(
        child_containment_layer_->Parent()->OffsetFromLayoutObject());
    child_containment_layer_->SetPosition(
        IntPoint(clipping_box.Location() - parent_location));
  } else {
    IntRect clipping_box = PixelSnappedIntRect(
        ToLayoutBox(GetLayoutObject())
            .ClippingRect(LayoutPoint(SubpixelAccumulation())));
    child_containment_layer_->SetSize(clipping_box.Size());
    child_containment_layer_->SetOffsetFromLayoutObject(
        ToIntSize(clipping_box.Location()));
    IntPoint parent_location(
        child_containment_layer_->Parent()->OffsetFromLayoutObject());
    child_containment_layer_->SetPosition(
        IntPoint(clipping_box.Location() - parent_location));
  }

  if (child_clipping_mask_layer_ && !scrolling_layer_ &&
      !GetLayoutObject().Style()->ClipPath()) {
    child_clipping_mask_layer_->SetSize(child_containment_layer_->Size());
    child_clipping_mask_layer_->SetOffsetFromLayoutObject(
        child_containment_layer_->OffsetFromLayoutObject());
  }
}

void CompositedLayerMapping::UpdateChildTransformLayerGeometry() {
  if (!child_transform_layer_)
    return;
  const IntRect border_box =
      ToLayoutBox(owning_layer_.GetLayoutObject())
          .PixelSnappedBorderBoxRect(SubpixelAccumulation());
  child_transform_layer_->SetSize(border_box.Size());
  child_transform_layer_->SetOffsetFromLayoutObject(
      ToIntSize(border_box.Location()));
  IntPoint parent_location(
      child_transform_layer_->Parent()->OffsetFromLayoutObject());
  child_transform_layer_->SetPosition(
      FloatPoint(border_box.Location() - parent_location));
}

void CompositedLayerMapping::UpdateMaskLayerGeometry() {
  if (!mask_layer_)
    return;

  if (mask_layer_->Size() != graphics_layer_->Size()) {
    mask_layer_->SetSize(graphics_layer_->Size());
    mask_layer_->SetNeedsDisplay();
  }
  mask_layer_->SetPosition(FloatPoint());
  mask_layer_->SetOffsetFromLayoutObject(
      graphics_layer_->OffsetFromLayoutObject());
}

void CompositedLayerMapping::UpdateTransformGeometry(
    const IntPoint& snapped_offset_from_composited_ancestor,
    const IntRect& relative_compositing_bounds) {
  if (owning_layer_.HasTransformRelatedProperty()) {
    const LayoutRect border_box =
        ToLayoutBox(GetLayoutObject()).BorderBoxRect();

    // Get layout bounds in the coords of compositingContainer to match
    // relativeCompositingBounds.
    IntRect layer_bounds = PixelSnappedIntRect(
        ToLayoutPoint(owning_layer_.SubpixelAccumulation()), border_box.Size());
    layer_bounds.MoveBy(snapped_offset_from_composited_ancestor);

    // Update properties that depend on layer dimensions
    FloatPoint3D transform_origin =
        ComputeTransformOrigin(IntRect(IntPoint(), layer_bounds.Size()));

    // |transformOrigin| is in the local space of this layer.
    // layerBounds - relativeCompositingBounds converts to the space of the
    // compositing bounds relative to the composited ancestor. This does not
    // apply to the z direction, since the page is 2D.
    FloatPoint3D composited_transform_origin(
        layer_bounds.X() - relative_compositing_bounds.X() +
            transform_origin.X(),
        layer_bounds.Y() - relative_compositing_bounds.Y() +
            transform_origin.Y(),
        transform_origin.Z());
    graphics_layer_->SetTransformOrigin(composited_transform_origin);
  }
}

void CompositedLayerMapping::UpdateScrollingLayerGeometry(
    const IntRect& local_compositing_bounds) {
  if (!scrolling_layer_)
    return;

  DCHECK(scrolling_contents_layer_);
  LayoutBox& layout_box = ToLayoutBox(GetLayoutObject());
  IntRect overflow_clip_rect = PixelSnappedIntRect(layout_box.OverflowClipRect(
      LayoutPoint(owning_layer_.SubpixelAccumulation())));

  // When a m_childTransformLayer exists, local content offsets for the
  // m_scrollingLayer have already been applied. Otherwise, we apply them here.
  IntSize local_content_offset(0, 0);
  if (!child_transform_layer_) {
    local_content_offset =
        RoundedIntPoint(owning_layer_.SubpixelAccumulation()) -
        local_compositing_bounds.Location();
  }
  scrolling_layer_->SetPosition(
      FloatPoint(overflow_clip_rect.Location() + local_content_offset));

  auto old_scroll_container_size = scrolling_layer_->Size();
  scrolling_layer_->SetSize(overflow_clip_rect.Size());
  bool scroll_container_size_changed =
      old_scroll_container_size != scrolling_layer_->Size();

  IntSize old_scrolling_layer_offset =
      scrolling_layer_->OffsetFromLayoutObject();
  scrolling_layer_->SetOffsetFromLayoutObject(
      ToIntSize(overflow_clip_rect.Location()));

  if (child_clipping_mask_layer_ && !GetLayoutObject().Style()->ClipPath()) {
    child_clipping_mask_layer_->SetPosition(scrolling_layer_->GetPosition());
    child_clipping_mask_layer_->SetSize(scrolling_layer_->Size());
    child_clipping_mask_layer_->SetOffsetFromLayoutObject(
        ToIntSize(overflow_clip_rect.Location()));
  }

  bool overflow_clip_rect_offset_changed =
      old_scrolling_layer_offset != scrolling_layer_->OffsetFromLayoutObject();

  IntSize scroll_size =
      PixelSnappedIntRect(
          LayoutRect(
              LayoutPoint(owning_layer_.SubpixelAccumulation()),
              LayoutSize(layout_box.ScrollWidth(), layout_box.ScrollHeight())))
          .Size();
  // Ensure scrolling contents are at least as large as the scroll clip
  scroll_size = scroll_size.ExpandedTo(overflow_clip_rect.Size());

  if (overflow_clip_rect_offset_changed)
    scrolling_contents_layer_->SetNeedsDisplay();

  FloatPoint scroll_position =
      owning_layer_.GetScrollableArea()->ScrollPosition();
  DoubleSize scrolling_contents_offset(
      overflow_clip_rect.Location().X() - scroll_position.X(),
      overflow_clip_rect.Location().Y() - scroll_position.Y());
  // The scroll offset change is compared using floating point so that
  // fractional scroll offset change can be propagated to compositor.
  if (scrolling_contents_offset != scrolling_contents_offset_ ||
      scroll_size != scrolling_contents_layer_->Size() ||
      scroll_container_size_changed) {
    bool coordinator_handles_offset = false;
    auto* scrolling_coordinator = owning_layer_.GetScrollingCoordinator();
    auto* scrollable_area = owning_layer_.GetScrollableArea();
    if (scrolling_coordinator && scrollable_area) {
      coordinator_handles_offset =
          scrolling_coordinator->ScrollableAreaScrollLayerDidChange(
              scrollable_area);
    }
    scrolling_contents_layer_->SetPosition(
        coordinator_handles_offset ? FloatPoint()
                                   : FloatPoint(-ToFloatSize(scroll_position)));
  }
  scrolling_contents_offset_ = scrolling_contents_offset;

  scrolling_contents_layer_->SetSize(scroll_size);

  IntPoint scrolling_contents_layer_offset_from_layout_object;
  if (PaintLayerScrollableArea* scrollable_area =
          owning_layer_.GetScrollableArea()) {
    scrolling_contents_layer_offset_from_layout_object =
        -scrollable_area->ScrollOrigin();
  }
  scrolling_contents_layer_offset_from_layout_object.MoveBy(
      overflow_clip_rect.Location());

  scrolling_contents_layer_->SetOffsetDoubleFromLayoutObject(
      ToIntSize(scrolling_contents_layer_offset_from_layout_object),
      GraphicsLayer::kDontSetNeedsDisplay);
}

void CompositedLayerMapping::UpdateChildClippingMaskLayerGeometry() {
  if (!child_clipping_mask_layer_ || !GetLayoutObject().Style()->ClipPath() ||
      !GetLayoutObject().IsBox())
    return;
  LayoutBox& layout_box = ToLayoutBox(GetLayoutObject());
  IntRect padding_box = EnclosingIntRect(layout_box.PaddingBoxRect());

  child_clipping_mask_layer_->SetPosition(graphics_layer_->GetPosition());
  child_clipping_mask_layer_->SetSize(graphics_layer_->Size());
  child_clipping_mask_layer_->SetOffsetFromLayoutObject(
      ToIntSize(padding_box.Location()));

  // NOTE: also some stuff happening in updateChildContainmentLayerGeometry().
}

void CompositedLayerMapping::UpdateForegroundLayerGeometry() {
  if (!foreground_layer_)
    return;

  // Should be equivalent to local_compositing_bounds.
  IntRect compositing_bounds(
      IntPoint(graphics_layer_->OffsetFromLayoutObject()),
      FlooredIntSize(graphics_layer_->Size()));
  if (scrolling_layer_) {
    // Override compositing bounds to include full overflow if composited
    // scrolling is used.
    compositing_bounds =
        IntRect(IntPoint(scrolling_contents_layer_->OffsetFromLayoutObject()),
                FlooredIntSize(scrolling_contents_layer_->Size()));
  } else if (child_containment_layer_) {
    // If we have a clipping layer, shrink compositing bounds to the clip rect.
    // Note: this is technically incorrect because non-composited positive
    // z-index children can paint into the foreground layer, and positioned
    // elements can escape clips. We currently always composite layers that
    // escape clips, thus shrinking the layer won't cause bug.
    IntRect clipping_box(
        IntPoint(child_containment_layer_->OffsetFromLayoutObject()),
        FlooredIntSize(child_containment_layer_->Size()));
    compositing_bounds.Intersect(clipping_box);
  }

  IntRect old_compositing_bounds(
      IntPoint(foreground_layer_->OffsetFromLayoutObject()),
      FlooredIntSize(foreground_layer_->Size()));
  if (compositing_bounds != old_compositing_bounds) {
    foreground_layer_->SetOffsetFromLayoutObject(
        ToIntSize(compositing_bounds.Location()));
    foreground_layer_->SetSize(compositing_bounds.Size());
    foreground_layer_->SetNeedsDisplay();
  }
  IntPoint parent_location(ParentForSublayers()->OffsetFromLayoutObject());
  foreground_layer_->SetPosition(
      IntPoint(compositing_bounds.Location() - parent_location));
}

void CompositedLayerMapping::UpdateDecorationOutlineLayerGeometry(
    const IntSize& relative_compositing_bounds_size) {
  if (!decoration_outline_layer_)
    return;
  const auto& decoration_size = relative_compositing_bounds_size;
  decoration_outline_layer_->SetPosition(FloatPoint());
  if (decoration_size != decoration_outline_layer_->Size()) {
    decoration_outline_layer_->SetSize(decoration_size);
    decoration_outline_layer_->SetNeedsDisplay();
  }
  decoration_outline_layer_->SetOffsetFromLayoutObject(
      graphics_layer_->OffsetFromLayoutObject());
}

void CompositedLayerMapping::UpdateInternalHierarchy() {
  // m_foregroundLayer has to be inserted in the correct order with child
  // layers, so it's not inserted here.
  if (ancestor_clipping_layer_)
    ancestor_clipping_layer_->RemoveAllChildren();

  graphics_layer_->RemoveFromParent();

  if (ancestor_clipping_layer_)
    ancestor_clipping_layer_->AddChild(graphics_layer_.get());

  // Layer to which children should be attached as we build the hierarchy.
  GraphicsLayer* bottom_layer = graphics_layer_.get();
  auto update_bottom_layer = [&bottom_layer](GraphicsLayer* layer) {
    if (layer) {
      bottom_layer->AddChild(layer);
      bottom_layer = layer;
    }
  };

  update_bottom_layer(child_transform_layer_.get());
  update_bottom_layer(child_containment_layer_.get());
  update_bottom_layer(scrolling_layer_.get());

  // Now constructing the subtree for the overflow controls.
  bottom_layer = graphics_layer_.get();
  // TODO(pdr): Ensure painting uses the correct GraphicsLayer when root layer
  // scrolls is enabled.  crbug.com/638719
  if (is_main_frame_layout_view_layer_ &&
      !RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
    bottom_layer = GetLayoutObject()
                       .GetFrame()
                       ->GetPage()
                       ->GetVisualViewport()
                       .ContainerLayer();
  }
  update_bottom_layer(overflow_controls_ancestor_clipping_layer_.get());
  update_bottom_layer(overflow_controls_host_layer_.get());
  if (layer_for_horizontal_scrollbar_) {
    overflow_controls_host_layer_->AddChild(
        layer_for_horizontal_scrollbar_.get());
  }
  if (layer_for_vertical_scrollbar_) {
    overflow_controls_host_layer_->AddChild(
        layer_for_vertical_scrollbar_.get());
  }
  if (layer_for_scroll_corner_)
    overflow_controls_host_layer_->AddChild(layer_for_scroll_corner_.get());

  // Now add the DecorationOutlineLayer as a subtree to GraphicsLayer
  if (decoration_outline_layer_.get())
    graphics_layer_->AddChild(decoration_outline_layer_.get());

  // The squashing containment layer, if it exists, becomes a no-op parent.
  if (squashing_layer_) {
    DCHECK((ancestor_clipping_layer_ && !squashing_containment_layer_) ||
           (!ancestor_clipping_layer_ && squashing_containment_layer_));

    if (squashing_containment_layer_) {
      squashing_containment_layer_->RemoveAllChildren();
      squashing_containment_layer_->AddChild(graphics_layer_.get());
      squashing_containment_layer_->AddChild(squashing_layer_.get());
    } else {
      // The ancestor clipping layer is already set up and has m_graphicsLayer
      // under it.
      ancestor_clipping_layer_->AddChild(squashing_layer_.get());
    }
  }
}

void CompositedLayerMapping::UpdatePaintingPhases() {
  graphics_layer_->SetPaintingPhase(PaintingPhaseForPrimaryLayer());
  if (scrolling_contents_layer_) {
    GraphicsLayerPaintingPhase paint_phase =
        kGraphicsLayerPaintOverflowContents |
        kGraphicsLayerPaintCompositedScroll;
    if (!foreground_layer_)
      paint_phase |= kGraphicsLayerPaintForeground;
    scrolling_contents_layer_->SetPaintingPhase(paint_phase);
  }
  if (foreground_layer_) {
    GraphicsLayerPaintingPhase paint_phase = kGraphicsLayerPaintForeground;
    if (scrolling_contents_layer_)
      paint_phase |= kGraphicsLayerPaintOverflowContents;
    foreground_layer_->SetPaintingPhase(paint_phase);
  }
}

void CompositedLayerMapping::UpdateContentsRect() {
  graphics_layer_->SetContentsRect(PixelSnappedIntRect(ContentsBox()));
}

void CompositedLayerMapping::UpdateContentsOffsetInCompositingLayer(
    const IntPoint& snapped_offset_from_composited_ancestor,
    const IntPoint& graphics_layer_parent_location) {
  // m_graphicsLayer is positioned relative to our compositing ancestor
  // PaintLayer, but it's not positioned at the origin of m_owningLayer, it's
  // offset by m_contentBounds.location(). This is what
  // contentOffsetInCompositingLayer is meant to capture, roughly speaking
  // (ignoring rounding and subpixel accumulation).
  //
  // Our ancestor graphics layers in this CLM (m_graphicsLayer and potentially
  // m_ancestorClippingLayer) have pixel snapped, so if we don't adjust this
  // offset, we'll see accumulated rounding errors due to that snapping.
  //
  // In order to ensure that we account for this rounding, we compute
  // contentsOffsetInCompositingLayer in a somewhat roundabout way.
  //
  // our position = (desired position) - (inherited graphics layer offset).
  //
  // Precisely,
  // Offset = snappedOffsetFromCompositedAncestor -
  //          offsetDueToAncestorGraphicsLayers (See code below)
  //        = snappedOffsetFromCompositedAncestor -
  //          (m_graphicsLayer->position() + graphicsLayerParentLocation)
  //        = snappedOffsetFromCompositedAncestor -
  //          (relativeCompositingBounds.location() -
  //              graphicsLayerParentLocation +
  //              graphicsLayerParentLocation)
  //          (See updateMainGraphicsLayerGeometry)
  //        = snappedOffsetFromCompositedAncestor -
  //          relativeCompositingBounds.location()
  //        = snappedOffsetFromCompositedAncestor -
  //          (pixelSnappedIntRect(contentBounds.location()) +
  //              snappedOffsetFromCompositedAncestor)
  //          (See computeBoundsOfOwningLayer)
  //      = -pixelSnappedIntRect(contentBounds.location())
  //
  // As you can see, we've ended up at the same spot
  // (-contentBounds.location()), but by subtracting off our ancestor graphics
  // layers positions, we can be sure we've accounted correctly for any pixel
  // snapping due to ancestor graphics layers.
  //
  // And drawing of composited children takes into account the subpixel
  // accumulation of this CLM already (through its own
  // graphicsLayerParentLocation it appears).
  FloatPoint offset_due_to_ancestor_graphics_layers =
      graphics_layer_->GetPosition() + graphics_layer_parent_location;
  content_offset_in_compositing_layer_ =
      LayoutSize(snapped_offset_from_composited_ancestor -
                 offset_due_to_ancestor_graphics_layers);
  content_offset_in_compositing_layer_dirty_ = false;
}

void CompositedLayerMapping::UpdateDrawsContent() {
  bool in_overlay_fullscreen_video = false;
  if (GetLayoutObject().IsVideo()) {
    HTMLVideoElement* video_element =
        ToHTMLVideoElement(GetLayoutObject().GetNode());
    if (video_element->IsFullscreen() &&
        video_element->UsesOverlayFullscreenVideo())
      in_overlay_fullscreen_video = true;
  }
  bool has_painted_content =
      in_overlay_fullscreen_video ? false : ContainsPaintedContent();
  graphics_layer_->SetDrawsContent(has_painted_content);

  if (scrolling_layer_) {
    // m_scrollingLayer never has backing store.
    // m_scrollingContentsLayer only needs backing store if the scrolled
    // contents need to paint.
    scrolling_contents_are_empty_ =
        !owning_layer_.HasVisibleContent() ||
        !(GetLayoutObject().StyleRef().HasBackground() ||
          GetLayoutObject().HasBackdropFilter() || PaintsChildren());
    scrolling_contents_layer_->SetDrawsContent(!scrolling_contents_are_empty_);
  }

  draws_background_onto_content_layer_ = false;

  if (has_painted_content && IsTextureLayerCanvas(GetLayoutObject())) {
    CanvasRenderingContext* context =
        ToHTMLCanvasElement(GetLayoutObject().GetNode())->RenderingContext();
    // Content layer may be null if context is lost.
    if (cc::Layer* content_layer = context->CcLayer()) {
      Color bg_color(Color::kTransparent);
      if (ContentLayerSupportsDirectBackgroundComposition(GetLayoutObject())) {
        bg_color = LayoutObjectBackgroundColor();
        has_painted_content = false;
        draws_background_onto_content_layer_ = true;
      }
      content_layer->SetBackgroundColor(bg_color.Rgb());
    }
  }

  // FIXME: we could refine this to only allocate backings for one of these
  // layers if possible.
  if (foreground_layer_)
    foreground_layer_->SetDrawsContent(has_painted_content);

  if (decoration_outline_layer_)
    decoration_outline_layer_->SetDrawsContent(true);

  if (ancestor_clipping_mask_layer_)
    ancestor_clipping_mask_layer_->SetDrawsContent(true);

  if (mask_layer_)
    mask_layer_->SetDrawsContent(true);

  if (child_clipping_mask_layer_)
    child_clipping_mask_layer_->SetDrawsContent(true);
}

void CompositedLayerMapping::UpdateChildrenTransform() {
  if (GraphicsLayer* child_transform_layer = ChildTransformLayer()) {
    child_transform_layer->SetTransform(OwningLayer().PerspectiveTransform());
    child_transform_layer->SetTransformOrigin(
        OwningLayer().PerspectiveOrigin());
  }

  UpdateShouldFlattenTransform();
}

// Return true if the layers changed.
bool CompositedLayerMapping::UpdateClippingLayers(
    bool needs_ancestor_clip,
    bool needs_ancestor_clipping_mask,
    bool needs_descendant_clip) {
  bool layers_changed = false;

  if (needs_ancestor_clip) {
    if (!ancestor_clipping_layer_) {
      ancestor_clipping_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForAncestorClip);
      ancestor_clipping_layer_->SetMasksToBounds(true);
      ancestor_clipping_layer_->SetShouldFlattenTransform(false);
      layers_changed = true;
    }
  } else if (ancestor_clipping_layer_) {
    if (ancestor_clipping_mask_layer_) {
      ancestor_clipping_mask_layer_->RemoveFromParent();
      ancestor_clipping_mask_layer_ = nullptr;
    }
    ancestor_clipping_layer_->RemoveFromParent();
    ancestor_clipping_layer_ = nullptr;
    layers_changed = true;
  }

  if (needs_ancestor_clipping_mask) {
    DCHECK(ancestor_clipping_layer_);
    if (!ancestor_clipping_mask_layer_) {
      ancestor_clipping_mask_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForAncestorClippingMask);
      ancestor_clipping_mask_layer_->SetPaintingPhase(
          kGraphicsLayerPaintAncestorClippingMask);
      ancestor_clipping_layer_->SetMaskLayer(
          ancestor_clipping_mask_layer_.get());
      layers_changed = true;
    }
  } else if (ancestor_clipping_mask_layer_) {
    ancestor_clipping_mask_layer_->RemoveFromParent();
    ancestor_clipping_mask_layer_ = nullptr;
    ancestor_clipping_layer_->SetMaskLayer(nullptr);
    layers_changed = true;
  }

  if (needs_descendant_clip) {
    // We don't need a child containment layer if we're the main frame layout
    // view layer. It's redundant as the frame clip above us will handle this
    // clipping.
    if (!child_containment_layer_ && !is_main_frame_layout_view_layer_) {
      child_containment_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForDescendantClip);
      child_containment_layer_->SetMasksToBounds(true);
      layers_changed = true;
    }
  } else if (HasClippingLayer()) {
    child_containment_layer_->RemoveFromParent();
    child_containment_layer_ = nullptr;
    layers_changed = true;
  }

  return layers_changed;
}

bool CompositedLayerMapping::UpdateChildTransformLayer(
    bool needs_child_transform_layer) {
  bool layers_changed = false;

  if (needs_child_transform_layer) {
    if (!child_transform_layer_) {
      child_transform_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForPerspective);
      child_transform_layer_->SetDrawsContent(false);
      layers_changed = true;
    }
  } else if (child_transform_layer_) {
    child_transform_layer_->RemoveFromParent();
    child_transform_layer_ = nullptr;
    layers_changed = true;
  }

  return layers_changed;
}

bool CompositedLayerMapping::ToggleScrollbarLayerIfNeeded(
    std::unique_ptr<GraphicsLayer>& layer,
    bool needs_layer,
    CompositingReasons reason) {
  if (needs_layer == !!layer)
    return false;
  layer = needs_layer ? CreateGraphicsLayer(reason) : nullptr;

  if (PaintLayerScrollableArea* scrollable_area =
          owning_layer_.GetScrollableArea()) {
    if (ScrollingCoordinator* scrolling_coordinator =
            owning_layer_.GetScrollingCoordinator()) {
      if (reason == CompositingReason::kLayerForHorizontalScrollbar) {
        scrolling_coordinator->ScrollableAreaScrollbarLayerDidChange(
            scrollable_area, kHorizontalScrollbar);
      } else if (reason == CompositingReason::kLayerForVerticalScrollbar) {
        scrolling_coordinator->ScrollableAreaScrollbarLayerDidChange(
            scrollable_area, kVerticalScrollbar);
      }
    }
  }
  return true;
}

bool CompositedLayerMapping::UpdateOverflowControlsLayers(
    bool needs_horizontal_scrollbar_layer,
    bool needs_vertical_scrollbar_layer,
    bool needs_scroll_corner_layer,
    bool needs_ancestor_clip) {
  if (PaintLayerScrollableArea* scrollable_area =
          owning_layer_.GetScrollableArea()) {
    // If the scrollable area is marked as needing a new scrollbar layer,
    // destroy the layer now so that it will be created again below.
    if (layer_for_horizontal_scrollbar_ && needs_horizontal_scrollbar_layer &&
        scrollable_area->ShouldRebuildHorizontalScrollbarLayer()) {
      ToggleScrollbarLayerIfNeeded(
          layer_for_horizontal_scrollbar_, false,
          CompositingReason::kLayerForHorizontalScrollbar);
    }
    if (layer_for_vertical_scrollbar_ && needs_vertical_scrollbar_layer &&
        scrollable_area->ShouldRebuildVerticalScrollbarLayer()) {
      ToggleScrollbarLayerIfNeeded(
          layer_for_vertical_scrollbar_, false,
          CompositingReason::kLayerForVerticalScrollbar);
    }
    scrollable_area->ResetRebuildScrollbarLayerFlags();

    if (scrolling_contents_layer_ &&
        scrollable_area->NeedsShowScrollbarLayers()) {
      scrolling_contents_layer_->CcLayer()->ShowScrollbars();
      scrollable_area->DidShowScrollbarLayers();
    }
  }

  // If the subtree is invisible, we don't actually need scrollbar layers.
  // Only do this check if at least one of the bits is currently true.
  // This is important because this method is called during the destructor
  // of CompositedLayerMapping, which may happen during style recalc,
  // and therefore visible content status may be invalid.
  if (needs_horizontal_scrollbar_layer || needs_vertical_scrollbar_layer ||
      needs_scroll_corner_layer) {
    bool invisible = owning_layer_.SubtreeIsInvisible();
    needs_horizontal_scrollbar_layer &= !invisible;
    needs_vertical_scrollbar_layer &= !invisible;
    needs_scroll_corner_layer &= !invisible;
  }

  bool horizontal_scrollbar_layer_changed = ToggleScrollbarLayerIfNeeded(
      layer_for_horizontal_scrollbar_, needs_horizontal_scrollbar_layer,
      CompositingReason::kLayerForHorizontalScrollbar);
  bool vertical_scrollbar_layer_changed = ToggleScrollbarLayerIfNeeded(
      layer_for_vertical_scrollbar_, needs_vertical_scrollbar_layer,
      CompositingReason::kLayerForVerticalScrollbar);
  bool scroll_corner_layer_changed = ToggleScrollbarLayerIfNeeded(
      layer_for_scroll_corner_, needs_scroll_corner_layer,
      CompositingReason::kLayerForScrollCorner);

  bool needs_overflow_controls_host_layer = needs_horizontal_scrollbar_layer ||
                                            needs_vertical_scrollbar_layer ||
                                            needs_scroll_corner_layer;
  ToggleScrollbarLayerIfNeeded(
      overflow_controls_host_layer_, needs_overflow_controls_host_layer,
      CompositingReason::kLayerForOverflowControlsHost);
  bool needs_overflow_ancestor_clip_layer =
      needs_overflow_controls_host_layer && needs_ancestor_clip;
  ToggleScrollbarLayerIfNeeded(
      overflow_controls_ancestor_clipping_layer_,
      needs_overflow_ancestor_clip_layer,
      CompositingReason::kLayerForOverflowControlsHost);

  return horizontal_scrollbar_layer_changed ||
         vertical_scrollbar_layer_changed || scroll_corner_layer_changed;
}

void CompositedLayerMapping::PositionOverflowControlsLayers() {
  if (GraphicsLayer* layer = LayerForHorizontalScrollbar()) {
    Scrollbar* h_bar = owning_layer_.GetScrollableArea()->HorizontalScrollbar();
    if (h_bar) {
      IntRect frame_rect = h_bar->FrameRect();
      layer->SetPosition(frame_rect.Location());
      layer->SetOffsetFromLayoutObject(ToIntSize(frame_rect.Location()));
      layer->SetSize(frame_rect.Size());
      if (layer->HasContentsLayer())
        layer->SetContentsRect(IntRect(IntPoint(), frame_rect.Size()));
    }
    layer->SetDrawsContent(h_bar && !layer->HasContentsLayer());
  }

  if (GraphicsLayer* layer = LayerForVerticalScrollbar()) {
    Scrollbar* v_bar = owning_layer_.GetScrollableArea()->VerticalScrollbar();
    if (v_bar) {
      IntRect frame_rect = v_bar->FrameRect();
      layer->SetPosition(frame_rect.Location());
      layer->SetOffsetFromLayoutObject(ToIntSize(frame_rect.Location()));
      layer->SetSize(frame_rect.Size());
      if (layer->HasContentsLayer())
        layer->SetContentsRect(IntRect(IntPoint(), frame_rect.Size()));
    }
    layer->SetDrawsContent(v_bar && !layer->HasContentsLayer());
  }

  if (GraphicsLayer* layer = LayerForScrollCorner()) {
    const IntRect& scroll_corner_and_resizer =
        owning_layer_.GetScrollableArea()->ScrollCornerAndResizerRect();
    layer->SetPosition(FloatPoint(scroll_corner_and_resizer.Location()));
    layer->SetOffsetFromLayoutObject(
        ToIntSize(scroll_corner_and_resizer.Location()));
    layer->SetSize(scroll_corner_and_resizer.Size());
    layer->SetDrawsContent(!scroll_corner_and_resizer.IsEmpty());
  }
}

enum ApplyToGraphicsLayersModeFlags {
  kApplyToLayersAffectedByPreserve3D = (1 << 0),
  kApplyToSquashingLayer = (1 << 1),
  kApplyToScrollbarLayers = (1 << 2),
  kApplyToMaskLayers = (1 << 3),
  kApplyToContentLayers = (1 << 4),
  kApplyToChildContainingLayers =
      (1 << 5),  // layers between m_graphicsLayer and children
  kApplyToNonScrollingContentLayers = (1 << 6),
  kApplyToScrollingContentLayers = (1 << 7),
  kApplyToDecorationOutlineLayer = (1 << 8),
  kApplyToAllGraphicsLayers =
      (kApplyToSquashingLayer | kApplyToScrollbarLayers | kApplyToMaskLayers |
       kApplyToLayersAffectedByPreserve3D | kApplyToContentLayers |
       kApplyToScrollingContentLayers | kApplyToDecorationOutlineLayer)
};
typedef unsigned ApplyToGraphicsLayersMode;

// Flags to layers mapping matrix:
//                  bit 0 1 2 3 4 5 6 7 8
// ChildTransform       *         *
// Main                 *       *   *
// Clipping             *         *
// Scrolling            *         *
// ScrollingContents    *       * *   *
// Foreground           *       *     *
// Squashing              *
// Mask                       * *   *
// ChildClippingMask          * *   *
// AncestorClippingMask       * *   *
// HorizontalScrollbar      *
// VerticalScrollbar        *
// ScrollCorner             *
// DecorationOutline                *   *
template <typename Func>
static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping,
                                  const Func& f,
                                  ApplyToGraphicsLayersMode mode) {
  DCHECK(mode);

  if (((mode & kApplyToLayersAffectedByPreserve3D) ||
       (mode & kApplyToChildContainingLayers)) &&
      mapping->ChildTransformLayer())
    f(mapping->ChildTransformLayer());
  if (((mode & kApplyToLayersAffectedByPreserve3D) ||
       (mode & kApplyToContentLayers) ||
       (mode & kApplyToNonScrollingContentLayers)) &&
      mapping->MainGraphicsLayer())
    f(mapping->MainGraphicsLayer());
  if (((mode & kApplyToLayersAffectedByPreserve3D) ||
       (mode & kApplyToChildContainingLayers)) &&
      mapping->ClippingLayer())
    f(mapping->ClippingLayer());
  if (((mode & kApplyToLayersAffectedByPreserve3D) ||
       (mode & kApplyToChildContainingLayers)) &&
      mapping->ScrollingLayer())
    f(mapping->ScrollingLayer());
  if (((mode & kApplyToLayersAffectedByPreserve3D) ||
       (mode & kApplyToContentLayers) ||
       (mode & kApplyToChildContainingLayers) ||
       (mode & kApplyToScrollingContentLayers)) &&
      mapping->ScrollingContentsLayer())
    f(mapping->ScrollingContentsLayer());
  if (((mode & kApplyToLayersAffectedByPreserve3D) ||
       (mode & kApplyToContentLayers) ||
       (mode & kApplyToScrollingContentLayers)) &&
      mapping->ForegroundLayer())
    f(mapping->ForegroundLayer());

  if ((mode & kApplyToSquashingLayer) && mapping->SquashingLayer())
    f(mapping->SquashingLayer());

  if (((mode & kApplyToMaskLayers) || (mode & kApplyToContentLayers) ||
       (mode & kApplyToNonScrollingContentLayers)) &&
      mapping->MaskLayer())
    f(mapping->MaskLayer());
  if (((mode & kApplyToMaskLayers) || (mode & kApplyToContentLayers) ||
       (mode & kApplyToNonScrollingContentLayers)) &&
      mapping->ChildClippingMaskLayer())
    f(mapping->ChildClippingMaskLayer());
  if (((mode & kApplyToMaskLayers) || (mode & kApplyToContentLayers) ||
       (mode & kApplyToNonScrollingContentLayers)) &&
      mapping->AncestorClippingMaskLayer())
    f(mapping->AncestorClippingMaskLayer());

  if ((mode & kApplyToScrollbarLayers) &&
      mapping->LayerForHorizontalScrollbar())
    f(mapping->LayerForHorizontalScrollbar());
  if ((mode & kApplyToScrollbarLayers) && mapping->LayerForVerticalScrollbar())
    f(mapping->LayerForVerticalScrollbar());
  if ((mode & kApplyToScrollbarLayers) && mapping->LayerForScrollCorner())
    f(mapping->LayerForScrollCorner());

  if (((mode & kApplyToDecorationOutlineLayer) ||
       (mode & kApplyToNonScrollingContentLayers)) &&
      mapping->DecorationOutlineLayer())
    f(mapping->DecorationOutlineLayer());
}

struct UpdateRenderingContextFunctor {
  void operator()(GraphicsLayer* layer) const {
    layer->SetRenderingContext(rendering_context);
  }
  int rendering_context;
};

void CompositedLayerMapping::UpdateRenderingContext() {
  // All layers but the squashing layer (which contains 'alien' content) should
  // be included in this rendering context.
  int id = 0;

  // NB, it is illegal at this point to query an ancestor's compositing state.
  // Some compositing reasons depend on the compositing state of ancestors. So
  // if we want a rendering context id for the context root, we cannot ask for
  // the id of its associated cc::Layer now; it may not have one yet. We could
  // do a second pass after doing the compositing updates to get these ids, but
  // this would actually be harmful. We do not want to attach any semantic
  // meaning to the context id other than the fact that they group a number of
  // layers together for the sake of 3d sorting. So instead we will ask the
  // compositor to vend us an arbitrary, but consistent id.
  if (PaintLayer* root = owning_layer_.RenderingContextRoot()) {
    if (Node* node = root->GetLayoutObject().GetNode())
      id = static_cast<int>(PtrHash<Node>::GetHash(node));
  }

  UpdateRenderingContextFunctor functor = {id};
  ApplyToGraphicsLayers<UpdateRenderingContextFunctor>(
      this, functor, kApplyToAllGraphicsLayers);
}

void CompositedLayerMapping::UpdateShouldFlattenTransform() {
  // TODO(trchen): Simplify logic here.
  //
  // The code here is equivalent to applying kApplyToLayersAffectedByPreserve3D
  // layer with the computed ShouldPreserve3D() value, then disable flattening
  // on kApplyToChildContainingLayers layers if the current layer has
  // perspective transform, then again disable flattening on main layer and
  // scrolling layer if we have scrolling layer. See crbug.com/521768.
  //
  // If we toggle flattening back and forth as said above, it will result in
  // unnecessary redrawing because the compositor doesn't have delayed
  // invalidation for this flag. See crbug.com/783614.
  bool is_flat = !owning_layer_.ShouldPreserve3D();

  if (GraphicsLayer* layer = ChildTransformLayer())
    layer->SetShouldFlattenTransform(false);
  if (GraphicsLayer* layer = ScrollingLayer())
    layer->SetShouldFlattenTransform(false);
  graphics_layer_->SetShouldFlattenTransform(is_flat && !HasScrollingLayer());
  if (GraphicsLayer* layer = ClippingLayer())
    layer->SetShouldFlattenTransform(is_flat && !HasChildTransformLayer());
  if (GraphicsLayer* layer = ScrollingContentsLayer())
    layer->SetShouldFlattenTransform(is_flat && !HasChildTransformLayer());
  if (GraphicsLayer* layer = ForegroundLayer())
    layer->SetShouldFlattenTransform(is_flat);
}

struct AnimatingData {
  STACK_ALLOCATED();
  Persistent<Node> owning_node = nullptr;
  Persistent<Element> animating_element = nullptr;
  const ComputedStyle* animating_style = nullptr;
};

// You receive an element id if you have an animation, or you're a scroller (and
// might impl animate).
//
// The element id for the scroll layers is assigned when they're constructed,
// since this is unconditional. However, the element id for the primary layer
// may change according to the rules above so we update those values here.
void CompositedLayerMapping::UpdateElementId() {
  CompositorElementId element_id = CompositorElementIdFromUniqueObjectId(
      owning_layer_.GetLayoutObject().UniqueId(),
      CompositorElementIdNamespace::kPrimary);

  graphics_layer_->SetElementId(element_id);
}

bool CompositedLayerMapping::UpdateForegroundLayer(
    bool needs_foreground_layer) {
  bool layer_changed = false;
  if (needs_foreground_layer) {
    if (!foreground_layer_) {
      foreground_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForForeground);
      foreground_layer_->SetHitTestableWithoutDrawsContent(true);
      layer_changed = true;
    }
  } else if (foreground_layer_) {
    foreground_layer_->RemoveFromParent();
    foreground_layer_ = nullptr;
    layer_changed = true;
  }

  return layer_changed;
}

bool CompositedLayerMapping::UpdateDecorationOutlineLayer(
    bool needs_decoration_outline_layer) {
  bool layer_changed = false;
  if (needs_decoration_outline_layer) {
    if (!decoration_outline_layer_) {
      decoration_outline_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForDecoration);
      decoration_outline_layer_->SetPaintingPhase(
          kGraphicsLayerPaintDecoration);
      layer_changed = true;
    }
  } else if (decoration_outline_layer_) {
    decoration_outline_layer_ = nullptr;
    layer_changed = true;
  }

  return layer_changed;
}

bool CompositedLayerMapping::UpdateMaskLayer(bool needs_mask_layer) {
  bool layer_changed = false;
  if (needs_mask_layer) {
    if (!mask_layer_) {
      mask_layer_ = CreateGraphicsLayer(CompositingReason::kLayerForMask);
      mask_layer_->SetPaintingPhase(kGraphicsLayerPaintMask);
      layer_changed = true;
    }
  } else if (mask_layer_) {
    mask_layer_ = nullptr;
    layer_changed = true;
  }

  return layer_changed;
}

bool CompositedLayerMapping::UpdateChildClippingMaskLayer(
    bool needs_child_clipping_mask_layer) {
  if (needs_child_clipping_mask_layer && !child_clipping_mask_layer_) {
    child_clipping_mask_layer_ =
        CreateGraphicsLayer(CompositingReason::kLayerForClippingMask);
    child_clipping_mask_layer_->SetPaintingPhase(
        kGraphicsLayerPaintChildClippingMask);
    return true;
  }
  if (!needs_child_clipping_mask_layer && child_clipping_mask_layer_) {
    child_clipping_mask_layer_ = nullptr;
    return true;
  }
  return false;
}

bool CompositedLayerMapping::UpdateScrollingLayers(
    bool needs_scrolling_layers) {
  ScrollingCoordinator* scrolling_coordinator =
      owning_layer_.GetScrollingCoordinator();

  auto* scrollable_area = owning_layer_.GetScrollableArea();
  if (scrollable_area)
    scrollable_area->SetUsesCompositedScrolling(needs_scrolling_layers);

  bool layer_changed = false;
  if (needs_scrolling_layers) {
    if (scrolling_layer_) {
      if (scrolling_coordinator) {
        scrolling_coordinator->UpdateUserInputScrollable(
            owning_layer_.GetScrollableArea());
      }
    } else {
      // Outer layer which corresponds with the scroll view.
      scrolling_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForScrollingContainer);
      scrolling_layer_->SetDrawsContent(false);
      scrolling_layer_->SetMasksToBounds(true);

      // Inner layer which renders the content that scrolls.
      scrolling_contents_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForScrollingContents);
      scrolling_contents_layer_->SetHitTestableWithoutDrawsContent(true);

      auto element_id = scrollable_area->GetCompositorElementId();
      scrolling_contents_layer_->SetElementId(element_id);

      scrolling_layer_->AddChild(scrolling_contents_layer_.get());

      layer_changed = true;
      if (scrolling_coordinator && scrollable_area) {
        scrolling_coordinator->ScrollableAreaScrollLayerDidChange(
            scrollable_area);
        const auto& object = GetLayoutObject();
        if (object.IsLayoutView())
          ToLayoutView(object).GetFrameView()->ScrollableAreasDidChange();
      }
    }
  } else if (scrolling_layer_) {
    scrolling_layer_ = nullptr;
    scrolling_contents_layer_ = nullptr;
    layer_changed = true;
    if (scrolling_coordinator && scrollable_area) {
      scrolling_coordinator->ScrollableAreaScrollLayerDidChange(
          scrollable_area);
      const auto& object = GetLayoutObject();
      if (object.IsLayoutView())
        ToLayoutView(object).GetFrameView()->ScrollableAreasDidChange();
    }
  }

  return layer_changed;
}

static void UpdateScrollParentForGraphicsLayer(
    GraphicsLayer* layer,
    GraphicsLayer* topmost_layer,
    const PaintLayer* scroll_parent,
    ScrollingCoordinator* scrolling_coordinator) {
  if (!layer)
    return;

  // Only the topmost layer has a scroll parent. All other layers have a null
  // scroll parent.
  if (layer != topmost_layer)
    scroll_parent = nullptr;

  scrolling_coordinator->UpdateScrollParentForGraphicsLayer(layer,
                                                            scroll_parent);
}

void CompositedLayerMapping::UpdateScrollParent(
    const PaintLayer* scroll_parent) {
  if (ScrollingCoordinator* scrolling_coordinator =
          owning_layer_.GetScrollingCoordinator()) {
    GraphicsLayer* topmost_layer = ChildForSuperlayers();
    UpdateScrollParentForGraphicsLayer(squashing_containment_layer_.get(),
                                       topmost_layer, scroll_parent,
                                       scrolling_coordinator);
    UpdateScrollParentForGraphicsLayer(ancestor_clipping_layer_.get(),
                                       topmost_layer, scroll_parent,
                                       scrolling_coordinator);
    UpdateScrollParentForGraphicsLayer(graphics_layer_.get(), topmost_layer,
                                       scroll_parent, scrolling_coordinator);
  }
}

static void UpdateClipParentForGraphicsLayer(
    GraphicsLayer* layer,
    GraphicsLayer* topmost_layer,
    const PaintLayer* clip_parent,
    ScrollingCoordinator* scrolling_coordinator) {
  if (!layer)
    return;

  // Only the topmost layer has a scroll parent. All other layers have a null
  // scroll parent.
  if (layer != topmost_layer)
    clip_parent = nullptr;

  scrolling_coordinator->UpdateClipParentForGraphicsLayer(layer, clip_parent);
}

void CompositedLayerMapping::UpdateClipParent(const PaintLayer* scroll_parent) {
  const PaintLayer* clip_parent = CompositedClipParent();

  if (ScrollingCoordinator* scrolling_coordinator =
          owning_layer_.GetScrollingCoordinator()) {
    GraphicsLayer* topmost_layer = ChildForSuperlayers();
    UpdateClipParentForGraphicsLayer(squashing_containment_layer_.get(),
                                     topmost_layer, clip_parent,
                                     scrolling_coordinator);
    UpdateClipParentForGraphicsLayer(ancestor_clipping_layer_.get(),
                                     topmost_layer, clip_parent,
                                     scrolling_coordinator);
    UpdateClipParentForGraphicsLayer(graphics_layer_.get(), topmost_layer,
                                     clip_parent, scrolling_coordinator);
  }
}

void CompositedLayerMapping::RegisterScrollingLayers() {
  // Register fixed position layers and their containers with the scrolling
  // coordinator.
  ScrollingCoordinator* scrolling_coordinator =
      owning_layer_.GetScrollingCoordinator();
  if (!scrolling_coordinator)
    return;

  scrolling_coordinator->UpdateLayerPositionConstraint(&owning_layer_);

  // In non-RLS mode, the fixed container will actually be the special viewport
  // scrolling layers, higher up in the hierarchy, above the LayoutView "root
  // layer". So avoid marking the LayoutView's layer a container in that case.
  // The layout viewport scrolling layer will be correctly marked as such by
  // PaintLayerCompositor.
  bool is_container =
      owning_layer_.GetLayoutObject().CanContainFixedPositionObjects() &&
      (!owning_layer_.IsRootLayer() ||
       RuntimeEnabledFeatures::RootLayerScrollingEnabled());
  bool resized_by_url_bar =
      owning_layer_.GetLayoutObject().IsLayoutView() &&
      owning_layer_.Compositor()->IsRootScrollerAncestor();
  graphics_layer_->SetIsContainerForFixedPositionLayers(is_container);
  graphics_layer_->SetIsResizedByBrowserControls(resized_by_url_bar);
  // Fixed-pos descendants inherits the space that has all CSS property applied,
  // including perspective, overflow scroll/clip. Thus we also mark every layers
  // below the main graphics layer so transforms implemented by them don't get
  // skipped.
  ApplyToGraphicsLayers(
      this,
      [is_container, resized_by_url_bar](GraphicsLayer* layer) {
        layer->SetIsContainerForFixedPositionLayers(is_container);
        layer->SetIsResizedByBrowserControls(resized_by_url_bar);
        if (resized_by_url_bar)
          layer->SetMasksToBounds(false);
      },
      kApplyToChildContainingLayers);
}

bool CompositedLayerMapping::UpdateSquashingLayers(
    bool needs_squashing_layers) {
  bool layers_changed = false;

  if (needs_squashing_layers) {
    if (!squashing_layer_) {
      squashing_layer_ =
          CreateGraphicsLayer(CompositingReason::kLayerForSquashingContents);
      squashing_layer_->SetDrawsContent(true);
      layers_changed = true;
    }

    if (ancestor_clipping_layer_) {
      if (squashing_containment_layer_) {
        squashing_containment_layer_->RemoveFromParent();
        squashing_containment_layer_ = nullptr;
        layers_changed = true;
      }
    } else {
      if (!squashing_containment_layer_) {
        squashing_containment_layer_ =
            CreateGraphicsLayer(CompositingReason::kLayerForSquashingContainer);
        squashing_containment_layer_->SetShouldFlattenTransform(false);
        layers_changed = true;
      }
    }

    DCHECK((ancestor_clipping_layer_ && !squashing_containment_layer_) ||
           (!ancestor_clipping_layer_ && squashing_containment_layer_));
    DCHECK(squashing_layer_);
  } else {
    if (squashing_layer_) {
      squashing_layer_->RemoveFromParent();
      squashing_layer_ = nullptr;
      layers_changed = true;
    }
    if (squashing_containment_layer_) {
      squashing_containment_layer_->RemoveFromParent();
      squashing_containment_layer_ = nullptr;
      layers_changed = true;
    }
    DCHECK(!squashing_layer_);
    DCHECK(!squashing_containment_layer_);
  }

  return layers_changed;
}

GraphicsLayerPaintingPhase
CompositedLayerMapping::PaintingPhaseForPrimaryLayer() const {
  unsigned phase = kGraphicsLayerPaintBackground;
  if (!foreground_layer_)
    phase |= kGraphicsLayerPaintForeground;
  if (!mask_layer_)
    phase |= kGraphicsLayerPaintMask;
  if (!decoration_outline_layer_)
    phase |= kGraphicsLayerPaintDecoration;

  if (scrolling_contents_layer_) {
    phase &= ~kGraphicsLayerPaintForeground;
    phase |= kGraphicsLayerPaintCompositedScroll;
  }

  return static_cast<GraphicsLayerPaintingPhase>(phase);
}

float CompositedLayerMapping::CompositingOpacity(
    float layout_object_opacity) const {
  float final_opacity = layout_object_opacity;

  for (PaintLayer* curr = owning_layer_.Parent(); curr; curr = curr->Parent()) {
    // We only care about parents that are stacking contexts.
    // Recall that opacity creates stacking context.
    if (!curr->StackingNode()->IsStackingContext())
      continue;

    // If we found a composited layer, regardless of whether it actually
    // paints into it, we want to compute opacity relative to it. So we can
    // break here.
    //
    // FIXME: with grouped backings, a composited descendant will have to
    // continue past the grouped (squashed) layers that its parents may
    // contribute to. This whole confusion can be avoided by specifying
    // explicitly the composited ancestor where we would stop accumulating
    // opacity.
    if (curr->GetCompositingState() == kPaintsIntoOwnBacking)
      break;

    final_opacity *= curr->GetLayoutObject().Opacity();
  }

  return final_opacity;
}

Color CompositedLayerMapping::LayoutObjectBackgroundColor() const {
  const auto& object = GetLayoutObject();
  auto background_color = object.ResolveColor(GetCSSPropertyBackgroundColor());
  if (object.IsLayoutView() && object.GetDocument().IsInMainFrame()) {
    return ToLayoutView(object).GetFrameView()->BaseBackgroundColor().Blend(
        background_color);
  }
  return background_color;
}

void CompositedLayerMapping::UpdateBackgroundColor() {
  auto color = LayoutObjectBackgroundColor();
  graphics_layer_->SetBackgroundColor(color);
  if (scrolling_contents_layer_)
    scrolling_contents_layer_->SetBackgroundColor(color);
}

bool CompositedLayerMapping::PaintsChildren() const {
  if (owning_layer_.HasVisibleContent() &&
      owning_layer_.HasNonEmptyChildLayoutObjects())
    return true;

  if (HasVisibleNonCompositingDescendant(&owning_layer_))
    return true;

  return false;
}

static bool IsCompositedPlugin(LayoutObject& layout_object) {
  return layout_object.IsEmbeddedObject() &&
         ToLayoutEmbeddedObject(layout_object).RequiresAcceleratedCompositing();
}

bool CompositedLayerMapping::HasVisibleNonCompositingDescendant(
    PaintLayer* parent) {
  if (!parent->HasVisibleDescendant())
    return false;

  // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
  parent->StackingNode()->UpdateLayerListsIfNeeded();

#if DCHECK_IS_ON()
  LayerListMutationDetector mutation_checker(parent->StackingNode());
#endif

  PaintLayerStackingNodeIterator normal_flow_iterator(*parent->StackingNode(),
                                                      kAllChildren);
  while (PaintLayerStackingNode* cur_node = normal_flow_iterator.Next()) {
    PaintLayer* cur_layer = cur_node->Layer();
    if (cur_layer->HasCompositedLayerMapping())
      continue;
    if (cur_layer->HasVisibleContent() ||
        HasVisibleNonCompositingDescendant(cur_layer))
      return true;
  }

  return false;
}

bool CompositedLayerMapping::ContainsPaintedContent() const {
  if (GetLayoutObject().IsImage() && IsDirectlyCompositedImage())
    return false;

  LayoutObject& layout_object = GetLayoutObject();
  // FIXME: we could optimize cases where the image, video or canvas is known to
  // fill the border box entirely, and set background color on the layer in that
  // case, instead of allocating backing store and painting.
  if (layout_object.IsVideo() &&
      ToLayoutVideo(layout_object).ShouldDisplayVideo())
    return owning_layer_.HasBoxDecorationsOrBackground();

  if (layout_object.GetNode() && layout_object.GetNode()->IsDocumentNode()) {
    if (owning_layer_.NeedsCompositedScrolling())
      return background_paints_onto_graphics_layer_;

    // Look to see if the root object has a non-simple background
    LayoutObject* root_object =
        layout_object.GetDocument().documentElement()
            ? layout_object.GetDocument().documentElement()->GetLayoutObject()
            : nullptr;
    // Reject anything that has a border, a border-radius or outline,
    // or is not a simple background (no background, or solid color).
    if (root_object &&
        HasBoxDecorationsOrBackgroundImage(root_object->StyleRef()))
      return true;

    // Now look at the body's layoutObject.
    HTMLElement* body = layout_object.GetDocument().body();
    LayoutObject* body_object =
        IsHTMLBodyElement(body) ? body->GetLayoutObject() : nullptr;
    if (body_object &&
        HasBoxDecorationsOrBackgroundImage(body_object->StyleRef()))
      return true;
  }

  if (owning_layer_.HasVisibleBoxDecorations())
    return true;

  if (layout_object.HasMask())  // masks require special treatment
    return true;

  if (layout_object.IsAtomicInlineLevel() && !IsCompositedPlugin(layout_object))
    return true;

  if (layout_object.IsLayoutMultiColumnSet())
    return true;

  // FIXME: it's O(n^2). A better solution is needed.
  return PaintsChildren();
}

// An image can be directly composited if it's the sole content of the layer,
// and has no box decorations or clipping that require painting. Direct
// compositing saves a backing store.
bool CompositedLayerMapping::IsDirectlyCompositedImage() const {
  DCHECK(GetLayoutObject().IsImage());
  LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());

  if (owning_layer_.HasBoxDecorationsOrBackground() ||
      image_layout_object.HasClip() || image_layout_object.HasClipPath() ||
      image_layout_object.HasObjectFit())
    return false;

  if (ImageResourceContent* cached_image = image_layout_object.CachedImage()) {
    if (!cached_image->HasImage())
      return false;

    Image* image = cached_image->GetImage();
    if (!image->IsBitmapImage())
      return false;

    return true;
  }

  return false;
}

void CompositedLayerMapping::ContentChanged(ContentChangeType change_type) {
  if ((change_type == kImageChanged) && GetLayoutObject().IsImage() &&
      IsDirectlyCompositedImage()) {
    UpdateImageContents();
    return;
  }

  if (change_type == kCanvasChanged &&
      IsTextureLayerCanvas(GetLayoutObject())) {
    graphics_layer_->SetContentsNeedsDisplay();
    return;
  }
}

void CompositedLayerMapping::UpdateImageContents() {
  DCHECK(GetLayoutObject().IsImage());
  LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject());

  ImageResourceContent* cached_image = image_layout_object.CachedImage();
  if (!cached_image)
    return;

  Image* image = cached_image->GetImage();
  if (!image)
    return;

  Node* node = image_layout_object.GetNode();
  Image::ImageDecodingMode decode_mode =
      IsHTMLImageElement(node)
          ? ToHTMLImageElement(node)->GetDecodingModeForPainting(
                image->paint_image_id())
          : Image::kUnspecifiedDecode;

  // This is a no-op if the layer doesn't have an inner layer for the image.
  graphics_layer_->SetContentsToImage(
      image, decode_mode,
      LayoutObject::ShouldRespectImageOrientation(&image_layout_object));

  graphics_layer_->SetFilterQuality(
      GetLayoutObject().Style()->ImageRendering() == EImageRendering::kPixelated
          ? kNone_SkFilterQuality
          : kLow_SkFilterQuality);

  // Prevent double-drawing: https://bugs.webkit.org/show_bug.cgi?id=58632
  UpdateDrawsContent();

  // Image animation is "lazy", in that it automatically stops unless someone is
  // drawing the image. So we have to kick the animation each time; this has the
  // downside that the image will keep animating, even if its layer is not
  // visible.
  image->StartAnimation();
}

FloatPoint3D CompositedLayerMapping::ComputeTransformOrigin(
    const IntRect& border_box) const {
  const ComputedStyle& style = GetLayoutObject().StyleRef();

  FloatPoint3D origin;
  origin.SetX(
      FloatValueForLength(style.TransformOriginX(), border_box.Width()));
  origin.SetY(
      FloatValueForLength(style.TransformOriginY(), border_box.Height()));
  origin.SetZ(style.TransformOriginZ());

  return origin;
}

// Return the offset from the top-left of this compositing layer at which the
// LayoutObject's contents are painted.
LayoutSize CompositedLayerMapping::ContentOffsetInCompositingLayer() const {
  DCHECK(!content_offset_in_compositing_layer_dirty_);
  return content_offset_in_compositing_layer_;
}

LayoutRect CompositedLayerMapping::ContentsBox() const {
  LayoutRect contents_box = LayoutRect(ContentsRect(GetLayoutObject()));
  contents_box.Move(ContentOffsetInCompositingLayer());
  return contents_box;
}

bool CompositedLayerMapping::NeedsToReparentOverflowControls() const {
  return owning_layer_.GetScrollableArea() &&
         owning_layer_.GetScrollableArea()->HasOverlayScrollbars() &&
         owning_layer_.GetScrollableArea()->TopmostScrollChild();
}

GraphicsLayer* CompositedLayerMapping::DetachLayerForOverflowControls() {
  GraphicsLayer* host = overflow_controls_ancestor_clipping_layer_.get();
  if (!host)
    host = overflow_controls_host_layer_.get();
  host->RemoveFromParent();
  return host;
}

GraphicsLayer* CompositedLayerMapping::ParentForSublayers() const {
  if (scrolling_contents_layer_)
    return scrolling_contents_layer_.get();

  if (child_containment_layer_)
    return child_containment_layer_.get();

  if (child_transform_layer_)
    return child_transform_layer_.get();

  return graphics_layer_.get();
}

void CompositedLayerMapping::SetSublayers(
    const GraphicsLayerVector& sublayers) {
  GraphicsLayer* overflow_controls_container =
      overflow_controls_ancestor_clipping_layer_
          ? overflow_controls_ancestor_clipping_layer_.get()
          : overflow_controls_host_layer_.get();
  GraphicsLayer* parent = ParentForSublayers();
  bool needs_overflow_controls_reattached =
      overflow_controls_container &&
      overflow_controls_container->Parent() == parent;

  parent->SetChildren(sublayers);

  // If we have scrollbars, but are not using composited scrolling, then
  // parentForSublayers may return m_graphicsLayer.  In that case, the above
  // call to setChildren has clobbered the overflow controls host layer, so we
  // need to reattach it.
  if (needs_overflow_controls_reattached)
    parent->AddChild(overflow_controls_container);
}

GraphicsLayer* CompositedLayerMapping::ChildForSuperlayers() const {
  if (squashing_containment_layer_)
    return squashing_containment_layer_.get();

  if (ancestor_clipping_layer_)
    return ancestor_clipping_layer_.get();

  return graphics_layer_.get();
}

void CompositedLayerMapping::SetBlendMode(BlendMode blend_mode) {
  if (ancestor_clipping_layer_) {
    ancestor_clipping_layer_->SetBlendMode(blend_mode);
    graphics_layer_->SetBlendMode(BlendMode::kNormal);
  } else {
    graphics_layer_->SetBlendMode(blend_mode);
  }
}

GraphicsLayerUpdater::UpdateType CompositedLayerMapping::UpdateTypeForChildren(
    GraphicsLayerUpdater::UpdateType update_type) const {
  if (pending_update_scope_ >= kGraphicsLayerUpdateSubtree)
    return GraphicsLayerUpdater::kForceUpdate;
  return update_type;
}

struct SetContentsNeedsDisplayFunctor {
  void operator()(GraphicsLayer* layer) const {
    if (layer->DrawsContent())
      layer->SetNeedsDisplay();
  }
};

void CompositedLayerMapping::SetSquashingContentsNeedDisplay() {
  ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(),
                        kApplyToSquashingLayer);
}

void CompositedLayerMapping::SetContentsNeedDisplay() {
  // FIXME: need to split out paint invalidations for the background.
  ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(),
                        kApplyToContentLayers);
}

struct SetContentsNeedsDisplayInRectFunctor {
  void operator()(GraphicsLayer* layer) const {
    if (layer->DrawsContent()) {
      IntRect layer_dirty_rect = r;
      layer_dirty_rect.Move(-layer->OffsetFromLayoutObject());
      layer->SetNeedsDisplayInRect(layer_dirty_rect, invalidation_reason,
                                   client);
    }
  }

  IntRect r;
  PaintInvalidationReason invalidation_reason;
  const DisplayItemClient& client;
};

void CompositedLayerMapping::SetContentsNeedDisplayInRect(
    const LayoutRect& r,
    PaintInvalidationReason invalidation_reason,
    const DisplayItemClient& client) {
  DCHECK(!owning_layer_.GetLayoutObject().UsesCompositedScrolling());
  // TODO(wangxianzhu): Enable the following assert after paint invalidation for
  // spv2 is ready.
  // DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());

  SetContentsNeedsDisplayInRectFunctor functor = {
      EnclosingIntRect(LayoutRect(
          r.Location() + owning_layer_.SubpixelAccumulation(), r.Size())),
      invalidation_reason, client};
  ApplyToGraphicsLayers(this, functor, kApplyToContentLayers);
}

void CompositedLayerMapping::SetNonScrollingContentsNeedDisplayInRect(
    const LayoutRect& r,
    PaintInvalidationReason invalidation_reason,
    const DisplayItemClient& client) {
  DCHECK(owning_layer_.GetLayoutObject().UsesCompositedScrolling());
  // TODO(wangxianzhu): Enable the following assert after paint invalidation for
  // spv2 is ready.
  // DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());

  SetContentsNeedsDisplayInRectFunctor functor = {
      EnclosingIntRect(LayoutRect(
          r.Location() + owning_layer_.SubpixelAccumulation(), r.Size())),
      invalidation_reason, client};
  ApplyToGraphicsLayers(this, functor, kApplyToNonScrollingContentLayers);
}

void CompositedLayerMapping::SetScrollingContentsNeedDisplayInRect(
    const LayoutRect& r,
    PaintInvalidationReason invalidation_reason,
    const DisplayItemClient& client) {
  DCHECK(owning_layer_.GetLayoutObject().UsesCompositedScrolling());
  // TODO(wangxianzhu): Enable the following assert after paint invalidation for
  // spv2 is ready.
  // DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());

  SetContentsNeedsDisplayInRectFunctor functor = {
      EnclosingIntRect(LayoutRect(
          r.Location() + owning_layer_.SubpixelAccumulation(), r.Size())),
      invalidation_reason, client};
  ApplyToGraphicsLayers(this, functor, kApplyToScrollingContentLayers);
}

void CompositedLayerMapping::SetNeedsCheckRasterInvalidation() {
  ApplyToGraphicsLayers(this,
                        [](GraphicsLayer* graphics_layer) {
                          if (graphics_layer->DrawsContent())
                            graphics_layer->SetNeedsCheckRasterInvalidation();
                        },
                        kApplyToAllGraphicsLayers);
}

const GraphicsLayerPaintInfo* CompositedLayerMapping::ContainingSquashedLayer(
    const LayoutObject* layout_object,
    const Vector<GraphicsLayerPaintInfo>& layers,
    unsigned max_squashed_layer_index) {
  if (!layout_object)
    return nullptr;
  for (size_t i = 0; i < layers.size() && i < max_squashed_layer_index; ++i) {
    if (layout_object->IsDescendantOf(
            &layers[i].paint_layer->GetLayoutObject()))
      return &layers[i];
  }
  return nullptr;
}

const GraphicsLayerPaintInfo* CompositedLayerMapping::ContainingSquashedLayer(
    const LayoutObject* layout_object,
    unsigned max_squashed_layer_index) {
  return CompositedLayerMapping::ContainingSquashedLayer(
      layout_object, squashed_layers_, max_squashed_layer_index);
}

void CompositedLayerMapping::LocalClipRectForSquashedLayer(
    const PaintLayer& reference_layer,
    const Vector<GraphicsLayerPaintInfo>& layers,
    GraphicsLayerPaintInfo& paint_info) {
  const LayoutObject* clipping_container =
      paint_info.paint_layer->ClippingContainer();
  if (clipping_container == reference_layer.ClippingContainer()) {
    paint_info.local_clip_rect_for_squashed_layer =
        ClipRect(LayoutRect(LayoutRect::InfiniteIntRect()));
    paint_info.offset_from_clip_rect_root = LayoutPoint();
    paint_info.local_clip_rect_root = paint_info.paint_layer;
    return;
  }

  DCHECK(clipping_container);

  const GraphicsLayerPaintInfo* ancestor_paint_info =
      ContainingSquashedLayer(clipping_container, layers, layers.size());
  // Must be there, otherwise
  // CompositingLayerAssigner::canSquashIntoCurrentSquashingOwner would have
  // disallowed squashing.
  DCHECK(ancestor_paint_info);

  // FIXME: this is a potential performance issue. We should consider caching
  // these clip rects or otherwise optimizing.
  ClipRectsContext clip_rects_context(ancestor_paint_info->paint_layer,
                                      kUncachedClipRects);
  ClipRect parent_clip_rect;
  paint_info.paint_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
      .CalculateBackgroundClipRect(clip_rects_context, parent_clip_rect);

  // Convert from ancestor to local coordinates.
  IntSize ancestor_to_local_offset =
      paint_info.offset_from_layout_object -
      ancestor_paint_info->offset_from_layout_object;
  parent_clip_rect.Move(ancestor_to_local_offset);
  paint_info.local_clip_rect_for_squashed_layer = parent_clip_rect;
  paint_info.offset_from_clip_rect_root = LayoutPoint(
      ancestor_to_local_offset.Width(), ancestor_to_local_offset.Height());
  paint_info.local_clip_rect_root = ancestor_paint_info->paint_layer;
}

void CompositedLayerMapping::DoPaintTask(
    const GraphicsLayerPaintInfo& paint_info,
    const GraphicsLayer& graphics_layer,
    const PaintLayerFlags& paint_layer_flags,
    GraphicsContext& context,
    const IntRect& clip /* In the coords of rootLayer */) const {
  FontCachePurgePreventer font_cache_purge_preventer;

  IntSize offset = paint_info.offset_from_layout_object;
  AffineTransform translation;
  translation.Translate(-offset.Width(), -offset.Height());
  TransformRecorder transform_recorder(context, graphics_layer, translation);

  // The dirtyRect is in the coords of the painting root.
  IntRect dirty_rect(clip);
  dirty_rect.Move(offset);

  if (paint_layer_flags & (kPaintLayerPaintingOverflowContents |
                           kPaintLayerPaintingAncestorClippingMaskPhase)) {
    dirty_rect.Move(
        RoundedIntSize(paint_info.paint_layer->SubpixelAccumulation()));
  } else {
    LayoutRect bounds = paint_info.composited_bounds;
    bounds.Move(paint_info.paint_layer->SubpixelAccumulation());
    dirty_rect.Intersect(PixelSnappedIntRect(bounds));
  }

#if DCHECK_IS_ON()
  if (!GetLayoutObject().View()->GetFrame() ||
      !GetLayoutObject().View()->GetFrame()->ShouldThrottleRendering())
    paint_info.paint_layer->GetLayoutObject().AssertSubtreeIsLaidOut();
#endif

  float device_scale_factor = blink::DeviceScaleFactorDeprecated(
      paint_info.paint_layer->GetLayoutObject().GetFrame());
  context.SetDeviceScaleFactor(device_scale_factor);

  Settings* settings = GetLayoutObject().GetFrame()->GetSettings();
  HighContrastSettings high_contrast_settings;
  high_contrast_settings.mode = settings->GetHighContrastMode();
  high_contrast_settings.grayscale = settings->GetHighContrastGrayscale();
  high_contrast_settings.contrast = settings->GetHighContrastContrast();
  high_contrast_settings.image_policy = settings->GetHighContrastImagePolicy();
  context.SetHighContrast(high_contrast_settings);

  if (paint_info.paint_layer->GetCompositingState() !=
      kPaintsIntoGroupedBacking) {
    // FIXME: GraphicsLayers need a way to split for multicol.
    PaintLayerPaintingInfo painting_info(
        paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase,
        paint_info.paint_layer->SubpixelAccumulation());
    PaintLayerPainter(*paint_info.paint_layer)
        .PaintLayerContents(context, painting_info, paint_layer_flags);

    if (paint_info.paint_layer->ContainsDirtyOverlayScrollbars()) {
      PaintLayerPainter(*paint_info.paint_layer)
          .PaintLayerContents(
              context, painting_info,
              paint_layer_flags | kPaintLayerPaintingOverlayScrollbars);
    }
  } else {
    PaintLayerPaintingInfo painting_info(
        paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase,
        paint_info.paint_layer->SubpixelAccumulation());

    // PaintLayer::paintLayer assumes that the caller clips to the passed rect.
    // Squashed layers need to do this clipping in software, since there is no
    // graphics layer to clip them precisely. Furthermore, in some cases we
    // squash layers that need clipping in software from clipping ancestors (see
    // CompositedLayerMapping::localClipRectForSquashedLayer()).
    // FIXME: Is it correct to clip to dirtyRect in slimming paint mode?
    ClipRect clip_rect = paint_info.local_clip_rect_for_squashed_layer;
    clip_rect.Intersect(LayoutRect(dirty_rect));

    LayerClipRecorder layer_clip_recorder(
        context, *paint_info.paint_layer,
        DisplayItem::kClipLayerOverflowControls, clip_rect,
        paint_info.local_clip_rect_root, paint_info.offset_from_clip_rect_root,
        paint_layer_flags, graphics_layer,
        LayerClipRecorder::kDoNotIncludeSelfForBorderRadius);
    PaintLayerPainter(*paint_info.paint_layer)
        .Paint(context, painting_info, paint_layer_flags);
  }
}

// TODO(eseckler): Make recording distance configurable, e.g. for use in
// headless, where we would like to record an exact area.
// Note however that the minimum value for this constant is the size of a
// raster tile. This is because the raster system is not able to raster a
// tile that is not completely covered by a display list. If the constant
// were less than the size of a tile, then a tile which partially overlaps
// the screen may not be rastered.
static const int kPixelDistanceToRecord = 4000;

IntRect CompositedLayerMapping::RecomputeInterestRect(
    const GraphicsLayer* graphics_layer) const {
  IntRect graphics_layer_bounds(IntPoint(), graphics_layer->Size());

  FloatSize offset_from_anchor_layout_object;
  const LayoutBoxModelObject* anchor_layout_object;
  bool should_apply_anchor_overflow_clip = false;
  if (graphics_layer == squashing_layer_.get()) {
    // All squashed layers have the same clip and transform space, so we can use
    // the first squashed layer's layoutObject to map the squashing layer's
    // bounds into viewport space, with offsetFromAnchorLayoutObject to
    // translate squashing layer's bounds into the first squashed layer's space.
    anchor_layout_object =
        &owning_layer_.TransformAncestorOrRoot().GetLayoutObject();
    offset_from_anchor_layout_object =
        ToFloatSize(FloatPoint(SquashingOffsetFromTransformedAncestor()));

    // SquashingOffsetFromTransformedAncestor does not include scroll
    // offset.
    if (anchor_layout_object->UsesCompositedScrolling()) {
      offset_from_anchor_layout_object -=
          FloatSize(ToLayoutBox(anchor_layout_object)->ScrolledContentOffset());
    }
  } else {
    DCHECK(graphics_layer == graphics_layer_.get() ||
           graphics_layer == scrolling_contents_layer_.get());
    anchor_layout_object = &owning_layer_.GetLayoutObject();
    IntSize offset = graphics_layer->OffsetFromLayoutObject();
    should_apply_anchor_overflow_clip =
        AdjustForCompositedScrolling(graphics_layer, offset) &&
        (RuntimeEnabledFeatures::RootLayerScrollingEnabled() ||
         !owning_layer_.IsRootLayer());
    offset_from_anchor_layout_object = FloatSize(offset);
  }

  LayoutView* root_view = anchor_layout_object->View();
  while (root_view->GetFrame()->OwnerLayoutObject())
    root_view = root_view->GetFrame()->OwnerLayoutObject()->View();

  // Start with the bounds of the graphics layer in the space of the anchor
  // LayoutObject.
  FloatRect graphics_layer_bounds_in_object_space(graphics_layer_bounds);
  graphics_layer_bounds_in_object_space.Move(offset_from_anchor_layout_object);
  if (should_apply_anchor_overflow_clip && anchor_layout_object != root_view) {
    FloatRect clip_rect(
        ToLayoutBox(anchor_layout_object)->OverflowClipRect(LayoutPoint()));
    graphics_layer_bounds_in_object_space.Intersect(clip_rect);
  }

  // Now map the bounds to its visible content rect in root view space,
  // including applying clips along the way.
  LayoutRect graphics_layer_bounds_in_root_view_space(
      graphics_layer_bounds_in_object_space);

  anchor_layout_object->MapToVisualRectInAncestorSpace(
      root_view, graphics_layer_bounds_in_root_view_space, kUseGeometryMapper);

  // In RLS, the root_view is scrolled. However, MapToVisualRectInAncestorSpace
  // doesn't account for this scroll, since it earlies out as soon as we reach
  // this ancestor. That is, it only maps to the space of the root_view, not
  // accounting for the fact that the root_view itself can be scrolled. If the
  // root_view is our anchor_layout_object, then this extra offset is counted in
  // offset_from_anchor_layout_object. In other cases, we need to account for it
  // here. Otherwise, the paint clip below might clip the whole (visible) rect
  // out.
  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
      root_view != anchor_layout_object) {
    if (auto* scrollable_area = root_view->GetScrollableArea()) {
      graphics_layer_bounds_in_root_view_space.MoveBy(
          -scrollable_area->VisibleContentRect().Location());
    }
  }

  FloatRect visible_content_rect(graphics_layer_bounds_in_root_view_space);
  root_view->GetFrameView()->ClipPaintRect(&visible_content_rect);

  // Map the visible content rect from root view space to local graphics layer
  // space.
  FloatRect local_interest_rect;
  // If the visible content rect is empty, then it makes no sense to map it back
  // since there is nothing to map.
  if (!visible_content_rect.IsEmpty()) {
    local_interest_rect =
        anchor_layout_object
            ->AbsoluteToLocalQuad(visible_content_rect,
                                  kUseTransforms | kTraverseDocumentBoundaries)
            .EnclosingBoundingBox();
    local_interest_rect.Move(-offset_from_anchor_layout_object);
    // TODO(chrishtr): the code below is a heuristic, instead we should detect
    // and return whether the mapping failed.  In some cases,
    // absoluteToLocalQuad can fail to map back to the local space, due to
    // passing through non-invertible transforms or floating-point accuracy
    // issues. Examples include rotation near 90 degrees or perspective. In such
    // cases, fall back to painting the first kPixelDistanceToRecord pixels in
    // each direction.

    // Expand by interest rect padding amount, scaled by the approximate scale
    // of the GraphicsLayer relative to screen pixels. If width or height
    // are zero or nearly zero, fall back to kPixelDistanceToRecord.
    // This is the same as the else clause below.
    float x_scale =
        visible_content_rect.Width() > std::numeric_limits<float>::epsilon()
            ? local_interest_rect.Width() / visible_content_rect.Width()
            : 1.0f;
    float y_scale =
        visible_content_rect.Height() > std::numeric_limits<float>::epsilon()
            ? local_interest_rect.Height() / visible_content_rect.Height()
            : 1.0f;
    local_interest_rect.InflateX(kPixelDistanceToRecord * x_scale);
    local_interest_rect.InflateY(kPixelDistanceToRecord * y_scale);
  } else {
    // Expand by interest rect padding amount.
    local_interest_rect.Inflate(kPixelDistanceToRecord);
  }
  return Intersection(EnclosingIntRect(local_interest_rect),
                      graphics_layer_bounds);
}

static const int kMinimumDistanceBeforeRepaint = 512;

bool CompositedLayerMapping::InterestRectChangedEnoughToRepaint(
    const IntRect& previous_interest_rect,
    const IntRect& new_interest_rect,
    const IntSize& layer_size) {
  if (previous_interest_rect.IsEmpty() && new_interest_rect.IsEmpty())
    return false;

  // Repaint when going from empty to not-empty, to cover cases where the layer
  // is painted for the first time, or otherwise becomes visible.
  if (previous_interest_rect.IsEmpty())
    return true;

  // Repaint if the new interest rect includes area outside of a skirt around
  // the existing interest rect.
  IntRect expanded_previous_interest_rect(previous_interest_rect);
  expanded_previous_interest_rect.Inflate(kMinimumDistanceBeforeRepaint);
  if (!expanded_previous_interest_rect.Contains(new_interest_rect))
    return true;

  // Even if the new interest rect doesn't include enough new area to satisfy
  // the condition above, repaint anyway if it touches a layer edge not touched
  // by the existing interest rect.  Because it's impossible to expose more area
  // in the direction, repainting cannot be deferred until the exposed new area
  // satisfies the condition above.
  if (new_interest_rect.X() == 0 && previous_interest_rect.X() != 0)
    return true;
  if (new_interest_rect.Y() == 0 && previous_interest_rect.Y() != 0)
    return true;
  if (new_interest_rect.MaxX() == layer_size.Width() &&
      previous_interest_rect.MaxX() != layer_size.Width())
    return true;
  if (new_interest_rect.MaxY() == layer_size.Height() &&
      previous_interest_rect.MaxY() != layer_size.Height())
    return true;

  return false;
}

IntRect CompositedLayerMapping::ComputeInterestRect(
    const GraphicsLayer* graphics_layer,
    const IntRect& previous_interest_rect) const {
  // Use the previous interest rect if it covers the whole layer.
  IntRect whole_layer_rect =
      IntRect(IntPoint(), ExpandedIntSize(graphics_layer->Size()));
  if (!NeedsRepaint(*graphics_layer) &&
      previous_interest_rect == whole_layer_rect)
    return previous_interest_rect;

  if (graphics_layer != graphics_layer_.get() &&
      graphics_layer != squashing_layer_.get() &&
      graphics_layer != scrolling_contents_layer_.get())
    return whole_layer_rect;

  IntRect new_interest_rect = RecomputeInterestRect(graphics_layer);
  if (NeedsRepaint(*graphics_layer) ||
      InterestRectChangedEnoughToRepaint(
          previous_interest_rect, new_interest_rect,
          ExpandedIntSize(graphics_layer->Size())))
    return new_interest_rect;
  return previous_interest_rect;
}

LayoutSize CompositedLayerMapping::SubpixelAccumulation() const {
  return owning_layer_.SubpixelAccumulation();
}

bool CompositedLayerMapping::NeedsRepaint(
    const GraphicsLayer& graphics_layer) const {
  return IsScrollableAreaLayer(&graphics_layer) ? true
                                                : owning_layer_.NeedsRepaint();
}

bool CompositedLayerMapping::AdjustForCompositedScrolling(
    const GraphicsLayer* graphics_layer,
    IntSize& offset) const {
  if (graphics_layer == scrolling_contents_layer_.get() ||
      graphics_layer == foreground_layer_.get()) {
    if (PaintLayerScrollableArea* scrollable_area =
            owning_layer_.GetScrollableArea()) {
      if (scrollable_area->UsesCompositedScrolling()) {
        // Note: this is the offset from the beginning of flow of the block, not
        // the offset from the top/left of the overflow rect.
        // offsetFromLayoutObject adds the origin offset from top/left to the
        // beginning of flow.
        ScrollOffset scroll_offset = scrollable_area->GetScrollOffset();
        offset.Expand(-scroll_offset.Width(), -scroll_offset.Height());
        return true;
      }
    }
  }
  return false;
}

void CompositedLayerMapping::PaintContents(
    const GraphicsLayer* graphics_layer,
    GraphicsContext& context,
    GraphicsLayerPaintingPhase graphics_layer_painting_phase,
    const IntRect& interest_rect) const {
  FramePaintTiming frame_paint_timing(context, GetLayoutObject().GetFrame());

  // https://code.google.com/p/chromium/issues/detail?id=343772
  DisableCompositingQueryAsserts disabler;
  // Allow throttling to make sure no painting paths (e.g.,
  // GraphicsLayer::PaintContents) try to paint throttled content.
  DocumentLifecycle::AllowThrottlingScope allow_throttling(
      owning_layer_.GetLayoutObject().GetDocument().Lifecycle());
#if DCHECK_IS_ON()
  // FIXME: once the state machine is ready, this can be removed and we can
  // refer to that instead.
  if (Page* page = GetLayoutObject().GetFrame()->GetPage())
    page->SetIsPainting(true);
#endif

  TRACE_EVENT1(
      "devtools.timeline,rail", "Paint", "data",
      InspectorPaintEvent::Data(&owning_layer_.GetLayoutObject(),
                                LayoutRect(interest_rect), graphics_layer));

  PaintLayerFlags paint_layer_flags = 0;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintBackground)
    paint_layer_flags |= kPaintLayerPaintingCompositingBackgroundPhase;
  else
    paint_layer_flags |= kPaintLayerPaintingSkipRootBackground;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintForeground)
    paint_layer_flags |= kPaintLayerPaintingCompositingForegroundPhase;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintMask)
    paint_layer_flags |= kPaintLayerPaintingCompositingMaskPhase;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintChildClippingMask)
    paint_layer_flags |= kPaintLayerPaintingChildClippingMaskPhase;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintAncestorClippingMask)
    paint_layer_flags |= kPaintLayerPaintingAncestorClippingMaskPhase;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintOverflowContents)
    paint_layer_flags |= kPaintLayerPaintingOverflowContents;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintCompositedScroll)
    paint_layer_flags |= kPaintLayerPaintingCompositingScrollingPhase;
  if (graphics_layer_painting_phase & kGraphicsLayerPaintDecoration)
    paint_layer_flags |= kPaintLayerPaintingCompositingDecorationPhase;

  if (graphics_layer == graphics_layer_.get() ||
      graphics_layer == foreground_layer_.get() ||
      graphics_layer == mask_layer_.get() ||
      graphics_layer == child_clipping_mask_layer_.get() ||
      graphics_layer == scrolling_contents_layer_.get() ||
      graphics_layer == decoration_outline_layer_.get() ||
      graphics_layer == ancestor_clipping_mask_layer_.get()) {
    bool paint_root_background_onto_scrolling_contents_layer =
        background_paints_onto_scrolling_contents_layer_;
    DCHECK(!paint_root_background_onto_scrolling_contents_layer ||
           !foreground_layer_);
    if (paint_root_background_onto_scrolling_contents_layer) {
      if (graphics_layer == scrolling_contents_layer_.get())
        paint_layer_flags &= ~kPaintLayerPaintingSkipRootBackground;
      else if (!background_paints_onto_graphics_layer_)
        paint_layer_flags |= kPaintLayerPaintingSkipRootBackground;
    }

    GraphicsLayerPaintInfo paint_info;
    paint_info.paint_layer = &owning_layer_;
    paint_info.composited_bounds = CompositedBounds();
    paint_info.offset_from_layout_object =
        graphics_layer->OffsetFromLayoutObject();
    AdjustForCompositedScrolling(graphics_layer,
                                 paint_info.offset_from_layout_object);

    // We have to use the same root as for hit testing, because both methods can
    // compute and cache clipRects.
    DoPaintTask(paint_info, *graphics_layer, paint_layer_flags, context,
                interest_rect);
  } else if (graphics_layer == squashing_layer_.get()) {
    for (size_t i = 0; i < squashed_layers_.size(); ++i) {
      DoPaintTask(squashed_layers_[i], *graphics_layer, paint_layer_flags,
                  context, interest_rect);
    }
  } else if (IsScrollableAreaLayer(graphics_layer)) {
    PaintScrollableArea(graphics_layer, context, interest_rect);
  }
  probe::didPaint(owning_layer_.GetLayoutObject().GetFrame(), graphics_layer,
                  context, LayoutRect(interest_rect));
#if DCHECK_IS_ON()
  if (Page* page = GetLayoutObject().GetFrame()->GetPage())
    page->SetIsPainting(false);
#endif
}

void CompositedLayerMapping::PaintScrollableArea(
    const GraphicsLayer* graphics_layer,
    GraphicsContext& context,
    const IntRect& interest_rect) const {
  // Note the composited scrollable area painted here is never associated with a
  // frame. For painting frame ScrollableAreas, see
  // PaintLayerCompositor::paintContents.

  // Map context and cull_rect which are in the local space of the scrollbar
  // to the space of the containing scrollable area in which Scrollbar::Paint()
  // will paint the scrollbar.
  auto offset = graphics_layer->OffsetFromLayoutObject();
  CullRect cull_rect(CullRect(interest_rect), offset);
  TransformRecorder transform_recorder(
      context, *graphics_layer,
      AffineTransform::Translation(-offset.Width(), -offset.Height()));

  PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
  if (graphics_layer == LayerForHorizontalScrollbar()) {
    if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar())
      scrollbar->Paint(context, cull_rect);
  } else if (graphics_layer == LayerForVerticalScrollbar()) {
    if (const Scrollbar* scrollbar = scrollable_area->VerticalScrollbar())
      scrollbar->Paint(context, cull_rect);
  } else if (graphics_layer == LayerForScrollCorner()) {
    ScrollableAreaPainter painter(*scrollable_area);
    painter.PaintScrollCorner(context, IntPoint(), cull_rect);
    painter.PaintResizer(context, IntPoint(), cull_rect);
  }
}

bool CompositedLayerMapping::IsScrollableAreaLayer(
    const GraphicsLayer* graphics_layer) const {
  return graphics_layer == LayerForHorizontalScrollbar() ||
         graphics_layer == LayerForVerticalScrollbar() ||
         graphics_layer == LayerForScrollCorner();
}

bool CompositedLayerMapping::ShouldThrottleRendering() const {
  return Compositor()->ShouldThrottleRendering();
}

bool CompositedLayerMapping::IsTrackingRasterInvalidations() const {
  return Compositor()->IsTrackingRasterInvalidations();
}

#if DCHECK_IS_ON()
void CompositedLayerMapping::VerifyNotPainting() {
  DCHECK(!GetLayoutObject().GetFrame()->GetPage() ||
         !GetLayoutObject().GetFrame()->GetPage()->IsPainting());
}
#endif

// Only used for performance benchmark testing. Intended to be a
// sufficiently-unique element id name to allow picking out the target element
// for invalidation.
static const char kTestPaintInvalidationTargetName[] =
    "blinkPaintInvalidationTarget";

void CompositedLayerMapping::InvalidateTargetElementForTesting() {
  // The below is an artificial construct formed intentionally to focus a
  // microbenchmark on the cost of paint with a partial invalidation.
  Element* target_element =
      owning_layer_.GetLayoutObject().GetDocument().getElementById(
          AtomicString(kTestPaintInvalidationTargetName));
  // TODO(wkorman): If we don't find the expected target element, we could
  // consider walking to the first leaf node so that the partial-invalidation
  // benchmark mode still provides some value when running on generic pages.
  if (!target_element)
    return;
  LayoutObject* target_object = target_element->GetLayoutObject();
  if (!target_object)
    return;
  target_object->EnclosingLayer()->SetNeedsRepaint();
  // TODO(wkorman): Consider revising the below to invalidate all
  // non-compositing descendants as well.
  target_object->InvalidateDisplayItemClients(
      PaintInvalidationReason::kForTesting);
}

bool CompositedLayerMapping::InvalidateLayerIfNoPrecedingEntry(
    size_t index_to_clear) {
  PaintLayer* layer_to_remove = squashed_layers_[index_to_clear].paint_layer;
  size_t previous_index = 0;
  for (; previous_index < index_to_clear; ++previous_index) {
    if (squashed_layers_[previous_index].paint_layer == layer_to_remove)
      break;
  }
  if (previous_index == index_to_clear &&
      layer_to_remove->GroupedMapping() == this) {
    Compositor()->PaintInvalidationOnCompositingChange(layer_to_remove);
    return true;
  }
  return false;
}

bool CompositedLayerMapping::UpdateSquashingLayerAssignment(
    PaintLayer* squashed_layer,
    size_t next_squashed_layer_index) {
  GraphicsLayerPaintInfo paint_info;
  paint_info.paint_layer = squashed_layer;
  // NOTE: composited bounds are updated elsewhere
  // NOTE: offsetFromLayoutObject is updated elsewhere

  // Change tracking on squashing layers: at the first sign of something
  // changed, just invalidate the layer.
  // FIXME: Perhaps we can find a tighter more clever mechanism later.
  if (next_squashed_layer_index < squashed_layers_.size()) {
    if (paint_info.paint_layer ==
        squashed_layers_[next_squashed_layer_index].paint_layer)
      return false;

    // Must invalidate before adding the squashed layer to the mapping.
    Compositor()->PaintInvalidationOnCompositingChange(squashed_layer);

    // If the layer which was previously at |nextSquashedLayerIndex| is not
    // earlier in the grouped mapping, invalidate its current backing now, since
    // it will move later or be removed from the squashing layer.
    InvalidateLayerIfNoPrecedingEntry(next_squashed_layer_index);

    squashed_layers_.insert(next_squashed_layer_index, paint_info);
  } else {
    // Must invalidate before adding the squashed layer to the mapping.
    Compositor()->PaintInvalidationOnCompositingChange(squashed_layer);
    squashed_layers_.push_back(paint_info);
  }
  squashed_layer->SetGroupedMapping(
      this, PaintLayer::kInvalidateLayerAndRemoveFromMapping);

  return true;
}

void CompositedLayerMapping::RemoveLayerFromSquashingGraphicsLayer(
    const PaintLayer* layer) {
  size_t layer_index = 0;
  for (; layer_index < squashed_layers_.size(); ++layer_index) {
    if (squashed_layers_[layer_index].paint_layer == layer)
      break;
  }

  // Assert on incorrect mappings between layers and groups
  DCHECK_LT(layer_index, squashed_layers_.size());
  if (layer_index == squashed_layers_.size())
    return;

  squashed_layers_.EraseAt(layer_index);
}

#if DCHECK_IS_ON()
bool CompositedLayerMapping::VerifyLayerInSquashingVector(
    const PaintLayer* layer) {
  for (size_t layer_index = 0; layer_index < squashed_layers_.size();
       ++layer_index) {
    if (squashed_layers_[layer_index].paint_layer == layer)
      return true;
  }

  return false;
}
#endif

void CompositedLayerMapping::FinishAccumulatingSquashingLayers(
    size_t next_squashed_layer_index,
    Vector<PaintLayer*>& layers_needing_paint_invalidation) {
  if (next_squashed_layer_index < squashed_layers_.size()) {
    // Any additional squashed Layers in the array no longer belong here, but
    // they might have been added already at an earlier index. Clear pointers on
    // those that do not appear in the valid set before removing all the extra
    // entries.
    for (size_t i = next_squashed_layer_index; i < squashed_layers_.size();
         ++i) {
      if (InvalidateLayerIfNoPrecedingEntry(i)) {
        squashed_layers_[i].paint_layer->SetGroupedMapping(
            nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
      }
      layers_needing_paint_invalidation.push_back(
          squashed_layers_[i].paint_layer);
    }

    squashed_layers_.EraseAt(
        next_squashed_layer_index,
        squashed_layers_.size() - next_squashed_layer_index);
  }
}

String CompositedLayerMapping::DebugName(
    const GraphicsLayer* graphics_layer) const {
  String name;
  if (graphics_layer == graphics_layer_.get()) {
    name = owning_layer_.DebugName();
  } else if (graphics_layer == squashing_containment_layer_.get()) {
    name = "Squashing Containment Layer";
  } else if (graphics_layer == squashing_layer_.get()) {
    name = "Squashing Layer (first squashed layer: " +
           (squashed_layers_.size() > 0
                ? squashed_layers_[0].paint_layer->DebugName()
                : "") +
           ")";
  } else if (graphics_layer == ancestor_clipping_layer_.get()) {
    name = "Ancestor Clipping Layer";
  } else if (graphics_layer == ancestor_clipping_mask_layer_.get()) {
    name = "Ancestor Clipping Mask Layer";
  } else if (graphics_layer == foreground_layer_.get()) {
    name = owning_layer_.DebugName() + " (foreground) Layer";
  } else if (graphics_layer == child_containment_layer_.get()) {
    name = "Child Containment Layer";
  } else if (graphics_layer == child_transform_layer_.get()) {
    name = "Child Transform Layer";
  } else if (graphics_layer == mask_layer_.get()) {
    name = "Mask Layer";
  } else if (graphics_layer == child_clipping_mask_layer_.get()) {
    name = "Child Clipping Mask Layer";
  } else if (graphics_layer == layer_for_horizontal_scrollbar_.get()) {
    name = "Horizontal Scrollbar Layer";
  } else if (graphics_layer == layer_for_vertical_scrollbar_.get()) {
    name = "Vertical Scrollbar Layer";
  } else if (graphics_layer == layer_for_scroll_corner_.get()) {
    name = "Scroll Corner Layer";
  } else if (graphics_layer == overflow_controls_host_layer_.get()) {
    name = "Overflow Controls Host Layer";
  } else if (graphics_layer ==
             overflow_controls_ancestor_clipping_layer_.get()) {
    name = "Overflow Controls Ancestor Clipping Layer";
  } else if (graphics_layer == scrolling_layer_.get()) {
    name = "Scrolling Layer";
  } else if (graphics_layer == scrolling_contents_layer_.get()) {
    name = "Scrolling Contents Layer";
  } else if (graphics_layer == decoration_outline_layer_.get()) {
    name = "Decoration Layer";
  } else {
    NOTREACHED();
  }

  return name;
}

}  // namespace blink
