/*
 * 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 "core/layout/compositing/CompositedLayerMapping.h"

#include "core/HTMLNames.h"
#include "core/dom/DOMNodeIds.h"
#include "core/fetch/ImageResourceContent.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/RemoteFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLVideoElement.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/layout/LayoutEmbeddedObject.h"
#include "core/layout/LayoutHTMLCanvas.h"
#include "core/layout/LayoutImage.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/LayoutVideo.h"
#include "core/layout/LayoutView.h"
#include "core/layout/api/LayoutAPIShim.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/layout/compositing/PaintLayerCompositor.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/page/scrolling/StickyPositionScrollingConstraints.h"
#include "core/page/scrolling/TopDocumentRootScrollerController.h"
#include "core/paint/ObjectPaintInvalidator.h"
#include "core/paint/PaintInfo.h"
#include "core/paint/PaintLayerPainter.h"
#include "core/paint/PaintLayerStackingNodeIterator.h"
#include "core/paint/PaintTiming.h"
#include "core/paint/ScrollableAreaPainter.h"
#include "core/paint/TransformRecorder.h"
#include "core/plugins/PluginView.h"
#include "platform/LengthFunctions.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/fonts/FontCache.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/BitmapImage.h"
#include "platform/graphics/CompositorFilterOperations.h"
#include "platform/graphics/CompositorMutableProperties.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/paint/ClipDisplayItem.h"
#include "platform/graphics/paint/CullRect.h"
#include "platform/graphics/paint/DrawingRecorder.h"
#include "platform/graphics/paint/PaintController.h"
#include "platform/graphics/paint/SkPictureBuilder.h"
#include "platform/graphics/paint/TransformDisplayItem.h"
#include "public/platform/WebLayerStickyPositionConstraint.h"
#include "wtf/CurrentTime.h"
#include "wtf/text/StringBuilder.h"
#include <memory>

namespace blink {

using namespace HTMLNames;

static IntRect clipBox(LayoutBox* layoutObject);

static IntRect contentsRect(const LayoutObject* layoutObject) {
  if (!layoutObject->isBox())
    return IntRect();
  if (layoutObject->isCanvas())
    return pixelSnappedIntRect(
        toLayoutHTMLCanvas(layoutObject)->replacedContentRect());
  if (layoutObject->isVideo())
    return pixelSnappedIntRect(
        toLayoutVideo(layoutObject)->replacedContentRect());

  return pixelSnappedIntRect(toLayoutBox(layoutObject)->contentBoxRect());
}

static IntRect backgroundRect(const LayoutObject* layoutObject) {
  if (!layoutObject->isBox())
    return IntRect();

  LayoutRect rect;
  const LayoutBox* box = toLayoutBox(layoutObject);
  return pixelSnappedIntRect(box->backgroundRect(BackgroundClipRect));
}

static inline bool isAcceleratedCanvas(const LayoutObject* layoutObject) {
  if (layoutObject->isCanvas()) {
    HTMLCanvasElement* canvas = toHTMLCanvasElement(layoutObject->node());
    if (CanvasRenderingContext* context = canvas->renderingContext())
      return context->isAccelerated();
  }
  return false;
}

static inline bool isCanvasControlledByOffscreen(
    const LayoutObject* layoutObject) {
  if (layoutObject->isCanvas()) {
    HTMLCanvasElement* canvas = toHTMLCanvasElement(layoutObject->node());
    if (canvas->surfaceLayerBridge())
      return true;
  }
  return false;
}

static bool hasBoxDecorationsOrBackgroundImage(const ComputedStyle& style) {
  return style.hasBoxDecorations() || style.hasBackgroundImage();
}

static bool contentLayerSupportsDirectBackgroundComposition(
    const LayoutObject* layoutObject) {
  // No support for decorations - border, border-radius or outline.
  // Only simple background - solid color or transparent.
  if (hasBoxDecorationsOrBackgroundImage(layoutObject->styleRef()))
    return false;

  // If there is no background, there is nothing to support.
  if (!layoutObject->style()->hasBackground())
    return true;

  // Simple background that is contained within the contents rect.
  return contentsRect(layoutObject).contains(backgroundRect(layoutObject));
}

static WebLayer* platformLayerForPlugin(LayoutObject* layoutObject) {
  if (!layoutObject->isEmbeddedObject())
    return nullptr;
  Widget* widget = toLayoutEmbeddedObject(layoutObject)->widget();
  if (!widget || !widget->isPluginView())
    return nullptr;
  return toPluginView(widget)->platformLayer();
}

static inline bool isAcceleratedContents(LayoutObject* layoutObject) {
  return isAcceleratedCanvas(layoutObject) ||
         (layoutObject->isEmbeddedObject() &&
          toLayoutEmbeddedObject(layoutObject)
              ->requiresAcceleratedCompositing()) ||
         layoutObject->isVideo();
}

// Get the scrolling coordinator in a way that works inside
// CompositedLayerMapping's destructor.
static ScrollingCoordinator* scrollingCoordinatorFromLayer(PaintLayer& layer) {
  Page* page = layer.layoutObject()->frame()->page();
  return (!page) ? nullptr : page->scrollingCoordinator();
}

CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer)
    : m_owningLayer(layer),
      m_contentOffsetInCompositingLayerDirty(false),
      m_pendingUpdateScope(GraphicsLayerUpdateNone),
      m_isMainFrameLayoutViewLayer(false),
      m_backgroundLayerPaintsFixedRootBackground(false),
      m_scrollingContentsAreEmpty(false),
      m_backgroundPaintsOntoScrollingContentsLayer(false),
      m_backgroundPaintsOntoGraphicsLayer(false) {
  if (layer.isRootLayer() && layoutObject()->frame()->isMainFrame())
    m_isMainFrameLayoutViewLayer = 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 < m_squashedLayers.size(); ++i) {
    PaintLayer* oldSquashedLayer = m_squashedLayers[i].paintLayer;
    // Assert on incorrect mappings between layers and groups
    ASSERT(oldSquashedLayer->groupedMapping() == this);
    if (oldSquashedLayer->groupedMapping() == this) {
      oldSquashedLayer->setGroupedMapping(
          0, PaintLayer::DoNotInvalidateLayerAndRemoveFromMapping);
      oldSquashedLayer->setLostGroupedMapping(true);
    }
  }

  updateClippingLayers(false, false);
  updateOverflowControlsLayers(false, false, false, false);
  updateChildTransformLayer(false);
  updateForegroundLayer(false);
  updateBackgroundLayer(false);
  updateMaskLayer(false);
  updateChildClippingMaskLayer(false);
  updateScrollingLayers(false);
  updateSquashingLayers(false);
  destroyGraphicsLayers();
}

std::unique_ptr<GraphicsLayer> CompositedLayerMapping::createGraphicsLayer(
    CompositingReasons reasons,
    SquashingDisallowedReasons squashingDisallowedReasons) {
  std::unique_ptr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(this);

  graphicsLayer->setCompositingReasons(reasons);
  graphicsLayer->setSquashingDisallowedReasons(squashingDisallowedReasons);
  if (Node* owningNode = m_owningLayer.layoutObject()->node())
    graphicsLayer->setOwnerNodeId(DOMNodeIds::idForNode(owningNode));

  return graphicsLayer;
}

void CompositedLayerMapping::createPrimaryGraphicsLayer() {
  m_graphicsLayer =
      createGraphicsLayer(m_owningLayer.getCompositingReasons(),
                          m_owningLayer.getSquashingDisallowedReasons());

  updateOpacity(layoutObject()->styleRef());
  updateTransform(layoutObject()->styleRef());
  updateFilters(layoutObject()->styleRef());
  updateBackdropFilters(layoutObject()->styleRef());
  updateStickyConstraints(layoutObject()->styleRef());
  updateLayerBlendMode(layoutObject()->styleRef());
  updateIsRootForIsolatedGroup();
}

void CompositedLayerMapping::destroyGraphicsLayers() {
  if (m_graphicsLayer)
    m_graphicsLayer->removeFromParent();

  m_ancestorClippingLayer = nullptr;
  m_graphicsLayer = nullptr;
  m_foregroundLayer = nullptr;
  m_backgroundLayer = nullptr;
  m_childContainmentLayer = nullptr;
  m_childTransformLayer = nullptr;
  m_maskLayer = nullptr;
  m_childClippingMaskLayer = nullptr;

  m_scrollingLayer = nullptr;
  m_scrollingContentsLayer = nullptr;
}

void CompositedLayerMapping::updateOpacity(const ComputedStyle& style) {
  m_graphicsLayer->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 (m_owningLayer.hasTransformRelatedProperty()) {
    style.applyTransform(
        t, LayoutSize(toLayoutBox(layoutObject())->pixelSnappedSize()),
        ComputedStyle::ExcludeTransformOrigin, ComputedStyle::IncludeMotionPath,
        ComputedStyle::IncludeIndependentTransformProperties);
    makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing());
  }

  m_graphicsLayer->setTransform(t);
}

void CompositedLayerMapping::updateFilters(const ComputedStyle& style) {
  m_graphicsLayer->setFilters(
      owningLayer().createCompositorFilterOperationsForFilter(style));
}

void CompositedLayerMapping::updateBackdropFilters(const ComputedStyle& style) {
  m_graphicsLayer->setBackdropFilters(
      owningLayer().createCompositorFilterOperationsForBackdropFilter(style));
}

void CompositedLayerMapping::updateStickyConstraints(
    const ComputedStyle& style) {
  bool sticky = style.position() == EPosition::StickyPosition;
  const PaintLayer* ancestorOverflowLayer =
      m_owningLayer.ancestorOverflowLayer();
  // TODO(flackr): Do we still need this?
  if (sticky) {
    if (!ancestorOverflowLayer->isRootLayer()) {
      sticky = ancestorOverflowLayer->needsCompositedScrolling();
    } else {
      sticky = layoutObject()->view()->frameView()->isScrollable();
    }
  }

  WebLayerStickyPositionConstraint webConstraint;
  if (sticky) {
    const StickyPositionScrollingConstraints& constraints =
        ancestorOverflowLayer->getScrollableArea()->stickyConstraintsMap().get(
            &m_owningLayer);

    // Find the layout offset of the unshifted sticky box within its enclosing
    // layer.
    LayoutPoint enclosingLayerOffset;
    m_owningLayer.enclosingLayerWithCompositedLayerMapping(ExcludeSelf)
        ->convertToLayerCoords(m_owningLayer.ancestorOverflowLayer(),
                               enclosingLayerOffset);
    FloatPoint stickyBoxOffset =
        constraints.scrollContainerRelativeStickyBoxRect().location();
    stickyBoxOffset.moveBy(FloatPoint(-enclosingLayerOffset));

    webConstraint.isSticky = true;
    webConstraint.isAnchoredLeft =
        constraints.anchorEdges() &
        StickyPositionScrollingConstraints::AnchorEdgeLeft;
    webConstraint.isAnchoredRight =
        constraints.anchorEdges() &
        StickyPositionScrollingConstraints::AnchorEdgeRight;
    webConstraint.isAnchoredTop =
        constraints.anchorEdges() &
        StickyPositionScrollingConstraints::AnchorEdgeTop;
    webConstraint.isAnchoredBottom =
        constraints.anchorEdges() &
        StickyPositionScrollingConstraints::AnchorEdgeBottom;
    webConstraint.leftOffset = constraints.leftOffset();
    webConstraint.rightOffset = constraints.rightOffset();
    webConstraint.topOffset = constraints.topOffset();
    webConstraint.bottomOffset = constraints.bottomOffset();
    webConstraint.parentRelativeStickyBoxOffset =
        roundedIntPoint(stickyBoxOffset);
    webConstraint.scrollContainerRelativeStickyBoxRect =
        enclosingIntRect(constraints.scrollContainerRelativeStickyBoxRect());
    webConstraint.scrollContainerRelativeContainingBlockRect = enclosingIntRect(
        constraints.scrollContainerRelativeContainingBlockRect());
  }

  m_graphicsLayer->setStickyPositionConstraint(webConstraint);
}

void CompositedLayerMapping::updateLayerBlendMode(const ComputedStyle& style) {
  setBlendMode(style.blendMode());
}

void CompositedLayerMapping::updateIsRootForIsolatedGroup() {
  bool isolate = m_owningLayer.shouldIsolateCompositedDescendants();

  // non stacking context layers should never isolate
  ASSERT(m_owningLayer.stackingNode()->isStackingContext() || !isolate);

  m_graphicsLayer->setIsRootForIsolatedGroup(isolate);
}

void CompositedLayerMapping::
    updateBackgroundPaintsOntoScrollingContentsLayer() {
  // 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 paintLocation =
      m_owningLayer.backgroundPaintLocation();
  bool shouldPaintOntoScrollingContentsLayer =
      paintLocation & BackgroundPaintInScrollingContents &&
      m_owningLayer.getScrollableArea()->usesCompositedScrolling();
  if (shouldPaintOntoScrollingContentsLayer !=
      backgroundPaintsOntoScrollingContentsLayer()) {
    m_backgroundPaintsOntoScrollingContentsLayer =
        shouldPaintOntoScrollingContentsLayer;
    // The scrolling contents layer needs to be updated for changed
    // m_backgroundPaintsOntoScrollingContentsLayer.
    if (hasScrollingLayer())
      m_scrollingContentsLayer->setNeedsDisplay();
  }
  bool shouldPaintOntoGraphicsLayer =
      !m_backgroundPaintsOntoScrollingContentsLayer ||
      paintLocation & BackgroundPaintInGraphicsLayer;
  if (shouldPaintOntoGraphicsLayer != !!m_backgroundPaintsOntoGraphicsLayer) {
    m_backgroundPaintsOntoGraphicsLayer = shouldPaintOntoGraphicsLayer;
    // The graphics layer needs to be updated for changed
    // m_backgroundPaintsOntoGraphicsLayer.
    m_graphicsLayer->setNeedsDisplay();
  }
}

void CompositedLayerMapping::updateContentsOpaque() {
  if (isAcceleratedCanvas(layoutObject())) {
    // Determine whether the rendering context's external texture layer is
    // opaque.
    CanvasRenderingContext* context =
        toHTMLCanvasElement(layoutObject()->node())->renderingContext();
    if (!context->creationAttributes().alpha())
      m_graphicsLayer->setContentsOpaque(true);
    else if (WebLayer* layer = context->platformLayer())
      m_graphicsLayer->setContentsOpaque(
          !Color(layer->backgroundColor()).hasAlpha());
    else
      m_graphicsLayer->setContentsOpaque(false);
  } else if (m_backgroundLayer) {
    m_graphicsLayer->setContentsOpaque(false);
    m_backgroundLayer->setContentsOpaque(
        m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
  } 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() && m_backgroundPaintsOntoScrollingContentsLayer) {
      // 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.
      m_scrollingContentsLayer->setContentsOpaque(
          m_owningLayer.backgroundIsKnownToBeOpaqueInRect(
              toLayoutBox(layoutObject())->paddingBoxRect()));

      if (m_owningLayer.backgroundPaintLocation() &
          BackgroundPaintInGraphicsLayer) {
        m_graphicsLayer->setContentsOpaque(
            m_owningLayer.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.
        m_graphicsLayer->setContentsOpaque(false);
      }
    } else {
      if (hasScrollingLayer())
        m_scrollingContentsLayer->setContentsOpaque(false);
      m_graphicsLayer->setContentsOpaque(
          m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
    }
  }
}

void CompositedLayerMapping::updateCompositedBounds() {
  ASSERT(m_owningLayer.compositor()->lifecycle().state() ==
         DocumentLifecycle::InCompositingUpdate);
  // FIXME: if this is really needed for performance, it would be better to
  // store it on Layer.
  m_compositedBounds = m_owningLayer.boundingBoxForCompositing();
  m_contentOffsetInCompositingLayerDirty = true;
}

void CompositedLayerMapping::updateAfterPartResize() {
  if (layoutObject()->isLayoutPart()) {
    if (PaintLayerCompositor* innerCompositor =
            PaintLayerCompositor::frameContentsCompositor(
                toLayoutPart(layoutObject()))) {
      innerCompositor->frameViewDidChangeSize();
      // We can floor this point because our frameviews are always aligned to
      // pixel boundaries.
      ASSERT(m_compositedBounds.location() ==
             flooredIntPoint(m_compositedBounds.location()));
      innerCompositor->frameViewDidChangeLocation(
          flooredIntPoint(contentsBox().location()));
    }
  }
}

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.
  m_graphicsLayer->setCompositingReasons(m_owningLayer.getCompositingReasons());
  m_graphicsLayer->setSquashingDisallowedReasons(
      m_owningLayer.getSquashingDisallowedReasons());
}

bool CompositedLayerMapping::
    owningLayerClippedByLayerNotAboveCompositedAncestor(
        const PaintLayer* scrollParent) {
  if (!m_owningLayer.parent())
    return false;

  const PaintLayer* compositingAncestor =
      m_owningLayer.enclosingLayerWithCompositedLayerMapping(ExcludeSelf);
  if (!compositingAncestor)
    return false;

  const LayoutObject* clippingContainer = m_owningLayer.clippingContainer();
  if (!clippingContainer)
    return false;

  if (clippingContainer->enclosingLayer() == scrollParent)
    return false;

  if (clippingContainer->enclosingLayer()->hasRootScrollerAsDescendant())
    return false;

  if (compositingAncestor->layoutObject()->isDescendantOf(clippingContainer))
    return false;

  // We ignore overflow clip here; we want composited overflow content to
  // behave as if it lives in an unclipped universe so it can prepaint, etc.
  // This means that we need to check if we are actually clipped before
  // setting up m_ancestorClippingLayer otherwise
  // updateAncestorClippingLayerGeometry will fail as the clip rect will be
  // infinite.
  // FIXME: this should use cached clip rects, but this sometimes give
  // inaccurate results (and trips the ASSERTS in PaintLayerClipper).
  ClipRectsContext clipRectsContext(compositingAncestor, UncachedClipRects,
                                    IgnoreOverlayScrollbarSize);
  clipRectsContext.setIgnoreOverflowClip();
  IntRect parentClipRect = pixelSnappedIntRect(
      m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
  return parentClipRect != LayoutRect::infiniteIntRect();
}

const PaintLayer* CompositedLayerMapping::scrollParent() {
  const PaintLayer* scrollParent = m_owningLayer.scrollParent();
  if (scrollParent && !scrollParent->needsCompositedScrolling())
    return nullptr;
  return scrollParent;
}

bool CompositedLayerMapping::updateGraphicsLayerConfiguration() {
  ASSERT(m_owningLayer.compositor()->lifecycle().state() ==
         DocumentLifecycle::InCompositingUpdate);

  // 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 = this->compositor();
  LayoutObject* layoutObject = this->layoutObject();
  const ComputedStyle& style = layoutObject->styleRef();

  bool layerConfigChanged = false;
  setBackgroundLayerPaintsFixedRootBackground(
      compositor->needsFixedRootBackgroundLayer(&m_owningLayer));

  // The background layer is currently only used for fixed root backgrounds.
  if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
    layerConfigChanged = true;

  if (updateForegroundLayer(
          compositor->needsContentsCompositingLayer(&m_owningLayer)))
    layerConfigChanged = true;

  bool needsDescendantsClippingLayer =
      compositor->clipsCompositingDescendants(&m_owningLayer);

  // Our scrolling layer will clip.
  if (m_owningLayer.needsCompositedScrolling())
    needsDescendantsClippingLayer = false;

  // We disable clipping on ancestor layers of the root scroller to give it
  // the same behavior w.r.t browser controls as the real root layer. See the
  // RootScrollerController class for more details.
  if (m_owningLayer.hasRootScrollerAsDescendant())
    needsDescendantsClippingLayer = false;

  const PaintLayer* scrollParent = this->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 needsAncestorClip =
      owningLayerClippedByLayerNotAboveCompositedAncestor(scrollParent);

  if (updateClippingLayers(needsAncestorClip, needsDescendantsClippingLayer))
    layerConfigChanged = true;

  bool scrollingConfigChanged = false;
  if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling())) {
    layerConfigChanged = true;
    scrollingConfigChanged = 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 minBorderWidth =
      std::min(layoutObject->style()->borderTopWidth(),
               std::min(layoutObject->style()->borderLeftWidth(),
                        std::min(layoutObject->style()->borderRightWidth(),
                                 layoutObject->style()->borderBottomWidth())));
  bool needsDecorationOutlineLayer =
      m_owningLayer.getScrollableArea() &&
      m_owningLayer.getScrollableArea()->usesCompositedScrolling() &&
      layoutObject->style()->hasOutline() &&
      layoutObject->style()->outlineOffset() < -minBorderWidth;

  if (updateDecorationOutlineLayer(needsDecorationOutlineLayer))
    layerConfigChanged = true;

  if (updateOverflowControlsLayers(
          requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(),
          requiresScrollCornerLayer(), needsAncestorClip))
    layerConfigChanged = true;

  bool hasPerspective = style.hasPerspective();
  bool needsChildTransformLayer = hasPerspective && layoutObject->isBox();
  if (updateChildTransformLayer(needsChildTransformLayer))
    layerConfigChanged = true;

  if (updateSquashingLayers(!m_squashedLayers.isEmpty()))
    layerConfigChanged = true;

  updateScrollParent(scrollParent);
  updateClipParent(scrollParent);

  if (layerConfigChanged)
    updateInternalHierarchy();

  if (scrollingConfigChanged) {
    if (layoutObject->view())
      compositor->scrollingLayerDidChange(&m_owningLayer);
  }

  // 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 maskLayerChanged = updateMaskLayer(layoutObject->hasMask());
  if (maskLayerChanged)
    m_graphicsLayer->setMaskLayer(m_maskLayer.get());

  bool hasChildClippingLayer =
      compositor->clipsCompositingDescendants(&m_owningLayer) &&
      (hasClippingLayer() || hasScrollingLayer());
  // If we have a border radius or clip path on a scrolling layer, we need a
  // clipping mask to properly clip the scrolled contents, even if there are no
  // composited descendants.
  bool hasClipPath = style.clipPath();
  bool needsChildClippingMask =
      (hasClipPath || style.hasBorderRadius()) &&
      (hasChildClippingLayer || isAcceleratedContents(layoutObject) ||
       hasScrollingLayer());

  GraphicsLayer* layerToApplyChildClippingMask = nullptr;
  bool shouldApplyChildClippingMaskOnContents = false;
  if (needsChildClippingMask) {
    if (hasClipPath) {
      // Clip path clips the entire subtree, including scrollbars. It must be
      // attached directly onto the main m_graphicsLayer.
      layerToApplyChildClippingMask = m_graphicsLayer.get();
    } else if (hasClippingLayer()) {
      layerToApplyChildClippingMask = clippingLayer();
    } else if (hasScrollingLayer()) {
      layerToApplyChildClippingMask = scrollingLayer();
    } else if (isAcceleratedContents(layoutObject)) {
      shouldApplyChildClippingMaskOnContents = true;
    }
  }

  updateChildClippingMaskLayer(needsChildClippingMask);

  if (layerToApplyChildClippingMask == m_graphicsLayer.get()) {
    if (m_graphicsLayer->maskLayer() != m_childClippingMaskLayer.get()) {
      m_graphicsLayer->setMaskLayer(m_childClippingMaskLayer.get());
      maskLayerChanged = true;
    }
  } else if (m_graphicsLayer->maskLayer() &&
             m_graphicsLayer->maskLayer() != m_maskLayer.get()) {
    m_graphicsLayer->setMaskLayer(nullptr);
    maskLayerChanged = true;
  }
  if (hasClippingLayer())
    clippingLayer()->setMaskLayer(layerToApplyChildClippingMask ==
                                          clippingLayer()
                                      ? m_childClippingMaskLayer.get()
                                      : nullptr);
  if (hasScrollingLayer())
    scrollingLayer()->setMaskLayer(layerToApplyChildClippingMask ==
                                           scrollingLayer()
                                       ? m_childClippingMaskLayer.get()
                                       : nullptr);
  m_graphicsLayer->setContentsClippingMaskLayer(
      shouldApplyChildClippingMaskOnContents ? m_childClippingMaskLayer.get()
                                             : nullptr);

  updateBackgroundColor();

  if (layoutObject->isImage()) {
    if (isDirectlyCompositedImage()) {
      updateImageContents();
    } else if (m_graphicsLayer->hasContentsLayer()) {
      m_graphicsLayer->setContentsToImage(nullptr);
    }
  }

  if (WebLayer* layer = platformLayerForPlugin(layoutObject)) {
    m_graphicsLayer->setContentsToPlatformLayer(layer);
  } else if (layoutObject->node() &&
             layoutObject->node()->isFrameOwnerElement() &&
             toHTMLFrameOwnerElement(layoutObject->node())->contentFrame()) {
    Frame* frame =
        toHTMLFrameOwnerElement(layoutObject->node())->contentFrame();
    if (frame->isRemoteFrame()) {
      WebLayer* layer = toRemoteFrame(frame)->webLayer();
      m_graphicsLayer->setContentsToPlatformLayer(layer);
    }
  } else if (layoutObject->isVideo()) {
    HTMLMediaElement* mediaElement = toHTMLMediaElement(layoutObject->node());
    m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer());
  } else if (isCanvasControlledByOffscreen(layoutObject)) {
    HTMLCanvasElement* canvas = toHTMLCanvasElement(layoutObject->node());
    m_graphicsLayer->setContentsToPlatformLayer(
        canvas->surfaceLayerBridge()->getWebLayer());
    layerConfigChanged = true;
  } else if (isAcceleratedCanvas(layoutObject)) {
    HTMLCanvasElement* canvas = toHTMLCanvasElement(layoutObject->node());
    if (CanvasRenderingContext* context = canvas->renderingContext())
      m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer());
    layerConfigChanged = true;
  }
  if (layoutObject->isLayoutPart()) {
    if (PaintLayerCompositor::attachFrameContentLayersToIframeLayer(
            toLayoutPart(layoutObject)))
      layerConfigChanged = true;
  }

  // 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.
  if (layerConfigChanged || maskLayerChanged)
    updatePaintingPhases();

  updateElementIdAndCompositorMutableProperties();

  m_graphicsLayer->setHasWillChangeTransformHint(
      style.hasWillChangeTransformHint());

  m_owningLayer.update3DTransformedDescendantStatus();
  if (style.preserves3D() && style.hasOpacity() &&
      m_owningLayer.has3DTransformedDescendant())
    UseCounter::count(layoutObject->document(),
                      UseCounter::OpacityWithPreserve3DQuirk);

  return layerConfigChanged;
}

static IntRect clipBox(LayoutBox* layoutObject) {
  // TODO(chrishtr): pixel snapping is most likely incorrect here.
  return pixelSnappedIntRect(layoutObject->clippingRect());
}

static LayoutPoint computeOffsetFromCompositedAncestor(
    const PaintLayer* layer,
    const PaintLayer* compositedAncestor) {
  LayoutPoint offset = layer->visualOffsetFromAncestor(compositedAncestor);
  if (compositedAncestor)
    offset.move(compositedAncestor->compositedLayerMapping()
                    ->owningLayer()
                    .subpixelAccumulation());
  return offset;
}

void CompositedLayerMapping::computeBoundsOfOwningLayer(
    const PaintLayer* compositedAncestor,
    IntRect& localBounds,
    IntRect& compositingBoundsRelativeToCompositedAncestor,
    LayoutPoint& offsetFromCompositedAncestor,
    IntPoint& snappedOffsetFromCompositedAncestor) {
  LayoutRect localRawCompositingBounds = compositedBounds();
  offsetFromCompositedAncestor =
      computeOffsetFromCompositedAncestor(&m_owningLayer, compositedAncestor);
  snappedOffsetFromCompositedAncestor =
      IntPoint(offsetFromCompositedAncestor.x().round(),
               offsetFromCompositedAncestor.y().round());

  LayoutSize subpixelAccumulation =
      offsetFromCompositedAncestor - snappedOffsetFromCompositedAncestor;
  m_owningLayer.setSubpixelAccumulation(subpixelAccumulation);

  // Move the bounds by the subpixel accumulation so that it pixel-snaps
  // relative to absolute pixels instead of local coordinates.
  localRawCompositingBounds.move(subpixelAccumulation);
  localBounds = pixelSnappedIntRect(localRawCompositingBounds);

  compositingBoundsRelativeToCompositedAncestor = localBounds;
  compositingBoundsRelativeToCompositedAncestor.moveBy(
      snappedOffsetFromCompositedAncestor);
}

void CompositedLayerMapping::updateSquashingLayerGeometry(
    const IntPoint& graphicsLayerParentLocation,
    const PaintLayer* compositingContainer,
    Vector<GraphicsLayerPaintInfo>& layers,
    GraphicsLayer* squashingLayer,
    LayoutPoint* offsetFromTransformedAncestor,
    Vector<PaintLayer*>& layersNeedingPaintInvalidation) {
  if (!squashingLayer)
    return;

  LayoutPoint compositingContainerOffsetFromParentGraphicsLayer =
      -graphicsLayerParentLocation;
  if (compositingContainer)
    compositingContainerOffsetFromParentGraphicsLayer +=
        compositingContainer->subpixelAccumulation();

#if DCHECK_IS_ON()
  const PaintLayer* commonTransformAncestor = nullptr;
  if (compositingContainer && compositingContainer->transform())
    commonTransformAncestor = compositingContainer;
  else if (compositingContainer)
    commonTransformAncestor = compositingContainer->transformAncestor();
#endif
  // FIXME: Cache these offsets.
  LayoutPoint compositingContainerOffsetFromTransformedAncestor;
  if (compositingContainer && !compositingContainer->transform())
    compositingContainerOffsetFromTransformedAncestor =
        compositingContainer->computeOffsetFromTransformedAncestor();

  LayoutRect totalSquashBounds;
  for (size_t i = 0; i < layers.size(); ++i) {
    LayoutRect squashedBounds =
        layers[i].paintLayer->boundingBoxForCompositing();

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

#if DCHECK_IS_ON()
    DCHECK(layers[i].paintLayer->transformAncestor() ==
           commonTransformAncestor);
#endif
    LayoutPoint squashedLayerOffsetFromTransformedAncestor =
        layers[i].paintLayer->computeOffsetFromTransformedAncestor();
    LayoutSize squashedLayerOffsetFromCompositingContainer =
        squashedLayerOffsetFromTransformedAncestor -
        compositingContainerOffsetFromTransformedAncestor;

    squashedBounds.move(squashedLayerOffsetFromCompositingContainer);
    totalSquashBounds.unite(squashedBounds);
  }

  // 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.
  totalSquashBounds.moveBy(compositingContainerOffsetFromParentGraphicsLayer);
  const IntRect squashLayerBounds = enclosingIntRect(totalSquashBounds);
  const IntPoint squashLayerOrigin = squashLayerBounds.location();
  const LayoutSize squashLayerOriginInCompositingContainerSpace =
      squashLayerOrigin - compositingContainerOffsetFromParentGraphicsLayer;

  // 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 squashedLayerOffsetFromTransformedAncestor =
        layers[i].paintLayer->computeOffsetFromTransformedAncestor();
    const LayoutSize offsetFromSquashLayerOrigin =
        (squashedLayerOffsetFromTransformedAncestor -
         compositingContainerOffsetFromTransformedAncestor) -
        squashLayerOriginInCompositingContainerSpace;

    IntSize newOffsetFromLayoutObject =
        -IntSize(offsetFromSquashLayerOrigin.width().round(),
                 offsetFromSquashLayerOrigin.height().round());
    LayoutSize subpixelAccumulation =
        offsetFromSquashLayerOrigin + newOffsetFromLayoutObject;
    if (layers[i].offsetFromLayoutObjectSet &&
        layers[i].offsetFromLayoutObject != newOffsetFromLayoutObject) {
      // 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].paintLayer->layoutObject())
          .invalidatePaintIncludingNonCompositingDescendants();

      TRACE_LAYER_INVALIDATION(layers[i].paintLayer,
                               InspectorLayerInvalidationTrackingEvent::
                                   SquashingLayerGeometryWasUpdated);
      layersNeedingPaintInvalidation.append(layers[i].paintLayer);
    }
    layers[i].offsetFromLayoutObject = newOffsetFromLayoutObject;
    layers[i].offsetFromLayoutObjectSet = true;

    layers[i].paintLayer->setSubpixelAccumulation(subpixelAccumulation);
  }

  squashingLayer->setPosition(squashLayerBounds.location());
  squashingLayer->setSize(FloatSize(squashLayerBounds.size()));

  *offsetFromTransformedAncestor =
      compositingContainerOffsetFromTransformedAncestor;
  offsetFromTransformedAncestor->move(
      squashLayerOriginInCompositingContainerSpace);

  for (size_t i = 0; i < layers.size(); ++i)
    layers[i].localClipRectForSquashedLayer =
        localClipRectForSquashedLayer(m_owningLayer, layers[i], layers);
}

void CompositedLayerMapping::updateGraphicsLayerGeometry(
    const PaintLayer* compositingContainer,
    const PaintLayer* compositingStackingContext,
    Vector<PaintLayer*>& layersNeedingPaintInvalidation) {
  ASSERT(m_owningLayer.compositor()->lifecycle().state() ==
         DocumentLifecycle::InCompositingUpdate);

  // Set transform property, if it is not animating. We have to do this here
  // because the transform is affected by the layer dimensions.
  if (!layoutObject()->style()->isRunningTransformAnimationOnCompositor())
    updateTransform(layoutObject()->styleRef());

  // Set opacity, if it is not animating.
  if (!layoutObject()->style()->isRunningOpacityAnimationOnCompositor())
    updateOpacity(layoutObject()->styleRef());

  if (!layoutObject()->style()->isRunningFilterAnimationOnCompositor())
    updateFilters(layoutObject()->styleRef());

  if (!layoutObject()->style()->isRunningBackdropFilterAnimationOnCompositor())
    updateBackdropFilters(layoutObject()->styleRef());

  updateStickyConstraints(layoutObject()->styleRef());

  // We compute everything relative to the enclosing compositing layer.
  IntRect ancestorCompositingBounds;
  if (compositingContainer) {
    ASSERT(compositingContainer->hasCompositedLayerMapping());
    ancestorCompositingBounds = compositingContainer->compositedLayerMapping()
                                    ->pixelSnappedCompositedBounds();
  }

  IntRect localCompositingBounds;
  IntRect relativeCompositingBounds;
  LayoutPoint offsetFromCompositedAncestor;
  IntPoint snappedOffsetFromCompositedAncestor;
  computeBoundsOfOwningLayer(
      compositingContainer, localCompositingBounds, relativeCompositingBounds,
      offsetFromCompositedAncestor, snappedOffsetFromCompositedAncestor);

  IntPoint graphicsLayerParentLocation;
  computeGraphicsLayerParentLocation(compositingContainer,
                                     ancestorCompositingBounds,
                                     graphicsLayerParentLocation);

  // Might update graphicsLayerParentLocation.
  updateAncestorClippingLayerGeometry(compositingContainer,
                                      snappedOffsetFromCompositedAncestor,
                                      graphicsLayerParentLocation);

  FloatSize contentsSize(relativeCompositingBounds.size());

  updateMainGraphicsLayerGeometry(relativeCompositingBounds,
                                  localCompositingBounds,
                                  graphicsLayerParentLocation);
  updateOverflowControlsHostLayerGeometry(compositingStackingContext,
                                          compositingContainer,
                                          graphicsLayerParentLocation);
  updateContentsOffsetInCompositingLayer(snappedOffsetFromCompositedAncestor,
                                         graphicsLayerParentLocation);
  updateSquashingLayerGeometry(
      graphicsLayerParentLocation, compositingContainer, m_squashedLayers,
      m_squashingLayer.get(), &m_squashingLayerOffsetFromTransformedAncestor,
      layersNeedingPaintInvalidation);

  // If we have a layer that clips children, position it.
  IntRect clippingBox;
  if (m_childContainmentLayer)
    clippingBox = clipBox(toLayoutBox(layoutObject()));

  updateChildTransformLayerGeometry();
  updateChildContainmentLayerGeometry(clippingBox, localCompositingBounds);

  updateMaskLayerGeometry();
  updateTransformGeometry(snappedOffsetFromCompositedAncestor,
                          relativeCompositingBounds);
  updateForegroundLayerGeometry(contentsSize, clippingBox);
  updateBackgroundLayerGeometry(contentsSize);
  // TODO(yigu): Currently the decoration layer uses the same contentSize
  // as background layer and foreground layer. There are scenarios that
  // the sizes could be different. The actual size of the decoration layer
  // should be calculated separately.
  // The size of the background layer should be different as well. We need to
  // check whether we are painting the decoration layer into the background and
  // then ignore or consider the outline when determining the contentSize.
  updateDecorationOutlineLayerGeometry(contentsSize);
  updateScrollingLayerGeometry(localCompositingBounds);
  updateChildClippingMaskLayerGeometry();

  if (m_owningLayer.getScrollableArea() &&
      m_owningLayer.getScrollableArea()->scrollsOverflow())
    m_owningLayer.getScrollableArea()->positionOverflowControls();

  updateLayerBlendMode(layoutObject()->styleRef());
  updateIsRootForIsolatedGroup();
  updateContentsRect();
  updateBackgroundColor();
  updateDrawsContent();
  updateElementIdAndCompositorMutableProperties();
  updateBackgroundPaintsOntoScrollingContentsLayer();
  updateContentsOpaque();
  updateAfterPartResize();
  updateRenderingContext();
  updateShouldFlattenTransform();
  updateChildrenTransform();
  updateScrollParent(scrollParent());
  registerScrollingLayers();

  updateCompositingReasons();
}

void CompositedLayerMapping::updateMainGraphicsLayerGeometry(
    const IntRect& relativeCompositingBounds,
    const IntRect& localCompositingBounds,
    const IntPoint& graphicsLayerParentLocation) {
  m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() -
                                          graphicsLayerParentLocation));
  m_graphicsLayer->setOffsetFromLayoutObject(
      toIntSize(localCompositingBounds.location()));

  FloatSize oldSize = m_graphicsLayer->size();
  const FloatSize contentsSize(relativeCompositingBounds.size());
  if (oldSize != contentsSize)
    m_graphicsLayer->setSize(contentsSize);

  // 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 contentsVisible = m_owningLayer.hasVisibleContent() ||
                         hasVisibleNonCompositingDescendant(&m_owningLayer);
  m_graphicsLayer->setContentsVisible(contentsVisible);

  m_graphicsLayer->setBackfaceVisibility(
      layoutObject()->style()->backfaceVisibility() ==
      BackfaceVisibilityVisible);
}

void CompositedLayerMapping::computeGraphicsLayerParentLocation(
    const PaintLayer* compositingContainer,
    const IntRect& ancestorCompositingBounds,
    IntPoint& graphicsLayerParentLocation) {
  if (compositingContainer &&
      compositingContainer->compositedLayerMapping()->hasClippingLayer()) {
    // If the compositing ancestor has a layer to clip children, we parent in
    // that, and therefore position relative to it.
    IntRect clippingBox =
        clipBox(toLayoutBox(compositingContainer->layoutObject()));
    graphicsLayerParentLocation =
        clippingBox.location() +
        roundedIntSize(compositingContainer->subpixelAccumulation());
  } else if (compositingContainer &&
             compositingContainer->compositedLayerMapping()
                 ->childTransformLayer()) {
    // Similarly, if the compositing ancestor has a child transform layer, we
    // parent in that, and therefore position relative to it. It's already taken
    // into account the contents offset, so we do not need to here.
    graphicsLayerParentLocation =
        roundedIntPoint(compositingContainer->subpixelAccumulation());
  } else if (compositingContainer) {
    graphicsLayerParentLocation = ancestorCompositingBounds.location();
  } else {
    graphicsLayerParentLocation =
        layoutObject()->view()->documentRect().location();
  }

  if (compositingContainer &&
      compositingContainer->needsCompositedScrolling()) {
    LayoutBox* layoutBox = toLayoutBox(compositingContainer->layoutObject());
    IntSize scrollOffset = layoutBox->scrolledContentOffset();
    IntPoint scrollOrigin =
        compositingContainer->getScrollableArea()->scrollOrigin();
    scrollOrigin.move(-layoutBox->borderLeft(), -layoutBox->borderTop());
    graphicsLayerParentLocation = -(scrollOrigin + scrollOffset);
  }
}

void CompositedLayerMapping::updateAncestorClippingLayerGeometry(
    const PaintLayer* compositingContainer,
    const IntPoint& snappedOffsetFromCompositedAncestor,
    IntPoint& graphicsLayerParentLocation) {
  if (!compositingContainer || !m_ancestorClippingLayer)
    return;

  ClipRectsContext clipRectsContext(compositingContainer,
                                    PaintingClipRectsIgnoringOverflowClip,
                                    IgnoreOverlayScrollbarSize);
  IntRect parentClipRect = pixelSnappedIntRect(
      m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
  ASSERT(parentClipRect != LayoutRect::infiniteIntRect());
  m_ancestorClippingLayer->setPosition(
      FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
  m_ancestorClippingLayer->setSize(FloatSize(parentClipRect.size()));

  // backgroundRect is relative to compositingContainer, so subtract
  // snappedOffsetFromCompositedAncestor.X/snappedOffsetFromCompositedAncestor.Y
  // to get back to local coords.
  m_ancestorClippingLayer->setOffsetFromLayoutObject(
      parentClipRect.location() - snappedOffsetFromCompositedAncestor);

  // The primary layer is then parented in, and positioned relative to this
  // clipping layer.
  graphicsLayerParentLocation = parentClipRect.location();
}

void CompositedLayerMapping::updateOverflowControlsHostLayerGeometry(
    const PaintLayer* compositingStackingContext,
    const PaintLayer* compositingContainer,
    IntPoint graphicsLayerParentLocation) {
  if (!m_overflowControlsHostLayer)
    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 hostLayerPosition;

  if (needsToReparentOverflowControls()) {
    CompositedLayerMapping* stackingCLM =
        compositingStackingContext->compositedLayerMapping();
    DCHECK(stackingCLM);

    // Either m_overflowControlsHostLayer or
    // m_overflowControlsAncestorClippingLayer (if it exists) will be a child of
    // the main GraphicsLayer of the compositing stacking context.
    IntSize stackingOffsetFromLayoutObject =
        stackingCLM->mainGraphicsLayer()->offsetFromLayoutObject();

    if (m_overflowControlsAncestorClippingLayer) {
      m_overflowControlsAncestorClippingLayer->setSize(
          m_ancestorClippingLayer->size());
      m_overflowControlsAncestorClippingLayer->setOffsetFromLayoutObject(
          m_ancestorClippingLayer->offsetFromLayoutObject());
      m_overflowControlsAncestorClippingLayer->setMasksToBounds(true);

      FloatPoint position;
      if (compositingStackingContext == compositingContainer) {
        position = m_ancestorClippingLayer->position();
      } else {
        // graphicsLayerParentLocation is the location of
        // m_ancestorClippingLayer relative to compositingContainer (including
        // any offset from compositingContainer's m_childContainmentLayer).
        LayoutPoint offset = LayoutPoint(graphicsLayerParentLocation);
        compositingContainer->convertToLayerCoords(compositingStackingContext,
                                                   offset);
        position =
            FloatPoint(offset) - FloatSize(stackingOffsetFromLayoutObject);
      }

      m_overflowControlsAncestorClippingLayer->setPosition(position);
      hostLayerPosition.move(
          -m_ancestorClippingLayer->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 transformState(TransformState::ApplyTransformDirection,
                                    FloatPoint());
      m_owningLayer.layoutObject()->mapLocalToAncestor(
          compositingStackingContext->layoutObject(), transformState,
          ApplyContainerFlip);
      transformState.flatten();
      hostLayerPosition = LayoutPoint(transformState.lastPlanarPoint());
      if (PaintLayerScrollableArea* scrollableArea =
              compositingStackingContext->getScrollableArea()) {
        hostLayerPosition.move(
            LayoutSize(toFloatSize(scrollableArea->scrollPosition())));
      }
      hostLayerPosition.move(-stackingOffsetFromLayoutObject);
    }
  } else {
    hostLayerPosition.move(-m_graphicsLayer->offsetFromLayoutObject());
  }

  m_overflowControlsHostLayer->setPosition(FloatPoint(hostLayerPosition));

  const IntRect borderBox =
      toLayoutBox(m_owningLayer.layoutObject())->pixelSnappedBorderBoxRect();
  m_overflowControlsHostLayer->setSize(FloatSize(borderBox.size()));
  m_overflowControlsHostLayer->setMasksToBounds(true);
}

void CompositedLayerMapping::updateChildContainmentLayerGeometry(
    const IntRect& clippingBox,
    const IntRect& localCompositingBounds) {
  if (!m_childContainmentLayer)
    return;

  FloatPoint clipPositionInLayoutObjectSpace(
      clippingBox.location() - localCompositingBounds.location() +
      roundedIntSize(m_owningLayer.subpixelAccumulation()));

  // If there are layers between the the child containment layer and
  // m_graphicsLayer (eg, the child transform layer), we must adjust the clip
  // position to get it in the correct space.
  FloatPoint clipPositionInParentSpace = clipPositionInLayoutObjectSpace;
  for (GraphicsLayer* ancestor = m_childContainmentLayer->parent();
       ancestor != mainGraphicsLayer(); ancestor = ancestor->parent())
    clipPositionInParentSpace -= toFloatSize(ancestor->position());

  m_childContainmentLayer->setPosition(clipPositionInParentSpace);
  m_childContainmentLayer->setSize(FloatSize(clippingBox.size()));
  m_childContainmentLayer->setOffsetFromLayoutObject(
      toIntSize(clippingBox.location()));
  if (m_childClippingMaskLayer && !m_scrollingLayer &&
      !layoutObject()->style()->clipPath()) {
    m_childClippingMaskLayer->setSize(m_childContainmentLayer->size());
    m_childClippingMaskLayer->setOffsetFromLayoutObject(
        m_childContainmentLayer->offsetFromLayoutObject());
  }
}

void CompositedLayerMapping::updateChildTransformLayerGeometry() {
  if (!m_childTransformLayer)
    return;
  const IntRect borderBox =
      toLayoutBox(m_owningLayer.layoutObject())->pixelSnappedBorderBoxRect();
  m_childTransformLayer->setSize(FloatSize(borderBox.size()));
  m_childTransformLayer->setPosition(
      FloatPoint(contentOffsetInCompositingLayer()));
}

void CompositedLayerMapping::updateMaskLayerGeometry() {
  if (!m_maskLayer)
    return;

  if (m_maskLayer->size() != m_graphicsLayer->size()) {
    m_maskLayer->setSize(m_graphicsLayer->size());
    m_maskLayer->setNeedsDisplay();
  }
  m_maskLayer->setPosition(FloatPoint());
  m_maskLayer->setOffsetFromLayoutObject(
      m_graphicsLayer->offsetFromLayoutObject());
}

void CompositedLayerMapping::updateTransformGeometry(
    const IntPoint& snappedOffsetFromCompositedAncestor,
    const IntRect& relativeCompositingBounds) {
  if (m_owningLayer.hasTransformRelatedProperty()) {
    const LayoutRect borderBox = toLayoutBox(layoutObject())->borderBoxRect();

    // Get layout bounds in the coords of compositingContainer to match
    // relativeCompositingBounds.
    IntRect layerBounds = pixelSnappedIntRect(
        toLayoutPoint(m_owningLayer.subpixelAccumulation()), borderBox.size());
    layerBounds.moveBy(snappedOffsetFromCompositedAncestor);

    // Update properties that depend on layer dimensions
    FloatPoint3D transformOrigin =
        computeTransformOrigin(IntRect(IntPoint(), layerBounds.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 compositedTransformOrigin(
        layerBounds.x() - relativeCompositingBounds.x() + transformOrigin.x(),
        layerBounds.y() - relativeCompositingBounds.y() + transformOrigin.y(),
        transformOrigin.z());
    m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
  } else {
    FloatPoint3D compositedTransformOrigin(
        relativeCompositingBounds.width() * 0.5f,
        relativeCompositingBounds.height() * 0.5f, 0.f);
    m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
  }
}

void CompositedLayerMapping::updateScrollingLayerGeometry(
    const IntRect& localCompositingBounds) {
  if (!m_scrollingLayer)
    return;

  ASSERT(m_scrollingContentsLayer);
  LayoutBox* layoutBox = toLayoutBox(layoutObject());
  IntRect overflowClipRect =
      pixelSnappedIntRect(layoutBox->overflowClipRect(LayoutPoint()));

  const TopDocumentRootScrollerController& globalRootScrollerController =
      layoutBox->document().frameHost()->globalRootScrollerController();

  if (&m_owningLayer == globalRootScrollerController.rootScrollerPaintLayer()) {
    LayoutRect clipRect =
        layoutBox->document().layoutView()->overflowClipRect(LayoutPoint());
    DCHECK(clipRect.size() == LayoutSize(pixelSnappedIntRect(clipRect).size()));
    overflowClipRect.setSize(pixelSnappedIntRect(clipRect).size());
  }

  FloatPoint scrollPosition =
      m_owningLayer.getScrollableArea()->scrollPosition();
  m_scrollingLayer->setPosition(FloatPoint(
      overflowClipRect.location() - localCompositingBounds.location() +
      roundedIntSize(m_owningLayer.subpixelAccumulation())));
  m_scrollingLayer->setSize(FloatSize(overflowClipRect.size()));

  IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromLayoutObject();
  m_scrollingLayer->setOffsetFromLayoutObject(
      -toIntSize(overflowClipRect.location()));

  if (m_childClippingMaskLayer && !layoutObject()->style()->clipPath()) {
    m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
    m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
    m_childClippingMaskLayer->setOffsetFromLayoutObject(
        toIntSize(overflowClipRect.location()));
  }

  bool overflowClipRectOffsetChanged =
      oldScrollingLayerOffset != m_scrollingLayer->offsetFromLayoutObject();

  IntSize scrollSize(layoutBox->pixelSnappedScrollWidth(),
                     layoutBox->pixelSnappedScrollHeight());
  if (overflowClipRectOffsetChanged)
    m_scrollingContentsLayer->setNeedsDisplay();

  DoubleSize scrollingContentsOffset(
      overflowClipRect.location().x() - scrollPosition.x(),
      overflowClipRect.location().y() - scrollPosition.y());
  // The scroll offset change is compared using floating point so that
  // fractional scroll offset change can be propagated to compositor.
  if (scrollingContentsOffset != m_scrollingContentsOffset ||
      scrollSize != m_scrollingContentsLayer->size()) {
    bool coordinatorHandlesOffset =
        compositor()->scrollingLayerDidChange(&m_owningLayer);
    m_scrollingContentsLayer->setPosition(
        coordinatorHandlesOffset ? FloatPoint()
                                 : FloatPoint(-toFloatSize(scrollPosition)));
  }
  m_scrollingContentsOffset = scrollingContentsOffset;

  m_scrollingContentsLayer->setSize(FloatSize(scrollSize));

  IntPoint scrollingContentsLayerOffsetFromLayoutObject;
  if (PaintLayerScrollableArea* scrollableArea =
          m_owningLayer.getScrollableArea()) {
    scrollingContentsLayerOffsetFromLayoutObject =
        -scrollableArea->scrollOrigin();
  }
  scrollingContentsLayerOffsetFromLayoutObject.moveBy(
      overflowClipRect.location());

  m_scrollingContentsLayer->setOffsetDoubleFromLayoutObject(
      toIntSize(scrollingContentsLayerOffsetFromLayoutObject),
      GraphicsLayer::DontSetNeedsDisplay);

  if (m_foregroundLayer) {
    if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
      m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
    m_foregroundLayer->setNeedsDisplay();
    m_foregroundLayer->setOffsetFromLayoutObject(
        m_scrollingContentsLayer->offsetFromLayoutObject());
  }
}

void CompositedLayerMapping::updateChildClippingMaskLayerGeometry() {
  if (!m_childClippingMaskLayer || !layoutObject()->style()->clipPath())
    return;
  LayoutBox* layoutBox = toLayoutBox(layoutObject());
  IntRect clientBox = enclosingIntRect(layoutBox->clientBoxRect());

  m_childClippingMaskLayer->setPosition(m_graphicsLayer->position());
  m_childClippingMaskLayer->setSize(m_graphicsLayer->size());
  m_childClippingMaskLayer->setOffsetFromLayoutObject(
      toIntSize(clientBox.location()));

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

void CompositedLayerMapping::updateForegroundLayerGeometry(
    const FloatSize& relativeCompositingBoundsSize,
    const IntRect& clippingBox) {
  if (!m_foregroundLayer)
    return;

  FloatSize foregroundSize = relativeCompositingBoundsSize;
  IntSize foregroundOffset = m_graphicsLayer->offsetFromLayoutObject();
  m_foregroundLayer->setPosition(FloatPoint());

  if (hasClippingLayer()) {
    // If we have a clipping layer (which clips descendants), then the
    // foreground layer is a child of it, so that it gets correctly sorted with
    // children. In that case, position relative to the clipping layer.
    foregroundSize = FloatSize(clippingBox.size());
    foregroundOffset = toIntSize(clippingBox.location());
  } else if (m_childTransformLayer) {
    // Things are different if we have a child transform layer rather
    // than a clipping layer. In this case, we want to actually change
    // the position of the layer (to compensate for our ancestor
    // compositing PaintLayer's position) rather than leave the position the
    // same and use offset-from-layoutObject + size to describe a clipped
    // "window" onto the clipped layer.

    m_foregroundLayer->setPosition(-m_childTransformLayer->position());
  }

  if (foregroundSize != m_foregroundLayer->size()) {
    m_foregroundLayer->setSize(foregroundSize);
    m_foregroundLayer->setNeedsDisplay();
  }
  m_foregroundLayer->setOffsetFromLayoutObject(foregroundOffset);

  // NOTE: there is some more configuring going on in
  // updateScrollingLayerGeometry().
}

void CompositedLayerMapping::updateBackgroundLayerGeometry(
    const FloatSize& relativeCompositingBoundsSize) {
  if (!m_backgroundLayer)
    return;

  FloatSize backgroundSize = relativeCompositingBoundsSize;
  if (backgroundLayerPaintsFixedRootBackground()) {
    FrameView* frameView = toLayoutView(layoutObject())->frameView();
    backgroundSize = FloatSize(frameView->visibleContentRect().size());
  }
  m_backgroundLayer->setPosition(FloatPoint());
  if (backgroundSize != m_backgroundLayer->size()) {
    m_backgroundLayer->setSize(backgroundSize);
    m_backgroundLayer->setNeedsDisplay();
  }
  m_backgroundLayer->setOffsetFromLayoutObject(
      m_graphicsLayer->offsetFromLayoutObject());
}

void CompositedLayerMapping::updateDecorationOutlineLayerGeometry(
    const FloatSize& relativeCompositingBoundsSize) {
  if (!m_decorationOutlineLayer)
    return;
  FloatSize decorationSize = relativeCompositingBoundsSize;
  m_decorationOutlineLayer->setPosition(FloatPoint());
  if (decorationSize != m_decorationOutlineLayer->size()) {
    m_decorationOutlineLayer->setSize(decorationSize);
    m_decorationOutlineLayer->setNeedsDisplay();
  }
  m_decorationOutlineLayer->setOffsetFromLayoutObject(
      m_graphicsLayer->offsetFromLayoutObject());
}

void CompositedLayerMapping::registerScrollingLayers() {
  // Register fixed position layers and their containers with the scrolling
  // coordinator.
  ScrollingCoordinator* scrollingCoordinator =
      scrollingCoordinatorFromLayer(m_owningLayer);
  if (!scrollingCoordinator)
    return;

  scrollingCoordinator->updateLayerPositionConstraint(&m_owningLayer);

  // Page scale is applied as a transform on the root layout view layer. Because
  // the scroll layer is further up in the hierarchy, we need to avoid marking
  // the root layout view layer as a container.
  bool isContainer =
      m_owningLayer.layoutObject()->style()->canContainFixedPositionObjects() &&
      !m_owningLayer.isRootLayer();
  // FIXME: we should make certain that childForSuperLayers will never be the
  // m_squashingContainmentLayer here
  scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(
      childForSuperlayers(), isContainer);
}

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

  m_graphicsLayer->removeFromParent();

  if (m_ancestorClippingLayer)
    m_ancestorClippingLayer->addChild(m_graphicsLayer.get());

  // Layer to which children should be attached as we build the hierarchy.
  GraphicsLayer* bottomLayer = m_graphicsLayer.get();
  auto updateBottomLayer = [&bottomLayer](GraphicsLayer* layer) {
    if (layer) {
      bottomLayer->addChild(layer);
      bottomLayer = layer;
    }
  };

  updateBottomLayer(m_childTransformLayer.get());
  updateBottomLayer(m_childContainmentLayer.get());
  updateBottomLayer(m_scrollingLayer.get());

  // Now constructing the subtree for the overflow controls.
  bottomLayer = m_graphicsLayer.get();
  // TODO(pdr): Ensure painting uses the correct GraphicsLayer when root layer
  // scrolls is enabled.  crbug.com/638719
  if (m_isMainFrameLayoutViewLayer &&
      !RuntimeEnabledFeatures::slimmingPaintV2Enabled())
    bottomLayer = layoutObject()
                      ->frame()
                      ->page()
                      ->frameHost()
                      .visualViewport()
                      .containerLayer();
  updateBottomLayer(m_overflowControlsAncestorClippingLayer.get());
  updateBottomLayer(m_overflowControlsHostLayer.get());
  if (m_layerForHorizontalScrollbar)
    m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
  if (m_layerForVerticalScrollbar)
    m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
  if (m_layerForScrollCorner)
    m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());

  // Now add the DecorationOutlineLayer as a subtree to GraphicsLayer
  if (m_decorationOutlineLayer.get())
    m_graphicsLayer->addChild(m_decorationOutlineLayer.get());

  // The squashing containment layer, if it exists, becomes a no-op parent.
  if (m_squashingLayer) {
    ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) ||
           (!m_ancestorClippingLayer && m_squashingContainmentLayer));

    if (m_squashingContainmentLayer) {
      m_squashingContainmentLayer->removeAllChildren();
      m_squashingContainmentLayer->addChild(m_graphicsLayer.get());
      m_squashingContainmentLayer->addChild(m_squashingLayer.get());
    } else {
      // The ancestor clipping layer is already set up and has m_graphicsLayer
      // under it.
      m_ancestorClippingLayer->addChild(m_squashingLayer.get());
    }
  }
}

void CompositedLayerMapping::updatePaintingPhases() {
  m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
  if (m_scrollingContentsLayer) {
    GraphicsLayerPaintingPhase paintPhase =
        GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
    if (!m_foregroundLayer)
      paintPhase |= GraphicsLayerPaintForeground;
    m_scrollingContentsLayer->setPaintingPhase(paintPhase);
  }
  if (m_foregroundLayer) {
    GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintForeground;
    if (m_scrollingContentsLayer)
      paintPhase |= GraphicsLayerPaintOverflowContents;
    m_foregroundLayer->setPaintingPhase(paintPhase);
  }
}

void CompositedLayerMapping::updateContentsRect() {
  m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
}

void CompositedLayerMapping::updateContentsOffsetInCompositingLayer(
    const IntPoint& snappedOffsetFromCompositedAncestor,
    const IntPoint& graphicsLayerParentLocation) {
  // 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 offsetDueToAncestorGraphicsLayers =
      m_graphicsLayer->position() + graphicsLayerParentLocation;
  m_contentOffsetInCompositingLayer = LayoutSize(
      snappedOffsetFromCompositedAncestor - offsetDueToAncestorGraphicsLayers);
  m_contentOffsetInCompositingLayerDirty = false;
}

void CompositedLayerMapping::updateDrawsContent() {
  bool inOverlayFullscreenVideo = false;
  if (layoutObject()->isVideo()) {
    HTMLVideoElement* videoElement = toHTMLVideoElement(layoutObject()->node());
    if (videoElement->isFullscreen() &&
        videoElement->usesOverlayFullscreenVideo())
      inOverlayFullscreenVideo = true;
  }
  bool hasPaintedContent =
      inOverlayFullscreenVideo ? false : containsPaintedContent();
  m_graphicsLayer->setDrawsContent(hasPaintedContent);

  if (m_scrollingLayer) {
    // m_scrollingLayer never has backing store.
    // m_scrollingContentsLayer only needs backing store if the scrolled
    // contents need to paint.
    m_scrollingContentsAreEmpty =
        !m_owningLayer.hasVisibleContent() ||
        !(layoutObject()->styleRef().hasBackground() ||
          layoutObject()->hasBackdropFilter() || paintsChildren());
    m_scrollingContentsLayer->setDrawsContent(!m_scrollingContentsAreEmpty);
  }

  if (hasPaintedContent && isAcceleratedCanvas(layoutObject())) {
    CanvasRenderingContext* context =
        toHTMLCanvasElement(layoutObject()->node())->renderingContext();
    // Content layer may be null if context is lost.
    if (WebLayer* contentLayer = context->platformLayer()) {
      Color bgColor(Color::transparent);
      if (contentLayerSupportsDirectBackgroundComposition(layoutObject())) {
        bgColor = layoutObjectBackgroundColor();
        hasPaintedContent = false;
      }
      contentLayer->setBackgroundColor(bgColor.rgb());
    }
  }

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

  // TODO(yigu): The background should no longer setDrawsContent(true) if we
  // only have an outline and we are drawing the outline into the decoration
  // layer (i.e. if there is nothing actually drawn into the
  // background anymore.)
  // "hasPaintedContent" should be calculated in a way that does not take the
  // outline into consideration.
  if (m_backgroundLayer)
    m_backgroundLayer->setDrawsContent(hasPaintedContent);

  if (m_decorationOutlineLayer)
    m_decorationOutlineLayer->setDrawsContent(true);

  if (m_maskLayer)
    m_maskLayer->setDrawsContent(true);

  if (m_childClippingMaskLayer)
    m_childClippingMaskLayer->setDrawsContent(true);
}

void CompositedLayerMapping::updateChildrenTransform() {
  if (GraphicsLayer* childTransformLayer = this->childTransformLayer()) {
    childTransformLayer->setTransform(owningLayer().perspectiveTransform());
    childTransformLayer->setTransformOrigin(owningLayer().perspectiveOrigin());
  }

  updateShouldFlattenTransform();
}

// Return true if the layers changed.
bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip,
                                                  bool needsDescendantClip) {
  bool layersChanged = false;

  if (needsAncestorClip) {
    if (!m_ancestorClippingLayer) {
      m_ancestorClippingLayer =
          createGraphicsLayer(CompositingReasonLayerForAncestorClip);
      m_ancestorClippingLayer->setMasksToBounds(true);
      m_ancestorClippingLayer->setShouldFlattenTransform(false);
      layersChanged = true;
    }
  } else if (m_ancestorClippingLayer) {
    m_ancestorClippingLayer->removeFromParent();
    m_ancestorClippingLayer = nullptr;
    layersChanged = true;
  }

  if (needsDescendantClip) {
    // 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 (!m_childContainmentLayer && !m_isMainFrameLayoutViewLayer) {
      m_childContainmentLayer =
          createGraphicsLayer(CompositingReasonLayerForDescendantClip);
      m_childContainmentLayer->setMasksToBounds(true);
      layersChanged = true;
    }
  } else if (hasClippingLayer()) {
    m_childContainmentLayer->removeFromParent();
    m_childContainmentLayer = nullptr;
    layersChanged = true;
  }

  return layersChanged;
}

bool CompositedLayerMapping::updateChildTransformLayer(
    bool needsChildTransformLayer) {
  bool layersChanged = false;

  if (needsChildTransformLayer) {
    if (!m_childTransformLayer) {
      m_childTransformLayer =
          createGraphicsLayer(CompositingReasonLayerForPerspective);
      m_childTransformLayer->setDrawsContent(false);
      layersChanged = true;
    }
  } else if (m_childTransformLayer) {
    m_childTransformLayer->removeFromParent();
    m_childTransformLayer = nullptr;
    layersChanged = true;
  }

  return layersChanged;
}

void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(
    bool backgroundLayerPaintsFixedRootBackground) {
  m_backgroundLayerPaintsFixedRootBackground =
      backgroundLayerPaintsFixedRootBackground;
}

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

  if (PaintLayerScrollableArea* scrollableArea =
          m_owningLayer.getScrollableArea()) {
    if (ScrollingCoordinator* scrollingCoordinator =
            scrollingCoordinatorFromLayer(m_owningLayer)) {
      if (reason == CompositingReasonLayerForHorizontalScrollbar)
        scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(
            scrollableArea, HorizontalScrollbar);
      else if (reason == CompositingReasonLayerForVerticalScrollbar)
        scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(
            scrollableArea, VerticalScrollbar);
    }
  }
  return true;
}

bool CompositedLayerMapping::updateOverflowControlsLayers(
    bool needsHorizontalScrollbarLayer,
    bool needsVerticalScrollbarLayer,
    bool needsScrollCornerLayer,
    bool needsAncestorClip) {
  if (PaintLayerScrollableArea* scrollableArea =
          m_owningLayer.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 (m_layerForHorizontalScrollbar && needsHorizontalScrollbarLayer &&
        scrollableArea->shouldRebuildHorizontalScrollbarLayer())
      toggleScrollbarLayerIfNeeded(
          m_layerForHorizontalScrollbar, false,
          CompositingReasonLayerForHorizontalScrollbar);
    if (m_layerForVerticalScrollbar && needsVerticalScrollbarLayer &&
        scrollableArea->shouldRebuildVerticalScrollbarLayer())
      toggleScrollbarLayerIfNeeded(m_layerForVerticalScrollbar, false,
                                   CompositingReasonLayerForVerticalScrollbar);
    scrollableArea->resetRebuildScrollbarLayerFlags();
  }

  // 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 (needsHorizontalScrollbarLayer || needsVerticalScrollbarLayer ||
      needsScrollCornerLayer) {
    bool invisible = m_owningLayer.subtreeIsInvisible();
    needsHorizontalScrollbarLayer &= !invisible;
    needsVerticalScrollbarLayer &= !invisible;
    needsScrollCornerLayer &= !invisible;
  }

  bool horizontalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(
      m_layerForHorizontalScrollbar, needsHorizontalScrollbarLayer,
      CompositingReasonLayerForHorizontalScrollbar);
  bool verticalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(
      m_layerForVerticalScrollbar, needsVerticalScrollbarLayer,
      CompositingReasonLayerForVerticalScrollbar);
  bool scrollCornerLayerChanged = toggleScrollbarLayerIfNeeded(
      m_layerForScrollCorner, needsScrollCornerLayer,
      CompositingReasonLayerForScrollCorner);

  bool needsOverflowControlsHostLayer = needsHorizontalScrollbarLayer ||
                                        needsVerticalScrollbarLayer ||
                                        needsScrollCornerLayer;
  toggleScrollbarLayerIfNeeded(m_overflowControlsHostLayer,
                               needsOverflowControlsHostLayer,
                               CompositingReasonLayerForOverflowControlsHost);
  bool needsOverflowAncestorClipLayer =
      needsOverflowControlsHostLayer && needsAncestorClip;
  toggleScrollbarLayerIfNeeded(m_overflowControlsAncestorClippingLayer,
                               needsOverflowAncestorClipLayer,
                               CompositingReasonLayerForOverflowControlsHost);

  return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged ||
         scrollCornerLayerChanged;
}

void CompositedLayerMapping::positionOverflowControlsLayers() {
  if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
    Scrollbar* hBar = m_owningLayer.getScrollableArea()->horizontalScrollbar();
    if (hBar) {
      layer->setPosition(hBar->frameRect().location());
      layer->setSize(FloatSize(hBar->frameRect().size()));
      if (layer->hasContentsLayer())
        layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
    }
    layer->setDrawsContent(hBar && !layer->hasContentsLayer());
  }

  if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
    Scrollbar* vBar = m_owningLayer.getScrollableArea()->verticalScrollbar();
    if (vBar) {
      layer->setPosition(vBar->frameRect().location());
      layer->setSize(FloatSize(vBar->frameRect().size()));
      if (layer->hasContentsLayer())
        layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
    }
    layer->setDrawsContent(vBar && !layer->hasContentsLayer());
  }

  if (GraphicsLayer* layer = layerForScrollCorner()) {
    const IntRect& scrollCornerAndResizer =
        m_owningLayer.getScrollableArea()->scrollCornerAndResizerRect();
    layer->setPosition(FloatPoint(scrollCornerAndResizer.location()));
    layer->setSize(FloatSize(scrollCornerAndResizer.size()));
    layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
  }
}

enum ApplyToGraphicsLayersModeFlags {
  ApplyToLayersAffectedByPreserve3D = (1 << 0),
  ApplyToSquashingLayer = (1 << 1),
  ApplyToScrollbarLayers = (1 << 2),
  ApplyToBackgroundLayer = (1 << 3),
  ApplyToMaskLayers = (1 << 4),
  ApplyToContentLayers = (1 << 5),
  ApplyToChildContainingLayers =
      (1 << 6),  // layers between m_graphicsLayer and children
  ApplyToNonScrollingContentLayers = (1 << 7),
  ApplyToScrollingContentLayers = (1 << 8),
  ApplyToDecorationOutlineLayer = (1 << 9),
  ApplyToAllGraphicsLayers =
      (ApplyToSquashingLayer | ApplyToScrollbarLayers | ApplyToBackgroundLayer |
       ApplyToMaskLayers |
       ApplyToLayersAffectedByPreserve3D |
       ApplyToContentLayers |
       ApplyToScrollingContentLayers |
       ApplyToDecorationOutlineLayer)
};
typedef unsigned ApplyToGraphicsLayersMode;

template <typename Func>
static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping,
                                  const Func& f,
                                  ApplyToGraphicsLayersMode mode) {
  ASSERT(mode);

  if ((mode & ApplyToLayersAffectedByPreserve3D) &&
      mapping->childTransformLayer())
    f(mapping->childTransformLayer());
  if (((mode & ApplyToLayersAffectedByPreserve3D) ||
       (mode & ApplyToContentLayers) ||
       (mode & ApplyToNonScrollingContentLayers)) &&
      mapping->mainGraphicsLayer())
    f(mapping->mainGraphicsLayer());
  if (((mode & ApplyToLayersAffectedByPreserve3D) ||
       (mode & ApplyToChildContainingLayers)) &&
      mapping->clippingLayer())
    f(mapping->clippingLayer());
  if (((mode & ApplyToLayersAffectedByPreserve3D) ||
       (mode & ApplyToChildContainingLayers)) &&
      mapping->scrollingLayer())
    f(mapping->scrollingLayer());
  if (((mode & ApplyToLayersAffectedByPreserve3D) ||
       (mode & ApplyToContentLayers) || (mode & ApplyToChildContainingLayers) ||
       (mode & ApplyToScrollingContentLayers)) &&
      mapping->scrollingContentsLayer())
    f(mapping->scrollingContentsLayer());
  if (((mode & ApplyToLayersAffectedByPreserve3D) ||
       (mode & ApplyToContentLayers) ||
       (mode & ApplyToScrollingContentLayers)) &&
      mapping->foregroundLayer())
    f(mapping->foregroundLayer());

  if ((mode & ApplyToChildContainingLayers) && mapping->childTransformLayer())
    f(mapping->childTransformLayer());

  if ((mode & ApplyToSquashingLayer) && mapping->squashingLayer())
    f(mapping->squashingLayer());

  if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers) ||
       (mode & ApplyToNonScrollingContentLayers)) &&
      mapping->maskLayer())
    f(mapping->maskLayer());
  if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers) ||
       (mode & ApplyToNonScrollingContentLayers)) &&
      mapping->childClippingMaskLayer())
    f(mapping->childClippingMaskLayer());

  if (((mode & ApplyToBackgroundLayer) || (mode & ApplyToContentLayers) ||
       (mode & ApplyToNonScrollingContentLayers)) &&
      mapping->backgroundLayer())
    f(mapping->backgroundLayer());

  if ((mode & ApplyToScrollbarLayers) && mapping->layerForHorizontalScrollbar())
    f(mapping->layerForHorizontalScrollbar());
  if ((mode & ApplyToScrollbarLayers) && mapping->layerForVerticalScrollbar())
    f(mapping->layerForVerticalScrollbar());
  if ((mode & ApplyToScrollbarLayers) && mapping->layerForScrollCorner())
    f(mapping->layerForScrollCorner());

  if (((mode & ApplyToDecorationOutlineLayer) ||
       (mode & ApplyToNonScrollingContentLayers)) &&
      mapping->decorationOutlineLayer())
    f(mapping->decorationOutlineLayer());
}

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

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 WebLayer now; it may not have one yet. We could do
  // a second past 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 = m_owningLayer.renderingContextRoot()) {
    if (Node* node = root->layoutObject()->node())
      id = static_cast<int>(PtrHash<Node>::hash(node));
  }

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

struct UpdateShouldFlattenTransformFunctor {
  void operator()(GraphicsLayer* layer) const {
    layer->setShouldFlattenTransform(shouldFlatten);
  }
  bool shouldFlatten;
};

void CompositedLayerMapping::updateShouldFlattenTransform() {
  // All CLM-managed layers that could affect a descendant layer should update
  // their should-flatten-transform value (the other layers' transforms don't
  // matter here).
  UpdateShouldFlattenTransformFunctor functor = {
      !m_owningLayer.shouldPreserve3D()};
  ApplyToGraphicsLayersMode mode = ApplyToLayersAffectedByPreserve3D;
  ApplyToGraphicsLayers(this, functor, mode);

  // Note, if we apply perspective, we have to set should flatten differently
  // so that the transform propagates to child layers correctly.
  if (hasChildTransformLayer()) {
    ApplyToGraphicsLayers(
        this,
        [](GraphicsLayer* layer) { layer->setShouldFlattenTransform(false); },
        ApplyToChildContainingLayers);
  }

  // Regardless, mark the graphics layer, scrolling layer and scrolling block
  // selection layer (if they exist) as not flattening. Having them flatten
  // causes unclipped render surfaces which cause bugs.
  // http://crbug.com/521768
  if (hasScrollingLayer()) {
    m_graphicsLayer->setShouldFlattenTransform(false);
    m_scrollingLayer->setShouldFlattenTransform(false);
  }
}

// Some background on when you receive an element id or mutable properties.
//
// element id:
//   If you have a compositor proxy, an animation, or you're a scroller (and
//   might impl animate).
//
// mutable properties:
//   Only if you have a compositor proxy.
//
// 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 as
// well as the mutable properties for all layers may change according to the
// rules above so we update those values here.
void CompositedLayerMapping::updateElementIdAndCompositorMutableProperties() {
  int elementId = 0;
  uint32_t primaryMutableProperties = CompositorMutableProperty::kNone;
  uint32_t scrollMutableProperties = CompositorMutableProperty::kNone;

  Node* owningNode = m_owningLayer.layoutObject()->node();
  Element* animatingElement = nullptr;
  const ComputedStyle* animatingStyle = nullptr;
  if (owningNode) {
    Document& document = owningNode->document();
    Element* scrollingElement = document.scrollingElement();
    if (owningNode->isElementNode() &&
        (!RuntimeEnabledFeatures::rootLayerScrollingEnabled() ||
         owningNode != scrollingElement)) {
      animatingElement = toElement(owningNode);
      animatingStyle = m_owningLayer.layoutObject()->style();
    } else if (owningNode->isDocumentNode() &&
               RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
      owningNode = animatingElement = scrollingElement;
      if (scrollingElement && scrollingElement->layoutObject())
        animatingStyle = scrollingElement->layoutObject()->style();
    }
  }

  if (RuntimeEnabledFeatures::compositorWorkerEnabled() && animatingStyle &&
      animatingStyle->hasCompositorProxy()) {
    uint32_t compositorMutableProperties =
        animatingElement->compositorMutableProperties();
    elementId = DOMNodeIds::idForNode(owningNode);
    primaryMutableProperties = (CompositorMutableProperty::kOpacity |
                                CompositorMutableProperty::kTransform) &
                               compositorMutableProperties;
    scrollMutableProperties = (CompositorMutableProperty::kScrollLeft |
                               CompositorMutableProperty::kScrollTop) &
                              compositorMutableProperties;
  }

  if (animatingStyle && animatingStyle->shouldCompositeForCurrentAnimations())
    elementId = DOMNodeIds::idForNode(owningNode);

  CompositorElementId compositorElementId;
  if (elementId)
    compositorElementId =
        createCompositorElementId(elementId, CompositorSubElementId::Primary);

  m_graphicsLayer->setElementId(compositorElementId);
  m_graphicsLayer->setCompositorMutableProperties(primaryMutableProperties);

  // We always set the elementId for m_scrollingContentsLayer since it can be
  // animated for smooth scrolling, so we don't need to set it conditionally
  // here.
  if (m_scrollingContentsLayer.get())
    m_scrollingContentsLayer->setCompositorMutableProperties(
        scrollMutableProperties);
}

bool CompositedLayerMapping::updateForegroundLayer(bool needsForegroundLayer) {
  bool layerChanged = false;
  if (needsForegroundLayer) {
    if (!m_foregroundLayer) {
      m_foregroundLayer =
          createGraphicsLayer(CompositingReasonLayerForForeground);
      layerChanged = true;
    }
  } else if (m_foregroundLayer) {
    m_foregroundLayer->removeFromParent();
    m_foregroundLayer = nullptr;
    layerChanged = true;
  }

  return layerChanged;
}

bool CompositedLayerMapping::updateBackgroundLayer(bool needsBackgroundLayer) {
  bool layerChanged = false;
  if (needsBackgroundLayer) {
    if (!m_backgroundLayer) {
      m_backgroundLayer =
          createGraphicsLayer(CompositingReasonLayerForBackground);
      m_backgroundLayer->setTransformOrigin(FloatPoint3D());
      m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
      layerChanged = true;
    }
  } else {
    if (m_backgroundLayer) {
      m_backgroundLayer->removeFromParent();
      m_backgroundLayer = nullptr;
      layerChanged = true;
    }
  }

  if (layerChanged && !m_owningLayer.layoutObject()->documentBeingDestroyed())
    compositor()->rootFixedBackgroundsChanged();

  return layerChanged;
}

bool CompositedLayerMapping::updateDecorationOutlineLayer(
    bool needsDecorationOutlineLayer) {
  bool layerChanged = false;
  if (needsDecorationOutlineLayer) {
    if (!m_decorationOutlineLayer) {
      m_decorationOutlineLayer =
          createGraphicsLayer(CompositingReasonLayerForDecoration);
      m_decorationOutlineLayer->setPaintingPhase(GraphicsLayerPaintDecoration);
      layerChanged = true;
    }
  } else if (m_decorationOutlineLayer) {
    m_decorationOutlineLayer = nullptr;
    layerChanged = true;
  }

  return layerChanged;
}

bool CompositedLayerMapping::updateMaskLayer(bool needsMaskLayer) {
  bool layerChanged = false;
  if (needsMaskLayer) {
    if (!m_maskLayer) {
      m_maskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
      m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
      layerChanged = true;
    }
  } else if (m_maskLayer) {
    m_maskLayer = nullptr;
    layerChanged = true;
  }

  return layerChanged;
}

void CompositedLayerMapping::updateChildClippingMaskLayer(
    bool needsChildClippingMaskLayer) {
  if (needsChildClippingMaskLayer) {
    if (!m_childClippingMaskLayer) {
      m_childClippingMaskLayer =
          createGraphicsLayer(CompositingReasonLayerForClippingMask);
      m_childClippingMaskLayer->setPaintingPhase(
          GraphicsLayerPaintChildClippingMask);
    }
    return;
  }
  m_childClippingMaskLayer = nullptr;
}

bool CompositedLayerMapping::updateScrollingLayers(bool needsScrollingLayers) {
  ScrollingCoordinator* scrollingCoordinator =
      scrollingCoordinatorFromLayer(m_owningLayer);

  bool layerChanged = false;
  if (needsScrollingLayers) {
    if (!m_scrollingLayer) {
      // Outer layer which corresponds with the scroll view.
      m_scrollingLayer =
          createGraphicsLayer(CompositingReasonLayerForScrollingContainer);
      m_scrollingLayer->setDrawsContent(false);

      // Inner layer which renders the content that scrolls.
      m_scrollingContentsLayer =
          createGraphicsLayer(CompositingReasonLayerForScrollingContents);

      if (Node* owningNode = m_owningLayer.layoutObject()->node())
        m_scrollingContentsLayer->setElementId(createCompositorElementId(
            DOMNodeIds::idForNode(owningNode), CompositorSubElementId::Scroll));

      m_scrollingLayer->addChild(m_scrollingContentsLayer.get());

      layerChanged = true;
      if (scrollingCoordinator) {
        scrollingCoordinator->scrollableAreaScrollLayerDidChange(
            m_owningLayer.getScrollableArea());
        scrollingCoordinator->scrollableAreasDidChange();
      }
    }

    m_scrollingLayer->setMasksToBounds(
        !m_owningLayer.hasRootScrollerAsDescendant());
  } else if (m_scrollingLayer) {
    m_scrollingLayer = nullptr;
    m_scrollingContentsLayer = nullptr;
    layerChanged = true;
    if (scrollingCoordinator) {
      scrollingCoordinator->scrollableAreaScrollLayerDidChange(
          m_owningLayer.getScrollableArea());
      scrollingCoordinator->scrollableAreasDidChange();
    }
  }

  return layerChanged;
}

static void updateScrollParentForGraphicsLayer(
    GraphicsLayer* layer,
    GraphicsLayer* topmostLayer,
    const PaintLayer* scrollParent,
    ScrollingCoordinator* scrollingCoordinator) {
  if (!layer)
    return;

  // Only the topmost layer has a scroll parent. All other layers have a null
  // scroll parent.
  if (layer != topmostLayer)
    scrollParent = 0;

  scrollingCoordinator->updateScrollParentForGraphicsLayer(layer, scrollParent);
}

void CompositedLayerMapping::updateScrollParent(
    const PaintLayer* scrollParent) {
  if (ScrollingCoordinator* scrollingCoordinator =
          scrollingCoordinatorFromLayer(m_owningLayer)) {
    GraphicsLayer* topmostLayer = childForSuperlayers();
    updateScrollParentForGraphicsLayer(m_squashingContainmentLayer.get(),
                                       topmostLayer, scrollParent,
                                       scrollingCoordinator);
    updateScrollParentForGraphicsLayer(m_ancestorClippingLayer.get(),
                                       topmostLayer, scrollParent,
                                       scrollingCoordinator);
    updateScrollParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer,
                                       scrollParent, scrollingCoordinator);
  }
}

static void updateClipParentForGraphicsLayer(
    GraphicsLayer* layer,
    GraphicsLayer* topmostLayer,
    const PaintLayer* clipParent,
    ScrollingCoordinator* scrollingCoordinator) {
  if (!layer)
    return;

  // Only the topmost layer has a scroll parent. All other layers have a null
  // scroll parent.
  if (layer != topmostLayer)
    clipParent = 0;

  scrollingCoordinator->updateClipParentForGraphicsLayer(layer, clipParent);
}

void CompositedLayerMapping::updateClipParent(const PaintLayer* scrollParent) {
  const PaintLayer* clipParent = nullptr;
  if (!owningLayerClippedByLayerNotAboveCompositedAncestor(scrollParent)) {
    clipParent = m_owningLayer.clipParent();
    if (clipParent)
      clipParent =
          clipParent->enclosingLayerWithCompositedLayerMapping(IncludeSelf);
  }

  if (ScrollingCoordinator* scrollingCoordinator =
          scrollingCoordinatorFromLayer(m_owningLayer)) {
    GraphicsLayer* topmostLayer = childForSuperlayers();
    updateClipParentForGraphicsLayer(m_squashingContainmentLayer.get(),
                                     topmostLayer, clipParent,
                                     scrollingCoordinator);
    updateClipParentForGraphicsLayer(m_ancestorClippingLayer.get(),
                                     topmostLayer, clipParent,
                                     scrollingCoordinator);
    updateClipParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer,
                                     clipParent, scrollingCoordinator);
  }
}

bool CompositedLayerMapping::updateSquashingLayers(bool needsSquashingLayers) {
  bool layersChanged = false;

  if (needsSquashingLayers) {
    if (!m_squashingLayer) {
      m_squashingLayer =
          createGraphicsLayer(CompositingReasonLayerForSquashingContents);
      m_squashingLayer->setDrawsContent(true);
      layersChanged = true;
    }

    if (m_ancestorClippingLayer) {
      if (m_squashingContainmentLayer) {
        m_squashingContainmentLayer->removeFromParent();
        m_squashingContainmentLayer = nullptr;
        layersChanged = true;
      }
    } else {
      if (!m_squashingContainmentLayer) {
        m_squashingContainmentLayer =
            createGraphicsLayer(CompositingReasonLayerForSquashingContainer);
        m_squashingContainmentLayer->setShouldFlattenTransform(false);
        layersChanged = true;
      }
    }

    ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) ||
           (!m_ancestorClippingLayer && m_squashingContainmentLayer));
    ASSERT(m_squashingLayer);
  } else {
    if (m_squashingLayer) {
      m_squashingLayer->removeFromParent();
      m_squashingLayer = nullptr;
      layersChanged = true;
    }
    if (m_squashingContainmentLayer) {
      m_squashingContainmentLayer->removeFromParent();
      m_squashingContainmentLayer = nullptr;
      layersChanged = true;
    }
    ASSERT(!m_squashingLayer && !m_squashingContainmentLayer);
  }

  return layersChanged;
}

GraphicsLayerPaintingPhase
CompositedLayerMapping::paintingPhaseForPrimaryLayer() const {
  unsigned phase = 0;
  if (!m_backgroundLayer)
    phase |= GraphicsLayerPaintBackground;
  if (!m_foregroundLayer)
    phase |= GraphicsLayerPaintForeground;
  if (!m_maskLayer)
    phase |= GraphicsLayerPaintMask;
  if (!m_decorationOutlineLayer)
    phase |= GraphicsLayerPaintDecoration;

  if (m_scrollingContentsLayer) {
    phase &= ~GraphicsLayerPaintForeground;
    phase |= GraphicsLayerPaintCompositedScroll;
  }

  return static_cast<GraphicsLayerPaintingPhase>(phase);
}

float CompositedLayerMapping::compositingOpacity(
    float layoutObjectOpacity) const {
  float finalOpacity = layoutObjectOpacity;

  for (PaintLayer* curr = m_owningLayer.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->compositingState() == PaintsIntoOwnBacking)
      break;

    finalOpacity *= curr->layoutObject()->opacity();
  }

  return finalOpacity;
}

Color CompositedLayerMapping::layoutObjectBackgroundColor() const {
  return layoutObject()->resolveColor(CSSPropertyBackgroundColor);
}

void CompositedLayerMapping::updateBackgroundColor() {
  m_graphicsLayer->setBackgroundColor(layoutObjectBackgroundColor());
}

bool CompositedLayerMapping::paintsChildren() const {
  if (m_owningLayer.hasVisibleContent() &&
      m_owningLayer.hasNonEmptyChildLayoutObjects())
    return true;

  if (hasVisibleNonCompositingDescendant(&m_owningLayer))
    return true;

  return false;
}

static bool isCompositedPlugin(LayoutObject* layoutObject) {
  return layoutObject->isEmbeddedObject() &&
         toLayoutEmbeddedObject(layoutObject)->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 ENABLE(ASSERT)
  LayerListMutationDetector mutationChecker(parent->stackingNode());
#endif

  PaintLayerStackingNodeIterator normalFlowIterator(*parent->stackingNode(),
                                                    AllChildren);
  while (PaintLayerStackingNode* curNode = normalFlowIterator.next()) {
    PaintLayer* curLayer = curNode->layer();
    if (curLayer->hasCompositedLayerMapping())
      continue;
    if (curLayer->hasVisibleContent() ||
        hasVisibleNonCompositingDescendant(curLayer))
      return true;
  }

  return false;
}

bool CompositedLayerMapping::containsPaintedContent() const {
  if (layoutObject()->isImage() && isDirectlyCompositedImage())
    return false;

  LayoutObject* layoutObject = this->layoutObject();
  // 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 (layoutObject->isVideo() &&
      toLayoutVideo(layoutObject)->shouldDisplayVideo())
    return m_owningLayer.hasBoxDecorationsOrBackground();

  if (m_owningLayer.hasVisibleBoxDecorations())
    return true;

  if (layoutObject->hasMask())  // masks require special treatment
    return true;

  if (layoutObject->isAtomicInlineLevel() && !isCompositedPlugin(layoutObject))
    return true;

  if (layoutObject->isLayoutMultiColumnSet())
    return true;

  if (layoutObject->node() && layoutObject->node()->isDocumentNode()) {
    // Look to see if the root object has a non-simple background
    LayoutObject* rootObject =
        layoutObject->document().documentElement()
            ? layoutObject->document().documentElement()->layoutObject()
            : 0;
    // Reject anything that has a border, a border-radius or outline,
    // or is not a simple background (no background, or solid color).
    if (rootObject &&
        hasBoxDecorationsOrBackgroundImage(rootObject->styleRef()))
      return true;

    // Now look at the body's layoutObject.
    HTMLElement* body = layoutObject->document().body();
    LayoutObject* bodyObject =
        isHTMLBodyElement(body) ? body->layoutObject() : 0;
    if (bodyObject &&
        hasBoxDecorationsOrBackgroundImage(bodyObject->styleRef()))
      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 {
  ASSERT(layoutObject()->isImage());
  LayoutImage* imageLayoutObject = toLayoutImage(layoutObject());

  if (m_owningLayer.hasBoxDecorationsOrBackground() ||
      imageLayoutObject->hasClip() || imageLayoutObject->hasClipPath() ||
      imageLayoutObject->hasObjectFit())
    return false;

  if (ImageResourceContent* cachedImage = imageLayoutObject->cachedImage()) {
    if (!cachedImage->hasImage())
      return false;

    Image* image = cachedImage->getImage();
    if (!image->isBitmapImage())
      return false;

    return true;
  }

  return false;
}

void CompositedLayerMapping::contentChanged(ContentChangeType changeType) {
  if ((changeType == ImageChanged) && layoutObject()->isImage() &&
      isDirectlyCompositedImage()) {
    updateImageContents();
    return;
  }

  if (changeType == CanvasChanged && isAcceleratedCanvas(layoutObject())) {
    m_graphicsLayer->setContentsNeedsDisplay();
    return;
  }
}

void CompositedLayerMapping::updateImageContents() {
  ASSERT(layoutObject()->isImage());
  LayoutImage* imageLayoutObject = toLayoutImage(layoutObject());

  ImageResourceContent* cachedImage = imageLayoutObject->cachedImage();
  if (!cachedImage)
    return;

  Image* image = cachedImage->getImage();
  if (!image)
    return;

  // This is a no-op if the layer doesn't have an inner layer for the image.
  m_graphicsLayer->setContentsToImage(
      image, LayoutObject::shouldRespectImageOrientation(imageLayoutObject));

  m_graphicsLayer->setFilterQuality(layoutObject()->style()->imageRendering() ==
                                            ImageRenderingPixelated
                                        ? 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& borderBox) const {
  const ComputedStyle& style = layoutObject()->styleRef();

  FloatPoint3D origin;
  origin.setX(floatValueForLength(style.transformOriginX(), borderBox.width()));
  origin.setY(
      floatValueForLength(style.transformOriginY(), borderBox.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 {
  ASSERT(!m_contentOffsetInCompositingLayerDirty);
  return m_contentOffsetInCompositingLayer;
}

LayoutRect CompositedLayerMapping::contentsBox() const {
  LayoutRect contentsBox = LayoutRect(contentsRect(layoutObject()));
  contentsBox.move(contentOffsetInCompositingLayer());
  return contentsBox;
}

bool CompositedLayerMapping::needsToReparentOverflowControls() const {
  return m_owningLayer.getScrollableArea() &&
         m_owningLayer.getScrollableArea()->hasOverlayScrollbars() &&
         m_owningLayer.getScrollableArea()->topmostScrollChild();
}

GraphicsLayer* CompositedLayerMapping::detachLayerForOverflowControls(
    const PaintLayer& enclosingLayer) {
  GraphicsLayer* host = m_overflowControlsAncestorClippingLayer.get();
  if (!host)
    host = m_overflowControlsHostLayer.get();
  host->removeFromParent();
  return host;
}

GraphicsLayer* CompositedLayerMapping::parentForSublayers() const {
  if (m_scrollingContentsLayer)
    return m_scrollingContentsLayer.get();

  if (m_childContainmentLayer)
    return m_childContainmentLayer.get();

  if (m_childTransformLayer)
    return m_childTransformLayer.get();

  return m_graphicsLayer.get();
}

void CompositedLayerMapping::setSublayers(
    const GraphicsLayerVector& sublayers) {
  GraphicsLayer* overflowControlsContainer =
      m_overflowControlsAncestorClippingLayer
          ? m_overflowControlsAncestorClippingLayer.get()
          : m_overflowControlsHostLayer.get();
  GraphicsLayer* parent = parentForSublayers();
  bool needsOverflowControlsReattached =
      overflowControlsContainer &&
      overflowControlsContainer->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 (needsOverflowControlsReattached)
    parent->addChild(overflowControlsContainer);
}

GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const {
  if (m_squashingContainmentLayer)
    return m_squashingContainmentLayer.get();

  if (m_ancestorClippingLayer)
    return m_ancestorClippingLayer.get();

  return m_graphicsLayer.get();
}

void CompositedLayerMapping::setBlendMode(WebBlendMode blendMode) {
  if (m_ancestorClippingLayer) {
    m_ancestorClippingLayer->setBlendMode(blendMode);
    m_graphicsLayer->setBlendMode(WebBlendModeNormal);
  } else {
    m_graphicsLayer->setBlendMode(blendMode);
  }
}

GraphicsLayerUpdater::UpdateType CompositedLayerMapping::updateTypeForChildren(
    GraphicsLayerUpdater::UpdateType updateType) const {
  if (m_pendingUpdateScope >= GraphicsLayerUpdateSubtree)
    return GraphicsLayerUpdater::ForceUpdate;
  return updateType;
}

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

void CompositedLayerMapping::setSquashingContentsNeedDisplay() {
  ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(),
                        ApplyToSquashingLayer);
}

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

struct SetContentsNeedsDisplayInRectFunctor {
  void operator()(GraphicsLayer* layer) const {
    if (layer->drawsContent()) {
      IntRect layerDirtyRect = r;
      layerDirtyRect.move(-layer->offsetFromLayoutObject());
      layer->setNeedsDisplayInRect(layerDirtyRect, invalidationReason, client);
    }
  }

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

void CompositedLayerMapping::setContentsNeedDisplayInRect(
    const LayoutRect& r,
    PaintInvalidationReason invalidationReason,
    const DisplayItemClient& client) {
  DCHECK(!m_owningLayer.layoutObject()->usesCompositedScrolling());
  // TODO(wangxianzhu): Enable the following assert after paint invalidation for
  // spv2 is ready.
  // ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled());

  SetContentsNeedsDisplayInRectFunctor functor = {
      enclosingIntRect(LayoutRect(
          r.location() + m_owningLayer.subpixelAccumulation(), r.size())),
      invalidationReason, client};
  ApplyToGraphicsLayers(this, functor, ApplyToContentLayers);
}

void CompositedLayerMapping::setNonScrollingContentsNeedDisplayInRect(
    const LayoutRect& r,
    PaintInvalidationReason invalidationReason,
    const DisplayItemClient& client) {
  DCHECK(m_owningLayer.layoutObject()->usesCompositedScrolling());
  // TODO(wangxianzhu): Enable the following assert after paint invalidation for
  // spv2 is ready.
  // ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled());

  SetContentsNeedsDisplayInRectFunctor functor = {
      enclosingIntRect(LayoutRect(
          r.location() + m_owningLayer.subpixelAccumulation(), r.size())),
      invalidationReason, client};
  ApplyToGraphicsLayers(this, functor, ApplyToNonScrollingContentLayers);
}

void CompositedLayerMapping::setScrollingContentsNeedDisplayInRect(
    const LayoutRect& r,
    PaintInvalidationReason invalidationReason,
    const DisplayItemClient& client) {
  DCHECK(m_owningLayer.layoutObject()->usesCompositedScrolling());
  // TODO(wangxianzhu): Enable the following assert after paint invalidation for
  // spv2 is ready.
  // ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled());

  SetContentsNeedsDisplayInRectFunctor functor = {
      enclosingIntRect(LayoutRect(
          r.location() + m_owningLayer.subpixelAccumulation(), r.size())),
      invalidationReason, client};
  ApplyToGraphicsLayers(this, functor, ApplyToScrollingContentLayers);
}

const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(
    const LayoutObject* layoutObject,
    const Vector<GraphicsLayerPaintInfo>& layers,
    unsigned maxSquashedLayerIndex) {
  if (!layoutObject)
    return nullptr;
  for (size_t i = 0; i < layers.size() && i < maxSquashedLayerIndex; ++i) {
    if (layoutObject->isDescendantOf(layers[i].paintLayer->layoutObject()))
      return &layers[i];
  }
  return nullptr;
}

const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(
    const LayoutObject* layoutObject,
    unsigned maxSquashedLayerIndex) {
  return CompositedLayerMapping::containingSquashedLayer(
      layoutObject, m_squashedLayers, maxSquashedLayerIndex);
}

IntRect CompositedLayerMapping::localClipRectForSquashedLayer(
    const PaintLayer& referenceLayer,
    const GraphicsLayerPaintInfo& paintInfo,
    const Vector<GraphicsLayerPaintInfo>& layers) {
  const LayoutObject* clippingContainer =
      paintInfo.paintLayer->clippingContainer();
  if (clippingContainer == referenceLayer.clippingContainer())
    return LayoutRect::infiniteIntRect();

  ASSERT(clippingContainer);

  const GraphicsLayerPaintInfo* ancestorPaintInfo =
      containingSquashedLayer(clippingContainer, layers, layers.size());
  // Must be there, otherwise
  // CompositingLayerAssigner::canSquashIntoCurrentSquashingOwner would have
  // disallowed squashing.
  ASSERT(ancestorPaintInfo);

  // FIXME: this is a potential performance issue. We should consider caching
  // these clip rects or otherwise optimizing.
  ClipRectsContext clipRectsContext(ancestorPaintInfo->paintLayer,
                                    UncachedClipRects);
  IntRect parentClipRect =
      pixelSnappedIntRect(paintInfo.paintLayer->clipper()
                              .backgroundClipRect(clipRectsContext)
                              .rect());
  ASSERT(parentClipRect != LayoutRect::infiniteIntRect());

  // Convert from ancestor to local coordinates.
  IntSize ancestorToLocalOffset = paintInfo.offsetFromLayoutObject -
                                  ancestorPaintInfo->offsetFromLayoutObject;
  parentClipRect.move(ancestorToLocalOffset);
  return parentClipRect;
}

void CompositedLayerMapping::doPaintTask(
    const GraphicsLayerPaintInfo& paintInfo,
    const GraphicsLayer& graphicsLayer,
    const PaintLayerFlags& paintLayerFlags,
    GraphicsContext& context,
    const IntRect& clip /* In the coords of rootLayer */) const {
  FontCachePurgePreventer fontCachePurgePreventer;

  IntSize offset = paintInfo.offsetFromLayoutObject;
  AffineTransform translation;
  translation.translate(-offset.width(), -offset.height());
  TransformRecorder transformRecorder(context, graphicsLayer, translation);

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

  if (!(paintLayerFlags & PaintLayerPaintingOverflowContents)) {
    LayoutRect bounds = paintInfo.compositedBounds;
    bounds.move(paintInfo.paintLayer->subpixelAccumulation());
    dirtyRect.intersect(pixelSnappedIntRect(bounds));
  } else {
    dirtyRect.move(
        roundedIntSize(paintInfo.paintLayer->subpixelAccumulation()));
  }

#if DCHECK_IS_ON()
  if (!layoutObject()->view()->frame() ||
      !layoutObject()->view()->frame()->shouldThrottleRendering())
    paintInfo.paintLayer->layoutObject()->assertSubtreeIsLaidOut();
#endif

  float deviceScaleFactor =
      blink::deviceScaleFactor(paintInfo.paintLayer->layoutObject()->frame());
  context.setDeviceScaleFactor(deviceScaleFactor);

  if (paintInfo.paintLayer->compositingState() != PaintsIntoGroupedBacking) {
    // FIXME: GraphicsLayers need a way to split for multicol.
    PaintLayerPaintingInfo paintingInfo(
        paintInfo.paintLayer, LayoutRect(dirtyRect), GlobalPaintNormalPhase,
        paintInfo.paintLayer->subpixelAccumulation());
    PaintLayerPainter(*paintInfo.paintLayer)
        .paintLayerContents(context, paintingInfo, paintLayerFlags);

    if (paintInfo.paintLayer->containsDirtyOverlayScrollbars())
      PaintLayerPainter(*paintInfo.paintLayer)
          .paintLayerContents(
              context, paintingInfo,
              paintLayerFlags | PaintLayerPaintingOverlayScrollbars);
  } else {
    PaintLayerPaintingInfo paintingInfo(
        paintInfo.paintLayer, LayoutRect(dirtyRect), GlobalPaintNormalPhase,
        paintInfo.paintLayer->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?
    // FIXME: Combine similar code here and LayerClipRecorder.
    dirtyRect.intersect(paintInfo.localClipRectForSquashedLayer);
    context.getPaintController().createAndAppend<ClipDisplayItem>(
        graphicsLayer, DisplayItem::kClipLayerOverflowControls, dirtyRect);

    PaintLayerPainter(*paintInfo.paintLayer)
        .paintLayer(context, paintingInfo, paintLayerFlags);
    context.getPaintController().endItem<EndClipDisplayItem>(
        graphicsLayer, DisplayItem::clipTypeToEndClipType(
                           DisplayItem::kClipLayerOverflowControls));
  }
}

static void paintScrollbar(const Scrollbar* scrollbar,
                           GraphicsContext& context,
                           const IntRect& clip) {
  if (!scrollbar)
    return;

  const IntRect& scrollbarRect = scrollbar->frameRect();
  TransformRecorder transformRecorder(
      context, *scrollbar,
      AffineTransform::translation(-scrollbarRect.x(), -scrollbarRect.y()));
  IntRect transformedClip = clip;
  transformedClip.moveBy(scrollbarRect.location());
  scrollbar->paint(context, CullRect(transformedClip));
}

// 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* graphicsLayer) const {
  FloatRect graphicsLayerBounds(FloatPoint(), graphicsLayer->size());

  IntSize offsetFromAnchorLayoutObject;
  const LayoutBoxModelObject* anchorLayoutObject;
  if (graphicsLayer == m_squashingLayer.get()) {
    // TODO(chrishtr): this is a speculative fix for crbug.com/561306. However,
    // it should never be the case that m_squashingLayer exists,
    // yet m_squashedLayers.size() == 0. There must be a bug elsewhere.
    if (m_squashedLayers.size() == 0)
      return IntRect();
    // 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.
    anchorLayoutObject = m_squashedLayers[0].paintLayer->layoutObject();
    offsetFromAnchorLayoutObject = m_squashedLayers[0].offsetFromLayoutObject;
  } else {
    ASSERT(graphicsLayer == m_graphicsLayer.get() ||
           graphicsLayer == m_scrollingContentsLayer.get());
    anchorLayoutObject = m_owningLayer.layoutObject();
    offsetFromAnchorLayoutObject = graphicsLayer->offsetFromLayoutObject();
    adjustForCompositedScrolling(graphicsLayer, offsetFromAnchorLayoutObject);
  }

  // Start with the bounds of the graphics layer in the space of the anchor
  // LayoutObject.
  FloatRect graphicsLayerBoundsInObjectSpace(graphicsLayerBounds);
  graphicsLayerBoundsInObjectSpace.move(offsetFromAnchorLayoutObject);

  // Now map the bounds to its visible content rect in root view space,
  // including applying clips along the way.
  LayoutRect graphicsLayerBoundsInRootViewSpace(
      graphicsLayerBoundsInObjectSpace);
  LayoutView* rootView = anchorLayoutObject->view();
  while (!rootView->frame()->ownerLayoutItem().isNull())
    rootView =
        LayoutAPIShim::layoutObjectFrom(rootView->frame()->ownerLayoutItem())
            ->view();
  anchorLayoutObject->mapToVisualRectInAncestorSpace(
      rootView, graphicsLayerBoundsInRootViewSpace);
  FloatRect visibleContentRect(graphicsLayerBoundsInRootViewSpace);
  rootView->frameView()->clipPaintRect(&visibleContentRect);

  IntRect enclosingGraphicsLayerBounds(enclosingIntRect(graphicsLayerBounds));

  // Map the visible content rect from root view space to local graphics layer
  // space.
  IntRect localInterestRect;
  // If the visible content rect is empty, then it makes no sense to map it back
  // since there is nothing to map.
  if (!visibleContentRect.isEmpty()) {
    localInterestRect =
        anchorLayoutObject
            ->absoluteToLocalQuad(visibleContentRect,
                                  UseTransforms | TraverseDocumentBoundaries)
            .enclosingBoundingBox();
    localInterestRect.move(-offsetFromAnchorLayoutObject);
    // 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.
    localInterestRect.intersect(enclosingGraphicsLayerBounds);
  }
  // Expand by interest rect padding amount.
  localInterestRect.inflate(kPixelDistanceToRecord);
  localInterestRect.intersect(enclosingGraphicsLayerBounds);
  return localInterestRect;
}

static const int kMinimumDistanceBeforeRepaint = 512;

bool CompositedLayerMapping::interestRectChangedEnoughToRepaint(
    const IntRect& previousInterestRect,
    const IntRect& newInterestRect,
    const IntSize& layerSize) {
  if (previousInterestRect.isEmpty() && newInterestRect.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 (previousInterestRect.isEmpty())
    return true;

  // Repaint if the new interest rect includes area outside of a skirt around
  // the existing interest rect.
  IntRect expandedPreviousInterestRect(previousInterestRect);
  expandedPreviousInterestRect.inflate(kMinimumDistanceBeforeRepaint);
  if (!expandedPreviousInterestRect.contains(newInterestRect))
    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 (newInterestRect.x() == 0 && previousInterestRect.x() != 0)
    return true;
  if (newInterestRect.y() == 0 && previousInterestRect.y() != 0)
    return true;
  if (newInterestRect.maxX() == layerSize.width() &&
      previousInterestRect.maxX() != layerSize.width())
    return true;
  if (newInterestRect.maxY() == layerSize.height() &&
      previousInterestRect.maxY() != layerSize.height())
    return true;

  return false;
}

IntRect CompositedLayerMapping::computeInterestRect(
    const GraphicsLayer* graphicsLayer,
    const IntRect& previousInterestRect) const {
  // Use the previous interest rect if it covers the whole layer.
  IntRect wholeLayerRect =
      IntRect(IntPoint(), expandedIntSize(graphicsLayer->size()));
  if (!needsRepaint(*graphicsLayer) && previousInterestRect == wholeLayerRect)
    return previousInterestRect;

  if (graphicsLayer != m_graphicsLayer.get() &&
      graphicsLayer != m_squashingLayer.get() &&
      graphicsLayer != m_scrollingContentsLayer.get())
    return wholeLayerRect;

  IntRect newInterestRect = recomputeInterestRect(graphicsLayer);
  if (needsRepaint(*graphicsLayer) ||
      interestRectChangedEnoughToRepaint(
          previousInterestRect, newInterestRect,
          expandedIntSize(graphicsLayer->size())))
    return newInterestRect;
  return previousInterestRect;
}

LayoutSize CompositedLayerMapping::subpixelAccumulation() const {
  return m_owningLayer.subpixelAccumulation();
}

bool CompositedLayerMapping::needsRepaint(
    const GraphicsLayer& graphicsLayer) const {
  return isScrollableAreaLayer(&graphicsLayer) ? true
                                               : m_owningLayer.needsRepaint();
}

void CompositedLayerMapping::adjustForCompositedScrolling(
    const GraphicsLayer* graphicsLayer,
    IntSize& offset) const {
  if (graphicsLayer == m_scrollingContentsLayer.get() ||
      graphicsLayer == m_foregroundLayer.get()) {
    if (PaintLayerScrollableArea* scrollableArea =
            m_owningLayer.getScrollableArea()) {
      if (scrollableArea->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 scrollOffset = scrollableArea->getScrollOffset();
        offset.expand(-scrollOffset.width(), -scrollOffset.height());
      }
    }
  }
}

void CompositedLayerMapping::paintContents(
    const GraphicsLayer* graphicsLayer,
    GraphicsContext& context,
    GraphicsLayerPaintingPhase graphicsLayerPaintingPhase,
    const IntRect& interestRect) const {
  // https://code.google.com/p/chromium/issues/detail?id=343772
  DisableCompositingQueryAsserts disabler;
  // Allow throttling to make sure no painting paths (e.g.,
  // ContentLayerDelegate::paintContents) try to paint throttled content.
  DocumentLifecycle::AllowThrottlingScope allowThrottling(
      m_owningLayer.layoutObject()->document().lifecycle());
#if ENABLE(ASSERT)
  // FIXME: once the state machine is ready, this can be removed and we can
  // refer to that instead.
  if (Page* page = layoutObject()->frame()->page())
    page->setIsPainting(true);
#endif

  TRACE_EVENT1(
      "devtools.timeline,rail", "Paint", "data",
      InspectorPaintEvent::data(m_owningLayer.layoutObject(),
                                LayoutRect(interestRect), graphicsLayer));

  PaintLayerFlags paintLayerFlags = 0;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintBackground)
    paintLayerFlags |= PaintLayerPaintingCompositingBackgroundPhase;
  else
    paintLayerFlags |= PaintLayerPaintingSkipRootBackground;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintForeground)
    paintLayerFlags |= PaintLayerPaintingCompositingForegroundPhase;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintMask)
    paintLayerFlags |= PaintLayerPaintingCompositingMaskPhase;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintChildClippingMask)
    paintLayerFlags |= PaintLayerPaintingChildClippingMaskPhase;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintOverflowContents)
    paintLayerFlags |= PaintLayerPaintingOverflowContents;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintCompositedScroll)
    paintLayerFlags |= PaintLayerPaintingCompositingScrollingPhase;
  if (graphicsLayerPaintingPhase & GraphicsLayerPaintDecoration)
    paintLayerFlags |= PaintLayerPaintingCompositingDecorationPhase;

  if (graphicsLayer == m_backgroundLayer.get())
    paintLayerFlags |= PaintLayerPaintingRootBackgroundOnly;
  else if (compositor()->fixedRootBackgroundLayer() &&
           m_owningLayer.isRootLayer())
    paintLayerFlags |= PaintLayerPaintingSkipRootBackground;

  if (graphicsLayer == m_graphicsLayer.get() ||
      graphicsLayer == m_foregroundLayer.get() ||
      graphicsLayer == m_backgroundLayer.get() ||
      graphicsLayer == m_maskLayer.get() ||
      graphicsLayer == m_childClippingMaskLayer.get() ||
      graphicsLayer == m_scrollingContentsLayer.get() ||
      graphicsLayer == m_decorationOutlineLayer.get()) {
    bool paintRootBackgroundOntoScrollingContentsLayer =
        m_backgroundPaintsOntoScrollingContentsLayer;
    DCHECK(!paintRootBackgroundOntoScrollingContentsLayer ||
           (!m_backgroundLayer && !m_foregroundLayer));
    if (paintRootBackgroundOntoScrollingContentsLayer) {
      if (graphicsLayer == m_scrollingContentsLayer.get())
        paintLayerFlags &= ~PaintLayerPaintingSkipRootBackground;
      else if (!m_backgroundPaintsOntoGraphicsLayer)
        paintLayerFlags |= PaintLayerPaintingSkipRootBackground;
    }
    GraphicsLayerPaintInfo paintInfo;
    paintInfo.paintLayer = &m_owningLayer;
    paintInfo.compositedBounds = compositedBounds();
    paintInfo.offsetFromLayoutObject = graphicsLayer->offsetFromLayoutObject();
    adjustForCompositedScrolling(graphicsLayer,
                                 paintInfo.offsetFromLayoutObject);

    // We have to use the same root as for hit testing, because both methods can
    // compute and cache clipRects.
    doPaintTask(paintInfo, *graphicsLayer, paintLayerFlags, context,
                interestRect);
  } else if (graphicsLayer == m_squashingLayer.get()) {
    for (size_t i = 0; i < m_squashedLayers.size(); ++i)
      doPaintTask(m_squashedLayers[i], *graphicsLayer, paintLayerFlags, context,
                  interestRect);
  } else if (isScrollableAreaLayer(graphicsLayer)) {
    paintScrollableArea(graphicsLayer, context, interestRect);
  }
  InspectorInstrumentation::didPaint(m_owningLayer.layoutObject()->frame(),
                                     graphicsLayer, context,
                                     LayoutRect(interestRect));
#if ENABLE(ASSERT)
  if (Page* page = layoutObject()->frame()->page())
    page->setIsPainting(false);
#endif
}

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

  if (DrawingRecorder::useCachedDrawingIfPossible(
          context, *graphicsLayer, DisplayItem::kScrollbarCompositedScrollbar))
    return;

  FloatRect layerBounds(FloatPoint(), graphicsLayer->size());
  SkPictureBuilder pictureBuilder(layerBounds, nullptr, &context);
  PaintLayerScrollableArea* scrollableArea = m_owningLayer.getScrollableArea();
  if (graphicsLayer == layerForHorizontalScrollbar()) {
    paintScrollbar(scrollableArea->horizontalScrollbar(),
                   pictureBuilder.context(), interestRect);
  } else if (graphicsLayer == layerForVerticalScrollbar()) {
    paintScrollbar(scrollableArea->verticalScrollbar(),
                   pictureBuilder.context(), interestRect);
  } else if (graphicsLayer == layerForScrollCorner()) {
    // Note that scroll corners always paint into local space, whereas
    // scrollbars paint in the space of their containing frame.
    IntPoint scrollCornerAndResizerLocation =
        scrollableArea->scrollCornerAndResizerRect().location();
    CullRect cullRect(enclosingIntRect(interestRect));
    ScrollableAreaPainter(*scrollableArea)
        .paintScrollCorner(pictureBuilder.context(),
                           -scrollCornerAndResizerLocation, cullRect);
    ScrollableAreaPainter(*scrollableArea)
        .paintResizer(pictureBuilder.context(), -scrollCornerAndResizerLocation,
                      cullRect);
  }
  // Replay the painted scrollbar content with the GraphicsLayer backing as the
  // DisplayItemClient in order for the resulting DrawingDisplayItem to produce
  // the correct visualRect (i.e., the bounds of the involved GraphicsLayer).
  DrawingRecorder drawingRecorder(context, *graphicsLayer,
                                  DisplayItem::kScrollbarCompositedScrollbar,
                                  layerBounds);
  pictureBuilder.endRecording()->playback(context.canvas());
}

bool CompositedLayerMapping::isScrollableAreaLayer(
    const GraphicsLayer* graphicsLayer) const {
  return graphicsLayer == layerForHorizontalScrollbar() ||
         graphicsLayer == layerForVerticalScrollbar() ||
         graphicsLayer == layerForScrollCorner();
}

bool CompositedLayerMapping::isTrackingRasterInvalidations() const {
  GraphicsLayerClient* client = compositor();
  return client ? client->isTrackingRasterInvalidations() : false;
}

#if ENABLE(ASSERT)
void CompositedLayerMapping::verifyNotPainting() {
  ASSERT(!layoutObject()->frame()->page() ||
         !layoutObject()->frame()->page()->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* targetElement =
      m_owningLayer.layoutObject()->document().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 (!targetElement)
    return;
  LayoutObject* targetObject = targetElement->layoutObject();
  if (!targetObject)
    return;
  targetObject->enclosingLayer()->setNeedsRepaint();
  // TODO(wkorman): Consider revising the below to invalidate all
  // non-compositing descendants as well.
  targetObject->invalidateDisplayItemClients(PaintInvalidationForTesting);
}

void CompositedLayerMapping::notifyPaint(bool isFirstPaint,
                                         bool textPainted,
                                         bool imagePainted) {
  if (PaintTiming* timing = m_owningLayer.paintTiming())
    timing->notifyPaint(isFirstPaint, textPainted, imagePainted);
}

IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const {
  LayoutRect bounds = m_compositedBounds;
  bounds.move(m_owningLayer.subpixelAccumulation());
  return pixelSnappedIntRect(bounds);
}

bool CompositedLayerMapping::invalidateLayerIfNoPrecedingEntry(
    size_t indexToClear) {
  PaintLayer* layerToRemove = m_squashedLayers[indexToClear].paintLayer;
  size_t previousIndex = 0;
  for (; previousIndex < indexToClear; ++previousIndex) {
    if (m_squashedLayers[previousIndex].paintLayer == layerToRemove)
      break;
  }
  if (previousIndex == indexToClear &&
      layerToRemove->groupedMapping() == this) {
    compositor()->paintInvalidationOnCompositingChange(layerToRemove);
    return true;
  }
  return false;
}

bool CompositedLayerMapping::updateSquashingLayerAssignment(
    PaintLayer* squashedLayer,
    size_t nextSquashedLayerIndex) {
  GraphicsLayerPaintInfo paintInfo;
  paintInfo.paintLayer = squashedLayer;
  // 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 (nextSquashedLayerIndex < m_squashedLayers.size()) {
    if (paintInfo.paintLayer ==
        m_squashedLayers[nextSquashedLayerIndex].paintLayer)
      return false;

    // Must invalidate before adding the squashed layer to the mapping.
    compositor()->paintInvalidationOnCompositingChange(squashedLayer);

    // 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(nextSquashedLayerIndex);

    m_squashedLayers.insert(nextSquashedLayerIndex, paintInfo);
  } else {
    // Must invalidate before adding the squashed layer to the mapping.
    compositor()->paintInvalidationOnCompositingChange(squashedLayer);
    m_squashedLayers.append(paintInfo);
  }
  squashedLayer->setGroupedMapping(
      this, PaintLayer::InvalidateLayerAndRemoveFromMapping);

  return true;
}

void CompositedLayerMapping::removeLayerFromSquashingGraphicsLayer(
    const PaintLayer* layer) {
  size_t layerIndex = 0;
  for (; layerIndex < m_squashedLayers.size(); ++layerIndex) {
    if (m_squashedLayers[layerIndex].paintLayer == layer)
      break;
  }

  // Assert on incorrect mappings between layers and groups
  ASSERT(layerIndex < m_squashedLayers.size());
  if (layerIndex == m_squashedLayers.size())
    return;

  m_squashedLayers.remove(layerIndex);
}

#if ENABLE(ASSERT)
bool CompositedLayerMapping::verifyLayerInSquashingVector(
    const PaintLayer* layer) {
  for (size_t layerIndex = 0; layerIndex < m_squashedLayers.size();
       ++layerIndex) {
    if (m_squashedLayers[layerIndex].paintLayer == layer)
      return true;
  }

  return false;
}
#endif

void CompositedLayerMapping::finishAccumulatingSquashingLayers(
    size_t nextSquashedLayerIndex,
    Vector<PaintLayer*>& layersNeedingPaintInvalidation) {
  if (nextSquashedLayerIndex < m_squashedLayers.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 = nextSquashedLayerIndex; i < m_squashedLayers.size(); ++i) {
      if (invalidateLayerIfNoPrecedingEntry(i))
        m_squashedLayers[i].paintLayer->setGroupedMapping(
            nullptr, PaintLayer::DoNotInvalidateLayerAndRemoveFromMapping);
      layersNeedingPaintInvalidation.append(m_squashedLayers[i].paintLayer);
    }

    m_squashedLayers.remove(nextSquashedLayerIndex,
                            m_squashedLayers.size() - nextSquashedLayerIndex);
  }
}

String CompositedLayerMapping::debugName(
    const GraphicsLayer* graphicsLayer) const {
  String name;
  if (graphicsLayer == m_graphicsLayer.get()) {
    name = m_owningLayer.debugName();
  } else if (graphicsLayer == m_squashingContainmentLayer.get()) {
    name = "Squashing Containment Layer";
  } else if (graphicsLayer == m_squashingLayer.get()) {
    name = "Squashing Layer (first squashed layer: " +
           (m_squashedLayers.size() > 0
                ? m_squashedLayers[0].paintLayer->debugName()
                : "") +
           ")";
  } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
    name = "Ancestor Clipping Layer";
  } else if (graphicsLayer == m_foregroundLayer.get()) {
    name = m_owningLayer.debugName() + " (foreground) Layer";
  } else if (graphicsLayer == m_backgroundLayer.get()) {
    name = m_owningLayer.debugName() + " (background) Layer";
  } else if (graphicsLayer == m_childContainmentLayer.get()) {
    name = "Child Containment Layer";
  } else if (graphicsLayer == m_childTransformLayer.get()) {
    name = "Child Transform Layer";
  } else if (graphicsLayer == m_maskLayer.get()) {
    name = "Mask Layer";
  } else if (graphicsLayer == m_childClippingMaskLayer.get()) {
    name = "Child Clipping Mask Layer";
  } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
    name = "Horizontal Scrollbar Layer";
  } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
    name = "Vertical Scrollbar Layer";
  } else if (graphicsLayer == m_layerForScrollCorner.get()) {
    name = "Scroll Corner Layer";
  } else if (graphicsLayer == m_overflowControlsHostLayer.get()) {
    name = "Overflow Controls Host Layer";
  } else if (graphicsLayer == m_overflowControlsAncestorClippingLayer.get()) {
    name = "Overflow Controls Ancestor Clipping Layer";
  } else if (graphicsLayer == m_scrollingLayer.get()) {
    name = "Scrolling Layer";
  } else if (graphicsLayer == m_scrollingContentsLayer.get()) {
    name = "Scrolling Contents Layer";
  } else if (graphicsLayer == m_decorationOutlineLayer.get()) {
    name = "Decoration Layer";
  } else {
    ASSERT_NOT_REACHED();
  }

  return name;
}

}  // namespace blink
