Combine event and touch action regions into a single class
[WebKit-https.git] / Source / WebCore / rendering / RenderLayer.cpp
index ef43440..b2eb23e 100644 (file)
@@ -271,9 +271,11 @@ void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
 RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     : m_isRenderViewLayer(rendererLayerModelObject.isRenderView())
     , m_forcedStackingContext(rendererLayerModelObject.isMedia())
+    , m_zOrderListsDirty(false)
+    , m_normalFlowListDirty(true)
+    , m_hadNegativeZOrderList(false)
     , m_inResizeMode(false)
     , m_scrollDimensionsDirty(true)
-    , m_normalFlowListDirty(true)
     , m_hasSelfPaintingLayerDescendant(false)
     , m_hasSelfPaintingLayerDescendantDirty(false)
     , m_usedTransparency(false)
@@ -285,6 +287,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     , m_visibleDescendantStatusDirty(false)
     , m_hasVisibleDescendant(false)
     , m_registeredScrollableArea(false)
+    , m_isFixedIntersectingViewport(false)
     , m_3DTransformedDescendantStatusDirty(true)
     , m_has3DTransformedDescendant(false)
     , m_hasCompositingDescendant(false)
@@ -292,16 +295,13 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     , m_has3DTransformedAncestor(false)
     , m_indirectCompositingReason(static_cast<unsigned>(IndirectCompositingReason::None))
     , m_viewportConstrainedNotCompositedReason(NoNotCompositedReason)
-#if PLATFORM(IOS)
-    , m_adjustForIOSCaretWhenScrolling(false)
-#endif
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
 #if ENABLE(IOS_TOUCH_EVENTS)
     , m_registeredAsTouchEventListenerForScrolling(false)
 #endif
-    , m_inUserScroll(false)
-    , m_requiresScrollBoundsOriginUpdate(false)
+    , m_adjustForIOSCaretWhenScrolling(false)
 #endif
+    , m_requiresScrollPositionReconciliation(false)
     , m_containsDirtyOverlayScrollbars(false)
     , m_updatingMarqueePosition(false)
 #if !ASSERT_DISABLED
@@ -315,12 +315,10 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
 #endif
     , m_renderer(rendererLayerModelObject)
 {
-    m_isNormalFlowOnly = shouldBeNormalFlowOnly();
-    m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
+    setIsNormalFlowOnly(shouldBeNormalFlowOnly());
+    setIsStackingContext(shouldBeStackingContext());
 
-    // Non-stacking containers should have empty z-order lists. As this is already the case,
-    // there is no need to dirty / recompute these lists.
-    m_zOrderListsDirty = isStackingContext();
+    m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
 
     if (!renderer().firstChild()) {
         m_visibleContentStatusDirty = false;
@@ -372,8 +370,387 @@ RenderLayer::~RenderLayer()
     clearBacking(true);
 
     // Layer and all its children should be removed from the tree before destruction.
-    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(renderer().renderTreeBeingDestroyed() || !m_parent);
-    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(renderer().renderTreeBeingDestroyed() || !m_first);
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(renderer().renderTreeBeingDestroyed() || !parent());
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(renderer().renderTreeBeingDestroyed() || !firstChild());
+}
+
+void RenderLayer::addChild(RenderLayer& child, RenderLayer* beforeChild)
+{
+    RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
+    if (prevSibling) {
+        child.setPreviousSibling(prevSibling);
+        prevSibling->setNextSibling(&child);
+        ASSERT(prevSibling != &child);
+    } else
+        setFirstChild(&child);
+
+    if (beforeChild) {
+        beforeChild->setPreviousSibling(&child);
+        child.setNextSibling(beforeChild);
+        ASSERT(beforeChild != &child);
+    } else
+        setLastChild(&child);
+
+    child.setParent(this);
+
+    dirtyPaintOrderListsOnChildChange(child);
+
+    child.updateDescendantDependentFlags();
+    if (child.m_hasVisibleContent || child.m_hasVisibleDescendant)
+        setAncestorChainHasVisibleDescendant();
+
+    if (child.isSelfPaintingLayer() || child.hasSelfPaintingLayerDescendant())
+        setAncestorChainHasSelfPaintingLayerDescendant();
+
+    if (compositor().hasContentCompositingLayers())
+        setDescendantsNeedCompositingRequirementsTraversal();
+
+    if (child.hasDescendantNeedingCompositingRequirementsTraversal() || child.needsCompositingRequirementsTraversal())
+        child.setAncestorsHaveCompositingDirtyFlag(Compositing::HasDescendantNeedingRequirementsTraversal);
+
+    if (child.hasDescendantNeedingUpdateBackingOrHierarchyTraversal() || child.needsUpdateBackingOrHierarchyTraversal())
+        child.setAncestorsHaveCompositingDirtyFlag(Compositing::HasDescendantNeedingBackingOrHierarchyTraversal);
+
+#if ENABLE(CSS_COMPOSITING)
+    if (child.hasBlendMode() || (child.hasNotIsolatedBlendingDescendants() && !child.isolatesBlending()))
+        updateAncestorChainHasBlendingDescendants(); // Why not just dirty?
+#endif
+
+    compositor().layerWasAdded(*this, child);
+}
+
+void RenderLayer::removeChild(RenderLayer& oldChild)
+{
+    if (!renderer().renderTreeBeingDestroyed())
+        compositor().layerWillBeRemoved(*this, oldChild);
+
+    // remove the child
+    if (oldChild.previousSibling())
+        oldChild.previousSibling()->setNextSibling(oldChild.nextSibling());
+    if (oldChild.nextSibling())
+        oldChild.nextSibling()->setPreviousSibling(oldChild.previousSibling());
+
+    if (m_first == &oldChild)
+        m_first = oldChild.nextSibling();
+    if (m_last == &oldChild)
+        m_last = oldChild.previousSibling();
+
+    dirtyPaintOrderListsOnChildChange(oldChild);
+
+    oldChild.setPreviousSibling(nullptr);
+    oldChild.setNextSibling(nullptr);
+    oldChild.setParent(nullptr);
+    
+    oldChild.updateDescendantDependentFlags();
+    if (oldChild.m_hasVisibleContent || oldChild.m_hasVisibleDescendant)
+        dirtyAncestorChainVisibleDescendantStatus();
+
+    if (oldChild.isSelfPaintingLayer() || oldChild.hasSelfPaintingLayerDescendant())
+        dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+
+    if (compositor().hasContentCompositingLayers())
+        setDescendantsNeedCompositingRequirementsTraversal();
+
+#if ENABLE(CSS_COMPOSITING)
+    if (oldChild.hasBlendMode() || (oldChild.hasNotIsolatedBlendingDescendants() && !oldChild.isolatesBlending()))
+        dirtyAncestorChainHasBlendingDescendants();
+#endif
+}
+
+void RenderLayer::dirtyPaintOrderListsOnChildChange(RenderLayer& child)
+{
+    if (child.isNormalFlowOnly())
+        dirtyNormalFlowList();
+
+    if (!child.isNormalFlowOnly() || child.firstChild()) {
+        // Dirty the z-order list in which we are contained. The stackingContext() can be null in the
+        // case where we're building up generated content layers. This is ok, since the lists will start
+        // off dirty in that case anyway.
+        child.dirtyStackingContextZOrderLists();
+    }
+}
+
+void RenderLayer::insertOnlyThisLayer()
+{
+    if (!m_parent && renderer().parent()) {
+        // We need to connect ourselves when our renderer() has a parent.
+        // Find our enclosingLayer and add ourselves.
+        RenderLayer* parentLayer = renderer().parent()->enclosingLayer();
+        ASSERT(parentLayer);
+        RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer().parent()->findNextLayer(parentLayer, &renderer()) : nullptr;
+        parentLayer->addChild(*this, beforeChild);
+    }
+
+    // Remove all descendant layers from the hierarchy and add them to the new position.
+    for (auto& child : childrenOfType<RenderElement>(renderer()))
+        child.moveLayers(m_parent, this);
+
+    // Clear out all the clip rects.
+    clearClipRectsIncludingDescendants();
+}
+
+void RenderLayer::removeOnlyThisLayer()
+{
+    if (!m_parent)
+        return;
+
+    // Mark that we are about to lose our layer. This makes render tree
+    // walks ignore this layer while we're removing it.
+    renderer().setHasLayer(false);
+
+    compositor().layerWillBeRemoved(*m_parent, *this);
+
+    // Dirty the clip rects.
+    clearClipRectsIncludingDescendants();
+
+    RenderLayer* nextSib = nextSibling();
+
+    // Remove the child reflection layer before moving other child layers.
+    // The reflection layer should not be moved to the parent.
+    if (reflection())
+        removeChild(*reflectionLayer());
+
+    // Now walk our kids and reattach them to our parent.
+    RenderLayer* current = m_first;
+    while (current) {
+        RenderLayer* next = current->nextSibling();
+        removeChild(*current);
+        m_parent->addChild(*current, nextSib);
+        current->setRepaintStatus(NeedsFullRepaint);
+        current = next;
+    }
+
+    // Remove us from the parent.
+    m_parent->removeChild(*this);
+    renderer().destroyLayer();
+}
+
+static bool canCreateStackingContext(const RenderLayer& layer)
+{
+    auto& renderer = layer.renderer();
+    return renderer.hasTransformRelatedProperty()
+        || renderer.hasClipPath()
+        || renderer.hasFilter()
+        || renderer.hasMask()
+        || renderer.hasBackdropFilter()
+#if ENABLE(CSS_COMPOSITING)
+        || renderer.hasBlendMode()
+#endif
+        || renderer.isTransparent()
+        || renderer.isPositioned() // Note that this only creates stacking context in conjunction with explicit z-index.
+        || renderer.hasReflection()
+        || renderer.style().hasIsolation()
+        || !renderer.style().hasAutoZIndex()
+        || (renderer.style().willChange() && renderer.style().willChange()->canCreateStackingContext());
+}
+
+bool RenderLayer::shouldBeNormalFlowOnly() const
+{
+    if (canCreateStackingContext(*this))
+        return false;
+
+    return renderer().hasOverflowClip()
+        || renderer().isCanvas()
+        || renderer().isVideo()
+        || renderer().isEmbeddedObject()
+        || renderer().isRenderIFrame()
+        || (renderer().isRenderImage() && downcast<RenderImage>(renderer()).isEditableImage())
+        || (renderer().style().specifiesColumns() && !isRenderViewLayer())
+        || renderer().isInFlowRenderFragmentedFlow();
+}
+
+bool RenderLayer::shouldBeStackingContext() const
+{
+    return !renderer().style().hasAutoZIndex() || isRenderViewLayer() || isForcedStackingContext();
+}
+
+bool RenderLayer::setIsNormalFlowOnly(bool isNormalFlowOnly)
+{
+    if (isNormalFlowOnly == m_isNormalFlowOnly)
+        return false;
+    
+    m_isNormalFlowOnly = isNormalFlowOnly;
+
+    if (auto* p = parent())
+        p->dirtyNormalFlowList();
+    dirtyStackingContextZOrderLists();
+    return true;
+}
+
+bool RenderLayer::setIsStackingContext(bool isStackingContext)
+{
+    if (isStackingContext == m_isStackingContext)
+        return false;
+    
+    m_isStackingContext = isStackingContext;
+
+    dirtyStackingContextZOrderLists();
+    if (isStackingContext)
+        dirtyZOrderLists();
+    else
+        clearZOrderLists();
+
+    return true;
+}
+
+void RenderLayer::setParent(RenderLayer* parent)
+{
+    if (parent == m_parent)
+        return;
+
+    if (m_parent && !renderer().renderTreeBeingDestroyed())
+        compositor().layerWillBeRemoved(*m_parent, *this);
+
+    m_parent = parent;
+
+    if (m_parent && !renderer().renderTreeBeingDestroyed())
+        compositor().layerWasAdded(*m_parent, *this);
+}
+
+RenderLayer* RenderLayer::stackingContext() const
+{
+    auto* layer = parent();
+    while (layer && !layer->isStackingContext())
+        layer = layer->parent();
+
+    ASSERT(!layer || layer->isStackingContext());
+    return layer;
+}
+
+void RenderLayer::dirtyZOrderLists()
+{
+    ASSERT(layerListMutationAllowed());
+    ASSERT(isStackingContext());
+
+    if (m_posZOrderList)
+        m_posZOrderList->clear();
+    if (m_negZOrderList)
+        m_negZOrderList->clear();
+    m_zOrderListsDirty = true;
+
+    // FIXME: Ideally, we'd only dirty if the lists changed.
+    if (hasCompositingDescendant())
+        setNeedsCompositingPaintOrderChildrenUpdate();
+}
+
+void RenderLayer::dirtyStackingContextZOrderLists()
+{
+    if (auto* sc = stackingContext())
+        sc->dirtyZOrderLists();
+}
+
+void RenderLayer::dirtyNormalFlowList()
+{
+    ASSERT(layerListMutationAllowed());
+
+    if (m_normalFlowList)
+        m_normalFlowList->clear();
+    m_normalFlowListDirty = true;
+
+    if (hasCompositingDescendant())
+        setNeedsCompositingPaintOrderChildrenUpdate();
+}
+
+void RenderLayer::updateNormalFlowList()
+{
+    if (!m_normalFlowListDirty)
+        return;
+
+    ASSERT(layerListMutationAllowed());
+
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        // Ignore non-overflow layers and reflections.
+        if (child->isNormalFlowOnly() && !isReflectionLayer(*child)) {
+            if (!m_normalFlowList)
+                m_normalFlowList = std::make_unique<Vector<RenderLayer*>>();
+            m_normalFlowList->append(child);
+        }
+    }
+    
+    m_normalFlowListDirty = false;
+}
+
+void RenderLayer::rebuildZOrderLists()
+{
+    ASSERT(layerListMutationAllowed());
+    ASSERT(isDirtyStackingContext());
+    rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
+    m_zOrderListsDirty = false;
+    
+    bool hasNegativeZOrderList = m_negZOrderList && m_negZOrderList->size();
+    // Having negative z-order lists affect whether a compositing layer needs a foreground layer.
+    // Ideally we'd only trigger this when having z-order children changes, but we blow away the old z-order
+    // lists on dirtying so we don't know the old state.
+    if (hasNegativeZOrderList != m_hadNegativeZOrderList) {
+        m_hadNegativeZOrderList = hasNegativeZOrderList;
+        if (isComposited())
+            setNeedsCompositingConfigurationUpdate();
+    }
+}
+
+void RenderLayer::rebuildZOrderLists(std::unique_ptr<Vector<RenderLayer*>>& posZOrderList, std::unique_ptr<Vector<RenderLayer*>>& negZOrderList)
+{
+    bool includeHiddenLayers = compositor().usesCompositing();
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        if (!isReflectionLayer(*child))
+            child->collectLayers(includeHiddenLayers, posZOrderList, negZOrderList);
+    }
+
+    auto compareZIndex = [] (const RenderLayer* first, const RenderLayer* second) -> bool {
+        return first->zIndex() < second->zIndex();
+    };
+
+    // Sort the two lists.
+    if (posZOrderList)
+        std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
+
+    if (negZOrderList)
+        std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
+}
+
+void RenderLayer::collectLayers(bool includeHiddenLayers, std::unique_ptr<Vector<RenderLayer*>>& positiveZOrderList, std::unique_ptr<Vector<RenderLayer*>>& negativeZOrderList)
+{
+    updateDescendantDependentFlags();
+
+    bool isStacking = isStackingContext();
+    // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
+    bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStacking));
+    if (includeHiddenLayer && !isNormalFlowOnly()) {
+        auto& layerList = (zIndex() >= 0) ? positiveZOrderList : negativeZOrderList;
+        if (!layerList)
+            layerList = std::make_unique<Vector<RenderLayer*>>();
+        layerList->append(this);
+    }
+
+    // Recur into our children to collect more layers, but only if we don't establish
+    // a stacking context/container.
+    if ((includeHiddenLayers || m_hasVisibleDescendant) && !isStacking) {
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+            // Ignore reflections.
+            if (!isReflectionLayer(*child))
+                child->collectLayers(includeHiddenLayers, positiveZOrderList, negativeZOrderList);
+        }
+    }
+}
+
+void RenderLayer::setAncestorsHaveCompositingDirtyFlag(Compositing flag)
+{
+    for (auto* layer = paintOrderParent(); layer; layer = layer->paintOrderParent()) {
+        if (layer->m_compositingDirtyBits.contains(flag))
+            break;
+        layer->m_compositingDirtyBits.add(flag);
+    }
+}
+
+void RenderLayer::updateLayerListsIfNeeded()
+{
+    updateZOrderLists();
+    updateNormalFlowList();
+
+    if (RenderLayer* reflectionLayer = this->reflectionLayer()) {
+        reflectionLayer->updateZOrderLists();
+        reflectionLayer->updateNormalFlowList();
+    }
 }
 
 String RenderLayer::name() const
@@ -426,11 +803,13 @@ RenderLayerCompositor& RenderLayer::compositor() const
 
 void RenderLayer::contentChanged(ContentChangeType changeType)
 {
-    if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged || changeType == ImageChanged) && compositor().updateLayerCompositingState(*this))
-        compositor().setCompositingLayersNeedRebuild();
+    if (changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged || (isComposited() && changeType == ImageChanged)) {
+        setNeedsPostLayoutCompositingUpdate();
+        setNeedsCompositingConfigurationUpdate();
+    }
 
-    if (m_backing)
-        m_backing->contentChanged(changeType);
+    if (auto* backing = this->backing())
+        backing->contentChanged(changeType);
 }
 
 bool RenderLayer::canRender3DTransforms() const
@@ -468,10 +847,7 @@ void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer,
 
 void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet<UpdateLayerPositionsFlag> flags)
 {
-    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
-                           // we need to keep in sync, since we may have shifted relative
-                           // to our parent layer.
-
+    updateLayerPosition(&flags);
     applyPostLayoutScrollPositionIfNeeded();
 
     if (geometryMap)
@@ -540,11 +916,6 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
     if (m_reflection)
         m_reflection->layout();
 
-    // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
-    bool isUpdateRoot = flags.contains(IsCompositingUpdateRoot);
-    if (isComposited())
-        flags.remove(IsCompositingUpdateRoot);
-
     if (renderer().isInFlowRenderFragmentedFlow()) {
         updatePagination();
         flags.add(UpdatePagination);
@@ -559,15 +930,6 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
         child->updateLayerPositions(geometryMap, flags);
 
-    if ((flags & UpdateCompositingLayers) && isComposited()) {
-        OptionSet<RenderLayerBacking::UpdateAfterLayoutFlags> updateFlags;
-        if (flags & NeedsFullRepaintInBacking)
-            updateFlags.add(RenderLayerBacking::UpdateAfterLayoutFlags::NeedsFullRepaint);
-        if (isUpdateRoot)
-            updateFlags.add(RenderLayerBacking::UpdateAfterLayoutFlags::IsUpdateRoot);
-        backing()->updateAfterLayout(updateFlags);
-    }
-        
     // With all our children positioned, now update our marquee if we need to.
     if (m_marquee) {
         // FIXME: would like to use SetForScope<> but it doesn't work with bitfields.
@@ -577,6 +939,17 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, OptionSet
         m_updatingMarqueePosition = oldUpdatingMarqueePosition;
     }
 
+    if (renderer().isOutOfFlowPositioned() && renderer().style().position() == PositionType::Fixed && renderer().settings().acceleratedCompositingForFixedPositionEnabled()) {
+        bool intersectsViewport = compositor().fixedLayerIntersectsViewport(*this);
+        if (intersectsViewport != m_isFixedIntersectingViewport) {
+            m_isFixedIntersectingViewport = intersectsViewport;
+            setNeedsPostLayoutCompositingUpdate();
+        }
+    }
+
+    if (isComposited())
+        backing()->updateAfterLayout(flags.contains(ContainingClippingLayerChangedSize), flags.contains(NeedsFullRepaintInBacking));
+
     if (geometryMap)
         geometryMap->popMappingsToAncestor(parent());
 
@@ -800,8 +1173,11 @@ void RenderLayer::updateTransform()
         makeMatrixRenderable(*m_transform, canRender3DTransforms());
     }
 
-    if (had3DTransform != has3DTransform())
+    if (had3DTransform != has3DTransform()) {
         dirty3DTransformedDescendantStatus();
+        // Having a 3D transform affects whether enclosing perspective and preserve-3d layers composite, so trigger an update.
+        setNeedsPostLayoutCompositingUpdateOnAncestors();
+    }
 }
 
 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
@@ -823,7 +1199,7 @@ TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOr
             }
         }
     } else {
-        if (renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused)) {
+        if (renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform)) {
             TransformationMatrix currTransform;
             FloatRect pixelSnappedBorderRect = snapRectToDevicePixels(box->borderBoxRect(), box->document().deviceScaleFactor());
             std::unique_ptr<RenderStyle> style = renderer().animation().animatedStyleForRenderer(renderer());
@@ -1004,7 +1380,7 @@ void RenderLayer::setAncestorChainHasVisibleDescendant()
     }
 }
 
-void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks)
+void RenderLayer::updateDescendantDependentFlags()
 {
     if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || hasNotIsolatedBlendingDescendantsStatusDirty()) {
         bool hasVisibleDescendant = false;
@@ -1013,20 +1389,8 @@ void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* o
         bool hasNotIsolatedBlendingDescendants = false;
 #endif
 
-        HashSet<const RenderObject*> childOutOfFlowDescendantContainingBlocks;
         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
-            childOutOfFlowDescendantContainingBlocks.clear();
-            child->updateDescendantDependentFlags(&childOutOfFlowDescendantContainingBlocks);
-
-            bool childIsOutOfFlowPositioned = child->renderer().isOutOfFlowPositioned();
-            if (childIsOutOfFlowPositioned)
-                childOutOfFlowDescendantContainingBlocks.add(child->renderer().containingBlock());
-
-            if (outOfFlowDescendantContainingBlocks) {
-                HashSet<const RenderObject*>::const_iterator it = childOutOfFlowDescendantContainingBlocks.begin();
-                for (; it != childOutOfFlowDescendantContainingBlocks.end(); ++it)
-                    outOfFlowDescendantContainingBlocks->add(*it);
-            }
+            child->updateDescendantDependentFlags();
 
             hasVisibleDescendant |= child->m_hasVisibleContent || child->m_hasVisibleDescendant;
             hasSelfPaintingLayerDescendant |= child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
@@ -1042,9 +1406,6 @@ void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* o
                 break;
         }
 
-        if (outOfFlowDescendantContainingBlocks)
-            outOfFlowDescendantContainingBlocks->remove(&renderer());
-
         m_hasVisibleDescendant = hasVisibleDescendant;
         m_visibleDescendantStatusDirty = false;
         m_hasSelfPaintingLayerDescendant = hasSelfPaintingLayerDescendant;
@@ -1115,16 +1476,12 @@ bool RenderLayer::update3DTransformedDescendantStatus()
 
         // Transformed or preserve-3d descendants can only be in the z-order lists, not
         // in the normal flow list, so we only need to check those.
-        if (auto* positiveZOrderList = posZOrderList()) {
-            for (auto* layer : *positiveZOrderList)
-                m_has3DTransformedDescendant |= layer->update3DTransformedDescendantStatus();
-        }
+        for (auto* layer : positiveZOrderLayers())
+            m_has3DTransformedDescendant |= layer->update3DTransformedDescendantStatus();
 
         // Now check our negative z-index children.
-        if (auto* negativeZOrderList = negZOrderList()) {
-            for (auto* layer : *negativeZOrderList)
-                m_has3DTransformedDescendant |= layer->update3DTransformedDescendantStatus();
-        }
+        for (auto* layer : negativeZOrderLayers())
+            m_has3DTransformedDescendant |= layer->update3DTransformedDescendantStatus();
         
         m_3DTransformedDescendantStatusDirty = false;
     }
@@ -1137,7 +1494,7 @@ bool RenderLayer::update3DTransformedDescendantStatus()
     return has3DTransform();
 }
 
-bool RenderLayer::updateLayerPosition()
+bool RenderLayer::updateLayerPosition(OptionSet<UpdateLayerPositionsFlag>* flags)
 {
     LayoutPoint localPoint;
     LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
@@ -1149,7 +1506,19 @@ bool RenderLayer::updateLayerPosition()
         localPoint += inlineBoundingBoxOffset;
     } else if (RenderBox* box = renderBox()) {
         // FIXME: Is snapping the size really needed here for the RenderBox case?
-        setSize(snappedIntRect(box->frameRect()).size());
+        auto newSize = snappedIntRect(box->frameRect()).size();
+        if (newSize != size()) {
+            if (is<RenderWidget>(*box) && downcast<RenderWidget>(*box).requiresAcceleratedCompositing()) {
+                // Trigger RenderLayerCompositor::requiresCompositingForFrame() which depends on the contentBoxRect size.
+                setNeedsPostLayoutCompositingUpdate();
+            }
+
+            if (flags && renderer().hasOverflowClip())
+                flags->add(ContainingClippingLayerChangedSize);
+
+            setSize(newSize);
+        }
+        
         box->applyTopLeftLocationOffset(localPoint);
     }
 
@@ -1202,6 +1571,16 @@ bool RenderLayer::updateLayerPosition()
     
     positionOrOffsetChanged |= location() != localPoint;
     setLocation(localPoint);
+    
+    if (positionOrOffsetChanged && compositor().hasContentCompositingLayers()) {
+        if (isComposited())
+            setNeedsCompositingGeometryUpdate();
+        // This layer's position can affect the location of a composited descendant (which may be a sibling in z-order),
+        // so trigger a descendant walk from the paint-order parent.
+        if (auto* paintParent = paintOrderParent())
+            paintParent->setDescendantsNeedUpdateBackingAndHierarchyTraversal();
+    }
+
     return positionOrOffsetChanged;
 }
 
@@ -1248,16 +1627,6 @@ FloatPoint RenderLayer::perspectiveOrigin() const
                       floatValueForLength(style.perspectiveOriginY(), borderBox.height()));
 }
 
-RenderLayer* RenderLayer::stackingContext() const
-{
-    RenderLayer* layer = parent();
-    while (layer && !layer->isStackingContext())
-        layer = layer->parent();
-
-    ASSERT(!layer || layer->isStackingContext());
-    return layer;
-}
-
 static inline bool isContainerForPositioned(RenderLayer& layer, PositionType position)
 {
     switch (position) {
@@ -1282,22 +1651,27 @@ RenderLayer* RenderLayer::enclosingAncestorForPosition(PositionType position) co
     return curr;
 }
 
-static RenderLayer* parentLayerCrossFrame(const RenderLayer& layer)
+static RenderLayer* enclosingFrameRenderLayer(const RenderLayer& layer)
 {
-    if (layer.parent())
-        return layer.parent();
-
-    HTMLFrameOwnerElement* ownerElement = layer.renderer().document().ownerElement();
+    auto* ownerElement = layer.renderer().document().ownerElement();
     if (!ownerElement)
         return nullptr;
 
-    RenderElement* ownerRenderer = ownerElement->renderer();
+    auto* ownerRenderer = ownerElement->renderer();
     if (!ownerRenderer)
         return nullptr;
 
     return ownerRenderer->enclosingLayer();
 }
 
+static RenderLayer* parentLayerCrossFrame(const RenderLayer& layer)
+{
+    if (auto* parent = layer.parent())
+        return parent;
+
+    return enclosingFrameRenderLayer(layer);
+}
+
 RenderLayer* RenderLayer::enclosingScrollableLayer() const
 {
     for (RenderLayer* nextLayer = parentLayerCrossFrame(*this); nextLayer; nextLayer = parentLayerCrossFrame(*nextLayer)) {
@@ -1340,11 +1714,6 @@ RenderLayer* RenderLayer::enclosingTransformedAncestor() const
     return curr;
 }
 
-static inline const RenderLayer* compositingContainer(const RenderLayer& layer)
-{
-    return layer.isNormalFlowOnly() ? layer.parent() : layer.stackingContext();
-}
-
 inline bool RenderLayer::shouldRepaintAfterLayout() const
 {
     if (m_repaintStatus == NeedsNormalRepaint)
@@ -1366,7 +1735,7 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf
     if (includeSelf == IncludeSelf && isComposited())
         return const_cast<RenderLayer*>(this);
 
-    for (const RenderLayer* curr = compositingContainer(*this); curr; curr = compositingContainer(*curr)) {
+    for (const RenderLayer* curr = paintOrderParent(); curr; curr = curr->paintOrderParent()) {
         if (curr->isComposited())
             return const_cast<RenderLayer*>(curr);
     }
@@ -1379,7 +1748,7 @@ RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot i
     if (includeSelf == IncludeSelf && compositedWithOwnBackingStore(*this))
         return const_cast<RenderLayer*>(this);
 
-    for (const RenderLayer* curr = compositingContainer(*this); curr; curr = compositingContainer(*curr)) {
+    for (const RenderLayer* curr = paintOrderParent(); curr; curr = curr->paintOrderParent()) {
         if (compositedWithOwnBackingStore(*curr))
             return const_cast<RenderLayer*>(curr);
     }
@@ -1468,7 +1837,7 @@ RenderLayer* RenderLayer::clippingRootForPainting() const
         if (current->isRenderViewLayer())
             return const_cast<RenderLayer*>(current);
 
-        current = compositingContainer(*current);
+        current = current->paintOrderParent();
         ASSERT(current);
         if (current->transform() || compositedWithOwnBackingStore(*current))
             return const_cast<RenderLayer*>(current);
@@ -1528,7 +1897,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons
         // Note: we don't have to walk z-order lists since transparent elements always establish
         // a stacking container. This means we can just walk the layer tree directly.
         for (RenderLayer* curr = layer.firstChild(); curr; curr = curr->nextSibling()) {
-            if (!layer.reflection() || layer.reflectionLayer() != curr)
+            if (!layer.isReflectionLayer(*curr))
                 clipRect.unite(transparencyClipBox(*curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, paintBehavior));
         }
     }
@@ -1622,178 +1991,32 @@ void RenderLayer::beginTransparencyLayers(GraphicsContext& context, const LayerP
         context.beginTransparencyLayer(renderer().opacity());
 
 #if ENABLE(CSS_COMPOSITING)
-        if (usesCompositeOperation)
-            context.setCompositeOperation(context.compositeOperation(), BlendMode::Normal);
-#endif
-
-#ifdef REVEAL_TRANSPARENCY_LAYERS
-        context.setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
-        context.fillRect(pixelSnappedClipRect);
-#endif
-    }
-}
-
-#if PLATFORM(IOS)
-void RenderLayer::willBeDestroyed()
-{
-    if (RenderLayerBacking* layerBacking = backing())
-        layerBacking->layerWillBeDestroyed();
-}
-#endif
-
-bool RenderLayer::isDescendantOf(const RenderLayer& layer) const
-{
-    for (auto* ancestor = this; ancestor; ancestor = ancestor->parent()) {
-        if (&layer == ancestor)
-            return true;
-    }
-    return false;
-}
-
-void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
-{
-    RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
-    if (prevSibling) {
-        child->setPreviousSibling(prevSibling);
-        prevSibling->setNextSibling(child);
-        ASSERT(prevSibling != child);
-    } else
-        setFirstChild(child);
-
-    if (beforeChild) {
-        beforeChild->setPreviousSibling(child);
-        child->setNextSibling(beforeChild);
-        ASSERT(beforeChild != child);
-    } else
-        setLastChild(child);
-
-    child->setParent(this);
-
-    if (child->isNormalFlowOnly())
-        dirtyNormalFlowList();
-
-    if (!child->isNormalFlowOnly() || child->firstChild()) {
-        // Dirty the z-order list in which we are contained. The stackingContext() can be null in the
-        // case where we're building up generated content layers. This is ok, since the lists will start
-        // off dirty in that case anyway.
-        child->dirtyStackingContextZOrderLists();
-    }
-
-    child->updateDescendantDependentFlags();
-    if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
-        setAncestorChainHasVisibleDescendant();
-
-    if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
-        setAncestorChainHasSelfPaintingLayerDescendant();
-
-#if ENABLE(CSS_COMPOSITING)
-    if (child->hasBlendMode() || (child->hasNotIsolatedBlendingDescendants() && !child->isolatesBlending()))
-        updateAncestorChainHasBlendingDescendants();
-#endif
-
-    compositor().layerWasAdded(*this, *child);
-}
-
-RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
-{
-    if (!renderer().renderTreeBeingDestroyed())
-        compositor().layerWillBeRemoved(*this, *oldChild);
-
-    // remove the child
-    if (oldChild->previousSibling())
-        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
-    if (oldChild->nextSibling())
-        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
-    if (m_first == oldChild)
-        m_first = oldChild->nextSibling();
-    if (m_last == oldChild)
-        m_last = oldChild->previousSibling();
-
-    if (oldChild->isNormalFlowOnly())
-        dirtyNormalFlowList();
-    if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) { 
-        // Dirty the z-order list in which we are contained.  When called via the
-        // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
-        // from the main layer tree, so we need to null-check the |stackingContext| value.
-        oldChild->dirtyStackingContextZOrderLists();
-    }
-
-    oldChild->setPreviousSibling(nullptr);
-    oldChild->setNextSibling(nullptr);
-    oldChild->setParent(nullptr);
-    
-    oldChild->updateDescendantDependentFlags();
-    if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
-        dirtyAncestorChainVisibleDescendantStatus();
-
-    if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
-        dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
-
-#if ENABLE(CSS_COMPOSITING)
-    if (oldChild->hasBlendMode() || (oldChild->hasNotIsolatedBlendingDescendants() && !oldChild->isolatesBlending()))
-        dirtyAncestorChainHasBlendingDescendants();
-#endif
-
-    return oldChild;
-}
-
-void RenderLayer::removeOnlyThisLayer()
-{
-    if (!m_parent)
-        return;
-
-    // Mark that we are about to lose our layer. This makes render tree
-    // walks ignore this layer while we're removing it.
-    renderer().setHasLayer(false);
-
-    compositor().layerWillBeRemoved(*m_parent, *this);
-
-    // Dirty the clip rects.
-    clearClipRectsIncludingDescendants();
-
-    RenderLayer* nextSib = nextSibling();
-
-    // Remove the child reflection layer before moving other child layers.
-    // The reflection layer should not be moved to the parent.
-    if (reflection())
-        removeChild(reflectionLayer());
-
-    // Now walk our kids and reattach them to our parent.
-    RenderLayer* current = m_first;
-    while (current) {
-        RenderLayer* next = current->nextSibling();
-        removeChild(current);
-        m_parent->addChild(current, nextSib);
-        current->setRepaintStatus(NeedsFullRepaint);
-        // updateLayerPositions depends on hasLayer() already being false for proper layout.
-        ASSERT(!renderer().hasLayer());
-        current->updateLayerPositions(); // FIXME: use geometry map.
-        current = next;
+        if (usesCompositeOperation)
+            context.setCompositeOperation(context.compositeOperation(), BlendMode::Normal);
+#endif
+
+#ifdef REVEAL_TRANSPARENCY_LAYERS
+        context.setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
+        context.fillRect(pixelSnappedClipRect);
+#endif
     }
+}
 
-    // Remove us from the parent.
-    m_parent->removeChild(this);
-    renderer().destroyLayer();
+#if PLATFORM(IOS_FAMILY)
+void RenderLayer::willBeDestroyed()
+{
+    if (RenderLayerBacking* layerBacking = backing())
+        layerBacking->layerWillBeDestroyed();
 }
+#endif
 
-void RenderLayer::insertOnlyThisLayer()
+bool RenderLayer::isDescendantOf(const RenderLayer& layer) const
 {
-    if (!m_parent && renderer().parent()) {
-        // We need to connect ourselves when our renderer() has a parent.
-        // Find our enclosingLayer and add ourselves.
-        RenderLayer* parentLayer = renderer().parent()->enclosingLayer();
-        ASSERT(parentLayer);
-        RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer().parent()->findNextLayer(parentLayer, &renderer()) : nullptr;
-        parentLayer->addChild(this, beforeChild);
+    for (auto* ancestor = this; ancestor; ancestor = ancestor->parent()) {
+        if (&layer == ancestor)
+            return true;
     }
-
-    // Remove all descendant layers from the hierarchy and add them to the new position.
-    for (auto& child : childrenOfType<RenderElement>(renderer()))
-        child.moveLayers(m_parent, this);
-
-    // Clear out all the clip rects.
-    clearClipRectsIncludingDescendants();
+    return false;
 }
 
 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation, ColumnOffsetAdjustment adjustForColumns) const
@@ -1948,25 +2171,28 @@ LayoutSize RenderLayer::offsetFromAncestor(const RenderLayer* ancestorLayer, Col
     return toLayoutSize(convertToLayerCoords(ancestorLayer, LayoutPoint(), adjustForColumns));
 }
 
-bool RenderLayer::canUseAcceleratedTouchScrolling() const
+bool RenderLayer::canUseCompositedScrolling() const
 {
-#if PLATFORM(IOS) && ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    if (renderer().settings().asyncOverflowScrollingEnabled())
+        return scrollsOverflow();
+
+#if PLATFORM(IOS_FAMILY) && ENABLE(OVERFLOW_SCROLLING_TOUCH)
     return scrollsOverflow() && (renderer().style().useTouchOverflowScrolling() || renderer().settings().alwaysUseAcceleratedOverflowScroll());
 #else
     return false;
 #endif
 }
 
-bool RenderLayer::hasTouchScrollableOverflow() const
+bool RenderLayer::hasCompositedScrollableOverflow() const
 {
-    return canUseAcceleratedTouchScrolling() && (hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
+    return canUseCompositedScrolling() && (hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
 }
 
 #if ENABLE(IOS_TOUCH_EVENTS)
 bool RenderLayer::handleTouchEvent(const PlatformTouchEvent& touchEvent)
 {
     // If we have accelerated scrolling, let the scrolling be handled outside of WebKit.
-    if (hasTouchScrollableOverflow())
+    if (hasCompositedScrollableOverflow())
         return false;
 
     return ScrollableArea::handleTouchEvent(touchEvent);
@@ -2000,7 +2226,7 @@ bool RenderLayer::usesCompositedScrolling() const
 // FIXME: this is only valid after we've made layers.
 bool RenderLayer::usesAsyncScrolling() const
 {
-    return canUseAcceleratedTouchScrolling() && usesCompositedScrolling();
+    return compositor().useCoordinatedScrollingForLayer(*this);
 }
 
 static inline int adjustedScrollDelta(int beginningDelta)
@@ -2080,7 +2306,7 @@ void RenderLayer::scrollByRecursively(const IntSize& delta, ScrollableArea** scr
     }
 }
 
-void RenderLayer::setPostLayoutScrollPosition(std::optional<ScrollPosition> position)
+void RenderLayer::setPostLayoutScrollPosition(Optional<ScrollPosition> position)
 {
     m_postLayoutScrollPosition = position;
 }
@@ -2091,19 +2317,19 @@ void RenderLayer::applyPostLayoutScrollPositionIfNeeded()
         return;
 
     scrollToOffset(scrollOffsetFromPosition(m_postLayoutScrollPosition.value()));
-    m_postLayoutScrollPosition = std::nullopt;
+    m_postLayoutScrollPosition = WTF::nullopt;
 }
 
-void RenderLayer::scrollToXPosition(int x, ScrollClamping clamping)
+void RenderLayer::scrollToXPosition(int x, ScrollType scrollType, ScrollClamping clamping)
 {
     ScrollPosition position(x, m_scrollPosition.y());
-    scrollToOffset(scrollOffsetFromPosition(position), clamping);
+    scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping);
 }
 
-void RenderLayer::scrollToYPosition(int y, ScrollClamping clamping)
+void RenderLayer::scrollToYPosition(int y, ScrollType scrollType, ScrollClamping clamping)
 {
     ScrollPosition position(m_scrollPosition.x(), y);
-    scrollToOffset(scrollOffsetFromPosition(position), clamping);
+    scrollToOffset(scrollOffsetFromPosition(position), scrollType, clamping);
 }
 
 ScrollOffset RenderLayer::clampScrollOffset(const ScrollOffset& scrollOffset) const
@@ -2111,11 +2337,25 @@ ScrollOffset RenderLayer::clampScrollOffset(const ScrollOffset& scrollOffset) co
     return scrollOffset.constrainedBetween(IntPoint(), maximumScrollOffset());
 }
 
-void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollClamping clamping)
+void RenderLayer::scrollToOffset(const ScrollOffset& scrollOffset, ScrollType scrollType, ScrollClamping clamping)
 {
     ScrollOffset newScrollOffset = clamping == ScrollClamping::Clamped ? clampScrollOffset(scrollOffset) : scrollOffset;
-    if (newScrollOffset != this->scrollOffset())
+    if (newScrollOffset == this->scrollOffset())
+        return;
+
+    auto previousScrollType = currentScrollType();
+    setCurrentScrollType(scrollType);
+
+    bool handled = false;
+#if ENABLE(ASYNC_SCROLLING)
+    if (ScrollingCoordinator* scrollingCoordinator = page().scrollingCoordinator())
+        handled = scrollingCoordinator->requestScrollPositionUpdate(*this, scrollPositionFromOffset(scrollOffset));
+#endif
+
+    if (!handled)
         scrollToOffsetWithoutAnimation(newScrollOffset, clamping);
+
+    setCurrentScrollType(previousScrollType);
 }
 
 void RenderLayer::scrollTo(const ScrollPosition& position)
@@ -2124,14 +2364,14 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
     if (!box)
         return;
 
-    LOG_WITH_STREAM(Scrolling, stream << "RenderLayer::scrollTo " << position);
+    LOG_WITH_STREAM(Scrolling, stream << "RenderLayer::scrollTo " << position << " from " << m_scrollPosition << " (is user scroll " << (currentScrollType() == ScrollType::User) << ")");
 
     ScrollPosition newPosition = position;
     if (!box->isHTMLMarquee()) {
         // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
         if (m_scrollDimensionsDirty)
             computeScrollDimensions();
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
         if (adjustForIOSCaretWhenScrolling()) {
             // FIXME: It's not clear what this code is trying to do. Behavior seems reasonable with it removed.
             int maxOffset = scrollWidth() - roundToInt(box->clientWidth());
@@ -2151,10 +2391,12 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
     }
     
     if (m_scrollPosition == newPosition) {
-#if PLATFORM(IOS)
-        if (m_requiresScrollBoundsOriginUpdate)
+        // FIXME: Nothing guarantees we get a scrollTo() with an unchanged position at the end of a user gesture.
+        // The ScrollingCoordinator probably needs to message the main thread when a gesture ends.
+        if (requiresScrollPositionReconciliation()) {
+            setNeedsCompositingGeometryUpdate();
             updateCompositingLayersAfterScroll();
-#endif
+        }
         return;
     }
 
@@ -2167,10 +2409,7 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
     if (!view.frameView().layoutContext().isInRenderTreeLayout()) {
         // If we're in the middle of layout, we'll just update layers once layout has finished.
         updateLayerPositionsAfterOverflowScroll();
-        // Update regions, scrolling may change the clip of a particular region.
-#if ENABLE(DASHBOARD_SUPPORT)
-        view.frameView().updateAnnotatedRegions();
-#endif
+
         view.frameView().scheduleUpdateWidgetPositions();
 
         if (!m_updatingMarqueePosition) {
@@ -2178,12 +2417,16 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
             // positions. Updating layer positions requires a full walk of up-to-date RenderLayers, and
             // in this case we're still updating their positions; we'll update compositing layers later
             // when that completes.
+            if (usesCompositedScrolling()) {
+                setNeedsCompositingGeometryUpdate();
+                setDescendantsNeedUpdateBackingAndHierarchyTraversal();
+            }
+
             updateCompositingLayersAfterScroll();
         }
 
-#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
-        renderer().document().setTouchEventRegionsNeedUpdate();
-#endif
+        // Update regions, scrolling may change the clip of a particular region.
+        renderer().document().invalidateRenderingDependentRegions(Document::AnnotationsAction::Update);
         DebugPageOverlays::didLayout(renderer().frame());
     }
 
@@ -2200,8 +2443,11 @@ void RenderLayer::scrollTo(const ScrollPosition& position)
     frame.eventHandler().dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
 
     bool requiresRepaint = true;
-    if (compositor().inCompositingMode() && usesCompositedScrolling())
+    if (usesCompositedScrolling()) {
+        setNeedsCompositingGeometryUpdate();
+        setDescendantsNeedUpdateBackingAndHierarchyTraversal();
         requiresRepaint = false;
+    }
 
     // Just schedule a full repaint of our object.
     if (requiresRepaint)
@@ -2275,7 +2521,7 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
         RenderBox* box = renderBox();
         ASSERT(box);
         LayoutRect localExposeRect(box->absoluteToLocalQuad(FloatQuad(FloatRect(absoluteRect))).boundingBox());
-        LayoutRect layerBounds(0, 0, box->clientWidth(), box->clientHeight());
+        LayoutRect layerBounds(0_lu, 0_lu, box->clientWidth(), box->clientHeight());
         LayoutRect revealRect = getRectToExpose(layerBounds, localExposeRect, insideFixed, options.alignX, options.alignY);
 
         ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset() + toIntSize(roundedIntRect(revealRect).location()));
@@ -2319,10 +2565,10 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
             if (options.revealMode == SelectionRevealMode::RevealUpToMainFrame && frameView.frame().isMainFrame())
                 return;
 
-#if !PLATFORM(IOS)
+#if !PLATFORM(IOS_FAMILY)
             LayoutRect viewRect = frameView.visibleContentRect();
 #else
-            LayoutRect viewRect = frameView.unobscuredContentRect();
+            LayoutRect viewRect = frameView.unobscuredContentRectExpandedByContentInsets();
 #endif
             // Move the target rect into "scrollView contents" coordinates.
             LayoutRect targetRect = absoluteRect;
@@ -2347,19 +2593,22 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
 
 void RenderLayer::updateCompositingLayersAfterScroll()
 {
-    if (compositor().inCompositingMode()) {
+    if (compositor().hasContentCompositingLayers()) {
         // Our stacking container is guaranteed to contain all of our descendants that may need
         // repositioning, so update compositing layers from there.
         if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
             if (usesCompositedScrolling())
                 compositor().updateCompositingLayers(CompositingUpdateType::OnCompositedScroll, compositingAncestor);
-            else
+            else {
+                // FIXME: would be nice to only dirty layers whose positions were affected by scrolling.
+                compositingAncestor->setDescendantsNeedUpdateBackingAndHierarchyTraversal();
                 compositor().updateCompositingLayers(CompositingUpdateType::OnScroll, compositingAncestor);
+            }
         }
     }
 }
 
-LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const LayoutRect &exposeRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY) const
+LayoutRect RenderLayer::getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& exposeRect, bool insideFixed, const ScrollAlignment& alignX, const ScrollAlignment& alignY) const
 {
     FrameView& frameView = renderer().view().frameView();
     if (renderer().isRenderView() && insideFixed) {
@@ -2519,7 +2768,7 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOff
             styledElement->setInlineStyleProperty(CSSPropertyMarginLeft, renderer->marginLeft() / zoomFactor, CSSPrimitiveValue::CSS_PX);
             styledElement->setInlineStyleProperty(CSSPropertyMarginRight, renderer->marginRight() / zoomFactor, CSSPrimitiveValue::CSS_PX);
         }
-        LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? LayoutUnit() : renderer->horizontalBorderAndPaddingExtent());
+        LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? 0_lu : renderer->horizontalBorderAndPaddingExtent());
         baseWidth = baseWidth / zoomFactor;
         styledElement->setInlineStyleProperty(CSSPropertyWidth, roundToInt(baseWidth + difference.width()), CSSPrimitiveValue::CSS_PX);
     }
@@ -2530,7 +2779,7 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOff
             styledElement->setInlineStyleProperty(CSSPropertyMarginTop, renderer->marginTop() / zoomFactor, CSSPrimitiveValue::CSS_PX);
             styledElement->setInlineStyleProperty(CSSPropertyMarginBottom, renderer->marginBottom() / zoomFactor, CSSPrimitiveValue::CSS_PX);
         }
-        LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? LayoutUnit() : renderer->verticalBorderAndPaddingExtent());
+        LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? 0_lu : renderer->verticalBorderAndPaddingExtent());
         baseHeight = baseHeight / zoomFactor;
         styledElement->setInlineStyleProperty(CSSPropertyHeight, roundToInt(baseHeight + difference.height()), CSSPrimitiveValue::CSS_PX);
     }
@@ -2562,14 +2811,22 @@ int RenderLayer::scrollOffset(ScrollbarOrientation orientation) const
     return 0;
 }
 
+ScrollingNodeID RenderLayer::scrollingNodeID() const
+{
+    if (!isComposited())
+        return 0;
+
+    return backing()->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling);
+}
+
 IntRect RenderLayer::visibleContentRectInternal(VisibleContentRectIncludesScrollbars scrollbarInclusion, VisibleContentRectBehavior) const
 {
     IntSize scrollbarSpace;
     if (showsOverflowControls() && scrollbarInclusion == IncludeScrollbars)
         scrollbarSpace = scrollbarIntrusion();
     
-    // FIXME: This seems wrong: m_layerSize includes borders. Can we just use the ScrollableArea implementation?
-    return IntRect(scrollPosition(), IntSize(std::max(0, m_layerSize.width() - scrollbarSpace.width()), std::max(0, m_layerSize.height() - scrollbarSpace.height())));
+    auto visibleSize = this->visibleSize();
+    return { scrollPosition(), { std::max(0, visibleSize.width() - scrollbarSpace.width()), std::max(0, visibleSize.height() - scrollbarSpace.height()) } };
 }
 
 IntSize RenderLayer::overhangAmount() const
@@ -2582,15 +2839,16 @@ IntSize RenderLayer::overhangAmount() const
 
     // FIXME: use maximumScrollOffset(), or just move this to ScrollableArea.
     ScrollOffset scrollOffset = scrollOffsetFromPosition(scrollPosition());
+    auto reachableSize = reachableTotalContentsSize();
     if (scrollOffset.y() < 0)
         stretch.setHeight(scrollOffset.y());
-    else if (scrollableContentsSize().height() && scrollOffset.y() > scrollableContentsSize().height() - visibleHeight())
-        stretch.setHeight(scrollOffset.y() - (scrollableContentsSize().height() - visibleHeight()));
+    else if (reachableSize.height() && scrollOffset.y() > reachableSize.height() - visibleHeight())
+        stretch.setHeight(scrollOffset.y() - (reachableSize.height() - visibleHeight()));
 
     if (scrollOffset.x() < 0)
         stretch.setWidth(scrollOffset.x());
-    else if (scrollableContentsSize().width() && scrollOffset.x() > scrollableContentsSize().width() - visibleWidth())
-        stretch.setWidth(scrollOffset.x() - (scrollableContentsSize().width() - visibleWidth()));
+    else if (reachableSize.width() && scrollOffset.x() > reachableSize.width() - visibleWidth())
+        stretch.setWidth(scrollOffset.x() - (reachableSize.width() - visibleWidth()));
 
     return stretch;
 #else
@@ -2717,7 +2975,7 @@ IntSize RenderLayer::contentsSize() const
     return IntSize(scrollWidth(), scrollHeight());
 }
 
-IntSize RenderLayer::scrollableContentsSize() const
+IntSize RenderLayer::reachableTotalContentsSize() const
 {
     IntSize contentsSize = this->contentsSize();
 
@@ -2746,7 +3004,7 @@ bool RenderLayer::shouldSuspendScrollAnimations() const
     return renderer().view().frameView().shouldSuspendScrollAnimations();
 }
 
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
 void RenderLayer::didStartScroll()
 {
     page().chrome().client().didStartOverflowScroll();
@@ -2882,6 +3140,26 @@ void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
         m_resizer->repaintRectangle(rect);
 }
 
+static bool scrollbarHiddenByStyle(Scrollbar* scrollbar)
+{
+    if (!scrollbar || !scrollbar->isCustomScrollbar())
+        return false;
+
+    std::unique_ptr<RenderStyle> scrollbarStyle = static_cast<RenderScrollbar*>(scrollbar)->getScrollbarPseudoStyle(ScrollbarBGPart, PseudoId::Scrollbar);
+
+    return scrollbarStyle && scrollbarStyle->display() == DisplayType::None;
+}
+
+bool RenderLayer::horizontalScrollbarHiddenByStyle() const
+{
+    return scrollbarHiddenByStyle(horizontalScrollbar());
+}
+
+bool RenderLayer::verticalScrollbarHiddenByStyle() const
+{
+    return scrollbarHiddenByStyle(verticalScrollbar());
+}
+
 static inline RenderElement* rendererForScrollbar(RenderLayerModelObject& renderer)
 {
     if (Element* element = renderer.element()) {
@@ -2957,11 +3235,7 @@ void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
     if (m_vBar)
         m_vBar->styleChanged();
 
-    // Force an update since we know the scrollbars have changed things.
-#if ENABLE(DASHBOARD_SUPPORT)
-    if (renderer().document().hasAnnotatedRegions())
-        renderer().document().setAnnotatedRegionsDirty(true);
-#endif
+    renderer().document().invalidateScrollbarDependentRegions();
 }
 
 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
@@ -2988,11 +3262,7 @@ void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
     if (m_vBar)
         m_vBar->styleChanged();
 
-    // Force an update since we know the scrollbars have changed things.
-#if ENABLE(DASHBOARD_SUPPORT)
-    if (renderer().document().hasAnnotatedRegions())
-        renderer().document().setAnnotatedRegionsDirty(true);
-#endif
+    renderer().document().invalidateScrollbarDependentRegions();
 }
 
 ScrollableArea* RenderLayer::enclosingScrollableArea() const
@@ -3020,6 +3290,11 @@ bool RenderLayer::hasScrollableOrRubberbandableAncestor()
     return false;
 }
 
+bool RenderLayer::useDarkAppearance() const
+{
+    return renderer().useDarkAppearance();
+}
+
 #if ENABLE(CSS_SCROLL_SNAP)
 void RenderLayer::updateSnapOffsets()
 {
@@ -3258,12 +3533,7 @@ void RenderLayer::updateScrollbarsAfterLayout()
 
         updateSelfPaintingLayer();
 
-        // Force an update since we know the scrollbars have changed things.
-#if ENABLE(DASHBOARD_SUPPORT)
-        if (renderer().document().hasAnnotatedRegions())
-            renderer().document().setAnnotatedRegionsDirty(true);
-#endif
-
+        renderer().document().invalidateScrollbarDependentRegions();
         renderer().repaint();
 
         if (renderer().style().overflowX() == Overflow::Auto || renderer().style().overflowY() == Overflow::Auto) {
@@ -3324,7 +3594,7 @@ void RenderLayer::updateScrollInfoAfterLayout()
         // Layout may cause us to be at an invalid scroll position. In this case we need
         // to pull our scroll offsets back to the max (or push them up to the min).
         ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset());
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
         // FIXME: This looks wrong. The caret adjust mode should only be enabled on editing related entry points.
         // This code was added to fix an issue where the text insertion point would always be drawn on the right edge
         // of a text field whose content overflowed its bounds. See <rdar://problem/15579797> for more details.
@@ -3333,7 +3603,7 @@ void RenderLayer::updateScrollInfoAfterLayout()
         if (clampedScrollOffset != scrollOffset())
             scrollToOffset(clampedScrollOffset);
 
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
         setAdjustForIOSCaretWhenScrolling(false);
 #endif
     }
@@ -3343,10 +3613,15 @@ void RenderLayer::updateScrollInfoAfterLayout()
     if (originalScrollOffset != scrollOffset())
         scrollToOffsetWithoutAnimation(IntPoint(scrollOffset()));
 
-    // Composited scrolling may need to be enabled or disabled if the amount of overflow changed.
-    // FIXME: this should just dirty the layer and updateLayerPositions should do stuff.
-    if (compositor().updateLayerCompositingState(*this))
-        compositor().setCompositingLayersNeedRebuild();
+    if (isComposited()) {
+        setNeedsCompositingGeometryUpdate();
+        setNeedsCompositingConfigurationUpdate();
+    }
+
+#if PLATFORM(IOS_FAMILY)
+    if (canUseCompositedScrolling())
+        setNeedsPostLayoutCompositingUpdate();
+#endif
 
     updateScrollSnapState();
 }
@@ -3372,10 +3647,9 @@ bool RenderLayer::overflowControlsIntersectRect(const IntRect& localRect) const
 
 bool RenderLayer::showsOverflowControls() const
 {
-#if PLATFORM(IOS)
-    // Don't render (custom) scrollbars if we have accelerated scrolling.
-    if (canUseAcceleratedTouchScrolling())
-        return false;
+#if PLATFORM(IOS_FAMILY)
+    // On iOS, the scrollbars are made in the UI process.
+    return !canUseCompositedScrolling();
 #endif
 
     return true;
@@ -3530,7 +3804,7 @@ void RenderLayer::paintResizer(GraphicsContext& context, const LayoutPoint& pain
         GraphicsContextStateSaver stateSaver(context);
         context.clip(absRect);
         LayoutRect largerCorner = absRect;
-        largerCorner.setSize(LayoutSize(largerCorner.width() + LayoutUnit::fromPixel(1), largerCorner.height() + LayoutUnit::fromPixel(1)));
+        largerCorner.setSize(LayoutSize(largerCorner.width() + 1_lu, largerCorner.height() + 1_lu));
         context.setStrokeColor(Color(makeRGB(217, 217, 217)));
         context.setStrokeThickness(1.0f);
         context.setFillColor(Color::transparent);
@@ -3998,12 +4272,6 @@ void RenderLayer::applyFilters(GraphicsContext& originalContext, const LayerPain
     restoreClip(originalContext, paintingInfo, backgroundRect);
 }
 
-// Helper for the sorting of layers by z-index.
-static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
-{
-    return first->zIndex() < second->zIndex();
-}
-
 void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags)
 {
     ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
@@ -4016,21 +4284,21 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
     bool isPaintingCompositedForeground = paintFlags.contains(PaintLayerPaintingCompositingForegroundPhase);
     bool isPaintingCompositedBackground = paintFlags.contains(PaintLayerPaintingCompositingBackgroundPhase);
     bool isPaintingOverflowContents = paintFlags.contains(PaintLayerPaintingOverflowContents);
+    bool isCollectingEventRegion = paintFlags.contains(PaintLayerCollectingEventRegion);
     // Outline always needs to be painted even if we have no visible content. Also,
     // the outline is painted in the background phase during composited scrolling.
     // If it were painted in the foreground phase, it would move with the scrolled
     // content. When not composited scrolling, the outline is painted in the
     // foreground phase. Since scrolled contents are moved by repainting in this
     // case, the outline won't get 'dragged along'.
-    bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars
+    bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars && !isCollectingEventRegion
         && ((isPaintingScrollingContent && isPaintingCompositedBackground)
         || (!isPaintingScrollingContent && isPaintingCompositedForeground));
-    bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars;
+    bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars && !isCollectingEventRegion;
 
     if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer().isRenderView() && !renderer().isDocumentElementRenderer())
         return;
 
-    // Ensure our lists are up-to-date.
     updateLayerListsIfNeeded();
 
     LayoutSize offsetFromRoot = offsetFromAncestor(paintingInfo.rootLayer);
@@ -4097,7 +4365,7 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
             paintBehavior.add(PaintBehavior::ExcludeSelection);
 
         LayoutRect paintDirtyRect = localPaintingInfo.paintDirtyRect;
-        if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
+        if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars || isCollectingEventRegion) {
             // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
             // fragment should paint. If the parent's filter dictates full repaint to ensure proper filter effect,
             // use the overflow clip as dirty rect, instead of no clipping. It maintains proper clipping for overflow::scroll.
@@ -4122,7 +4390,7 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
 
         // Now walk the sorted list of children with negative z-indices.
         if ((isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground))
-            paintList(negZOrderList(), currentContext, localPaintingInfo, localPaintFlags);
+            paintList(negativeZOrderLayers(), currentContext, localPaintingInfo, localPaintFlags);
         
         if (isPaintingCompositedForeground) {
             if (shouldPaintContent) {
@@ -4131,15 +4399,18 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
             }
         }
 
+        if (isCollectingEventRegion)
+            collectEventRegionForFragments(layerFragments, currentContext, localPaintingInfo);
+
         if (shouldPaintOutline)
             paintOutlineForFragments(layerFragments, currentContext, localPaintingInfo, paintBehavior, subtreePaintRootForRenderer);
 
         if (isPaintingCompositedForeground) {
             // Paint any child layers that have overflow.
-            paintList(m_normalFlowList.get(), currentContext, localPaintingInfo, localPaintFlags);
+            paintList(normalFlowLayers(), currentContext, localPaintingInfo, localPaintFlags);
         
             // Now walk the sorted list of children with positive z-indices.
-            paintList(posZOrderList(), currentContext, localPaintingInfo, localPaintFlags);
+            paintList(positiveZOrderLayers(), currentContext, localPaintingInfo, localPaintFlags);
         }
 
         if (isPaintingOverlayScrollbars && hasScrollbars())
@@ -4224,25 +4495,25 @@ void RenderLayer::paintLayerByApplyingTransform(GraphicsContext& context, const
     LayoutSize adjustedSubpixelOffset = offsetForThisLayer - LayoutSize(devicePixelSnappedOffsetForThisLayer);
     LayerPaintingInfo transformedPaintingInfo(paintingInfo);
     transformedPaintingInfo.rootLayer = this;
-    transformedPaintingInfo.paintDirtyRect = LayoutRect(encloseRectToDevicePixels(transform.inverse().value_or(AffineTransform()).mapRect(paintingInfo.paintDirtyRect), deviceScaleFactor));
+    transformedPaintingInfo.paintDirtyRect = LayoutRect(encloseRectToDevicePixels(transform.inverse().valueOr(AffineTransform()).mapRect(paintingInfo.paintDirtyRect), deviceScaleFactor));
     transformedPaintingInfo.subpixelOffset = adjustedSubpixelOffset;
     paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags);
     context.setCTM(oldTransfrom);
 }
 
-void RenderLayer::paintList(Vector<RenderLayer*>* list, GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags)
+void RenderLayer::paintList(LayerList layerIterator, GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags)
 {
-    if (!list)
+    if (layerIterator.begin() == layerIterator.end())
         return;
 
     if (!hasSelfPaintingLayerDescendant())
         return;
 
 #if !ASSERT_DISABLED
-    LayerListMutationDetector mutationChecker(this);
+    LayerListMutationDetector mutationChecker(*this);
 #endif
 
-    for (auto* childLayer : *list)
+    for (auto* childLayer : layerIterator)
         childLayer->paintLayer(context, paintingInfo, paintFlags);
 }
 
@@ -4613,6 +4884,17 @@ void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerF
     }
 }
 
+void RenderLayer::collectEventRegionForFragments(const LayerFragments& layerFragments, GraphicsContext& context, const LayerPaintingInfo& localPaintingInfo)
+{
+    ASSERT(localPaintingInfo.eventRegion);
+
+    for (const auto& fragment : layerFragments) {
+        PaintInfo paintInfo(context, fragment.foregroundRect.rect(), PaintPhase::EventRegion, { });
+        paintInfo.eventRegion = localPaintingInfo.eventRegion;
+        renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
+    }
+}
+
 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
 {
     return hitTest(request, result.hitTestLocation(), result);
@@ -4623,8 +4905,6 @@ bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation&
     ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
     ASSERT(!renderer().view().needsLayout());
     
-    updateLayerListsIfNeeded();
-
     ASSERT(!isRenderFragmentedFlow());
     LayoutRect hitTestArea = renderer().view().documentRect();
     if (!request.ignoreClipping()) {
@@ -4767,6 +5047,8 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
                                        const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, bool appliedTransform,
                                        const HitTestingTransformState* transformState, double* zOffset)
 {
+    updateLayerListsIfNeeded();
+
     if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
         return nullptr;
 
@@ -4790,7 +5072,6 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
     }
 
     // Ensure our lists and 3d status are up-to-date.
-    updateCompositingAndLayerListsIfNeeded();
     update3DTransformedDescendantStatus();
 
     RefPtr<HitTestingTransformState> localTransformState;
@@ -4805,7 +5086,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
 
     // Check for hit test on backface if backface-visibility is 'hidden'
     if (localTransformState && renderer().style().backfaceVisibility() == BackfaceVisibility::Hidden) {
-        std::optional<TransformationMatrix> invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
+        Optional<TransformationMatrix> invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
         // If the z-vector of the matrix is negative, the back is facing towards the viewer.
         if (invertedMatrix && invertedMatrix.value().m33() < 0)
             return nullptr;
@@ -4840,11 +5121,11 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
     // This variable tracks which layer the mouse ends up being inside.
     RenderLayer* candidateLayer = nullptr;
 #if !ASSERT_DISABLED
-    LayerListMutationDetector mutationChecker(this);
+    LayerListMutationDetector mutationChecker(*this);
 #endif
 
     // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
-    auto* hitLayer = hitTestList(posZOrderList(), rootLayer, request, result, hitTestRect, hitTestLocation,
+    auto* hitLayer = hitTestList(positiveZOrderLayers(), rootLayer, request, result, hitTestRect, hitTestLocation,
                                         localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
     if (hitLayer) {
         if (!depthSortDescendants)
@@ -4853,7 +5134,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
     }
 
     // Now check our overflow objects.
-    hitLayer = hitTestList(m_normalFlowList.get(), rootLayer, request, result, hitTestRect, hitTestLocation,
+    hitLayer = hitTestList(normalFlowLayers(), rootLayer, request, result, hitTestRect, hitTestLocation,
                            localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
     if (hitLayer) {
         if (!depthSortDescendants)
@@ -4892,7 +5173,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
     }
 
     // Now check our negative z-index children.
-    hitLayer = hitTestList(negZOrderList(), rootLayer, request, result, hitTestRect, hitTestLocation,
+    hitLayer = hitTestList(negativeZOrderLayers(), rootLayer, request, result, hitTestRect, hitTestLocation,
         localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
     if (hitLayer) {
         if (!depthSortDescendants)
@@ -5057,7 +5338,7 @@ bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult&
     return true;
 }
 
-RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
+RenderLayer* RenderLayer::hitTestList(LayerList layerIterator, RenderLayer* rootLayer,
                                       const HitTestRequest& request, HitTestResult& result,
                                       const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
                                       const HitTestingTransformState* transformState, 
@@ -5065,18 +5346,19 @@ RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* r
                                       const HitTestingTransformState* unflattenedTransformState,
                                       bool depthSortDescendants)
 {
-    if (!list)
+    if (layerIterator.begin() == layerIterator.end())
         return nullptr;
 
     if (!hasSelfPaintingLayerDescendant())
         return nullptr;
 
     RenderLayer* resultLayer = nullptr;
-    for (size_t i = list->size(); i > 0; --i) {
-        RenderLayer* childLayer = list->at(i - 1);
-        RenderLayer* hitLayer = nullptr;
+
+    for (auto iter = layerIterator.rbegin(); iter != layerIterator.rend(); ++iter) {
+        auto* childLayer = *iter;
+
         HitTestResult tempResult(result.hitTestLocation());
-        hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
+        auto* hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
 
         // If it is a list-based test, we can safely append the temporary result since it might had hit
         // nodes but not necesserily had hitLayer set.
@@ -5188,7 +5470,7 @@ void RenderLayer::calculateClipRects(const ClipRectsContext& clipRectsContext, C
         clipRects.setOverflowClipRect(clipRects.posClipRect());
     
     // Update the clip rects that will be passed to child layers.
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
     if (renderer().hasClipOrOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || this != clipRectsContext.rootLayer)) {
 #else
     if ((renderer().hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || this != clipRectsContext.rootLayer)) || renderer().hasClip()) {
@@ -5245,16 +5527,18 @@ static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRect
 ClipRect RenderLayer::backgroundClipRect(const ClipRectsContext& clipRectsContext) const
 {
     ASSERT(parent());
-    auto computeParentRects = [this, &clipRectsContext] () {
-        // If we cross into a different pagination context, then we can't rely on the cache.
-        // Just switch over to using TemporaryClipRects.
-        if (clipRectsContext.clipRectsType != TemporaryClipRects
-            && parent()->enclosingPaginationLayer(IncludeCompositedPaginatedLayers) != enclosingPaginationLayer(IncludeCompositedPaginatedLayers)) {
-            ClipRectsContext tempContext(clipRectsContext);
-            tempContext.clipRectsType = TemporaryClipRects;
-            return parentClipRects(tempContext);
-        }
-        return parentClipRects(clipRectsContext);
+    auto computeParentRects = [&] {
+        if (clipRectsContext.clipRectsType == TemporaryClipRects)
+            return parentClipRects(clipRectsContext);
+        // If we cross into a different composition/pagination context, then we can't rely on the cache since the root layer differs.
+        bool crossesPaginationBoundary = parent()->enclosingPaginationLayer(IncludeCompositedPaginatedLayers) != enclosingPaginationLayer(IncludeCompositedPaginatedLayers);
+        bool crossesCompositingBoundary = parent()->enclosingCompositingLayerForRepaint() != enclosingCompositingLayerForRepaint();
+        if (!crossesPaginationBoundary && !crossesCompositingBoundary)
+            return parentClipRects(clipRectsContext);
+
+        ClipRectsContext tempContext(clipRectsContext);
+        tempContext.clipRectsType = TemporaryClipRects;
+        return parentClipRects(tempContext);
     };
     
     auto parentRects = computeParentRects();
@@ -5558,6 +5842,14 @@ FloatRect RenderLayer::absoluteBoundingBoxForPainting() const
     return snapRectToDevicePixels(boundingBox(rootLayer, offsetFromAncestor(rootLayer)), renderer().document().deviceScaleFactor());
 }
 
+LayoutRect RenderLayer::overlapBounds() const
+{
+    if (overlapBoundsIncludeChildren())
+        return calculateLayerBounds(this, { }, defaultCalculateLayerBoundsFlags() | IncludeFilterOutsets);
+    
+    return localBoundingBox();
+}
+
 LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutSize& offsetFromRoot, OptionSet<CalculateLayerBoundsFlag> flags) const
 {
     if (!isSelfPaintingLayer())
@@ -5615,10 +5907,10 @@ LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, c
         }
     }
     
-    ASSERT(isStackingContext() || (!posZOrderList() || !posZOrderList()->size()));
+    ASSERT(isStackingContext() || !positiveZOrderLayers().size());
 
 #if !ASSERT_DISABLED
-    LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this));
+    LayerListMutationDetector mutationChecker(const_cast<RenderLayer&>(*this));
 #endif
 
     auto computeLayersUnion = [this, &unionBounds, flags, descendantFlags] (const RenderLayer& childLayer) {
@@ -5630,25 +5922,16 @@ LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, c
         unionBounds.checkedUnite(childBounds);
     };
 
-    if (auto* negZOrderList = this->negZOrderList()) {
-        for (auto* childLayer : *negZOrderList)
-            computeLayersUnion(*childLayer);
-    }
+    for (auto* childLayer : negativeZOrderLayers())
+        computeLayersUnion(*childLayer);
 
-    if (auto* posZOrderList = this->posZOrderList()) {
-        for (auto* childLayer : *posZOrderList)
-            computeLayersUnion(*childLayer);
-    }
+    for (auto* childLayer : positiveZOrderLayers())
+        computeLayersUnion(*childLayer);
 
-    if (auto* normalFlowList = this->normalFlowList()) {
-        for (auto* childLayer : *normalFlowList)
-            computeLayersUnion(*childLayer);
-    }
+    for (auto* childLayer : normalFlowLayers())
+        computeLayersUnion(*childLayer);
 
-    // FIXME: We can optimize the size of the composited layers, by not enlarging
-    // filtered areas with the outsets if we know that the filter is going to render in hardware.
-    // https://bugs.webkit.org/show_bug.cgi?id=81239
-    if (flags & IncludeLayerFilterOutsets)
+    if (flags.contains(IncludeFilterOutsets) || (flags.contains(IncludePaintedFilterOutsets) && paintsWithFilters()))
         renderer().style().filterOutsets().expandRect(unionBounds);
 
     if ((flags & IncludeSelfTransform) && paintsWithTransform(PaintBehavior::Normal)) {
@@ -5696,8 +5979,13 @@ RenderLayerBacking* RenderLayer::ensureBacking()
 
 void RenderLayer::clearBacking(bool layerBeingDestroyed)
 {
-    if (m_backing && !renderer().renderTreeBeingDestroyed())
+    if (!m_backing)
+        return;
+
+    if (!renderer().renderTreeBeingDestroyed())
         compositor().layerBecameNonComposited(*this);
+    
+    m_backing->willBeDestroyed();
     m_backing = nullptr;
 
     if (!layerBeingDestroyed)
@@ -5709,11 +5997,6 @@ bool RenderLayer::hasCompositedMask() const
     return m_backing && m_backing->hasMaskLayer();
 }
 
-GraphicsLayer* RenderLayer::layerForScrolling() const
-{
-    return m_backing ? m_backing->scrollingContentsLayer() : nullptr;
-}
-
 GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const
 {
     return m_backing ? m_backing->layerForHorizontalScrollbar() : nullptr;
@@ -5740,269 +6023,101 @@ bool RenderLayer::shouldPaintMask(OptionSet<PaintBehavior> paintBehavior, Option
     if (!renderer().hasMask())
         return false;
 
-    bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
-    if (paintsToWindow || (paintBehavior & PaintBehavior::FlattenCompositingLayers))
-        return true;
-
-    return paintFlags.contains(PaintLayerPaintingCompositingMaskPhase);
-}
-
-bool RenderLayer::shouldApplyClipPath(OptionSet<PaintBehavior> paintBehavior, OptionSet<PaintLayerFlag> paintFlags) const
-{
-    if (!renderer().hasClipPath())
-        return false;
-
-    bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
-    if (paintsToWindow || (paintBehavior & PaintBehavior::FlattenCompositingLayers))
-        return true;
-
-    return paintFlags.contains(PaintLayerPaintingCompositingClipPathPhase);
-}
-
-bool RenderLayer::scrollingMayRevealBackground() const
-{
-    return scrollsOverflow() || usesCompositedScrolling();
-}
-
-bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
-{
-    if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
-        return false;
-
-    if (paintsWithTransparency(PaintBehavior::Normal))
-        return false;
-
-    if (renderer().isDocumentElementRenderer()) {
-        // Normally the document element doens't have a layer.  If it does have a layer, its background propagates to the RenderView
-        // so this layer doesn't draw it.
-        return false;
-    }
-
-    // We can't use hasVisibleContent(), because that will be true if our renderer is hidden, but some child
-    // is visible and that child doesn't cover the entire rect.
-    if (renderer().style().visibility() != Visibility::Visible)
-        return false;
-
-    if (paintsWithFilters() && renderer().style().filter().hasFilterThatAffectsOpacity())
-        return false;
-
-    // FIXME: Handle simple transforms.
-    if (paintsWithTransform(PaintBehavior::Normal))
-        return false;
-
-    // FIXME: Remove this check.
-    // This function should not be called when layer-lists are dirty.
-    // It is somehow getting triggered during style update.
-    if (m_zOrderListsDirty || m_normalFlowListDirty)
-        return false;
-
-    // Table painting is special; a table paints its sections.
-    if (renderer().isTablePart())
-        return false;
-
-    // FIXME: We currently only check the immediate renderer,
-    // which will miss many cases.
-    if (renderer().backgroundIsKnownToBeOpaqueInRect(localRect))
-        return true;
-    
-    // We can't consult child layers if we clip, since they might cover
-    // parts of the rect that are clipped out.
-    if (renderer().hasOverflowClip())
-        return false;
-    
-    return listBackgroundIsKnownToBeOpaqueInRect(posZOrderList(), localRect)
-        || listBackgroundIsKnownToBeOpaqueInRect(negZOrderList(), localRect)
-        || listBackgroundIsKnownToBeOpaqueInRect(normalFlowList(), localRect);
-}
-
-bool RenderLayer::listBackgroundIsKnownToBeOpaqueInRect(const Vector<RenderLayer*>* list, const LayoutRect& localRect) const
-{
-    if (!list || list->isEmpty())
-        return false;
-
-    for (auto iter = list->rbegin(); iter != list->rend(); ++iter) {
-        const RenderLayer* childLayer = *iter;
-        if (childLayer->isComposited())
-            continue;
-
-        if (!childLayer->canUseConvertToLayerCoords())
-            continue;
-
-        LayoutRect childLocalRect(localRect);
-        childLocalRect.move(-childLayer->offsetFromAncestor(this));
-
-        if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
-            return true;
-    }
-    return false;
-}
-
-void RenderLayer::setParent(RenderLayer* parent)
-{
-    if (parent == m_parent)
-        return;
-
-    if (m_parent && !renderer().renderTreeBeingDestroyed())
-        compositor().layerWillBeRemoved(*m_parent, *this);
-    
-    m_parent = parent;
-
-    if (m_parent && !renderer().renderTreeBeingDestroyed())
-        compositor().layerWasAdded(*m_parent, *this);
-}
-
-void RenderLayer::dirtyZOrderLists()
-{
-    ASSERT(m_layerListMutationAllowed);
-    ASSERT(isStackingContext());
-
-    if (m_posZOrderList)
-        m_posZOrderList->clear();
-    if (m_negZOrderList)
-        m_negZOrderList->clear();
-    m_zOrderListsDirty = true;
-
-    if (!renderer().renderTreeBeingDestroyed())
-        compositor().setCompositingLayersNeedRebuild();
-}
-
-void RenderLayer::dirtyStackingContextZOrderLists()
-{
-    RenderLayer* sc = stackingContext();
-    if (sc)
-        sc->dirtyZOrderLists();
-}
-
-void RenderLayer::dirtyNormalFlowList()
-{
-    ASSERT(m_layerListMutationAllowed);
-
-    if (m_normalFlowList)
-        m_normalFlowList->clear();
-    m_normalFlowListDirty = true;
-
-    if (!renderer().renderTreeBeingDestroyed())
-        compositor().setCompositingLayersNeedRebuild();
-}
-
-void RenderLayer::rebuildZOrderLists()
-{
-    ASSERT(m_layerListMutationAllowed);
-    ASSERT(isDirtyStackingContext());
-    rebuildZOrderLists(m_posZOrderList, m_negZOrderList);
-    m_zOrderListsDirty = false;
+    bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
+    if (paintsToWindow || (paintBehavior & PaintBehavior::FlattenCompositingLayers))
+        return true;
+
+    return paintFlags.contains(PaintLayerPaintingCompositingMaskPhase);
 }
 
-void RenderLayer::rebuildZOrderLists(std::unique_ptr<Vector<RenderLayer*>>& posZOrderList, std::unique_ptr<Vector<RenderLayer*>>& negZOrderList)
+bool RenderLayer::shouldApplyClipPath(OptionSet<PaintBehavior> paintBehavior, OptionSet<PaintLayerFlag> paintFlags) const
 {
-    bool includeHiddenLayers = compositor().inCompositingMode();
-    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
-        if (!m_reflection || reflectionLayer() != child)
-            child->collectLayers(includeHiddenLayers, posZOrderList, negZOrderList);
+    if (!renderer().hasClipPath())
+        return false;
 
-    // Sort the two lists.
-    if (posZOrderList)
-        std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
+    bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
+    if (paintsToWindow || (paintBehavior & PaintBehavior::FlattenCompositingLayers))
+        return true;
 
-    if (negZOrderList)
-        std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
+    return paintFlags.contains(PaintLayerPaintingCompositingClipPathPhase);
 }
 
-void RenderLayer::updateNormalFlowList()
+bool RenderLayer::scrollingMayRevealBackground() const
 {
-    if (!m_normalFlowListDirty)
-        return;
-
-    ASSERT(m_layerListMutationAllowed);
-
-    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
-        // Ignore non-overflow layers and reflections.
-        if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
-            if (!m_normalFlowList)
-                m_normalFlowList = std::make_unique<Vector<RenderLayer*>>();
-            m_normalFlowList->append(child);
-        }
-    }
-    
-    m_normalFlowListDirty = false;
+    return scrollsOverflow() || usesCompositedScrolling();
 }
 
-void RenderLayer::collectLayers(bool includeHiddenLayers, std::unique_ptr<Vector<RenderLayer*>>& posBuffer, std::unique_ptr<Vector<RenderLayer*>>& negBuffer)
+bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
 {
-    updateDescendantDependentFlags();
+    if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
+        return false;
 
-    bool isStacking = isStackingContext();
-    // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
-    bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStacking));
-    if (includeHiddenLayer && !isNormalFlowOnly()) {
-        // Determine which buffer the child should be in.
-        std::unique_ptr<Vector<RenderLayer*>>& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
+    if (paintsWithTransparency(PaintBehavior::Normal))
+        return false;
 
-        // Create the buffer if it doesn't exist yet.
-        if (!buffer)
-            buffer = std::make_unique<Vector<RenderLayer*>>();
-        
-        // Append ourselves at the end of the appropriate buffer.
-        buffer->append(this);
+    if (renderer().isDocumentElementRenderer()) {
+        // Normally the document element doens't have a layer.  If it does have a layer, its background propagates to the RenderView
+        // so this layer doesn't draw it.
+        return false;
     }
 
-    // Recur into our children to collect more layers, but only if we don't establish
-    // a stacking context/container.
-    if ((includeHiddenLayers || m_hasVisibleDescendant) && !isStacking) {
-        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
-            // Ignore reflections.
-            if (!m_reflection || reflectionLayer() != child)
-                child->collectLayers(includeHiddenLayers, posBuffer, negBuffer);
-        }
-    }
-}
+    // We can't use hasVisibleContent(), because that will be true if our renderer is hidden, but some child
+    // is visible and that child doesn't cover the entire rect.
+    if (renderer().style().visibility() != Visibility::Visible)
+        return false;
 
-void RenderLayer::updateLayerListsIfNeeded()
-{
-    updateZOrderLists();
-    updateNormalFlowList();
+    if (paintsWithFilters() && renderer().style().filter().hasFilterThatAffectsOpacity())
+        return false;
 
-    if (RenderLayer* reflectionLayer = this->reflectionLayer()) {
-        reflectionLayer->updateZOrderLists();
-        reflectionLayer->updateNormalFlowList();
-    }
-}
+    // FIXME: Handle simple transforms.
+    if (paintsWithTransform(PaintBehavior::Normal))
+        return false;
 
-void RenderLayer::updateDescendantsLayerListsIfNeeded(bool recursive)
-{
-    Vector<RenderLayer*> layersToUpdate;
-    
-    if (auto* list = negZOrderList()) {
-        for (auto* childLayer : *list)
-            layersToUpdate.append(childLayer);
-    }
-    
-    if (auto* list = normalFlowList()) {
-        for (auto* childLayer : *list)
-            layersToUpdate.append(childLayer);
-    }
+    // FIXME: Remove this check.
+    // This function should not be called when layer-lists are dirty.
+    // It is somehow getting triggered during style update.
+    if (zOrderListsDirty() || normalFlowListDirty())
+        return false;
+
+    // Table painting is special; a table paints its sections.
+    if (renderer().isTablePart())
+        return false;
+
+    // FIXME: We currently only check the immediate renderer,
+    // which will miss many cases.
+    if (renderer().backgroundIsKnownToBeOpaqueInRect(localRect))
+        return true;
     
-    if (auto* list = posZOrderList()) {
-        for (auto* childLayer : *list)
-            layersToUpdate.append(childLayer);
-    }
+    // We can't consult child layers if we clip, since they might cover
+    // parts of the rect that are clipped out.
+    if (renderer().hasOverflowClip())
+        return false;
     
-    for (auto* childLayer : layersToUpdate) {
-        childLayer->updateLayerListsIfNeeded();
-        if (recursive)
-            childLayer->updateDescendantsLayerListsIfNeeded(true);
-    }
+    return listBackgroundIsKnownToBeOpaqueInRect(positiveZOrderLayers(), localRect)
+        || listBackgroundIsKnownToBeOpaqueInRect(negativeZOrderLayers(), localRect)
+        || listBackgroundIsKnownToBeOpaqueInRect(normalFlowLayers(), localRect);
 }
 
-void RenderLayer::updateCompositingAndLayerListsIfNeeded()
+bool RenderLayer::listBackgroundIsKnownToBeOpaqueInRect(const LayerList& list, const LayoutRect& localRect) const
 {
-    if (compositor().inCompositingMode()) {
-        if (isDirtyStackingContext() || m_normalFlowListDirty)
-            compositor().updateCompositingLayers(CompositingUpdateType::OnHitTest, this);
-        return;
-    }
+    if (list.begin() == list.end())
+        return false;
 
-    updateLayerListsIfNeeded();
+    for (auto iter = list.rbegin(); iter != list.rend(); ++iter) {
+        const auto* childLayer = *iter;
+        if (childLayer->isComposited())
+            continue;
+
+        if (!childLayer->canUseConvertToLayerCoords())
+            continue;
+
+        LayoutRect childLocalRect(localRect);
+        childLocalRect.move(-childLayer->offsetFromAncestor(this));
+
+        if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
+            return true;
+    }
+    return false;
 }
 
 void RenderLayer::repaintIncludingDescendants()
@@ -6050,51 +6165,18 @@ void RenderLayer::repaintIncludingNonCompositingDescendants(RenderLayerModelObje
     }
 }
 
-static bool createsStackingContext(const RenderLayer& layer)
-{
-    auto& renderer = layer.renderer();
-    return renderer.hasTransformRelatedProperty()
-        || renderer.hasClipPath()
-        || renderer.hasFilter()
-        || renderer.hasMask()
-        || renderer.hasBackdropFilter()
-#if ENABLE(CSS_COMPOSITING)
-        || renderer.hasBlendMode()
-#endif
-        || renderer.isTransparent()
-        || renderer.isPositioned()
-        || renderer.hasReflection()
-        || renderer.style().hasIsolation()
-#if PLATFORM(IOS)
-        || layer.canUseAcceleratedTouchScrolling()
-#endif
-        || (renderer.style().willChange() && renderer.style().willChange()->canCreateStackingContext());
-}
-
-bool RenderLayer::shouldBeNormalFlowOnly() const
-{
-    if (createsStackingContext(*this))
-        return false;
-
-    return renderer().hasOverflowClip()
-        || renderer().isCanvas()
-        || renderer().isVideo()
-        || renderer().isEmbeddedObject()
-        || renderer().isRenderIFrame()
-        || (renderer().style().specifiesColumns() && !isRenderViewLayer())
-        || renderer().isInFlowRenderFragmentedFlow();
-}
-
 bool RenderLayer::shouldBeSelfPaintingLayer() const
 {
     if (!isNormalFlowOnly())
         return true;
 
     return hasOverlayScrollbars()
+        || canUseCompositedScrolling()
         || renderer().isTableRow()
         || renderer().isCanvas()
         || renderer().isVideo()
         || renderer().isEmbeddedObject()
+        || (renderer().isRenderImage() && downcast<RenderImage>(renderer()).isEditableImage())
         || renderer().isRenderIFrame()
         || renderer().isInFlowRenderFragmentedFlow();
 }
@@ -6237,47 +6319,8 @@ bool RenderLayer::isVisuallyNonEmpty(PaintedContentRequest* request) const
     PaintedContentRequest localRequest;
     if (!request)
         request = &localRequest;
-    return hasNonEmptyChildRenderers(*request);
-}
-
-void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle)
-{
-    if (!oldStyle)
-        return;
-
-    bool wasStackingContext = isStackingContext(oldStyle);
-    bool isStackingContext = this->isStackingContext();
-    if (isStackingContext != wasStackingContext) {
-        dirtyStackingContextZOrderLists();
-        if (isStackingContext)
-            dirtyZOrderLists();
-        else
-            clearZOrderLists();
-
-#if ENABLE(CSS_COMPOSITING)
-        if (parent()) {
-            if (isStackingContext) {
-                if (!hasNotIsolatedBlendingDescendantsStatusDirty() && hasNotIsolatedBlendingDescendants())
-                    parent()->dirtyAncestorChainHasBlendingDescendants();
-            } else {
-                if (hasNotIsolatedBlendingDescendantsStatusDirty())
-                    parent()->dirtyAncestorChainHasBlendingDescendants();
-                else if (hasNotIsolatedBlendingDescendants())
-                    parent()->updateAncestorChainHasBlendingDescendants();
-            }
-        }
-#endif
 
-        return;
-    }
-
-    // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could
-    // likely be folded along with the rest.
-    if (oldStyle->zIndex() != renderer().style().zIndex() || oldStyle->visibility() != renderer().style().visibility()) {
-        dirtyStackingContextZOrderLists();
-        if (isStackingContext)
-            dirtyZOrderLists();
-    }
+    return hasNonEmptyChildRenderers(*request);
 }
 
 void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
@@ -6314,26 +6357,42 @@ void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
 
 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
 {
-    bool isNormalFlowOnly = shouldBeNormalFlowOnly();
-    if (isNormalFlowOnly != m_isNormalFlowOnly) {
-        m_isNormalFlowOnly = isNormalFlowOnly;
-        RenderLayer* p = parent();
-        if (p)
-            p->dirtyNormalFlowList();
-        dirtyStackingContextZOrderLists();
+    setIsNormalFlowOnly(shouldBeNormalFlowOnly());
+
+    if (setIsStackingContext(shouldBeStackingContext())) {
+#if ENABLE(CSS_COMPOSITING)
+        if (parent()) {
+            if (isStackingContext()) {
+                if (!hasNotIsolatedBlendingDescendantsStatusDirty() && hasNotIsolatedBlendingDescendants())
+                    parent()->dirtyAncestorChainHasBlendingDescendants();
+            } else {
+                if (hasNotIsolatedBlendingDescendantsStatusDirty())
+                    parent()->dirtyAncestorChainHasBlendingDescendants();
+                else if (hasNotIsolatedBlendingDescendants())
+                    parent()->updateAncestorChainHasBlendingDescendants();
+            }
+        }
+#endif
+    }
+
+    // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could
+    // likely be folded along with the rest.
+    if (oldStyle) {
+        if (oldStyle->zIndex() != renderer().style().zIndex() || oldStyle->visibility() != renderer().style().visibility()) {
+            dirtyStackingContextZOrderLists();
+            if (isStackingContext())
+                dirtyZOrderLists();
+        }
     }
 
     if (renderer().isHTMLMarquee() && renderer().style().marqueeBehavior() != MarqueeBehavior::None && renderer().isBox()) {
         if (!m_marquee)
             m_marquee = std::make_unique<RenderMarquee>(this);
         m_marquee->updateMarqueeStyle();
-    }
-    else if (m_marquee) {
+    } else if (m_marquee)
         m_marquee = nullptr;
-    }
 
     updateScrollbarsAfterStyleChange(oldStyle);
-    updateStackingContextsAfterStyleChange(oldStyle);
     // Overlay scrollbars can make this layer self-painting so we need
     // to recompute the bit once scrollbars have been updated.
     updateSelfPaintingLayer();
@@ -6367,9 +6426,9 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle
 
     updateFilterPaintingStrategy();
 
-#if PLATFORM(IOS) && ENABLE(TOUCH_EVENTS)
+#if PLATFORM(IOS_FAMILY) && ENABLE(TOUCH_EVENTS)
     if (diff == StyleDifference::RecompositeLayer || diff >= StyleDifference::LayoutPositionedMovementOnly)
-        renderer().document().setTouchEventRegionsNeedUpdate();
+        renderer().document().invalidateRenderingDependentRegions();
 #else
     UNUSED_PARAM(diff);
 #endif
@@ -6400,7 +6459,7 @@ void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
 
 #if ENABLE(IOS_TOUCH_EVENTS)
     if (addedOrRemoved) {
-        if (isScrollable && !canUseAcceleratedTouchScrolling())
+        if (isScrollable && !canUseCompositedScrolling())
             registerAsTouchEventListenerForScrolling();
         else {
             // We only need the touch listener for unaccelerated overflow scrolling, so if we became
@@ -6408,6 +6467,8 @@ void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
             unregisterAsTouchEventListenerForScrolling();
         }
     }
+#else
+    UNUSED_VARIABLE(addedOrRemoved);
 #endif
 }
 
@@ -6470,6 +6531,11 @@ RenderLayer* RenderLayer::reflectionLayer() const
     return m_reflection ? m_reflection->layer() : nullptr;
 }
 
+bool RenderLayer::isReflectionLayer(const RenderLayer& layer) const
+{
+    return m_reflection ? &layer == m_reflection->layer() : false;
+}
+
 void RenderLayer::createReflection()
 {
     ASSERT(!m_reflection);
@@ -6582,11 +6648,47 @@ void RenderLayer::updateFilterPaintingStrategy()
 void RenderLayer::filterNeedsRepaint()
 {
     // We use the enclosing element so that we recalculate style for the ancestor of an anonymous object.
-    if (Element* element = enclosingElement())
+    if (Element* element = enclosingElement()) {
+        // FIXME: This really shouldn't have to invalidate layer composition, but tests like css3/filters/effect-reference-delete.html fail if that doesn't happen.
         element->invalidateStyleAndLayerComposition();
+    }
     renderer().repaint();
 }
 
+bool RenderLayer::isTransparentOrFullyClippedRespectingParentFrames() const
+{
+    static const double minimumVisibleOpacity = 0.01;
+
+    float currentOpacity = 1;
+    for (auto* layer = this; layer; layer = parentLayerCrossFrame(*layer)) {
+        currentOpacity *= layer->renderer().style().opacity();
+        if (currentOpacity < minimumVisibleOpacity)
+            return true;
+    }
+
+    RenderLayer* enclosingClipLayer = nullptr;
+    for (auto* layer = this; layer; layer = enclosingClipLayer ? enclosingClipLayer->parent() : enclosingFrameRenderLayer(*layer)) {
+        enclosingClipLayer = layer->enclosingOverflowClipLayer(IncludeSelfOrNot::IncludeSelf);
+        if (!enclosingClipLayer)
+            continue;
+
+        LayoutRect layerBounds;
+        ClipRect backgroundRect;
+        ClipRect foregroundRect;
+        layer->calculateRects({ enclosingClipLayer, TemporaryClipRects }, LayoutRect::infiniteRect(), layerBounds, backgroundRect, foregroundRect, layer->offsetFromAncestor(enclosingClipLayer));
+        if (backgroundRect.isEmpty())
+            return true;
+    }
+
+    return false;
+}
+
+void RenderLayer::invalidateEventRegion()
+{
+    if (auto* compositingLayer = enclosingCompositingLayerForRepaint())
+        compositingLayer->setNeedsCompositingConfigurationUpdate();
+}
+
 TextStream& operator<<(TextStream& ts, const RenderLayer& layer)
 {
     ts << "RenderLayer " << &layer << " " << layer.size();
@@ -6625,4 +6727,131 @@ void showLayerTree(const WebCore::RenderObject* renderer)
     showLayerTree(renderer->enclosingLayer());
 }
 
+static void outputPaintOrderTreeLegend(TextStream& stream)
+{
+    stream.nextLine();
+    stream << "(S)tacking Context, (N)ormal flow only, (O)verflow clip, (A)lpha (opacity or mask), has (B)lend mode, (I)solates blending, (T)ransform-ish, (F)ilter, Fi(X)ed position, (C)omposited, (c)omposited descendant\n"
+        "Dirty (z)-lists, Dirty (n)ormal flow lists\n"
+        "Traversal needs: requirements (t)raversal on descendants, (b)acking or hierarchy traversal on descendants, (r)equirements traversal on all descendants, requirements traversal on all (s)ubsequent layers, (h)ierarchy traversal on all descendants, update of paint (o)rder children\n"
+        "Update needs:    post-(l)ayout requirements, (g)eometry, (k)ids geometry, (c)onfig, layer conne(x)ion, (s)crolling tree\n";
+    stream.nextLine();
+}
+
+static void outputIdent(TextStream& stream, unsigned depth)
+{
+    unsigned i = 0;
+    while (++i <= depth * 2)
+        stream << " ";
+}
+
+static void outputPaintOrderTreeRecursive(TextStream& stream, const WebCore::RenderLayer& layer, const char* prefix, unsigned depth = 0)
+{
+    stream << (layer.isStackingContext() ? "S" : "-");
+    stream << (layer.isNormalFlowOnly() ? "N" : "-");
+    stream << (layer.renderer().hasOverflowClip() ? "O" : "-");
+    stream << (layer.isTransparent() ? "A" : "-");
+    stream << (layer.hasBlendMode() ? "B" : "-");
+    stream << (layer.isolatesBlending() ? "I" : "-");
+    stream << (layer.renderer().hasTransformRelatedProperty() ? "T" : "-");
+    stream << (layer.hasFilter() ? "F" : "-");
+    stream << (layer.renderer().isFixedPositioned() ? "X" : "-");
+    stream << (layer.isComposited() ? "C" : "-");
+    stream << (layer.hasCompositingDescendant() ? "c" : "-");
+
+    stream << " ";
+
+    stream << (layer.zOrderListsDirty() ? "z" : "-");
+    stream << (layer.normalFlowListDirty() ? "n" : "-");
+
+    stream << " ";
+
+    stream << (layer.hasDescendantNeedingCompositingRequirementsTraversal() ? "t" : "-");
+    stream << (layer.hasDescendantNeedingUpdateBackingOrHierarchyTraversal() ? "b" : "-");
+    stream << (layer.descendantsNeedCompositingRequirementsTraversal() ? "r" : "-");
+    stream << (layer.subsequentLayersNeedCompositingRequirementsTraversal() ? "s" : "-");
+    stream << (layer.descendantsNeedUpdateBackingAndHierarchyTraversal() ? "h" : "-");
+    stream << (layer.needsCompositingPaintOrderChildrenUpdate() ? "o" : "-");
+
+    stream << " ";
+
+    stream << (layer.needsPostLayoutCompositingUpdate() ? "l" : "-");
+    stream << (layer.needsCompositingGeometryUpdate() ? "g" : "-");
+    stream << (layer.childrenNeedCompositingGeometryUpdate() ? "k" : "-");
+    stream << (layer.needsCompositingConfigurationUpdate() ? "c" : "-");
+    stream << (layer.needsCompositingLayerConnection() ? "x" : "-");
+    stream << (layer.needsScrollingTreeUpdate() ? "s" : "-");
+
+    stream << " ";
+
+    outputIdent(stream, depth);
+
+    stream << prefix;
+
+    auto layerRect = layer.rect();
+
+    stream << &layer << " " << layerRect;
+    if (layer.isComposited()) {
+        auto& backing = *layer.backing();
+        stream << " (layerID " << backing.graphicsLayer()->primaryLayerID() << ")";
+
+        auto scrollingNodeID = backing.scrollingNodeIDForRole(WebCore::ScrollCoordinationRole::Scrolling);
+        auto frameHostingNodeID = backing.scrollingNodeIDForRole(WebCore::ScrollCoordinationRole::FrameHosting);
+        auto viewportConstrainedNodeID = backing.scrollingNodeIDForRole(WebCore::ScrollCoordinationRole::ViewportConstrained);
+        auto positionedNodeID = backing.scrollingNodeIDForRole(WebCore::ScrollCoordinationRole::Positioning);
+
+        if (scrollingNodeID || frameHostingNodeID || viewportConstrainedNodeID || positionedNodeID) {
+            stream << " {";
+            bool first = true;
+            if (scrollingNodeID) {
+                stream << "sc " << scrollingNodeID;
+                first = false;
+            }
+
+            if (frameHostingNodeID) {
+                if (!first)
+                    stream << ", ";
+                stream << "fh " << frameHostingNodeID;
+                first = false;
+            }
+
+            if (viewportConstrainedNodeID) {
+                if (!first)
+                    stream << ", ";
+                stream << "vc " << viewportConstrainedNodeID;
+            }
+
+            if (positionedNodeID) {
+                if (!first)
+                    stream << ", ";
+                stream << "pos " << positionedNodeID;
+            }
+
+            stream << "}";
+        }
+    }
+    stream << " " << layer.name();
+    stream.nextLine();
+
+    const_cast<WebCore::RenderLayer&>(layer).updateLayerListsIfNeeded();
+
+    for (auto* child : layer.negativeZOrderLayers())
+        outputPaintOrderTreeRecursive(stream, *child, "- ", depth + 1);
+
+    for (auto* child : layer.normalFlowLayers())
+        outputPaintOrderTreeRecursive(stream, *child, "n ", depth + 1);
+
+    for (auto* child : layer.positiveZOrderLayers())
+        outputPaintOrderTreeRecursive(stream, *child, "+ ", depth + 1);
+}
+
+void showPaintOrderTree(const WebCore::RenderLayer* layer)
+{
+    TextStream stream;
+    outputPaintOrderTreeLegend(stream);
+    if (layer)
+        outputPaintOrderTreeRecursive(stream, *layer, "");
+    
+    WTFLogAlways("%s", stream.release().utf8().data());
+}
+
 #endif