/*
 * 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/ImageResource.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/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) {
  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.
  bool shouldPaintOntoScrollingContentsLayer =
      m_owningLayer.canPaintBackgroundOntoScrollingContentsLayer() &&
      m_owningLayer.getScrollableArea()->usesCompositedScrolling();
  if (shouldPaintOntoScrollingContentsLayer !=
      backgroundPaintsOntoScrollingContentsLayer()) {
    m_backgroundPaintsOntoScrollingContentsLayer =
        shouldPaintOntoScrollingContentsLayer;
    // If the background is no longer painted onto the scrolling contents layer
    // the scrolling contents layer needs to be updated. If it is going to be
    // painted onto the scrolling contents layer this update will be triggered
    // by LayoutBoxModelObject::setBackingNeedsPaintInvalidationInRect
    if (hasScrollingLayer() && !shouldPaintOntoScrollingContentsLayer)
      m_scrollingContentsLayer->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()));

      // When we 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 (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)->remotePlatformLayer();
      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);
  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()));
  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::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());

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

  if (m_backgroundLayer)
    m_backgroundLayer->setDrawsContent(hasPaintedContent);

  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.
  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),
  ApplyToAllGraphicsLayers =
      (ApplyToSquashingLayer | ApplyToScrollbarLayers | ApplyToBackgroundLayer |
       ApplyToMaskLayers |
       ApplyToLayersAffectedByPreserve3D |
       ApplyToContentLayers |
       ApplyToScrollingContentLayers)
};
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());
}

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::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_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 (ImageResource* 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());

  ImageResource* 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 ENABLE(ASSERT)
  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 (distance = 0).
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->scrollOffset();
        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 (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()) {
    bool paintRootBackgroundOntoScrollingContentsLayer =
        m_backgroundPaintsOntoScrollingContentsLayer;
    DCHECK(!paintRootBackgroundOntoScrollingContentsLayer ||
           (!m_backgroundLayer && !m_foregroundLayer));
    if (paintRootBackgroundOntoScrollingContentsLayer) {
      if (graphicsLayer == m_scrollingContentsLayer.get())
        paintLayerFlags &= ~PaintLayerPaintingSkipRootBackground;
      else
        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 {
    ASSERT_NOT_REACHED();
  }

  return name;
}

}  // namespace blink
