2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "RenderLayerCompositor.h"
30 #include "CSSAnimationController.h"
31 #include "CSSPropertyNames.h"
32 #include "CanvasRenderingContext.h"
34 #include "ChromeClient.h"
35 #include "DocumentTimeline.h"
37 #include "FrameView.h"
38 #include "FullscreenManager.h"
39 #include "GraphicsLayer.h"
40 #include "HTMLCanvasElement.h"
41 #include "HTMLIFrameElement.h"
42 #include "HTMLNames.h"
43 #include "HitTestResult.h"
44 #include "InspectorInstrumentation.h"
48 #include "PageOverlayController.h"
49 #include "RenderEmbeddedObject.h"
50 #include "RenderFragmentedFlow.h"
51 #include "RenderFullScreen.h"
52 #include "RenderGeometryMap.h"
53 #include "RenderIFrame.h"
54 #include "RenderLayerBacking.h"
55 #include "RenderReplica.h"
56 #include "RenderVideo.h"
57 #include "RenderView.h"
58 #include "RuntimeEnabledFeatures.h"
59 #include "ScrollingConstraints.h"
60 #include "ScrollingCoordinator.h"
62 #include "TiledBacking.h"
63 #include "TransformState.h"
64 #include <wtf/HexNumber.h>
65 #include <wtf/MemoryPressureHandler.h>
66 #include <wtf/SetForScope.h>
67 #include <wtf/text/CString.h>
68 #include <wtf/text/StringBuilder.h>
69 #include <wtf/text/StringConcatenateNumbers.h>
70 #include <wtf/text/TextStream.h>
72 #if PLATFORM(IOS_FAMILY)
73 #include "LegacyTileCache.h"
74 #include "RenderScrollbar.h"
78 #include "LocalDefaultSystemAppearance.h"
81 #if ENABLE(TREE_DEBUGGING)
82 #include "RenderTreeAsText.h"
85 #if ENABLE(3D_TRANSFORMS)
86 // This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm').
87 WEBCORE_EXPORT bool WebCoreHas3DRendering = true;
90 #if !PLATFORM(MAC) && !PLATFORM(IOS_FAMILY)
91 #define USE_COMPOSITING_FOR_SMALL_CANVASES 1
96 #if !USE(COMPOSITING_FOR_SMALL_CANVASES)
97 static const int canvasAreaThresholdRequiringCompositing = 50 * 100;
99 // During page loading delay layer flushes up to this many seconds to allow them coalesce, reducing workload.
100 #if PLATFORM(IOS_FAMILY)
101 static const Seconds throttledLayerFlushInitialDelay { 500_ms };
102 static const Seconds throttledLayerFlushDelay { 1.5_s };
104 static const Seconds throttledLayerFlushInitialDelay { 500_ms };
105 static const Seconds throttledLayerFlushDelay { 500_ms };
108 using namespace HTMLNames;
110 struct ScrollingTreeState {
111 Optional<ScrollingNodeID> parentNodeID;
112 size_t nextChildIndex { 0 };
115 class OverlapMapContainer {
117 void add(const LayoutRect& bounds)
119 m_layerRects.append(bounds);
120 m_boundingBox.unite(bounds);
123 bool overlapsLayers(const LayoutRect& bounds) const
125 // Checking with the bounding box will quickly reject cases when
126 // layers are created for lists of items going in one direction and
127 // never overlap with each other.
128 if (!bounds.intersects(m_boundingBox))
130 for (const auto& layerRect : m_layerRects) {
131 if (layerRect.intersects(bounds))
137 void unite(const OverlapMapContainer& otherContainer)
139 m_layerRects.appendVector(otherContainer.m_layerRects);
140 m_boundingBox.unite(otherContainer.m_boundingBox);
143 Vector<LayoutRect> m_layerRects;
144 LayoutRect m_boundingBox;
147 class RenderLayerCompositor::OverlapMap {
148 WTF_MAKE_NONCOPYABLE(OverlapMap);
151 : m_geometryMap(UseTransforms)
153 // Begin assuming the root layer will be composited so that there is
154 // something on the stack. The root layer should also never get an
155 // popCompositingContainer call.
156 pushCompositingContainer();
159 void add(const LayoutRect& bounds)
161 // Layers do not contribute to overlap immediately--instead, they will
162 // contribute to overlap as soon as their composited ancestor has been
163 // recursively processed and popped off the stack.
164 ASSERT(m_overlapStack.size() >= 2);
165 m_overlapStack[m_overlapStack.size() - 2].add(bounds);
169 bool overlapsLayers(const LayoutRect& bounds) const
171 return m_overlapStack.last().overlapsLayers(bounds);
179 void pushCompositingContainer()
181 m_overlapStack.append(OverlapMapContainer());
184 void popCompositingContainer()
186 m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
187 m_overlapStack.removeLast();
190 const RenderGeometryMap& geometryMap() const { return m_geometryMap; }
191 RenderGeometryMap& geometryMap() { return m_geometryMap; }
195 Vector<LayoutRect> rects;
196 LayoutRect boundingRect;
198 void append(const LayoutRect& rect)
201 boundingRect.unite(rect);
204 void append(const RectList& rectList)
206 rects.appendVector(rectList.rects);
207 boundingRect.unite(rectList.boundingRect);
210 bool intersects(const LayoutRect& rect) const
212 if (!rects.size() || !boundingRect.intersects(rect))
215 for (const auto& currentRect : rects) {
216 if (currentRect.intersects(rect))
223 Vector<OverlapMapContainer> m_overlapStack;
224 RenderGeometryMap m_geometryMap;
225 bool m_isEmpty { true };
228 struct RenderLayerCompositor::CompositingState {
229 CompositingState(RenderLayer* compAncestor, bool testOverlap = true)
230 : compositingAncestor(compAncestor)
231 , testingOverlap(testOverlap)
235 CompositingState stateForPaintOrderChildren(RenderLayer& layer) const
238 CompositingState childState(compositingAncestor);
239 if (layer.isStackingContext())
240 childState.stackingContextAncestor = &layer;
242 childState.stackingContextAncestor = stackingContextAncestor;
244 childState.backingSharingAncestor = backingSharingAncestor;
245 childState.subtreeIsCompositing = false;
246 childState.testingOverlap = testingOverlap;
247 childState.fullPaintOrderTraversalRequired = fullPaintOrderTraversalRequired;
248 childState.descendantsRequireCompositingUpdate = descendantsRequireCompositingUpdate;
249 childState.ancestorHasTransformAnimation = ancestorHasTransformAnimation;
250 #if ENABLE(CSS_COMPOSITING)
251 childState.hasNotIsolatedCompositedBlendingDescendants = false; // FIXME: should this only be reset for stacking contexts?
253 #if ENABLE(TREE_DEBUGGING)
254 childState.depth = depth + 1;
259 void propagateStateFromChildren(const CompositingState& childState)
261 // Subsequent layers in the parent stacking context also need to composite.
262 subtreeIsCompositing |= childState.subtreeIsCompositing;
263 fullPaintOrderTraversalRequired |= childState.fullPaintOrderTraversalRequired;
266 void propagateStateFromChildrenForUnchangedSubtree(const CompositingState& childState)
268 subtreeIsCompositing |= childState.subtreeIsCompositing;
271 RenderLayer* compositingAncestor;
272 RenderLayer* backingSharingAncestor { nullptr };
273 RenderLayer* stackingContextAncestor { nullptr };
274 bool subtreeIsCompositing { false };
275 bool testingOverlap { true };
276 bool fullPaintOrderTraversalRequired { false };
277 bool descendantsRequireCompositingUpdate { false };
278 bool ancestorHasTransformAnimation { false };
279 #if ENABLE(CSS_COMPOSITING)
280 bool hasNotIsolatedCompositedBlendingDescendants { false };
282 #if ENABLE(TREE_DEBUGGING)
287 struct RenderLayerCompositor::BackingSharingState {
288 RenderLayer* backingProviderCandidate { nullptr };
289 RenderLayer* backingProviderStackingContext { nullptr };
290 Vector<WeakPtr<RenderLayer>> backingSharingLayers;
292 void resetBackingProviderCandidate(RenderLayer* candidateLayer = nullptr, RenderLayer* candidateStackingContext = nullptr)
294 if (!backingSharingLayers.isEmpty()) {
295 ASSERT(backingProviderCandidate);
296 backingProviderCandidate->backing()->setBackingSharingLayers(WTFMove(backingSharingLayers));
298 backingProviderCandidate = candidateLayer;
299 backingProviderStackingContext = candidateLayer ? candidateStackingContext : nullptr;
303 struct RenderLayerCompositor::OverlapExtent {
305 bool extentComputed { false };
306 bool hasTransformAnimation { false };
307 bool animationCausesExtentUncertainty { false };
309 bool knownToBeHaveExtentUncertainty() const { return extentComputed && animationCausesExtentUncertainty; }
313 static inline bool compositingLogEnabled()
315 return LogCompositing.state == WTFLogChannelState::On;
318 static inline bool layersLogEnabled()
320 return LogLayers.state == WTFLogChannelState::On;
324 RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView)
325 : m_renderView(renderView)
326 , m_updateCompositingLayersTimer(*this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
327 , m_layerFlushTimer(*this, &RenderLayerCompositor::layerFlushTimerFired)
329 #if PLATFORM(IOS_FAMILY)
330 if (m_renderView.frameView().platformWidget())
331 m_legacyScrollingLayerCoordinator = std::make_unique<LegacyWebKitScrollingLayerCoordinator>(page().chrome().client(), isMainFrameCompositor());
335 RenderLayerCompositor::~RenderLayerCompositor()
337 // Take care that the owned GraphicsLayers are deleted first as their destructors may call back here.
338 GraphicsLayer::unparentAndClear(m_rootContentsLayer);
340 GraphicsLayer::unparentAndClear(m_clipLayer);
341 GraphicsLayer::unparentAndClear(m_scrollContainerLayer);
342 GraphicsLayer::unparentAndClear(m_scrolledContentsLayer);
344 GraphicsLayer::unparentAndClear(m_overflowControlsHostLayer);
346 GraphicsLayer::unparentAndClear(m_layerForHorizontalScrollbar);
347 GraphicsLayer::unparentAndClear(m_layerForVerticalScrollbar);
348 GraphicsLayer::unparentAndClear(m_layerForScrollCorner);
350 #if ENABLE(RUBBER_BANDING)
351 GraphicsLayer::unparentAndClear(m_layerForOverhangAreas);
352 GraphicsLayer::unparentAndClear(m_contentShadowLayer);
353 GraphicsLayer::unparentAndClear(m_layerForTopOverhangArea);
354 GraphicsLayer::unparentAndClear(m_layerForBottomOverhangArea);
355 GraphicsLayer::unparentAndClear(m_layerForHeader);
356 GraphicsLayer::unparentAndClear(m_layerForFooter);
359 ASSERT(m_rootLayerAttachment == RootLayerUnattached);
362 void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
364 if (enable != m_compositing) {
365 m_compositing = enable;
369 notifyIFramesOfCompositingChange();
374 m_renderView.layer()->setNeedsPostLayoutCompositingUpdate();
378 void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
380 auto& settings = m_renderView.settings();
381 bool hasAcceleratedCompositing = settings.acceleratedCompositingEnabled();
383 // We allow the chrome to override the settings, in case the page is rendered
384 // on a chrome that doesn't allow accelerated compositing.
385 if (hasAcceleratedCompositing) {
386 m_compositingTriggers = page().chrome().client().allowedCompositingTriggers();
387 hasAcceleratedCompositing = m_compositingTriggers;
390 bool showDebugBorders = settings.showDebugBorders();
391 bool showRepaintCounter = settings.showRepaintCounter();
392 bool acceleratedDrawingEnabled = settings.acceleratedDrawingEnabled();
393 bool displayListDrawingEnabled = settings.displayListDrawingEnabled();
395 // forceCompositingMode for subframes can only be computed after layout.
396 bool forceCompositingMode = m_forceCompositingMode;
397 if (isMainFrameCompositor())
398 forceCompositingMode = m_renderView.settings().forceCompositingMode() && hasAcceleratedCompositing;
400 if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode) {
401 if (auto* rootLayer = m_renderView.layer()) {
402 rootLayer->setNeedsCompositingConfigurationUpdate();
403 rootLayer->setDescendantsNeedUpdateBackingAndHierarchyTraversal();
407 bool debugBordersChanged = m_showDebugBorders != showDebugBorders;
408 m_hasAcceleratedCompositing = hasAcceleratedCompositing;
409 m_forceCompositingMode = forceCompositingMode;
410 m_showDebugBorders = showDebugBorders;
411 m_showRepaintCounter = showRepaintCounter;
412 m_acceleratedDrawingEnabled = acceleratedDrawingEnabled;
413 m_displayListDrawingEnabled = displayListDrawingEnabled;
415 if (debugBordersChanged) {
416 if (m_layerForHorizontalScrollbar)
417 m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
419 if (m_layerForVerticalScrollbar)
420 m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
422 if (m_layerForScrollCorner)
423 m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
426 if (updateCompositingPolicy())
427 rootRenderLayer().setDescendantsNeedCompositingRequirementsTraversal();
430 void RenderLayerCompositor::cacheAcceleratedCompositingFlagsAfterLayout()
432 cacheAcceleratedCompositingFlags();
434 if (isMainFrameCompositor())
437 RequiresCompositingData queryData;
438 bool forceCompositingMode = m_hasAcceleratedCompositing && m_renderView.settings().forceCompositingMode() && requiresCompositingForScrollableFrame(queryData);
439 if (forceCompositingMode != m_forceCompositingMode) {
440 m_forceCompositingMode = forceCompositingMode;
441 rootRenderLayer().setDescendantsNeedCompositingRequirementsTraversal();
445 bool RenderLayerCompositor::updateCompositingPolicy()
447 if (!usesCompositing())
450 auto currentPolicy = m_compositingPolicy;
451 if (page().compositingPolicyOverride()) {
452 m_compositingPolicy = page().compositingPolicyOverride().value();
453 return m_compositingPolicy != currentPolicy;
456 auto memoryPolicy = MemoryPressureHandler::currentMemoryUsagePolicy();
457 m_compositingPolicy = memoryPolicy == WTF::MemoryUsagePolicy::Unrestricted ? CompositingPolicy::Normal : CompositingPolicy::Conservative;
458 return m_compositingPolicy != currentPolicy;
461 bool RenderLayerCompositor::canRender3DTransforms() const
463 return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger);
466 void RenderLayerCompositor::willRecalcStyle()
468 cacheAcceleratedCompositingFlags();
471 bool RenderLayerCompositor::didRecalcStyleWithNoPendingLayout()
473 return updateCompositingLayers(CompositingUpdateType::AfterStyleChange);
476 void RenderLayerCompositor::customPositionForVisibleRectComputation(const GraphicsLayer* graphicsLayer, FloatPoint& position) const
478 if (graphicsLayer != m_scrolledContentsLayer.get())
481 FloatPoint scrollPosition = -position;
483 if (m_renderView.frameView().scrollBehaviorForFixedElements() == StickToDocumentBounds)
484 scrollPosition = m_renderView.frameView().constrainScrollPositionForOverhang(roundedIntPoint(scrollPosition));
486 position = -scrollPosition;
489 void RenderLayerCompositor::notifyFlushRequired(const GraphicsLayer* layer)
491 scheduleLayerFlush(layer->canThrottleLayerFlush());
494 void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle)
496 ASSERT(!m_flushingLayers);
499 startInitialLayerFlushTimerIfNeeded();
501 if (canThrottle && isThrottlingLayerFlushes())
502 m_hasPendingLayerFlush = true;
504 m_hasPendingLayerFlush = false;
505 page().renderingUpdateScheduler().scheduleRenderingUpdate();
509 FloatRect RenderLayerCompositor::visibleRectForLayerFlushing() const
511 const FrameView& frameView = m_renderView.frameView();
512 #if PLATFORM(IOS_FAMILY)
513 return frameView.exposedContentRect();
515 // Having a m_scrolledContentsLayer indicates that we're doing scrolling via GraphicsLayers.
516 FloatRect visibleRect = m_scrolledContentsLayer ? FloatRect({ }, frameView.sizeForVisibleContent()) : frameView.visibleContentRect();
518 if (frameView.viewExposedRect())
519 visibleRect.intersect(frameView.viewExposedRect().value());
525 void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot)
527 // FrameView::flushCompositingStateIncludingSubframes() flushes each subframe,
528 // but GraphicsLayer::flushCompositingState() will cross frame boundaries
529 // if the GraphicsLayers are connected (the RootLayerAttachedViaEnclosingFrame case).
530 // As long as we're not the root of the flush, we can bail.
531 if (!isFlushRoot && rootLayerAttachment() == RootLayerAttachedViaEnclosingFrame)
534 if (rootLayerAttachment() == RootLayerUnattached) {
535 #if PLATFORM(IOS_FAMILY)
536 startLayerFlushTimerIfNeeded();
538 m_shouldFlushOnReattach = true;
542 auto& frameView = m_renderView.frameView();
543 AnimationUpdateBlock animationUpdateBlock(&frameView.frame().animation());
545 ASSERT(!m_flushingLayers);
547 SetForScope<bool> flushingLayersScope(m_flushingLayers, true);
549 if (auto* rootLayer = rootGraphicsLayer()) {
550 FloatRect visibleRect = visibleRectForLayerFlushing();
551 LOG_WITH_STREAM(Compositing, stream << "\nRenderLayerCompositor " << this << " flushPendingLayerChanges (is root " << isFlushRoot << ") visible rect " << visibleRect);
552 rootLayer->flushCompositingState(visibleRect);
555 ASSERT(m_flushingLayers);
557 #if ENABLE(TREE_DEBUGGING)
558 if (layersLogEnabled()) {
559 LOG(Layers, "RenderLayerCompositor::flushPendingLayerChanges");
560 showGraphicsLayerTree(m_rootContentsLayer.get());
565 #if PLATFORM(IOS_FAMILY)
566 updateScrollCoordinatedLayersAfterFlushIncludingSubframes();
569 page().chrome().client().didFlushCompositingLayers();
573 startLayerFlushTimerIfNeeded();
576 #if PLATFORM(IOS_FAMILY)
577 void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlushIncludingSubframes()
579 updateScrollCoordinatedLayersAfterFlush();
581 auto& frame = m_renderView.frameView().frame();
582 for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().traverseNext(&frame)) {
583 auto* view = subframe->contentRenderer();
587 view->compositor().updateScrollCoordinatedLayersAfterFlush();
591 void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush()
593 if (m_legacyScrollingLayerCoordinator) {
594 m_legacyScrollingLayerCoordinator->registerAllViewportConstrainedLayers(*this);
595 m_legacyScrollingLayerCoordinator->registerScrollingLayersNeedingUpdate();
600 void RenderLayerCompositor::didChangePlatformLayerForLayer(RenderLayer& layer, const GraphicsLayer*)
602 #if PLATFORM(IOS_FAMILY)
603 if (m_legacyScrollingLayerCoordinator)
604 m_legacyScrollingLayerCoordinator->didChangePlatformLayerForLayer(layer);
607 auto* scrollingCoordinator = this->scrollingCoordinator();
608 if (!scrollingCoordinator)
611 auto* backing = layer.backing();
612 if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling))
613 updateScrollingNodeLayers(nodeID, layer, *scrollingCoordinator);
615 if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::ViewportConstrained))
616 scrollingCoordinator->setNodeLayers(nodeID, { backing->graphicsLayer() });
618 if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting))
619 scrollingCoordinator->setNodeLayers(nodeID, { backing->graphicsLayer() });
621 if (auto nodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::Positioning))
622 scrollingCoordinator->setNodeLayers(nodeID, { backing->graphicsLayer() });
625 void RenderLayerCompositor::didPaintBacking(RenderLayerBacking*)
627 auto& frameView = m_renderView.frameView();
628 frameView.setLastPaintTime(MonotonicTime::now());
629 if (frameView.milestonesPendingPaint())
630 frameView.firePaintRelatedMilestonesIfNeeded();
633 void RenderLayerCompositor::didChangeVisibleRect()
635 auto* rootLayer = rootGraphicsLayer();
639 FloatRect visibleRect = visibleRectForLayerFlushing();
640 bool requiresFlush = rootLayer->visibleRectChangeRequiresFlush(visibleRect);
641 LOG_WITH_STREAM(Compositing, stream << "RenderLayerCompositor::didChangeVisibleRect " << visibleRect << " requiresFlush " << requiresFlush);
643 scheduleLayerFlush();
646 void RenderLayerCompositor::notifyFlushBeforeDisplayRefresh(const GraphicsLayer*)
648 if (!m_layerUpdater) {
649 PlatformDisplayID displayID = page().chrome().displayID();
650 m_layerUpdater = std::make_unique<GraphicsLayerUpdater>(*this, displayID);
653 m_layerUpdater->scheduleUpdate();
656 void RenderLayerCompositor::flushLayersSoon(GraphicsLayerUpdater&)
658 scheduleLayerFlush(true);
661 void RenderLayerCompositor::layerTiledBackingUsageChanged(const GraphicsLayer* graphicsLayer, bool usingTiledBacking)
663 if (usingTiledBacking) {
664 ++m_layersWithTiledBackingCount;
665 graphicsLayer->tiledBacking()->setIsInWindow(page().isInWindow());
667 ASSERT(m_layersWithTiledBackingCount > 0);
668 --m_layersWithTiledBackingCount;
672 void RenderLayerCompositor::scheduleCompositingLayerUpdate()
674 if (!m_updateCompositingLayersTimer.isActive())
675 m_updateCompositingLayersTimer.startOneShot(0_s);
678 void RenderLayerCompositor::updateCompositingLayersTimerFired()
680 updateCompositingLayers(CompositingUpdateType::AfterLayout);
683 void RenderLayerCompositor::cancelCompositingLayerUpdate()
685 m_updateCompositingLayersTimer.stop();
688 static Optional<ScrollingNodeID> frameHostingNodeForFrame(Frame& frame)
690 if (!frame.document() || !frame.view())
693 // Find the frame's enclosing layer in our render tree.
694 auto* ownerElement = frame.document()->ownerElement();
698 auto* frameRenderer = ownerElement->renderer();
699 if (!frameRenderer || !is<RenderWidget>(frameRenderer))
702 auto& widgetRenderer = downcast<RenderWidget>(*frameRenderer);
703 if (!widgetRenderer.hasLayer() || !widgetRenderer.layer()->isComposited()) {
704 LOG(Scrolling, "frameHostingNodeForFrame: frame renderer has no layer or is not composited.");
708 if (auto frameHostingNodeID = widgetRenderer.layer()->backing()->scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting))
709 return frameHostingNodeID;
714 // Returns true on a successful update.
715 bool RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
717 LOG_WITH_STREAM(Compositing, stream << "RenderLayerCompositor " << this << " updateCompositingLayers " << updateType << " contentLayersCount " << m_contentLayersCount);
719 #if ENABLE(TREE_DEBUGGING)
720 if (compositingLogEnabled())
721 showPaintOrderTree(m_renderView.layer());
724 if (updateType == CompositingUpdateType::AfterStyleChange || updateType == CompositingUpdateType::AfterLayout)
725 cacheAcceleratedCompositingFlagsAfterLayout(); // Some flags (e.g. forceCompositingMode) depend on layout.
727 m_updateCompositingLayersTimer.stop();
729 ASSERT(m_renderView.document().pageCacheState() == Document::NotInPageCache);
731 // Compositing layers will be updated in Document::setVisualUpdatesAllowed(bool) if suppressed here.
732 if (!m_renderView.document().visualUpdatesAllowed())
735 // Avoid updating the layers with old values. Compositing layers will be updated after the layout is finished.
736 // This happens when m_updateCompositingLayersTimer fires before layout is updated.
737 if (m_renderView.needsLayout()) {
738 LOG_WITH_STREAM(Compositing, stream << "RenderLayerCompositor " << this << " updateCompositingLayers " << updateType << " - m_renderView.needsLayout, bailing ");
742 if (!m_compositing && (m_forceCompositingMode || (isMainFrameCompositor() && page().pageOverlayController().overlayCount())))
743 enableCompositingMode(true);
745 bool isPageScroll = !updateRoot || updateRoot == &rootRenderLayer();
746 updateRoot = &rootRenderLayer();
748 if (updateType == CompositingUpdateType::OnScroll || updateType == CompositingUpdateType::OnCompositedScroll) {
749 // We only get here if we didn't scroll on the scrolling thread, so this update needs to re-position viewport-constrained layers.
750 if (m_renderView.settings().acceleratedCompositingForFixedPositionEnabled() && isPageScroll) {
751 if (auto* viewportConstrainedObjects = m_renderView.frameView().viewportConstrainedObjects()) {
752 for (auto* renderer : *viewportConstrainedObjects) {
753 if (auto* layer = renderer->layer())
754 layer->setNeedsCompositingGeometryUpdate();
759 // Scrolling can affect overlap. FIXME: avoid for page scrolling.
760 updateRoot->setDescendantsNeedCompositingRequirementsTraversal();
763 if (updateType == CompositingUpdateType::AfterLayout) {
764 // Ensure that post-layout updates push new scroll position and viewport rects onto the root node.
765 rootRenderLayer().setNeedsScrollingTreeUpdate();
768 if (!updateRoot->hasDescendantNeedingCompositingRequirementsTraversal() && !m_compositing) {
769 LOG_WITH_STREAM(Compositing, stream << " no compositing work to do");
773 if (!updateRoot->needsAnyCompositingTraversal()) {
774 LOG_WITH_STREAM(Compositing, stream << " updateRoot has no dirty child and doesn't need update");
778 ++m_compositingUpdateCount;
780 AnimationUpdateBlock animationUpdateBlock(&m_renderView.frameView().frame().animation());
782 SetForScope<bool> postLayoutChange(m_inPostLayoutUpdate, true);
785 MonotonicTime startTime;
786 if (compositingLogEnabled()) {
787 ++m_rootLayerUpdateCount;
788 startTime = MonotonicTime::now();
791 if (compositingLogEnabled()) {
792 m_obligateCompositedLayerCount = 0;
793 m_secondaryCompositedLayerCount = 0;
794 m_obligatoryBackingStoreBytes = 0;
795 m_secondaryBackingStoreBytes = 0;
797 auto& frame = m_renderView.frameView().frame();
798 bool isMainFrame = isMainFrameCompositor();
799 LOG_WITH_STREAM(Compositing, stream << "\nUpdate " << m_rootLayerUpdateCount << " of " << (isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data()) << " - compositing policy is " << m_compositingPolicy);
803 // FIXME: optimize root-only update.
804 if (updateRoot->hasDescendantNeedingCompositingRequirementsTraversal() || updateRoot->needsCompositingRequirementsTraversal()) {
805 CompositingState compositingState(updateRoot);
806 BackingSharingState backingSharingState;
807 OverlapMap overlapMap;
809 bool descendantHas3DTransform = false;
810 computeCompositingRequirements(nullptr, rootRenderLayer(), overlapMap, compositingState, backingSharingState, descendantHas3DTransform);
813 LOG(Compositing, "\nRenderLayerCompositor::updateCompositingLayers - mid");
814 #if ENABLE(TREE_DEBUGGING)
815 if (compositingLogEnabled())
816 showPaintOrderTree(m_renderView.layer());
819 if (updateRoot->hasDescendantNeedingUpdateBackingOrHierarchyTraversal() || updateRoot->needsUpdateBackingOrHierarchyTraversal()) {
820 ScrollingTreeState scrollingTreeState = { 0, 0 };
821 if (!m_renderView.frame().isMainFrame())
822 scrollingTreeState.parentNodeID = frameHostingNodeForFrame(m_renderView.frame());
824 Vector<Ref<GraphicsLayer>> childList;
825 updateBackingAndHierarchy(*updateRoot, childList, scrollingTreeState);
827 // Host the document layer in the RenderView's root layer.
828 appendDocumentOverlayLayers(childList);
829 // Even when childList is empty, don't drop out of compositing mode if there are
830 // composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
831 if (childList.isEmpty() && !needsCompositingForContentOrOverlays())
833 else if (m_rootContentsLayer)
834 m_rootContentsLayer->setChildren(WTFMove(childList));
838 if (compositingLogEnabled()) {
839 MonotonicTime endTime = MonotonicTime::now();
840 LOG(Compositing, "Total layers primary secondary obligatory backing (KB) secondary backing(KB) total backing (KB) update time (ms)\n");
842 LOG(Compositing, "%8d %11d %9d %20.2f %22.2f %22.2f %18.2f\n",
843 m_obligateCompositedLayerCount + m_secondaryCompositedLayerCount, m_obligateCompositedLayerCount,
844 m_secondaryCompositedLayerCount, m_obligatoryBackingStoreBytes / 1024, m_secondaryBackingStoreBytes / 1024, (m_obligatoryBackingStoreBytes + m_secondaryBackingStoreBytes) / 1024, (endTime - startTime).milliseconds());
848 // FIXME: Only do if dirty.
849 updateRootLayerPosition();
851 #if ENABLE(TREE_DEBUGGING)
852 if (compositingLogEnabled()) {
853 LOG(Compositing, "RenderLayerCompositor::updateCompositingLayers - post");
854 showPaintOrderTree(m_renderView.layer());
858 InspectorInstrumentation::layerTreeDidChange(&page());
863 static bool backingProviderLayerCanIncludeLayer(const RenderLayer& sharedLayer, const RenderLayer& layer)
865 // Disable sharing when painting shared layers doesn't work correctly.
866 if (layer.hasReflection())
869 return layer.ancestorLayerIsInContainingBlockChain(sharedLayer);
872 void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer& layer, OverlapMap& overlapMap, CompositingState& compositingState, BackingSharingState& backingSharingState, bool& descendantHas3DTransform)
874 if (!layer.hasDescendantNeedingCompositingRequirementsTraversal()
875 && !layer.needsCompositingRequirementsTraversal()
876 && !compositingState.fullPaintOrderTraversalRequired
877 && !compositingState.descendantsRequireCompositingUpdate) {
878 traverseUnchangedSubtree(ancestorLayer, layer, overlapMap, compositingState, backingSharingState, descendantHas3DTransform);
882 #if ENABLE(TREE_DEBUGGING)
883 LOG(Compositing, "%*p %s computeCompositingRequirements (backing provider candidate %p)", 12 + compositingState.depth * 2, &layer, layer.isNormalFlowOnly() ? "n" : "s", backingSharingState.backingProviderCandidate);
886 // FIXME: maybe we can avoid updating all remaining layers in paint order.
887 compositingState.fullPaintOrderTraversalRequired |= layer.needsCompositingRequirementsTraversal();
888 compositingState.descendantsRequireCompositingUpdate |= layer.descendantsNeedCompositingRequirementsTraversal();
890 layer.updateDescendantDependentFlags();
891 layer.updateLayerListsIfNeeded();
893 layer.setHasCompositingDescendant(false);
894 layer.setBackingProviderLayer(nullptr);
896 // We updated compositing for direct reasons in layerStyleChanged(). Here, check for compositing that can only be evaluated after layout.
897 RequiresCompositingData queryData;
898 bool willBeComposited = layer.isComposited();
899 if (layer.needsPostLayoutCompositingUpdate() || compositingState.fullPaintOrderTraversalRequired || compositingState.descendantsRequireCompositingUpdate) {
900 layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::None);
901 willBeComposited = needsToBeComposited(layer, queryData);
904 compositingState.fullPaintOrderTraversalRequired |= layer.subsequentLayersNeedCompositingRequirementsTraversal();
906 OverlapExtent layerExtent;
907 // Use the fact that we're composited as a hint to check for an animating transform.
908 // FIXME: Maybe needsToBeComposited() should return a bitmask of reasons, to avoid the need to recompute things.
909 if (willBeComposited && !layer.isRenderViewLayer())
910 layerExtent.hasTransformAnimation = isRunningTransformAnimation(layer.renderer());
912 bool respectTransforms = !layerExtent.hasTransformAnimation;
913 overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer, respectTransforms);
915 RenderLayer::IndirectCompositingReason compositingReason = compositingState.subtreeIsCompositing ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None;
916 bool layerPaintsIntoProvidedBacking = false;
918 // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map
919 if (!willBeComposited && !overlapMap.isEmpty() && compositingState.testingOverlap) {
920 computeExtent(overlapMap, layer, layerExtent);
922 // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
923 if (overlapMap.overlapsLayers(layerExtent.bounds)) {
924 if (backingSharingState.backingProviderCandidate && canBeComposited(layer) && backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate, layer)) {
925 backingSharingState.backingSharingLayers.append(makeWeakPtr(layer));
926 LOG(Compositing, " layer %p can share with %p", &layer, backingSharingState.backingProviderCandidate);
927 compositingReason = RenderLayer::IndirectCompositingReason::None;
928 layerPaintsIntoProvidedBacking = true;
930 compositingReason = RenderLayer::IndirectCompositingReason::Overlap;
932 compositingReason = RenderLayer::IndirectCompositingReason::None;
936 // Video is special. It's the only RenderLayer type that can both have
937 // RenderLayer children and whose children can't use its backing to render
938 // into. These children (the controls) always need to be promoted into their
939 // own layers to draw on top of the accelerated video.
940 if (compositingState.compositingAncestor && compositingState.compositingAncestor->renderer().isVideo())
941 compositingReason = RenderLayer::IndirectCompositingReason::Overlap;
944 if (compositingReason != RenderLayer::IndirectCompositingReason::None)
945 layer.setIndirectCompositingReason(compositingReason);
947 // Check if the computed indirect reason will force the layer to become composited.
948 if (!willBeComposited && layer.mustCompositeForIndirectReasons() && canBeComposited(layer))
949 willBeComposited = true;
951 // The children of this layer don't need to composite, unless there is
952 // a compositing layer among them, so start by inheriting the compositing
953 // ancestor with subtreeIsCompositing set to false.
954 CompositingState childState = compositingState.stateForPaintOrderChildren(layer);
956 auto layerWillComposite = [&](bool postDescendants = false) {
957 // This layer now acts as the ancestor for kids.
958 childState.compositingAncestor = &layer;
959 overlapMap.pushCompositingContainer();
961 if (postDescendants) {
962 childState.subtreeIsCompositing = true;
963 addToOverlapMapRecursive(overlapMap, layer);
966 // This layer is going to be composited, so children can safely ignore the fact that there's an
967 // animation running behind this layer, meaning they can rely on the overlap map testing again.
968 childState.testingOverlap = true;
969 willBeComposited = true;
971 layerPaintsIntoProvidedBacking = false;
972 layer.disconnectFromBackingProviderLayer();
973 backingSharingState.backingSharingLayers.removeAll(&layer);
976 if (willBeComposited) {
977 // Tell the parent it has compositing descendants.
978 compositingState.subtreeIsCompositing = true;
980 layerWillComposite();
982 computeExtent(overlapMap, layer, layerExtent);
983 childState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation;
984 // Too hard to compute animated bounds if both us and some ancestor is animating transform.
985 layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation;
987 // Compositing for any reason disables backing sharing.
988 LOG_WITH_STREAM(Compositing, stream << &layer << " is compositing - flushing sharing to " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
989 backingSharingState.resetBackingProviderCandidate();
990 } else if (layerPaintsIntoProvidedBacking) {
991 childState.backingSharingAncestor = &layer;
992 overlapMap.pushCompositingContainer();
996 LayerListMutationDetector mutationChecker(layer);
999 bool anyDescendantHas3DTransform = false;
1001 for (auto* childLayer : layer.negativeZOrderLayers()) {
1002 computeCompositingRequirements(&layer, *childLayer, overlapMap, childState, backingSharingState, anyDescendantHas3DTransform);
1004 // If we have to make a layer for this child, make one now so we can have a contents layer
1005 // (since we need to ensure that the -ve z-order child renders underneath our contents).
1006 if (!willBeComposited && childState.subtreeIsCompositing) {
1007 // make layer compositing
1008 layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::BackgroundLayer);
1009 layerWillComposite();
1013 for (auto* childLayer : layer.normalFlowLayers())
1014 computeCompositingRequirements(&layer, *childLayer, overlapMap, childState, backingSharingState, anyDescendantHas3DTransform);
1016 for (auto* childLayer : layer.positiveZOrderLayers())
1017 computeCompositingRequirements(&layer, *childLayer, overlapMap, childState, backingSharingState, anyDescendantHas3DTransform);
1019 // If we just entered compositing mode, the root will have become composited (as long as accelerated compositing is enabled).
1020 if (layer.isRenderViewLayer()) {
1021 if (usesCompositing() && m_hasAcceleratedCompositing)
1022 willBeComposited = true;
1025 // All layers (even ones that aren't being composited) need to get added to
1026 // the overlap map. Layers that do not composite will draw into their
1027 // compositing ancestor's backing, and so are still considered for overlap.
1028 // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds
1029 // include descendants, so we don't need to add them all to the overlap map.
1030 if (childState.compositingAncestor && !childState.compositingAncestor->isRenderViewLayer())
1031 addToOverlapMap(overlapMap, layer, layerExtent);
1033 #if ENABLE(CSS_COMPOSITING)
1034 bool isolatedCompositedBlending = layer.isolatesCompositedBlending();
1035 layer.setHasNotIsolatedCompositedBlendingDescendants(childState.hasNotIsolatedCompositedBlendingDescendants);
1036 if (layer.isolatesCompositedBlending() != isolatedCompositedBlending) {
1037 // isolatedCompositedBlending affects the result of clippedByAncestor().
1038 layer.setChildrenNeedCompositingGeometryUpdate();
1041 ASSERT(!layer.hasNotIsolatedCompositedBlendingDescendants() || layer.hasNotIsolatedBlendingDescendants());
1043 // Now check for reasons to become composited that depend on the state of descendant layers.
1044 RenderLayer::IndirectCompositingReason indirectCompositingReason;
1045 if (!willBeComposited && canBeComposited(layer)
1046 && requiresCompositingForIndirectReason(layer, compositingState.compositingAncestor, childState.subtreeIsCompositing, anyDescendantHas3DTransform, layerPaintsIntoProvidedBacking, indirectCompositingReason)) {
1047 layer.setIndirectCompositingReason(indirectCompositingReason);
1048 layerWillComposite(true);
1051 if (layer.reflectionLayer()) {
1052 // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
1053 layer.reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None);
1056 // Set the flag to say that this layer has compositing children.
1057 layer.setHasCompositingDescendant(childState.subtreeIsCompositing);
1059 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, so test that again.
1060 bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer);
1062 // Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
1063 // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
1064 // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
1065 if ((!childState.testingOverlap && !isCompositedClippingLayer) || layerExtent.knownToBeHaveExtentUncertainty())
1066 compositingState.testingOverlap = false;
1068 if (isCompositedClippingLayer & !willBeComposited)
1069 layerWillComposite(true);
1071 #if ENABLE(CSS_COMPOSITING)
1072 if ((willBeComposited && layer.hasBlendMode()) || (layer.hasNotIsolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending()))
1073 compositingState.hasNotIsolatedCompositedBlendingDescendants = true;
1076 if ((childState.compositingAncestor == &layer && !layer.isRenderViewLayer()) || childState.backingSharingAncestor == &layer)
1077 overlapMap.popCompositingContainer();
1079 // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need
1080 // to be composited, then we can drop out of compositing mode altogether. However, don't drop out of compositing mode
1081 // if there are composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
1082 RequiresCompositingData rootLayerQueryData;
1083 if (layer.isRenderViewLayer() && !childState.subtreeIsCompositing && !requiresCompositingLayer(layer, rootLayerQueryData) && !m_forceCompositingMode && !needsCompositingForContentOrOverlays()) {
1084 // Don't drop out of compositing on iOS, because we may flash. See <rdar://problem/8348337>.
1085 #if !PLATFORM(IOS_FAMILY)
1086 enableCompositingMode(false);
1087 willBeComposited = false;
1091 compositingState.propagateStateFromChildren(childState);
1093 ASSERT(willBeComposited == needsToBeComposited(layer, queryData));
1095 // Create or destroy backing here. However, we can't update geometry because layers above us may become composited
1096 // during post-order traversal (e.g. for clipping).
1097 if (updateBacking(layer, queryData, CompositingChangeRepaintNow, willBeComposited ? BackingRequired::Yes : BackingRequired::No)) {
1098 layer.setNeedsCompositingLayerConnection();
1099 // Child layers need to get a geometry update to recompute their position.
1100 layer.setChildrenNeedCompositingGeometryUpdate();
1101 // The composited bounds of enclosing layers depends on which descendants are composited, so they need a geometry update.
1102 layer.setNeedsCompositingGeometryUpdateOnAncestors();
1103 } else if (layer.isComposited())
1104 layer.backing()->clearBackingSharingLayers();
1106 if (backingSharingState.backingProviderCandidate && &layer == backingSharingState.backingProviderStackingContext) {
1107 LOG_WITH_STREAM(Compositing, stream << &layer << " popping stacking context " << backingSharingState.backingProviderStackingContext << ", flushing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
1108 backingSharingState.resetBackingProviderCandidate();
1109 } else if (!backingSharingState.backingProviderCandidate && layer.isComposited()) {
1110 LOG_WITH_STREAM(Compositing, stream << &layer << " compositing - sharing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
1111 // Flush out any earlier candidate in this stacking context. This layer becomes a candidate.
1112 backingSharingState.resetBackingProviderCandidate(&layer, compositingState.stackingContextAncestor);
1115 if (layer.reflectionLayer() && updateLayerCompositingState(*layer.reflectionLayer(), queryData, CompositingChangeRepaintNow))
1116 layer.setNeedsCompositingLayerConnection();
1118 descendantHas3DTransform |= anyDescendantHas3DTransform || layer.has3DTransform();
1120 // FIXME: clarify needsCompositingPaintOrderChildrenUpdate. If a composited layer gets a new ancestor, it needs geometry computations.
1121 if (layer.needsCompositingPaintOrderChildrenUpdate()) {
1122 layer.setChildrenNeedCompositingGeometryUpdate();
1123 layer.setNeedsCompositingLayerConnection();
1126 #if ENABLE(TREE_DEBUGGING)
1127 LOG(Compositing, "%*p computeCompositingRequirements - willBeComposited %d (backing provider candidate %p)", 12 + compositingState.depth * 2, &layer, willBeComposited, backingSharingState.backingProviderCandidate);
1130 layer.clearCompositingRequirementsTraversalState();
1132 overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
1135 // We have to traverse unchanged layers to fill in the overlap map.
1136 void RenderLayerCompositor::traverseUnchangedSubtree(RenderLayer* ancestorLayer, RenderLayer& layer, OverlapMap& overlapMap, CompositingState& compositingState, BackingSharingState& backingSharingState, bool& descendantHas3DTransform)
1138 ASSERT(!compositingState.fullPaintOrderTraversalRequired);
1139 ASSERT(!layer.hasDescendantNeedingCompositingRequirementsTraversal());
1140 ASSERT(!layer.needsCompositingRequirementsTraversal());
1142 #if ENABLE(TREE_DEBUGGING)
1143 LOG(Compositing, "%*p traverseUnchangedSubtree", 12 + compositingState.depth * 2, &layer);
1146 layer.updateDescendantDependentFlags();
1147 layer.updateLayerListsIfNeeded();
1149 bool layerIsComposited = layer.isComposited();
1151 OverlapExtent layerExtent;
1152 if (layerIsComposited && !layer.isRenderViewLayer())
1153 layerExtent.hasTransformAnimation = isRunningTransformAnimation(layer.renderer());
1155 bool respectTransforms = !layerExtent.hasTransformAnimation;
1156 overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer, respectTransforms);
1158 // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map
1159 if (!layerIsComposited && !overlapMap.isEmpty() && compositingState.testingOverlap)
1160 computeExtent(overlapMap, layer, layerExtent);
1162 if (layer.paintsIntoProvidedBacking()) {
1163 ASSERT(backingSharingState.backingProviderCandidate);
1164 ASSERT(backingProviderLayerCanIncludeLayer(*backingSharingState.backingProviderCandidate, layer));
1165 backingSharingState.backingSharingLayers.append(makeWeakPtr(layer));
1168 CompositingState childState = compositingState.stateForPaintOrderChildren(layer);
1170 if (layerIsComposited) {
1171 // Tell the parent it has compositing descendants.
1172 compositingState.subtreeIsCompositing = true;
1173 // This layer now acts as the ancestor for kids.
1174 childState.compositingAncestor = &layer;
1176 overlapMap.pushCompositingContainer();
1177 // This layer is going to be composited, so children can safely ignore the fact that there's an
1178 // animation running behind this layer, meaning they can rely on the overlap map testing again.
1179 childState.testingOverlap = true;
1181 computeExtent(overlapMap, layer, layerExtent);
1182 childState.ancestorHasTransformAnimation |= layerExtent.hasTransformAnimation;
1183 // Too hard to compute animated bounds if both us and some ancestor is animating transform.
1184 layerExtent.animationCausesExtentUncertainty |= layerExtent.hasTransformAnimation && compositingState.ancestorHasTransformAnimation;
1186 // Compositing for any reason disables backing sharing.
1187 LOG_WITH_STREAM(Compositing, stream << "tus: " << &layer << " is compositing - flushing sharing to " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
1188 backingSharingState.resetBackingProviderCandidate();
1191 #if !ASSERT_DISABLED
1192 LayerListMutationDetector mutationChecker(layer);
1195 bool anyDescendantHas3DTransform = false;
1197 for (auto* childLayer : layer.negativeZOrderLayers()) {
1198 traverseUnchangedSubtree(&layer, *childLayer, overlapMap, childState, backingSharingState, anyDescendantHas3DTransform);
1199 if (childState.subtreeIsCompositing)
1200 ASSERT(layerIsComposited);
1203 for (auto* childLayer : layer.normalFlowLayers())
1204 traverseUnchangedSubtree(&layer, *childLayer, overlapMap, childState, backingSharingState, anyDescendantHas3DTransform);
1206 for (auto* childLayer : layer.positiveZOrderLayers())
1207 traverseUnchangedSubtree(&layer, *childLayer, overlapMap, childState, backingSharingState, anyDescendantHas3DTransform);
1209 // All layers (even ones that aren't being composited) need to get added to
1210 // the overlap map. Layers that do not composite will draw into their
1211 // compositing ancestor's backing, and so are still considered for overlap.
1212 // FIXME: When layerExtent has taken animation bounds into account, we also know that the bounds
1213 // include descendants, so we don't need to add them all to the overlap map.
1214 if (childState.compositingAncestor && !childState.compositingAncestor->isRenderViewLayer())
1215 addToOverlapMap(overlapMap, layer, layerExtent);
1217 compositingState.propagateStateFromChildrenForUnchangedSubtree(childState);
1219 // Set the flag to say that this layer has compositing children.
1220 ASSERT(layer.hasCompositingDescendant() == childState.subtreeIsCompositing);
1222 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, so test that again.
1223 bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer);
1225 // Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
1226 // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
1227 // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
1228 if ((!childState.testingOverlap && !isCompositedClippingLayer) || layerExtent.knownToBeHaveExtentUncertainty())
1229 compositingState.testingOverlap = false;
1231 if (isCompositedClippingLayer)
1232 ASSERT(layerIsComposited);
1234 #if ENABLE(CSS_COMPOSITING)
1235 if ((layerIsComposited && layer.hasBlendMode())
1236 || (layer.hasNotIsolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending()))
1237 compositingState.hasNotIsolatedCompositedBlendingDescendants = true;
1240 if ((childState.compositingAncestor == &layer && !layer.isRenderViewLayer()) || childState.backingSharingAncestor == &layer)
1241 overlapMap.popCompositingContainer();
1243 if (layer.isComposited())
1244 layer.backing()->clearBackingSharingLayers();
1246 if (backingSharingState.backingProviderCandidate && &layer == backingSharingState.backingProviderStackingContext) {
1247 LOG_WITH_STREAM(Compositing, stream << &layer << " tus: popping stacking context " << backingSharingState.backingProviderStackingContext << ", flushing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
1248 backingSharingState.resetBackingProviderCandidate();
1249 } else if (!backingSharingState.backingProviderCandidate && layer.isComposited()) {
1250 LOG_WITH_STREAM(Compositing, stream << &layer << " tus: compositing - sharing candidate " << backingSharingState.backingProviderCandidate << " with " << backingSharingState.backingSharingLayers.size() << " sharing layers");
1251 // Flush out any earlier candidate in this stacking context. This layer becomes a candidate.
1252 backingSharingState.resetBackingProviderCandidate(&layer, compositingState.stackingContextAncestor);
1255 descendantHas3DTransform |= anyDescendantHas3DTransform || layer.has3DTransform();
1257 ASSERT(!layer.needsCompositingRequirementsTraversal());
1259 overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
1262 void RenderLayerCompositor::updateBackingAndHierarchy(RenderLayer& layer, Vector<Ref<GraphicsLayer>>& childLayersOfEnclosingLayer, ScrollingTreeState& scrollingTreeState, OptionSet<UpdateLevel> updateLevel, int depth)
1264 layer.updateDescendantDependentFlags();
1265 layer.updateLayerListsIfNeeded();
1267 bool layerNeedsUpdate = !updateLevel.isEmpty();
1268 if (layer.descendantsNeedUpdateBackingAndHierarchyTraversal())
1269 updateLevel.add(UpdateLevel::AllDescendants);
1271 ScrollingTreeState stateForDescendants = scrollingTreeState;
1273 auto* layerBacking = layer.backing();
1275 updateLevel.remove(UpdateLevel::CompositedChildren);
1277 // We updated the composited bounds in RenderLayerBacking::updateAfterLayout(), but it may have changed
1278 // based on which descendants are now composited.
1279 if (layerBacking->updateCompositedBounds()) {
1280 layer.setNeedsCompositingGeometryUpdate();
1281 // Our geometry can affect descendants.
1282 updateLevel.add(UpdateLevel::CompositedChildren);
1285 if (layerNeedsUpdate || layer.needsCompositingConfigurationUpdate()) {
1286 if (layerBacking->updateConfiguration()) {
1287 layerNeedsUpdate = true; // We also need to update geometry.
1288 layer.setNeedsCompositingLayerConnection();
1291 layerBacking->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter);
1294 OptionSet<ScrollingNodeChangeFlags> scrollingNodeChanges = { ScrollingNodeChangeFlags::Layer };
1295 if (layerNeedsUpdate || layer.needsCompositingGeometryUpdate()) {
1296 layerBacking->updateGeometry();
1297 scrollingNodeChanges.add(ScrollingNodeChangeFlags::LayerGeometry);
1298 } else if (layer.needsScrollingTreeUpdate())
1299 scrollingNodeChanges.add(ScrollingNodeChangeFlags::LayerGeometry);
1301 if (auto* reflection = layer.reflectionLayer()) {
1302 if (auto* reflectionBacking = reflection->backing()) {
1303 reflectionBacking->updateCompositedBounds();
1304 reflectionBacking->updateGeometry();
1305 reflectionBacking->updateAfterDescendants();
1309 if (!layer.parent())
1310 updateRootLayerPosition();
1312 // FIXME: do based on dirty flags. Need to do this for changes of geometry, configuration and hierarchy.
1313 // Need to be careful to do the right thing when a scroll-coordinated layer loses a scroll-coordinated ancestor.
1314 stateForDescendants.parentNodeID = updateScrollCoordinationForLayer(layer, scrollingTreeState, layerBacking->coordinatedScrollingRoles(), scrollingNodeChanges);
1315 stateForDescendants.nextChildIndex = 0;
1318 logLayerInfo(layer, "updateBackingAndHierarchy", depth);
1320 UNUSED_PARAM(depth);
1324 if (layer.childrenNeedCompositingGeometryUpdate())
1325 updateLevel.add(UpdateLevel::CompositedChildren);
1327 // If this layer has backing, then we are collecting its children, otherwise appending
1328 // to the compositing child list of an enclosing layer.
1329 Vector<Ref<GraphicsLayer>> layerChildren;
1330 auto& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer;
1332 bool requireDescendantTraversal = layer.hasDescendantNeedingUpdateBackingOrHierarchyTraversal()
1333 || (layer.hasCompositingDescendant() && (!layerBacking || layer.needsCompositingLayerConnection() || !updateLevel.isEmpty()));
1335 bool requiresChildRebuild = layerBacking && layer.needsCompositingLayerConnection() && !layer.hasCompositingDescendant();
1337 #if !ASSERT_DISABLED
1338 LayerListMutationDetector mutationChecker(layer);
1341 auto appendForegroundLayerIfNecessary = [&] () {
1342 // If a negative z-order child is compositing, we get a foreground layer which needs to get parented.
1343 if (layer.negativeZOrderLayers().size()) {
1344 if (layerBacking && layerBacking->foregroundLayer())
1345 childList.append(*layerBacking->foregroundLayer());
1349 if (requireDescendantTraversal) {
1350 for (auto* renderLayer : layer.negativeZOrderLayers())
1351 updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);
1353 appendForegroundLayerIfNecessary();
1355 for (auto* renderLayer : layer.normalFlowLayers())
1356 updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);
1358 for (auto* renderLayer : layer.positiveZOrderLayers())
1359 updateBackingAndHierarchy(*renderLayer, childList, stateForDescendants, updateLevel, depth + 1);
1360 } else if (requiresChildRebuild)
1361 appendForegroundLayerIfNecessary();
1364 if (requireDescendantTraversal || requiresChildRebuild) {
1365 bool parented = false;
1366 if (is<RenderWidget>(layer.renderer()))
1367 parented = parentFrameContentLayers(downcast<RenderWidget>(layer.renderer()));
1370 layerBacking->parentForSublayers()->setChildren(WTFMove(layerChildren));
1372 // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
1373 // Otherwise, the overflow control layers are normal children.
1374 if (!layerBacking->hasClippingLayer() && !layerBacking->hasScrollingLayer()) {
1375 if (auto* overflowControlLayer = layerBacking->layerForHorizontalScrollbar())
1376 layerBacking->parentForSublayers()->addChild(*overflowControlLayer);
1378 if (auto* overflowControlLayer = layerBacking->layerForVerticalScrollbar())
1379 layerBacking->parentForSublayers()->addChild(*overflowControlLayer);
1381 if (auto* overflowControlLayer = layerBacking->layerForScrollCorner())
1382 layerBacking->parentForSublayers()->addChild(*overflowControlLayer);
1386 childLayersOfEnclosingLayer.append(*layerBacking->childForSuperlayers());
1388 layerBacking->updateAfterDescendants();
1391 layer.clearUpdateBackingOrHierarchyTraversalState();
1394 void RenderLayerCompositor::appendDocumentOverlayLayers(Vector<Ref<GraphicsLayer>>& childList)
1396 if (!isMainFrameCompositor() || !m_compositing)
1399 if (!page().pageOverlayController().hasDocumentOverlays())
1402 Ref<GraphicsLayer> overlayHost = page().pageOverlayController().layerWithDocumentOverlays();
1403 childList.append(WTFMove(overlayHost));
1406 bool RenderLayerCompositor::needsCompositingForContentOrOverlays() const
1408 return m_contentLayersCount + page().pageOverlayController().overlayCount();
1411 void RenderLayerCompositor::layerBecameComposited(const RenderLayer& layer)
1413 if (&layer != m_renderView.layer())
1414 ++m_contentLayersCount;
1417 void RenderLayerCompositor::layerBecameNonComposited(const RenderLayer& layer)
1419 // Inform the inspector that the given RenderLayer was destroyed.
1420 // FIXME: "destroyed" is a misnomer.
1421 InspectorInstrumentation::renderLayerDestroyed(&page(), layer);
1423 if (&layer != m_renderView.layer()) {
1424 ASSERT(m_contentLayersCount > 0);
1425 --m_contentLayersCount;
1430 void RenderLayerCompositor::logLayerInfo(const RenderLayer& layer, const char* phase, int depth)
1432 if (!compositingLogEnabled())
1435 auto* backing = layer.backing();
1436 RequiresCompositingData queryData;
1437 if (requiresCompositingLayer(layer, queryData) || layer.isRenderViewLayer()) {
1438 ++m_obligateCompositedLayerCount;
1439 m_obligatoryBackingStoreBytes += backing->backingStoreMemoryEstimate();
1441 ++m_secondaryCompositedLayerCount;
1442 m_secondaryBackingStoreBytes += backing->backingStoreMemoryEstimate();
1445 LayoutRect absoluteBounds = backing->compositedBounds();
1446 absoluteBounds.move(layer.offsetFromAncestor(m_renderView.layer()));
1448 StringBuilder logString;
1449 logString.append(makeString(pad(' ', 12 + depth * 2, hex(reinterpret_cast<uintptr_t>(&layer))), " id ", backing->graphicsLayer()->primaryLayerID(), " (", FormattedNumber::fixedWidth(absoluteBounds.x().toFloat(), 3), ',', FormattedNumber::fixedWidth(absoluteBounds.y().toFloat(), 3), '-', FormattedNumber::fixedWidth(absoluteBounds.maxX().toFloat(), 3), ',', FormattedNumber::fixedWidth(absoluteBounds.maxY().toFloat(), 3), ") ", FormattedNumber::fixedWidth(backing->backingStoreMemoryEstimate() / 1024, 2), "KB"));
1451 if (!layer.renderer().style().hasAutoZIndex())
1452 logString.append(makeString(" z-index: ", layer.renderer().style().zIndex()));
1454 logString.appendLiteral(" (");
1455 logString.append(logReasonsForCompositing(layer));
1456 logString.appendLiteral(") ");
1458 if (backing->graphicsLayer()->contentsOpaque() || backing->paintsIntoCompositedAncestor() || backing->foregroundLayer() || backing->backgroundLayer()) {
1459 logString.append('[');
1460 bool prependSpace = false;
1461 if (backing->graphicsLayer()->contentsOpaque()) {
1462 logString.appendLiteral("opaque");
1463 prependSpace = true;
1466 if (backing->paintsIntoCompositedAncestor()) {
1468 logString.appendLiteral(", ");
1469 logString.appendLiteral("paints into ancestor");
1470 prependSpace = true;
1473 if (backing->foregroundLayer() || backing->backgroundLayer()) {
1475 logString.appendLiteral(", ");
1476 if (backing->foregroundLayer() && backing->backgroundLayer()) {
1477 logString.appendLiteral("+foreground+background");
1478 prependSpace = true;
1479 } else if (backing->foregroundLayer()) {
1480 logString.appendLiteral("+foreground");
1481 prependSpace = true;
1483 logString.appendLiteral("+background");
1484 prependSpace = true;
1488 if (backing->paintsSubpixelAntialiasedText()) {
1490 logString.appendLiteral(", ");
1491 logString.appendLiteral("texty");
1494 logString.appendLiteral("] ");
1497 logString.append(layer.name());
1499 logString.appendLiteral(" - ");
1500 logString.append(phase);
1502 LOG(Compositing, "%s", logString.toString().utf8().data());
1506 static bool clippingChanged(const RenderStyle& oldStyle, const RenderStyle& newStyle)
1508 return oldStyle.overflowX() != newStyle.overflowX() || oldStyle.overflowY() != newStyle.overflowY()
1509 || oldStyle.hasClip() != newStyle.hasClip() || oldStyle.clip() != newStyle.clip();
1512 static bool styleAffectsLayerGeometry(const RenderStyle& style)
1514 return style.hasClip() || style.clipPath() || style.hasBorderRadius();
1517 static bool recompositeChangeRequiresGeometryUpdate(const RenderStyle& oldStyle, const RenderStyle& newStyle)
1519 return oldStyle.transform() != newStyle.transform()
1520 || oldStyle.transformOriginX() != newStyle.transformOriginX()
1521 || oldStyle.transformOriginY() != newStyle.transformOriginY()
1522 || oldStyle.transformOriginZ() != newStyle.transformOriginZ()
1523 || oldStyle.transformStyle3D() != newStyle.transformStyle3D()
1524 || oldStyle.perspective() != newStyle.perspective()
1525 || oldStyle.perspectiveOriginX() != newStyle.perspectiveOriginX()
1526 || oldStyle.perspectiveOriginY() != newStyle.perspectiveOriginY()
1527 || oldStyle.backfaceVisibility() != newStyle.backfaceVisibility()
1528 || !arePointingToEqualData(oldStyle.clipPath(), newStyle.clipPath());
1531 void RenderLayerCompositor::layerStyleChanged(StyleDifference diff, RenderLayer& layer, const RenderStyle* oldStyle)
1533 if (diff == StyleDifference::Equal)
1536 // Create or destroy backing here so that code that runs during layout can reliably use isComposited() (though this
1537 // is only true for layers composited for direct reasons).
1538 // Also, it allows us to avoid a tree walk in updateCompositingLayers() when no layer changed its compositing state.
1539 RequiresCompositingData queryData;
1540 queryData.layoutUpToDate = LayoutUpToDate::No;
1542 bool layerChanged = updateBacking(layer, queryData, CompositingChangeRepaintNow);
1544 layer.setChildrenNeedCompositingGeometryUpdate();
1545 layer.setNeedsCompositingLayerConnection();
1546 layer.setSubsequentLayersNeedCompositingRequirementsTraversal();
1547 // Ancestor layers that composited for indirect reasons (things listed in styleChangeMayAffectIndirectCompositingReasons()) need to get updated.
1548 // This could be optimized by only setting this flag on layers with the relevant styles.
1549 layer.setNeedsPostLayoutCompositingUpdateOnAncestors();
1552 if (queryData.reevaluateAfterLayout)
1553 layer.setNeedsPostLayoutCompositingUpdate();
1555 if (diff >= StyleDifference::LayoutPositionedMovementOnly && hasContentCompositingLayers()) {
1556 layer.setNeedsPostLayoutCompositingUpdate();
1557 layer.setNeedsCompositingGeometryUpdate();
1560 auto* backing = layer.backing();
1564 backing->updateConfigurationAfterStyleChange();
1566 const auto& newStyle = layer.renderer().style();
1568 if (diff >= StyleDifference::Repaint) {
1569 // Visibility change may affect geometry of the enclosing composited layer.
1570 if (oldStyle && oldStyle->visibility() != newStyle.visibility())
1571 layer.setNeedsCompositingGeometryUpdate();
1573 // We'll get a diff of Repaint when things like clip-path change; these might affect layer or inner-layer geometry.
1574 if (layer.isComposited() && oldStyle) {
1575 if (styleAffectsLayerGeometry(*oldStyle) || styleAffectsLayerGeometry(newStyle))
1576 layer.setNeedsCompositingGeometryUpdate();
1580 // This is necessary to get iframe layers hooked up in response to scheduleInvalidateStyleAndLayerComposition().
1581 if (diff == StyleDifference::RecompositeLayer && layer.isComposited() && is<RenderWidget>(layer.renderer()))
1582 layer.setNeedsCompositingConfigurationUpdate();
1584 if (diff >= StyleDifference::RecompositeLayer && oldStyle && recompositeChangeRequiresGeometryUpdate(*oldStyle, newStyle)) {
1585 // FIXME: transform changes really need to trigger layout. See RenderElement::adjustStyleDifference().
1586 layer.setNeedsPostLayoutCompositingUpdate();
1587 layer.setNeedsCompositingGeometryUpdate();
1590 if (diff >= StyleDifference::Layout) {
1591 // FIXME: only set flags here if we know we have a composited descendant, but we might not know at this point.
1592 if (oldStyle && clippingChanged(*oldStyle, newStyle)) {
1593 if (layer.isStackingContext()) {
1594 layer.setNeedsPostLayoutCompositingUpdate(); // Layer needs to become composited if it has composited descendants.
1595 layer.setNeedsCompositingConfigurationUpdate(); // If already composited, layer needs to create/destroy clipping layer.
1597 // Descendant (in containing block order) compositing layers need to re-evaluate their clipping,
1598 // but they might be siblings in z-order so go up to our stacking context.
1599 if (auto* stackingContext = layer.stackingContext())
1600 stackingContext->setDescendantsNeedUpdateBackingAndHierarchyTraversal();
1604 // These properties trigger compositing if some descendant is composited.
1605 if (oldStyle && styleChangeMayAffectIndirectCompositingReasons(*oldStyle, newStyle))
1606 layer.setNeedsPostLayoutCompositingUpdate();
1608 layer.setNeedsCompositingGeometryUpdate();
1612 bool RenderLayerCompositor::needsCompositingUpdateForStyleChangeOnNonCompositedLayer(RenderLayer& layer, const RenderStyle* oldStyle) const
1614 // Needed for scroll bars.
1615 if (layer.isRenderViewLayer())
1621 const RenderStyle& newStyle = layer.renderer().style();
1622 // Visibility change may affect geometry of the enclosing composited layer.
1623 if (oldStyle->visibility() != newStyle.visibility())
1626 // We don't have any direct reasons for this style change to affect layer composition. Test if it might affect things indirectly.
1627 if (styleChangeMayAffectIndirectCompositingReasons(*oldStyle, newStyle))
1633 bool RenderLayerCompositor::canCompositeClipPath(const RenderLayer& layer)
1635 ASSERT(layer.isComposited());
1636 ASSERT(layer.renderer().style().clipPath());
1638 if (layer.renderer().hasMask())
1641 auto& clipPath = *layer.renderer().style().clipPath();
1642 return (clipPath.type() != ClipPathOperation::Shape || clipPath.type() == ClipPathOperation::Shape) && GraphicsLayer::supportsLayerType(GraphicsLayer::Type::Shape);
1645 // FIXME: remove and never ask questions about reflection layers.
1646 static RenderLayerModelObject& rendererForCompositingTests(const RenderLayer& layer)
1648 auto* renderer = &layer.renderer();
1650 // The compositing state of a reflection should match that of its reflected layer.
1651 if (layer.isReflection())
1652 renderer = downcast<RenderLayerModelObject>(renderer->parent()); // The RenderReplica's parent is the object being reflected.
1657 void RenderLayerCompositor::updateRootContentLayerClipping()
1659 m_rootContentsLayer->setMasksToBounds(!m_renderView.settings().backgroundShouldExtendBeyondPage());
1662 bool RenderLayerCompositor::updateBacking(RenderLayer& layer, RequiresCompositingData& queryData, CompositingChangeRepaint shouldRepaint, BackingRequired backingRequired)
1664 bool layerChanged = false;
1665 if (backingRequired == BackingRequired::Unknown)
1666 backingRequired = needsToBeComposited(layer, queryData) ? BackingRequired::Yes : BackingRequired::No;
1668 // Need to fetch viewportConstrainedNotCompositedReason, but without doing all the work that needsToBeComposited does.
1669 requiresCompositingForPosition(rendererForCompositingTests(layer), layer, queryData);
1672 if (backingRequired == BackingRequired::Yes) {
1673 layer.disconnectFromBackingProviderLayer();
1675 enableCompositingMode();
1677 if (!layer.backing()) {
1678 // If we need to repaint, do so before making backing
1679 if (shouldRepaint == CompositingChangeRepaintNow)
1680 repaintOnCompositingChange(layer);
1682 layer.ensureBacking();
1684 if (layer.isRenderViewLayer() && useCoordinatedScrollingForLayer(layer)) {
1685 auto& frameView = m_renderView.frameView();
1686 if (auto* scrollingCoordinator = this->scrollingCoordinator())
1687 scrollingCoordinator->frameViewRootLayerDidChange(frameView);
1688 #if ENABLE(RUBBER_BANDING)
1689 updateLayerForHeader(frameView.headerHeight());
1690 updateLayerForFooter(frameView.footerHeight());
1692 updateRootContentLayerClipping();
1694 if (auto* tiledBacking = layer.backing()->tiledBacking())
1695 tiledBacking->setTopContentInset(frameView.topContentInset());
1698 // This layer and all of its descendants have cached repaints rects that are relative to
1699 // the repaint container, so change when compositing changes; we need to update them here.
1701 layer.computeRepaintRectsIncludingDescendants();
1703 layer.setNeedsCompositingGeometryUpdate();
1704 layer.setNeedsCompositingConfigurationUpdate();
1705 layer.setNeedsCompositingPaintOrderChildrenUpdate();
1707 layerChanged = true;
1710 if (layer.backing()) {
1711 // If we're removing backing on a reflection, clear the source GraphicsLayer's pointer to
1712 // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection
1713 // are both either composited, or not composited.
1714 if (layer.isReflection()) {
1715 auto* sourceLayer = downcast<RenderLayerModelObject>(*layer.renderer().parent()).layer();
1716 if (auto* backing = sourceLayer->backing()) {
1717 ASSERT(backing->graphicsLayer()->replicaLayer() == layer.backing()->graphicsLayer());
1718 backing->graphicsLayer()->setReplicatedByLayer(nullptr);
1722 layer.clearBacking();
1723 layerChanged = true;
1725 // This layer and all of its descendants have cached repaints rects that are relative to
1726 // the repaint container, so change when compositing changes; we need to update them here.
1727 layer.computeRepaintRectsIncludingDescendants();
1729 // If we need to repaint, do so now that we've removed the backing
1730 if (shouldRepaint == CompositingChangeRepaintNow)
1731 repaintOnCompositingChange(layer);
1736 if (layerChanged && is<RenderVideo>(layer.renderer())) {
1737 // If it's a video, give the media player a chance to hook up to the layer.
1738 downcast<RenderVideo>(layer.renderer()).acceleratedRenderingStateChanged();
1742 if (layerChanged && is<RenderWidget>(layer.renderer())) {
1743 auto* innerCompositor = frameContentsCompositor(downcast<RenderWidget>(layer.renderer()));
1744 if (innerCompositor && innerCompositor->usesCompositing())
1745 innerCompositor->updateRootLayerAttachment();
1749 layer.clearClipRectsIncludingDescendants(PaintingClipRects);
1751 // If a fixed position layer gained/lost a backing or the reason not compositing it changed,
1752 // the scrolling coordinator needs to recalculate whether it can do fast scrolling.
1753 if (layer.renderer().isFixedPositioned()) {
1754 if (layer.viewportConstrainedNotCompositedReason() != queryData.nonCompositedForPositionReason) {
1755 layer.setViewportConstrainedNotCompositedReason(queryData.nonCompositedForPositionReason);
1756 layerChanged = true;
1759 if (auto* scrollingCoordinator = this->scrollingCoordinator())
1760 scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView.frameView());
1763 layer.setViewportConstrainedNotCompositedReason(RenderLayer::NoNotCompositedReason);
1765 if (layer.backing())
1766 layer.backing()->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter);
1768 return layerChanged;
1771 bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer& layer, RequiresCompositingData& queryData, CompositingChangeRepaint shouldRepaint)
1773 bool layerChanged = updateBacking(layer, queryData, shouldRepaint);
1775 // See if we need content or clipping layers. Methods called here should assume
1776 // that the compositing state of descendant layers has not been updated yet.
1777 if (layer.backing() && layer.backing()->updateConfiguration())
1778 layerChanged = true;
1780 return layerChanged;
1783 void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer& layer)
1785 // If the renderer is not attached yet, no need to repaint.
1786 if (&layer.renderer() != &m_renderView && !layer.renderer().parent())
1789 auto* repaintContainer = layer.renderer().containerForRepaint();
1790 if (!repaintContainer)
1791 repaintContainer = &m_renderView;
1793 layer.repaintIncludingNonCompositingDescendants(repaintContainer);
1794 if (repaintContainer == &m_renderView) {
1795 // The contents of this layer may be moving between the window
1796 // and a GraphicsLayer, so we need to make sure the window system
1797 // synchronizes those changes on the screen.
1798 m_renderView.frameView().setNeedsOneShotDrawingSynchronization();
1802 // This method assumes that layout is up-to-date, unlike repaintOnCompositingChange().
1803 void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer& layer, const LayoutRect& rect)
1805 auto* compositedAncestor = layer.enclosingCompositingLayerForRepaint(ExcludeSelf);
1806 if (!compositedAncestor)
1809 ASSERT(compositedAncestor->backing());
1810 LayoutRect repaintRect = rect;
1811 repaintRect.move(layer.offsetFromAncestor(compositedAncestor));
1812 compositedAncestor->setBackingNeedsRepaintInRect(repaintRect);
1814 // The contents of this layer may be moving from a GraphicsLayer to the window,
1815 // so we need to make sure the window system synchronizes those changes on the screen.
1816 if (compositedAncestor->isRenderViewLayer())
1817 m_renderView.frameView().setNeedsOneShotDrawingSynchronization();
1821 void RenderLayerCompositor::layerWasAdded(RenderLayer&, RenderLayer&)
1825 void RenderLayerCompositor::layerWillBeRemoved(RenderLayer& parent, RenderLayer& child)
1827 if (parent.renderer().renderTreeBeingDestroyed())
1830 if (child.isComposited())
1831 repaintInCompositedAncestor(child, child.backing()->compositedBounds()); // FIXME: do via dirty bits?
1832 else if (child.paintsIntoProvidedBacking()) {
1833 auto* backingProviderLayer = child.backingProviderLayer();
1834 // FIXME: Optimize this repaint.
1835 backingProviderLayer->setBackingNeedsRepaint();
1836 backingProviderLayer->backing()->removeBackingSharingLayer(child);
1840 child.setNeedsCompositingLayerConnection();
1843 RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer& layer) const
1845 for (auto* parent = layer.parent(); parent; parent = parent->parent()) {
1846 if (parent->isStackingContext())
1848 if (parent->renderer().hasClipOrOverflowClip())
1854 void RenderLayerCompositor::computeExtent(const OverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent) const
1856 if (extent.extentComputed)
1859 LayoutRect layerBounds;
1860 if (extent.hasTransformAnimation)
1861 extent.animationCausesExtentUncertainty = !layer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(layerBounds);
1863 layerBounds = layer.overlapBounds();
1865 // In the animating transform case, we avoid double-accounting for the transform because
1866 // we told pushMappingsToAncestor() to ignore transforms earlier.
1867 extent.bounds = enclosingLayoutRect(overlapMap.geometryMap().absoluteRect(layerBounds));
1869 // Empty rects never intersect, but we need them to for the purposes of overlap testing.
1870 if (extent.bounds.isEmpty())
1871 extent.bounds.setSize(LayoutSize(1, 1));
1874 RenderLayerModelObject& renderer = layer.renderer();
1875 if (renderer.isFixedPositioned() && renderer.container() == &m_renderView) {
1876 // Because fixed elements get moved around without re-computing overlap, we have to compute an overlap
1877 // rect that covers all the locations that the fixed element could move to.
1878 // FIXME: need to handle sticky too.
1879 extent.bounds = m_renderView.frameView().fixedScrollableAreaBoundsInflatedForScrolling(extent.bounds);
1882 extent.extentComputed = true;
1885 void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, const RenderLayer& layer, OverlapExtent& extent)
1887 if (layer.isRenderViewLayer())
1890 computeExtent(overlapMap, layer, extent);
1892 LayoutRect clipRect = layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), AbsoluteClipRects)).rect(); // FIXME: Incorrect for CSS regions.
1894 // On iOS, pageScaleFactor() is not applied by RenderView, so we should not scale here.
1895 if (!m_renderView.settings().delegatesPageScaling())
1896 clipRect.scale(pageScaleFactor());
1897 clipRect.intersect(extent.bounds);
1898 overlapMap.add(clipRect);
1901 void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, const RenderLayer& layer, const RenderLayer* ancestorLayer)
1903 if (!canBeComposited(layer))
1906 // A null ancestorLayer is an indication that 'layer' has already been pushed.
1908 overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer);
1910 OverlapExtent layerExtent;
1911 addToOverlapMap(overlapMap, layer, layerExtent);
1913 #if !ASSERT_DISABLED
1914 LayerListMutationDetector mutationChecker(const_cast<RenderLayer&>(layer));
1917 for (auto* renderLayer : layer.negativeZOrderLayers())
1918 addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
1920 for (auto* renderLayer : layer.normalFlowLayers())
1921 addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
1923 for (auto* renderLayer : layer.positiveZOrderLayers())
1924 addToOverlapMapRecursive(overlapMap, *renderLayer, &layer);
1927 overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
1931 bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo& video) const
1933 if (!m_hasAcceleratedCompositing)
1936 return video.supportsAcceleratedRendering();
1940 void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
1942 if (m_overflowControlsHostLayer)
1943 m_overflowControlsHostLayer->setPosition(contentsOffset);
1946 void RenderLayerCompositor::frameViewDidChangeSize()
1948 if (auto* layer = m_renderView.layer())
1949 layer->setNeedsCompositingGeometryUpdate();
1951 if (m_scrolledContentsLayer) {
1952 updateScrollLayerClipping();
1953 frameViewDidScroll();
1954 updateOverflowControlsLayers();
1956 #if ENABLE(RUBBER_BANDING)
1957 if (m_layerForOverhangAreas) {
1958 auto& frameView = m_renderView.frameView();
1959 m_layerForOverhangAreas->setSize(frameView.frameRect().size());
1960 m_layerForOverhangAreas->setPosition(FloatPoint(0, frameView.topContentInset()));
1966 bool RenderLayerCompositor::hasCoordinatedScrolling() const
1968 auto* scrollingCoordinator = this->scrollingCoordinator();
1969 return scrollingCoordinator && scrollingCoordinator->coordinatesScrollingForFrameView(m_renderView.frameView());
1972 void RenderLayerCompositor::updateScrollLayerPosition()
1974 ASSERT(!hasCoordinatedScrolling());
1975 ASSERT(m_scrolledContentsLayer);
1977 auto& frameView = m_renderView.frameView();
1978 IntPoint scrollPosition = frameView.scrollPosition();
1980 m_scrolledContentsLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
1982 if (auto* fixedBackgroundLayer = fixedRootBackgroundLayer())
1983 fixedBackgroundLayer->setPosition(frameView.scrollPositionForFixedPosition());
1986 void RenderLayerCompositor::updateScrollLayerClipping()
1988 auto* layerForClipping = this->layerForClipping();
1989 if (!layerForClipping)
1992 layerForClipping->setSize(m_renderView.frameView().sizeForVisibleContent());
1993 layerForClipping->setPosition(positionForClipLayer());
1996 FloatPoint RenderLayerCompositor::positionForClipLayer() const
1998 auto& frameView = m_renderView.frameView();
2001 frameView.shouldPlaceBlockDirectionScrollbarOnLeft() ? frameView.horizontalScrollbarIntrusion() : 0,
2002 FrameView::yPositionForInsetClipLayer(frameView.scrollPosition(), frameView.topContentInset()));
2005 void RenderLayerCompositor::frameViewDidScroll()
2007 if (!m_scrolledContentsLayer)
2010 // If there's a scrolling coordinator that manages scrolling for this frame view,
2011 // it will also manage updating the scroll layer position.
2012 if (hasCoordinatedScrolling()) {
2013 // We have to schedule a flush in order for the main TiledBacking to update its tile coverage.
2014 scheduleLayerFlush();
2018 updateScrollLayerPosition();
2021 void RenderLayerCompositor::frameViewDidAddOrRemoveScrollbars()
2023 updateOverflowControlsLayers();
2026 void RenderLayerCompositor::frameViewDidLayout()
2028 if (auto* renderViewBacking = m_renderView.layer()->backing())
2029 renderViewBacking->adjustTiledBackingCoverage();
2032 void RenderLayerCompositor::rootLayerConfigurationChanged()
2034 auto* renderViewBacking = m_renderView.layer()->backing();
2035 if (renderViewBacking && renderViewBacking->isFrameLayerWithTiledBacking()) {
2036 m_renderView.layer()->setNeedsCompositingConfigurationUpdate();
2037 scheduleCompositingLayerUpdate();
2041 String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
2043 updateCompositingLayers(CompositingUpdateType::AfterLayout);
2045 if (!m_rootContentsLayer)
2048 flushPendingLayerChanges(true);
2049 page().renderingUpdateScheduler().scheduleCompositingLayerFlush();
2051 LayerTreeAsTextBehavior layerTreeBehavior = LayerTreeAsTextBehaviorNormal;
2052 if (flags & LayerTreeFlagsIncludeDebugInfo)
2053 layerTreeBehavior |= LayerTreeAsTextDebug;
2054 if (flags & LayerTreeFlagsIncludeVisibleRects)
2055 layerTreeBehavior |= LayerTreeAsTextIncludeVisibleRects;
2056 if (flags & LayerTreeFlagsIncludeTileCaches)
2057 layerTreeBehavior |= LayerTreeAsTextIncludeTileCaches;
2058 if (flags & LayerTreeFlagsIncludeRepaintRects)
2059 layerTreeBehavior |= LayerTreeAsTextIncludeRepaintRects;
2060 if (flags & LayerTreeFlagsIncludePaintingPhases)
2061 layerTreeBehavior |= LayerTreeAsTextIncludePaintingPhases;
2062 if (flags & LayerTreeFlagsIncludeContentLayers)
2063 layerTreeBehavior |= LayerTreeAsTextIncludeContentLayers;
2064 if (flags & LayerTreeFlagsIncludeAcceleratesDrawing)
2065 layerTreeBehavior |= LayerTreeAsTextIncludeAcceleratesDrawing;
2066 if (flags & LayerTreeFlagsIncludeBackingStoreAttached)
2067 layerTreeBehavior |= LayerTreeAsTextIncludeBackingStoreAttached;
2068 if (flags & LayerTreeFlagsIncludeRootLayerProperties)
2069 layerTreeBehavior |= LayerTreeAsTextIncludeRootLayerProperties;
2070 if (flags & LayerTreeFlagsIncludeEventRegion)
2071 layerTreeBehavior |= LayerTreeAsTextIncludeEventRegion;
2073 // We skip dumping the scroll and clip layers to keep layerTreeAsText output
2074 // similar between platforms.
2075 String layerTreeText = m_rootContentsLayer->layerTreeAsText(layerTreeBehavior);
2077 // Dump an empty layer tree only if the only composited layer is the main frame's tiled backing,
2078 // so that tests expecting us to drop out of accelerated compositing when there are no layers succeed.
2079 if (!hasContentCompositingLayers() && documentUsesTiledBacking() && !(layerTreeBehavior & LayerTreeAsTextIncludeTileCaches) && !(layerTreeBehavior & LayerTreeAsTextIncludeRootLayerProperties))
2080 layerTreeText = emptyString();
2082 // The true root layer is not included in the dump, so if we want to report
2083 // its repaint rects, they must be included here.
2084 if (flags & LayerTreeFlagsIncludeRepaintRects)
2085 return m_renderView.frameView().trackedRepaintRectsAsText() + layerTreeText;
2087 return layerTreeText;
2090 static RenderView* frameContentsRenderView(RenderWidget& renderer)
2092 if (auto* contentDocument = renderer.frameOwnerElement().contentDocument())
2093 return contentDocument->renderView();
2098 RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderWidget& renderer)
2100 if (auto* view = frameContentsRenderView(renderer))
2101 return &view->compositor();
2106 bool RenderLayerCompositor::parentFrameContentLayers(RenderWidget& renderer)
2108 auto* innerCompositor = frameContentsCompositor(renderer);
2109 if (!innerCompositor || !innerCompositor->usesCompositing() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
2112 auto* layer = renderer.layer();
2113 if (!layer->isComposited())
2116 auto* backing = layer->backing();
2117 auto* hostingLayer = backing->parentForSublayers();
2118 auto* rootLayer = innerCompositor->rootGraphicsLayer();
2119 if (hostingLayer->children().size() != 1 || hostingLayer->children()[0].ptr() != rootLayer) {
2120 hostingLayer->removeAllChildren();
2121 hostingLayer->addChild(*rootLayer);
2124 if (auto frameHostingNodeID = backing->scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting)) {
2125 auto* contentsRenderView = frameContentsRenderView(renderer);
2126 if (auto frameRootScrollingNodeID = contentsRenderView->frameView().scrollingNodeID()) {
2127 if (auto* scrollingCoordinator = this->scrollingCoordinator())
2128 scrollingCoordinator->insertNode(ScrollingNodeType::Subframe, frameRootScrollingNodeID, frameHostingNodeID, 0);
2132 // FIXME: Why always return true and not just when the layers changed?
2136 void RenderLayerCompositor::repaintCompositedLayers()
2138 recursiveRepaintLayer(rootRenderLayer());
2141 void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer& layer)
2143 layer.updateLayerListsIfNeeded();
2145 // FIXME: This method does not work correctly with transforms.
2146 if (layer.isComposited() && !layer.backing()->paintsIntoCompositedAncestor())
2147 layer.setBackingNeedsRepaint();
2149 #if !ASSERT_DISABLED
2150 LayerListMutationDetector mutationChecker(layer);
2153 if (layer.hasCompositingDescendant()) {
2154 for (auto* renderLayer : layer.negativeZOrderLayers())
2155 recursiveRepaintLayer(*renderLayer);
2157 for (auto* renderLayer : layer.positiveZOrderLayers())
2158 recursiveRepaintLayer(*renderLayer);
2161 for (auto* renderLayer : layer.normalFlowLayers())
2162 recursiveRepaintLayer(*renderLayer);
2165 RenderLayer& RenderLayerCompositor::rootRenderLayer() const
2167 return *m_renderView.layer();
2170 GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const
2172 if (m_overflowControlsHostLayer)
2173 return m_overflowControlsHostLayer.get();
2174 return m_rootContentsLayer.get();
2177 void RenderLayerCompositor::setIsInWindow(bool isInWindow)
2179 LOG(Compositing, "RenderLayerCompositor %p setIsInWindow %d", this, isInWindow);
2181 if (!usesCompositing())
2184 if (auto* rootLayer = rootGraphicsLayer()) {
2185 GraphicsLayer::traverse(*rootLayer, [isInWindow](GraphicsLayer& layer) {
2186 layer.setIsInWindow(isInWindow);
2191 if (m_rootLayerAttachment != RootLayerUnattached)
2194 RootLayerAttachment attachment = isMainFrameCompositor() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
2195 attachRootLayer(attachment);
2196 #if PLATFORM(IOS_FAMILY)
2197 if (m_legacyScrollingLayerCoordinator) {
2198 m_legacyScrollingLayerCoordinator->registerAllViewportConstrainedLayers(*this);
2199 m_legacyScrollingLayerCoordinator->registerAllScrollingLayers();
2203 if (m_rootLayerAttachment == RootLayerUnattached)
2207 #if PLATFORM(IOS_FAMILY)
2208 if (m_legacyScrollingLayerCoordinator) {
2209 m_legacyScrollingLayerCoordinator->unregisterAllViewportConstrainedLayers();
2210 m_legacyScrollingLayerCoordinator->unregisterAllScrollingLayers();
2216 void RenderLayerCompositor::clearBackingForLayerIncludingDescendants(RenderLayer& layer)
2218 if (layer.isComposited())
2219 layer.clearBacking();
2221 for (auto* childLayer = layer.firstChild(); childLayer; childLayer = childLayer->nextSibling())
2222 clearBackingForLayerIncludingDescendants(*childLayer);
2225 void RenderLayerCompositor::clearBackingForAllLayers()
2227 clearBackingForLayerIncludingDescendants(*m_renderView.layer());
2230 void RenderLayerCompositor::updateRootLayerPosition()
2232 if (m_rootContentsLayer) {
2233 m_rootContentsLayer->setSize(m_renderView.frameView().contentsSize());
2234 m_rootContentsLayer->setPosition(m_renderView.frameView().positionForRootContentLayer());
2235 m_rootContentsLayer->setAnchorPoint(FloatPoint3D());
2238 updateScrollLayerClipping();
2240 #if ENABLE(RUBBER_BANDING)
2241 if (m_contentShadowLayer && m_rootContentsLayer) {
2242 m_contentShadowLayer->setPosition(m_rootContentsLayer->position());
2243 m_contentShadowLayer->setSize(m_rootContentsLayer->size());
2246 updateLayerForTopOverhangArea(m_layerForTopOverhangArea != nullptr);
2247 updateLayerForBottomOverhangArea(m_layerForBottomOverhangArea != nullptr);
2248 updateLayerForHeader(m_layerForHeader != nullptr);
2249 updateLayerForFooter(m_layerForFooter != nullptr);
2253 bool RenderLayerCompositor::has3DContent() const
2255 return layerHas3DContent(rootRenderLayer());
2258 bool RenderLayerCompositor::needsToBeComposited(const RenderLayer& layer, RequiresCompositingData& queryData) const
2260 if (!canBeComposited(layer))
2263 return requiresCompositingLayer(layer, queryData) || layer.mustCompositeForIndirectReasons() || (usesCompositing() && layer.isRenderViewLayer());
2266 // Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
2267 // Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
2268 // FIXME: is clipsCompositingDescendants() an intrinsic reason?
2269 bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer& layer, RequiresCompositingData& queryData) const
2271 auto& renderer = rendererForCompositingTests(layer);
2273 // The root layer always has a compositing layer, but it may not have backing.
2274 return requiresCompositingForTransform(renderer)
2275 || requiresCompositingForAnimation(renderer)
2276 || clipsCompositingDescendants(*renderer.layer())
2277 || requiresCompositingForPosition(renderer, *renderer.layer(), queryData)
2278 || requiresCompositingForCanvas(renderer)
2279 || requiresCompositingForFilters(renderer)
2280 || requiresCompositingForWillChange(renderer)
2281 || requiresCompositingForBackfaceVisibility(renderer)
2282 || requiresCompositingForVideo(renderer)
2283 || requiresCompositingForFrame(renderer, queryData)
2284 || requiresCompositingForPlugin(renderer, queryData)
2285 || requiresCompositingForEditableImage(renderer)
2286 || requiresCompositingForOverflowScrolling(*renderer.layer(), queryData);
2289 bool RenderLayerCompositor::canBeComposited(const RenderLayer& layer) const
2291 if (m_hasAcceleratedCompositing && layer.isSelfPaintingLayer()) {
2292 if (!layer.isInsideFragmentedFlow())
2295 // CSS Regions flow threads do not need to be composited as we use composited RenderFragmentContainers
2296 // to render the background of the RenderFragmentedFlow.
2297 if (layer.isRenderFragmentedFlow())
2305 #if ENABLE(FULLSCREEN_API)
2306 enum class FullScreenDescendant { Yes, No, NotApplicable };
2307 static FullScreenDescendant isDescendantOfFullScreenLayer(const RenderLayer& layer)
2309 auto& document = layer.renderer().document();
2311 if (!document.fullscreenManager().isFullscreen() || !document.fullscreenManager().fullscreenRenderer())
2312 return FullScreenDescendant::NotApplicable;
2314 auto* fullScreenLayer = document.fullscreenManager().fullscreenRenderer()->layer();
2315 if (!fullScreenLayer) {
2316 ASSERT_NOT_REACHED();
2317 return FullScreenDescendant::NotApplicable;
2320 return layer.isDescendantOf(*fullScreenLayer) ? FullScreenDescendant::Yes : FullScreenDescendant::No;
2324 bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, const RenderLayer* compositingAncestorLayer, const LayoutRect& layerCompositedBoundsInAncestor, const LayoutRect& ancestorCompositedBounds) const
2326 auto& renderer = layer.renderer();
2328 if (compositingAncestorLayer
2329 && !(compositingAncestorLayer->backing()->graphicsLayer()->drawsContent()
2330 || compositingAncestorLayer->backing()->paintsIntoWindow()
2331 || compositingAncestorLayer->backing()->paintsIntoCompositedAncestor()))
2334 RequiresCompositingData queryData;
2335 if (layer.isRenderViewLayer()
2336 || layer.transform() // note: excludes perspective and transformStyle3D.
2337 || requiresCompositingForAnimation(renderer)
2338 || requiresCompositingForPosition(renderer, layer, queryData)
2339 || requiresCompositingForCanvas(renderer)
2340 || requiresCompositingForFilters(renderer)
2341 || requiresCompositingForWillChange(renderer)
2342 || requiresCompositingForBackfaceVisibility(renderer)
2343 || requiresCompositingForVideo(renderer)
2344 || requiresCompositingForFrame(renderer, queryData)
2345 || requiresCompositingForPlugin(renderer, queryData)
2346 || requiresCompositingForEditableImage(renderer)
2347 || requiresCompositingForOverflowScrolling(layer, queryData)
2348 || needsContentsCompositingLayer(layer)
2349 || renderer.isTransparent()
2350 || renderer.hasMask()
2351 || renderer.hasReflection()
2352 || renderer.hasFilter()
2353 || renderer.hasBackdropFilter())
2356 if (layer.mustCompositeForIndirectReasons()) {
2357 RenderLayer::IndirectCompositingReason reason = layer.indirectCompositingReason();
2358 return reason == RenderLayer::IndirectCompositingReason::Overlap
2359 || reason == RenderLayer::IndirectCompositingReason::OverflowScrollPositioning
2360 || reason == RenderLayer::IndirectCompositingReason::Stacking
2361 || reason == RenderLayer::IndirectCompositingReason::BackgroundLayer
2362 || reason == RenderLayer::IndirectCompositingReason::GraphicalEffect
2363 || reason == RenderLayer::IndirectCompositingReason::Preserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect.
2366 if (!ancestorCompositedBounds.contains(layerCompositedBoundsInAncestor))
2369 if (layer.isComposited() && layer.backing()->hasBackingSharingLayers())
2375 OptionSet<CompositingReason> RenderLayerCompositor::reasonsForCompositing(const RenderLayer& layer) const
2377 OptionSet<CompositingReason> reasons;
2379 if (!layer.isComposited())
2382 RequiresCompositingData queryData;
2384 auto& renderer = rendererForCompositingTests(layer);
2386 if (requiresCompositingForTransform(renderer))
2387 reasons.add(CompositingReason::Transform3D);
2389 if (requiresCompositingForVideo(renderer))
2390 reasons.add(CompositingReason::Video);
2391 else if (requiresCompositingForCanvas(renderer))
2392 reasons.add(CompositingReason::Canvas);
2393 else if (requiresCompositingForPlugin(renderer, queryData))
2394 reasons.add(CompositingReason::Plugin);
2395 else if (requiresCompositingForFrame(renderer, queryData))
2396 reasons.add(CompositingReason::IFrame);
2397 else if (requiresCompositingForEditableImage(renderer))
2398 reasons.add(CompositingReason::EmbeddedView);
2400 if ((canRender3DTransforms() && renderer.style().backfaceVisibility() == BackfaceVisibility::Hidden))
2401 reasons.add(CompositingReason::BackfaceVisibilityHidden);
2403 if (clipsCompositingDescendants(*renderer.layer()))
2404 reasons.add(CompositingReason::ClipsCompositingDescendants);
2406 if (requiresCompositingForAnimation(renderer))
2407 reasons.add(CompositingReason::Animation);
2409 if (requiresCompositingForFilters(renderer))
2410 reasons.add(CompositingReason::Filters);
2412 if (requiresCompositingForWillChange(renderer))
2413 reasons.add(CompositingReason::WillChange);
2415 if (requiresCompositingForPosition(renderer, *renderer.layer(), queryData))
2416 reasons.add(renderer.isFixedPositioned() ? CompositingReason::PositionFixed : CompositingReason::PositionSticky);
2418 if (requiresCompositingForOverflowScrolling(*renderer.layer(), queryData))
2419 reasons.add(CompositingReason::OverflowScrolling);
2421 switch (renderer.layer()->indirectCompositingReason()) {
2422 case RenderLayer::IndirectCompositingReason::None:
2424 case RenderLayer::IndirectCompositingReason::Stacking:
2425 reasons.add(CompositingReason::Stacking);
2427 case RenderLayer::IndirectCompositingReason::OverflowScrollPositioning:
2428 reasons.add(CompositingReason::OverflowScrollPositioning);
2430 case RenderLayer::IndirectCompositingReason::Overlap:
2431 reasons.add(CompositingReason::Overlap);
2433 case RenderLayer::IndirectCompositingReason::BackgroundLayer:
2434 reasons.add(CompositingReason::NegativeZIndexChildren);
2436 case RenderLayer::IndirectCompositingReason::GraphicalEffect:
2437 if (renderer.hasTransform())
2438 reasons.add(CompositingReason::TransformWithCompositedDescendants);
2440 if (renderer.isTransparent())
2441 reasons.add(CompositingReason::OpacityWithCompositedDescendants);
2443 if (renderer.hasMask())
2444 reasons.add(CompositingReason::MaskWithCompositedDescendants);
2446 if (renderer.hasReflection())
2447 reasons.add(CompositingReason::ReflectionWithCompositedDescendants);
2449 if (renderer.hasFilter() || renderer.hasBackdropFilter())
2450 reasons.add(CompositingReason::FilterWithCompositedDescendants);
2452 #if ENABLE(CSS_COMPOSITING)
2453 if (layer.isolatesCompositedBlending())
2454 reasons.add(CompositingReason::IsolatesCompositedBlendingDescendants);
2456 if (layer.hasBlendMode())
2457 reasons.add(CompositingReason::BlendingWithCompositedDescendants);
2460 case RenderLayer::IndirectCompositingReason::Perspective:
2461 reasons.add(CompositingReason::Perspective);
2463 case RenderLayer::IndirectCompositingReason::Preserve3D:
2464 reasons.add(CompositingReason::Preserve3D);
2468 if (usesCompositing() && renderer.layer()->isRenderViewLayer())
2469 reasons.add(CompositingReason::Root);
2475 const char* RenderLayerCompositor::logReasonsForCompositing(const RenderLayer& layer)
2477 OptionSet<CompositingReason> reasons = reasonsForCompositing(layer);
2479 if (reasons & CompositingReason::Transform3D)
2480 return "3D transform";
2482 if (reasons & CompositingReason::Video)
2485 if (reasons & CompositingReason::Canvas)
2488 if (reasons & CompositingReason::Plugin)
2491 if (reasons & CompositingReason::IFrame)
2494 if (reasons & CompositingReason::BackfaceVisibilityHidden)
2495 return "backface-visibility: hidden";
2497 if (reasons & CompositingReason::ClipsCompositingDescendants)
2498 return "clips compositing descendants";
2500 if (reasons & CompositingReason::Animation)
2503 if (reasons & CompositingReason::Filters)
2506 if (reasons & CompositingReason::PositionFixed)
2507 return "position: fixed";
2509 if (reasons & CompositingReason::PositionSticky)
2510 return "position: sticky";
2512 if (reasons & CompositingReason::OverflowScrolling)
2513 return "async overflow scrolling";
2515 if (reasons & CompositingReason::Stacking)
2518 if (reasons & CompositingReason::Overlap)
2521 if (reasons & CompositingReason::NegativeZIndexChildren)
2522 return "negative z-index children";
2524 if (reasons & CompositingReason::TransformWithCompositedDescendants)
2525 return "transform with composited descendants";
2527 if (reasons & CompositingReason::OpacityWithCompositedDescendants)
2528 return "opacity with composited descendants";
2530 if (reasons & CompositingReason::MaskWithCompositedDescendants)
2531 return "mask with composited descendants";
2533 if (reasons & CompositingReason::ReflectionWithCompositedDescendants)
2534 return "reflection with composited descendants";
2536 if (reasons & CompositingReason::FilterWithCompositedDescendants)
2537 return "filter with composited descendants";
2539 #if ENABLE(CSS_COMPOSITING)
2540 if (reasons & CompositingReason::BlendingWithCompositedDescendants)
2541 return "blending with composited descendants";
2543 if (reasons & CompositingReason::IsolatesCompositedBlendingDescendants)
2544 return "isolates composited blending descendants";
2547 if (reasons & CompositingReason::Perspective)
2548 return "perspective";
2550 if (reasons & CompositingReason::Preserve3D)
2551 return "preserve-3d";
2553 if (reasons & CompositingReason::Root)
2560 // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
2561 // up to the enclosing compositing ancestor. This is required because compositing layers are parented
2562 // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
2563 // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
2564 // but a sibling in the z-order hierarchy.
2565 // FIXME: can we do this without a tree walk?
2566 bool RenderLayerCompositor::clippedByAncestor(RenderLayer& layer) const
2568 ASSERT(layer.isComposited());
2569 if (!layer.parent())
2572 // On first pass in WK1, the root may not have become composited yet.
2573 auto* compositingAncestor = layer.ancestorCompositingLayer();
2574 if (!compositingAncestor)
2577 // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
2578 // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
2579 // and layer. The exception is when the compositingAncestor isolates composited blending children,
2580 // in this case it is not allowed to clipsCompositingDescendants() and each of its children
2581 // will be clippedByAncestor()s, including the compositingAncestor.
2582 auto* computeClipRoot = compositingAncestor;
2583 if (!compositingAncestor->isolatesCompositedBlending()) {
2584 computeClipRoot = nullptr;
2585 auto* parent = &layer;
2587 auto* next = parent->parent();
2588 if (next == compositingAncestor) {
2589 computeClipRoot = parent;
2595 if (!computeClipRoot || computeClipRoot == &layer)
2599 return !layer.backgroundClipRect(RenderLayer::ClipRectsContext(computeClipRoot, TemporaryClipRects)).isInfinite(); // FIXME: Incorrect for CSS regions.
2602 // Return true if the given layer is a stacking context and has compositing child
2603 // layers that it needs to clip. In this case we insert a clipping GraphicsLayer
2604 // into the hierarchy between this layer and its children in the z-order hierarchy.
2605 bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer& layer) const
2607 return layer.hasCompositingDescendant() && layer.renderer().hasClipOrOverflowClip() && !layer.isolatesCompositedBlending();
2610 bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObject& renderer) const
2612 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
2615 if (auto* element = renderer.element()) {
2616 if (auto* timeline = element->document().existingTimeline()) {
2617 if (timeline->runningAnimationsForElementAreAllAccelerated(*element))
2622 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
2625 auto& animController = renderer.animation();
2626 return (animController.isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity)
2627 && (usesCompositing() || (m_compositingTriggers & ChromeClient::AnimatedOpacityTrigger)))
2628 || animController.isRunningAnimationOnRenderer(renderer, CSSPropertyFilter)
2629 #if ENABLE(FILTERS_LEVEL_2)
2630 || animController.isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitBackdropFilter)
2632 || animController.isRunningAnimationOnRenderer(renderer, CSSPropertyTransform);
2635 bool RenderLayerCompositor::requiresCompositingForTransform(RenderLayerModelObject& renderer) const
2637 if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
2640 // Note that we ask the renderer if it has a transform, because the style may have transforms,
2641 // but the renderer may be an inline that doesn't suppport them.
2642 if (!renderer.hasTransform())
2645 switch (m_compositingPolicy) {
2646 case CompositingPolicy::Normal:
2647 return renderer.style().transform().has3DOperation();
2648 case CompositingPolicy::Conservative:
2649 // Continue to allow pages to avoid the very slow software filter path.
2650 if (renderer.style().transform().has3DOperation() && renderer.hasFilter())
2652 return renderer.style().transform().isRepresentableIn2D() ? false : true;
2657 bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const
2659 if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
2662 if (renderer.style().backfaceVisibility() != BackfaceVisibility::Hidden)
2665 if (renderer.layer()->has3DTransformedAncestor())
2668 // FIXME: workaround for webkit.org/b/132801
2669 auto* stackingContext = renderer.layer()->stackingContext();
2670 if (stackingContext && stackingContext->renderer().style().transformStyle3D() == TransformStyle3D::Preserve3D)
2676 bool RenderLayerCompositor::requiresCompositingForVideo(RenderLayerModelObject& renderer) const
2678 if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
2682 if (!is<RenderVideo>(renderer))
2685 auto& video = downcast<RenderVideo>(renderer);
2686 if ((video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video))
2689 UNUSED_PARAM(renderer);
2694 bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& renderer) const
2696 if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
2699 if (!renderer.isCanvas())
2702 bool isCanvasLargeEnoughToForceCompositing = true;
2703 #if !USE(COMPOSITING_FOR_SMALL_CANVASES)
2704 auto* canvas = downcast<HTMLCanvasElement>(renderer.element());
2705 auto canvasArea = canvas->size().area<RecordOverflow>();
2706 isCanvasLargeEnoughToForceCompositing = !canvasArea.hasOverflowed() && canvasArea.unsafeGet() >= canvasAreaThresholdRequiringCompositing;
2709 CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer);
2710 if (compositingStrategy == CanvasAsLayerContents)
2713 if (m_compositingPolicy == CompositingPolicy::Normal)
2714 return compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing;
2719 bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject& renderer) const
2721 #if ENABLE(FILTERS_LEVEL_2)
2722 if (renderer.hasBackdropFilter())
2726 if (!(m_compositingTriggers & ChromeClient::FilterTrigger))
2729 return renderer.hasFilter();
2732 bool RenderLayerCompositor::requiresCompositingForWillChange(RenderLayerModelObject& renderer) const
2734 if (!renderer.style().willChange() || !renderer.style().willChange()->canTriggerCompositing())
2737 #if ENABLE(FULLSCREEN_API)
2738 // FIXME: does this require layout?
2739 if (renderer.layer() && isDescendantOfFullScreenLayer(*renderer.layer()) == FullScreenDescendant::No)
2743 if (m_compositingPolicy == CompositingPolicy::Conservative)
2746 if (is<RenderBox>(renderer))
2749 return renderer.style().willChange()->canTriggerCompositingOnInline();
2752 bool RenderLayerCompositor::requiresCompositingForPlugin(RenderLayerModelObject& renderer, RequiresCompositingData& queryData) const
2754 if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
2757 bool isCompositedPlugin = is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
2758 if (!isCompositedPlugin)
2761 auto& pluginRenderer = downcast<RenderWidget>(renderer);
2762 if (pluginRenderer.style().visibility() != Visibility::Visible)
2765 // If we can't reliably know the size of the plugin yet, don't change compositing state.
2766 if (queryData.layoutUpToDate == LayoutUpToDate::No) {
2767 queryData.reevaluateAfterLayout = true;
2768 return pluginRenderer.isComposited();
2771 // Don't go into compositing mode if height or width are zero, or size is 1x1.
2772 IntRect contentBox = snappedIntRect(pluginRenderer.contentBoxRect());
2773 return (contentBox.height() * contentBox.width() > 1);
2776 bool RenderLayerCompositor::requiresCompositingForEditableImage(RenderLayerModelObject& renderer) const
2778 if (!renderer.isRenderImage())
2781 auto& image = downcast<RenderImage>(renderer);
2782 if (!image.isEditableImage())
2788 bool RenderLayerCompositor::requiresCompositingForFrame(RenderLayerModelObject& renderer, RequiresCompositingData& queryData) const
2790 if (!is<RenderWidget>(renderer))
2793 auto& frameRenderer = downcast<RenderWidget>(renderer);
2794 if (frameRenderer.style().visibility() != Visibility::Visible)
2797 if (!frameRenderer.requiresAcceleratedCompositing())
2800 if (queryData.layoutUpToDate == LayoutUpToDate::No) {
2801 queryData.reevaluateAfterLayout = true;
2802 return frameRenderer.isComposited();
2805 // Don't go into compositing mode if height or width are zero.
2806 return !snappedIntRect(frameRenderer.contentBoxRect()).isEmpty();
2809 bool RenderLayerCompositor::requiresCompositingForScrollableFrame(RequiresCompositingData& queryData) const
2811 if (isMainFrameCompositor())
2814 #if PLATFORM(MAC) || PLATFORM(IOS_FAMILY)
2815 if (!m_renderView.settings().asyncFrameScrollingEnabled())
2819 if (!(m_compositingTriggers & ChromeClient::ScrollableNonMainFrameTrigger))
2822 if (queryData.layoutUpToDate == LayoutUpToDate::No) {
2823 queryData.reevaluateAfterLayout = true;
2824 return m_renderView.isComposited();
2827 return m_renderView.frameView().isScrollable();
2830 bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObject& renderer, const RenderLayer& layer, RequiresCompositingData& queryData) const
2832 // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
2833 // opacity, transform) can get their own composited layer. A stacking context is required otherwise
2834 // z-index and clipping will be broken.
2835 if (!renderer.isPositioned())
2838 #if ENABLE(FULLSCREEN_API)
2839 if (isDescendantOfFullScreenLayer(layer) == FullScreenDescendant::No)
2843 auto position = renderer.style().position();
2844 bool isFixed = renderer.isFixedPositioned();
2845 if (isFixed && !layer.isStackingContext())
2848 bool isSticky = renderer.isInFlowPositioned() && position == PositionType::Sticky;
2849 if (!isFixed && !isSticky)
2852 // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled().
2853 if (!m_renderView.settings().acceleratedCompositingForFixedPositionEnabled())
2857 return isAsyncScrollableStickyLayer(layer);
2859 if (queryData.layoutUpToDate == LayoutUpToDate::No) {
2860 queryData.reevaluateAfterLayout = true;
2861 return layer.isComposited();
2864 auto container = renderer.container();
2867 // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
2868 // They will stay fixed wrt the container rather than the enclosing frame.j
2869 if (container != &m_renderView) {
2870 queryData.nonCompositedForPositionReason = RenderLayer::NotCompositedForNonViewContainer;
2874 bool paintsContent = layer.isVisuallyNonEmpty() || layer.hasVisibleDescendant();
2875 if (!paintsContent) {
2876 queryData.nonCompositedForPositionReason = RenderLayer::NotCompositedForNoVisibleContent;
2880 bool intersectsViewport = fixedLayerIntersectsViewport(layer);
2881 if (!intersectsViewport) {
2882 queryData.nonCompositedForPositionReason = RenderLayer::NotCompositedForBoundsOutOfView;
2883 LOG_WITH_STREAM(Compositing, stream << "Layer " << &layer << " is outside the viewport");
2890 bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer& layer, RequiresCompositingData& queryData) const
2892 if (!layer.canUseCompositedScrolling())
2895 if (queryData.layoutUpToDate == LayoutUpToDate::No) {
2896 queryData.reevaluateAfterLayout = true;
2897 return layer.isComposited();
2900 return layer.hasCompositedScrollableOverflow();
2903 // FIXME: why doesn't this handle the clipping cases?
2904 bool RenderLayerCompositor::requiresCompositingForIndirectReason(const RenderLayer& layer, const RenderLayer* compositingAncestor, bool hasCompositedDescendants, bool has3DTransformedDescendants, bool paintsIntoProvidedBacking, RenderLayer::IndirectCompositingReason& reason) const
2906 // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
2907 // via compositing so that they also apply to those composited descendants.
2908 auto& renderer = layer.renderer();
2909 if (hasCompositedDescendants && (layer.isolatesCompositedBlending() || layer.transform() || renderer.createsGroup() || renderer.hasReflection())) {
2910 reason = RenderLayer::IndirectCompositingReason::GraphicalEffect;
2914 // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that
2915 // will be affected by the preserve-3d or perspective.
2916 if (has3DTransformedDescendants) {
2917 if (renderer.style().transformStyle3D() == TransformStyle3D::Preserve3D) {
2918 reason = RenderLayer::IndirectCompositingReason::Preserve3D;
2922 if (renderer.style().hasPerspective()) {
2923 reason = RenderLayer::IndirectCompositingReason::Perspective;
2928 if (!paintsIntoProvidedBacking && renderer.isAbsolutelyPositioned() && compositingAncestor && layer.hasCompositedScrollingAncestor()) {
2929 if (layerContainingBlockCrossesCoordinatedScrollingBoundary(layer, *compositingAncestor)) {
2930 reason = RenderLayer::IndirectCompositingReason::OverflowScrollPositioning;
2935 reason = RenderLayer::IndirectCompositingReason::None;
2939 bool RenderLayerCompositor::styleChangeMayAffectIndirectCompositingReasons(const RenderStyle& oldStyle, const RenderStyle& newStyle)
2941 if (RenderElement::createsGroupForStyle(newStyle) != RenderElement::createsGroupForStyle(oldStyle))
2943 if (newStyle.isolation() != oldStyle.isolation())
2945 if (newStyle.hasTransform() != oldStyle.hasTransform())
2947 if (newStyle.boxReflect() != oldStyle.boxReflect())
2949 if (newStyle.transformStyle3D() != oldStyle.transformStyle3D())
2951 if (newStyle.hasPerspective() != oldStyle.hasPerspective())
2957 bool RenderLayerCompositor::isAsyncScrollableStickyLayer(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer) const
2959 ASSERT(layer.renderer().isStickilyPositioned());
2961 auto* enclosingOverflowLayer = layer.enclosingOverflowClipLayer(ExcludeSelf);
2963 if (enclosingOverflowLayer && enclosingOverflowLayer->hasCompositedScrollableOverflow()) {
2964 if (enclosingAcceleratedOverflowLayer)
2965 *enclosingAcceleratedOverflowLayer = enclosingOverflowLayer;
2969 // If the layer is inside normal overflow, it's not async-scrollable.
2970 if (enclosingOverflowLayer)
2973 // No overflow ancestor, so see if the frame supports async scrolling.
2974 if (hasCoordinatedScrolling())
2977 #if PLATFORM(IOS_FAMILY)
2978 // iOS WK1 has fixed/sticky support in the main frame via WebFixedPositionContent.
2979 return isMainFrameCompositor();
2985 bool RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer) const
2987 if (layer.renderer().isStickilyPositioned())
2988 return isAsyncScrollableStickyLayer(layer);
2990 if (!layer.renderer().isFixedPositioned())
2993 // FIXME: Handle fixed inside of a transform, which should not behave as fixed.
2994 for (auto* stackingContext = layer.stackingContext(); stackingContext; stackingContext = stackingContext->stackingContext()) {
2995 if (stackingContext->isComposited() && stackingContext->renderer().isFixedPositioned())
3002 bool RenderLayerCompositor::fixedLayerIntersectsViewport(const RenderLayer& layer) const
3004 ASSERT(layer.renderer().isFixedPositioned());
3006 // Fixed position elements that are invisible in the current view don't get their own layer.
3007 // FIXME: We shouldn't have to check useFixedLayout() here; one of the viewport rects needs to give the correct answer.
3008 LayoutRect viewBounds;
3009 if (m_renderView.frameView().useFixedLayout())
3010 viewBounds = m_renderView.unscaledDocumentRect();
3012 viewBounds = m_renderView.frameView().rectForFixedPositionLayout();
3014 LayoutRect layerBounds = layer.calculateLayerBounds(&layer, LayoutSize(), { RenderLayer::UseLocalClipRectIfPossible, RenderLayer::IncludeFilterOutsets, RenderLayer::UseFragmentBoxesExcludingCompositing,
3015 RenderLayer::ExcludeHiddenDescendants, RenderLayer::DontConstrainForMask, RenderLayer::IncludeCompositedDescendants });
3016 // Map to m_renderView to ignore page scale.
3017 FloatRect absoluteBounds = layer.renderer().localToContainerQuad(FloatRect(layerBounds), &m_renderView).boundingBox();
3018 return viewBounds.intersects(enclosingIntRect(absoluteBounds));
3021 bool RenderLayerCompositor::useCoordinatedScrollingForLayer(const RenderLayer& layer) const
3023 if (layer.isRenderViewLayer() && hasCoordinatedScrolling())
3026 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3027 return scrollingCoordinator->coordinatesScrollingForOverflowLayer(layer);
3032 static RenderLayer* enclosingCompositedScrollingLayer(const RenderLayer& layer, const RenderLayer& intermediateLayer, bool& sawIntermediateLayer)
3034 const auto* currLayer = &layer;
3036 if (currLayer == &intermediateLayer)
3037 sawIntermediateLayer = true;
3039 if (currLayer->hasCompositedScrollableOverflow())
3040 return const_cast<RenderLayer*>(currLayer);
3042 currLayer = currLayer->parent();
3048 // Return true if overflowScrollLayer is in layer's containing block chain.
3049 static bool isScrolledByOverflowScrollLayer(const RenderLayer& layer, const RenderLayer& overflowScrollLayer)
3051 bool containingBlockCanSkipLayers = layer.renderer().isAbsolutelyPositioned();
3053 for (const auto* currLayer = layer.parent(); currLayer; currLayer = currLayer->parent()) {
3054 bool inContainingBlockChain = true;
3055 if (containingBlockCanSkipLayers) {
3056 inContainingBlockChain = currLayer->renderer().canContainAbsolutelyPositionedObjects();
3057 if (inContainingBlockChain)
3058 containingBlockCanSkipLayers = currLayer->renderer().isAbsolutelyPositioned();
3061 if (currLayer == &overflowScrollLayer)
3062 return inContainingBlockChain;
3068 static bool isNonScrolledLayerInsideScrolledCompositedAncestor(const RenderLayer& layer, const RenderLayer& compositedAncestor, const RenderLayer& scrollingAncestor)
3070 bool ancestorMovedByScroller = &compositedAncestor == &scrollingAncestor || isScrolledByOverflowScrollLayer(compositedAncestor, scrollingAncestor);
3071 bool layerMovedByScroller = isScrolledByOverflowScrollLayer(layer, scrollingAncestor);
3073 return ancestorMovedByScroller && !layerMovedByScroller;
3076 bool RenderLayerCompositor::layerContainingBlockCrossesCoordinatedScrollingBoundary(const RenderLayer& layer, const RenderLayer& compositedAncestor)
3078 bool compositedAncestorIsInsideScroller = false;
3079 auto* scrollingAncestor = enclosingCompositedScrollingLayer(layer, compositedAncestor, compositedAncestorIsInsideScroller);
3080 if (!scrollingAncestor) {
3081 ASSERT_NOT_REACHED(); // layer.hasCompositedScrollingAncestor() should guarantee we have one.
3085 if (!compositedAncestorIsInsideScroller)
3088 return isNonScrolledLayerInsideScrolledCompositedAncestor(layer, compositedAncestor, *scrollingAncestor);
3091 static void collectStationaryLayerRelatedOverflowNodes(const RenderLayer& layer, const RenderLayer& /*compositedAncestor*/, Vector<ScrollingNodeID>& scrollingNodes)
3093 ASSERT(layer.isComposited());
3095 auto appendOverflowLayerNodeID = [&scrollingNodes] (const RenderLayer& overflowLayer) {
3096 ASSERT(overflowLayer.isComposited());
3097 auto scrollingNodeID = overflowLayer.backing()->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling);
3098 if (scrollingNodeID)
3099 scrollingNodes.append(scrollingNodeID);
3101 LOG(Scrolling, "Layer %p doesn't have scrolling node ID yet", &overflowLayer);
3104 ASSERT(layer.renderer().isAbsolutelyPositioned());
3105 bool containingBlockCanSkipLayers = true;
3107 for (const auto* currLayer = layer.parent(); currLayer; currLayer = currLayer->parent()) {
3108 bool inContainingBlockChain = true;
3109 if (containingBlockCanSkipLayers) {
3110 inContainingBlockChain = currLayer->renderer().canContainAbsolutelyPositionedObjects();
3111 if (inContainingBlockChain)
3112 containingBlockCanSkipLayers = currLayer->renderer().isAbsolutelyPositioned();
3115 if (currLayer->hasCompositedScrollableOverflow()) {
3116 appendOverflowLayerNodeID(*currLayer);
3123 ScrollPositioningBehavior RenderLayerCompositor::computeCoordinatedPositioningForLayer(const RenderLayer& layer) const
3125 if (layer.isRenderViewLayer())
3126 return ScrollPositioningBehavior::None;
3128 if (layer.renderer().isFixedPositioned())
3129 return ScrollPositioningBehavior::None;
3131 if (!layer.hasCompositedScrollingAncestor())
3132 return ScrollPositioningBehavior::None;
3134 auto* scrollingCoordinator = this->scrollingCoordinator();
3135 if (!scrollingCoordinator)
3136 return ScrollPositioningBehavior::None;
3138 auto* compositedAncestor = layer.ancestorCompositingLayer();
3139 if (!compositedAncestor) {
3140 ASSERT_NOT_REACHED();
3141 return ScrollPositioningBehavior::None;
3144 bool compositedAncestorIsInsideScroller = false;
3145 auto* scrollingAncestor = enclosingCompositedScrollingLayer(layer, *compositedAncestor, compositedAncestorIsInsideScroller);
3146 if (!scrollingAncestor) {
3147 ASSERT_NOT_REACHED(); // layer.hasCompositedScrollingAncestor() should guarantee we have one.
3148 return ScrollPositioningBehavior::None;
3151 // There are two cases we have to deal with here:
3152 // 1. There's a composited overflow:scroll in the parent chain between the renderer and its containing block, and the layer's
3153 // composited (z-order) ancestor is inside the scroller or is the scroller. In this case, we have to compensate for scroll position
3154 // changes to make the positioned layer stay in the same place. This only applies to position:absolute (since we handle fixed elsewhere).
3155 if (layer.renderer().isAbsolutelyPositioned()) {
3156 if (compositedAncestorIsInsideScroller && isNonScrolledLayerInsideScrolledCompositedAncestor(layer, *compositedAncestor, *scrollingAncestor))
3157 return ScrollPositioningBehavior::Stationary;
3160 // 2. The layer's containing block is the overflow or inside the overflow:scroll, but its z-order ancestor is
3161 // outside the overflow:scroll. In that case, we have to move the layer via the scrolling tree to make
3162 // it move along with the overflow scrolling.
3163 if (!compositedAncestorIsInsideScroller && isScrolledByOverflowScrollLayer(layer, *scrollingAncestor))
3164 return ScrollPositioningBehavior::Moves;
3166 return ScrollPositioningBehavior::None;
3169 static Vector<ScrollingNodeID> collectRelatedCoordinatedScrollingNodes(const RenderLayer& layer, ScrollPositioningBehavior positioningBehavior)
3171 Vector<ScrollingNodeID> overflowNodeData;
3173 switch (positioningBehavior) {
3174 case ScrollPositioningBehavior::Moves: {
3175 // Collect all the composited scrollers between this layer and its composited ancestor.
3176 auto* compositedAncestor = layer.ancestorCompositingLayer();
3177 for (const auto* currLayer = layer.parent(); currLayer != compositedAncestor; currLayer = currLayer->parent()) {
3178 if (currLayer->hasCompositedScrollableOverflow()) {
3179 auto scrollingNodeID = currLayer->isComposited() ? currLayer->backing()->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling) : 0;
3180 if (scrollingNodeID)
3181 overflowNodeData.append(scrollingNodeID);
3183 LOG(Scrolling, "Layer %p isn't composited or doesn't have scrolling node ID yet", &layer);
3188 case ScrollPositioningBehavior::Stationary: {
3189 ASSERT(layer.renderer().isAbsolutelyPositioned());
3190 // Collect all the composited scrollers between this layer and its composited ancestor.
3191 auto* compositedAncestor = layer.ancestorCompositingLayer();
3192 if (!compositedAncestor)
3193 return overflowNodeData;
3194 collectStationaryLayerRelatedOverflowNodes(layer, *compositedAncestor, overflowNodeData);
3197 case ScrollPositioningBehavior::None:
3198 ASSERT_NOT_REACHED();
3202 return overflowNodeData;
3205 bool RenderLayerCompositor::isLayerForIFrameWithScrollCoordinatedContents(const RenderLayer& layer) const
3207 if (!is<RenderWidget>(layer.renderer()))
3210 auto* contentDocument = downcast<RenderWidget>(layer.renderer()).frameOwnerElement().contentDocument();
3211 if (!contentDocument)
3214 auto* view = contentDocument->renderView();
3218 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3219 return scrollingCoordinator->coordinatesScrollingForFrameView(view->frameView());
3224 bool RenderLayerCompositor::isRunningTransformAnimation(RenderLayerModelObject& renderer) const
3226 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
3229 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
3230 if (auto* element = renderer.element()) {
3231 if (auto* timeline = element->document().existingTimeline())
3232 return timeline->isRunningAnimationOnRenderer(renderer, CSSPropertyTransform);
3236 return renderer.animation().isRunningAnimationOnRenderer(renderer, CSSPropertyTransform);
3239 // If an element has negative z-index children, those children render in front of the
3240 // layer background, so we need an extra 'contents' layer for the foreground of the layer object.
3241 bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer& layer) const
3243 return layer.hasNegativeZOrderLayers();
3246 bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) const
3248 auto& frameView = m_renderView.frameView();
3250 // This applies when the application UI handles scrolling, in which case RenderLayerCompositor doesn't need to manage it.
3251 if (frameView.delegatesScrolling() && isMainFrameCompositor())
3254 // We need to handle our own scrolling if we're:
3255 return !m_renderView.frameView().platformWidget() // viewless (i.e. non-Mac, or Mac in WebKit2)
3256 || attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac
3259 void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
3265 const IntRect& scrollbarRect = scrollbar->frameRect();
3266 context.translate(-scrollbarRect.location());
3267 IntRect transformedClip = clip;
3268 transformedClip.moveBy(scrollbarRect.location());
3269 scrollbar->paint(context, transformedClip);
3273 void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const FloatRect& clip, GraphicsLayerPaintBehavior)
3276 LocalDefaultSystemAppearance localAppearance(m_renderView.useDarkAppearance());
3279 IntRect pixelSnappedRectForIntegralPositionedItems = snappedIntRect(LayoutRect(clip));
3280 if (graphicsLayer == layerForHorizontalScrollbar())
3281 paintScrollbar(m_renderView.frameView().horizontalScrollbar(), context, pixelSnappedRectForIntegralPositionedItems);
3282 else if (graphicsLayer == layerForVerticalScrollbar())
3283 paintScrollbar(m_renderView.frameView().verticalScrollbar(), context, pixelSnappedRectForIntegralPositionedItems);
3284 else if (graphicsLayer == layerForScrollCorner()) {
3285 const IntRect& scrollCorner = m_renderView.frameView().scrollCornerRect();
3287 context.translate(-scrollCorner.location());
3288 IntRect transformedClip = pixelSnappedRectForIntegralPositionedItems;
3289 transformedClip.moveBy(scrollCorner.location());
3290 m_renderView.frameView().paintScrollCorner(context, transformedClip);
3295 bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
3297 auto* renderViewBacking = m_renderView.layer()->backing();
3298 return renderViewBacking && renderViewBacking->isFrameLayerWithTiledBacking();
3301 bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer& layer) const
3303 if (!layer.isRenderViewLayer())
3306 if (m_renderView.settings().fixedBackgroundsPaintRelativeToDocument())
3309 return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed();
3312 GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
3314 // Get the fixed root background from the RenderView layer's backing.
3315 auto* viewLayer = m_renderView.layer();
3319 if (viewLayer->isComposited() && viewLayer->backing()->backgroundLayerPaintsFixedRootBackground())
3320 return viewLayer->backing()->backgroundLayer();
3325 void RenderLayerCompositor::resetTrackedRepaintRects()
3327 if (auto* rootLayer = rootGraphicsLayer()) {
3328 GraphicsLayer::traverse(*rootLayer, [](GraphicsLayer& layer) {
3329 layer.resetTrackedRepaints();
3334 float RenderLayerCompositor::deviceScaleFactor() const
3336 return m_renderView.document().deviceScaleFactor();
3339 float RenderLayerCompositor::pageScaleFactor() const
3341 return page().pageScaleFactor();
3344 float RenderLayerCompositor::zoomedOutPageScaleFactor() const
3346 return page().zoomedOutPageScaleFactor();
3349 float RenderLayerCompositor::contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const
3351 #if PLATFORM(IOS_FAMILY)
3352 LegacyTileCache* tileCache = nullptr;
3353 if (auto* frameView = page().mainFrame().view())
3354 tileCache = frameView->legacyTileCache();
3359 return tileCache->tileControllerShouldUseLowScaleTiles() ? 0.125 : 1;
3365 bool RenderLayerCompositor::documentUsesTiledBacking() const
3367 auto* layer = m_renderView.layer();
3371 auto* backing = layer->backing();
3375 return backing->isFrameLayerWithTiledBacking();
3378 bool RenderLayerCompositor::isMainFrameCompositor() const
3380 return m_renderView.frameView().frame().isMainFrame();
3383 bool RenderLayerCompositor::shouldCompositeOverflowControls() const
3385 auto& frameView = m_renderView.frameView();
3387 if (!frameView.managesScrollbars())
3390 if (documentUsesTiledBacking())
3393 if (m_overflowControlsHostLayer && isMainFrameCompositor())
3396 #if !USE(COORDINATED_GRAPHICS)
3397 if (!frameView.hasOverlayScrollbars())
3404 bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
3406 return shouldCompositeOverflowControls() && m_renderView.frameView().horizontalScrollbar();
3409 bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
3411 return shouldCompositeOverflowControls() && m_renderView.frameView().verticalScrollbar();
3414 bool RenderLayerCompositor::requiresScrollCornerLayer() const
3416 return shouldCompositeOverflowControls() && m_renderView.frameView().isScrollCornerVisible();
3419 #if ENABLE(RUBBER_BANDING)
3420 bool RenderLayerCompositor::requiresOverhangAreasLayer() const
3422 if (!isMainFrameCompositor())
3425 // We do want a layer if we're using tiled drawing and can scroll.
3426 if (documentUsesTiledBacking() && m_renderView.frameView().hasOpaqueBackground() && !m_renderView.frameView().prohibitsScrolling())
3432 bool RenderLayerCompositor::requiresContentShadowLayer() const
3434 if (!isMainFrameCompositor())
3438 if (viewHasTransparentBackground())
3441 // If the background is going to extend, then it doesn't make sense to have a shadow layer.
3442 if (m_renderView.settings().backgroundShouldExtendBeyondPage())
3445 // On Mac, we want a content shadow layer if we're using tiled drawing and can scroll.
3446 if (documentUsesTiledBacking() && !m_renderView.frameView().prohibitsScrolling())
3453 GraphicsLayer* RenderLayerCompositor::updateLayerForTopOverhangArea(bool wantsLayer)
3455 if (!isMainFrameCompositor())
3459 GraphicsLayer::unparentAndClear(m_layerForTopOverhangArea);
3463 if (!m_layerForTopOverhangArea) {
3464 m_layerForTopOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), *this);
3465 m_layerForTopOverhangArea->setName("top overhang");
3466 m_scrolledContentsLayer->addChildBelow(*m_layerForTopOverhangArea, m_rootContentsLayer.get());
3469 return m_layerForTopOverhangArea.get();
3472 GraphicsLayer* RenderLayerCompositor::updateLayerForBottomOverhangArea(bool wantsLayer)
3474 if (!isMainFrameCompositor())
3478 GraphicsLayer::unparentAndClear(m_layerForBottomOverhangArea);
3482 if (!m_layerForBottomOverhangArea) {
3483 m_layerForBottomOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), *this);
3484 m_layerForBottomOverhangArea->setName("bottom overhang");
3485 m_scrolledContentsLayer->addChildBelow(*m_layerForBottomOverhangArea, m_rootContentsLayer.get());
3488 m_layerForBottomOverhangArea->setPosition(FloatPoint(0, m_rootContentsLayer->size().height() + m_renderView.frameView().headerHeight()
3489 + m_renderView.frameView().footerHeight() + m_renderView.frameView().topContentInset()));
3490 return m_layerForBottomOverhangArea.get();
3493 GraphicsLayer* RenderLayerCompositor::updateLayerForHeader(bool wantsLayer)
3495 if (!isMainFrameCompositor())
3499 if (m_layerForHeader) {
3500 GraphicsLayer::unparentAndClear(m_layerForHeader);
3502 // The ScrollingTree knows about the header layer, and the position of the root layer is affected
3503 // by the header layer, so if we remove the header, we need to tell the scrolling tree.
3504 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3505 scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
3510 if (!m_layerForHeader) {
3511 m_layerForHeader = GraphicsLayer::create(graphicsLayerFactory(), *this);
3512 m_layerForHeader->setName("header");
3513 m_scrolledContentsLayer->addChildAbove(*m_layerForHeader, m_rootContentsLayer.get());
3514 m_renderView.frameView().addPaintPendingMilestones(DidFirstFlushForHeaderLayer);
3517 m_layerForHeader->setPosition(FloatPoint(0,
3518 FrameView::yPositionForHeaderLayer(m_renderView.frameView().scrollPosition(), m_renderView.frameView().topContentInset())));
3519 m_layerForHeader->setAnchorPoint(FloatPoint3D());
3520 m_layerForHeader->setSize(FloatSize(m_renderView.frameView().visibleWidth(), m_renderView.frameView().headerHeight()));
3522 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3523 scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
3525 page().chrome().client().didAddHeaderLayer(*m_layerForHeader);
3527 return m_layerForHeader.get();
3530 GraphicsLayer* RenderLayerCompositor::updateLayerForFooter(bool wantsLayer)
3532 if (!isMainFrameCompositor())
3536 if (m_layerForFooter) {
3537 GraphicsLayer::unparentAndClear(m_layerForFooter);
3539 // The ScrollingTree knows about the footer layer, and the total scrollable size is affected
3540 // by the footer layer, so if we remove the footer, we need to tell the scrolling tree.
3541 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3542 scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
3547 if (!m_layerForFooter) {
3548 m_layerForFooter = GraphicsLayer::create(graphicsLayerFactory(), *this);
3549 m_layerForFooter->setName("footer");
3550 m_scrolledContentsLayer->addChildAbove(*m_layerForFooter, m_rootContentsLayer.get());
3553 float totalContentHeight = m_rootContentsLayer->size().height() + m_renderView.frameView().headerHeight() + m_renderView.frameView().footerHeight();
3554 m_layerForFooter->setPosition(FloatPoint(0, FrameView::yPositionForFooterLayer(m_renderView.frameView().scrollPosition(),
3555 m_renderView.frameView().topContentInset(), totalContentHeight, m_renderView.frameView().footerHeight())));
3556 m_layerForFooter->setAnchorPoint(FloatPoint3D());
3557 m_layerForFooter->setSize(FloatSize(m_renderView.frameView().visibleWidth(), m_renderView.frameView().footerHeight()));
3559 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3560 scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView());
3562 page().chrome().client().didAddFooterLayer(*m_layerForFooter);
3564 return m_layerForFooter.get();
3569 bool RenderLayerCompositor::viewHasTransparentBackground(Color* backgroundColor) const
3571 if (m_renderView.frameView().isTransparent()) {
3572 if (backgroundColor)
3573 *backgroundColor = Color(); // Return an invalid color.
3577 Color documentBackgroundColor = m_renderView.frameView().documentBackgroundColor();
3578 if (!documentBackgroundColor.isValid())
3579 documentBackgroundColor = m_renderView.frameView().baseBackgroundColor();
3581 ASSERT(documentBackgroundColor.isValid());
3583 if (backgroundColor)
3584 *backgroundColor = documentBackgroundColor;
3586 return !documentBackgroundColor.isOpaque();
3589 // We can't rely on getting layerStyleChanged() for a style change that affects the root background, because the style change may
3590 // be on the body which has no RenderLayer.
3591 void RenderLayerCompositor::rootOrBodyStyleChanged(RenderElement& renderer, const RenderStyle* oldStyle)
3593 if (!usesCompositing())
3596 Color oldBackgroundColor;
3598 oldBackgroundColor = oldStyle->visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
3600 if (oldBackgroundColor != renderer.style().visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor))
3601 rootBackgroundColorOrTransparencyChanged();
3603 bool hadFixedBackground = oldStyle && oldStyle->hasEntirelyFixedBackground();
3604 if (hadFixedBackground != renderer.style().hasEntirelyFixedBackground())
3605 rootLayerConfigurationChanged();
3608 void RenderLayerCompositor::rootBackgroundColorOrTransparencyChanged()
3610 if (!usesCompositing())
3613 Color backgroundColor;
3614 bool isTransparent = viewHasTransparentBackground(&backgroundColor);
3616 Color extendedBackgroundColor = m_renderView.settings().backgroundShouldExtendBeyondPage() ? backgroundColor : Color();
3618 bool transparencyChanged = m_viewBackgroundIsTransparent != isTransparent;
3619 bool backgroundColorChanged = m_viewBackgroundColor != backgroundColor;
3620 bool extendedBackgroundColorChanged = m_rootExtendedBackgroundColor != extendedBackgroundColor;
3622 if (!transparencyChanged && !backgroundColorChanged && !extendedBackgroundColorChanged)
3625 LOG(Compositing, "RenderLayerCompositor %p rootBackgroundColorOrTransparencyChanged. isTransparent=%d", this, isTransparent);
3627 m_viewBackgroundIsTransparent = isTransparent;
3628 m_viewBackgroundColor = backgroundColor;
3629 m_rootExtendedBackgroundColor = extendedBackgroundColor;
3631 if (extendedBackgroundColorChanged) {
3632 page().chrome().client().pageExtendedBackgroundColorDidChange(m_rootExtendedBackgroundColor);
3634 #if ENABLE(RUBBER_BANDING)
3635 if (m_layerForOverhangAreas) {
3636 m_layerForOverhangAreas->setBackgroundColor(m_rootExtendedBackgroundColor);
3638 if (!m_rootExtendedBackgroundColor.isValid())
3639 m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::CustomAppearance::ScrollingOverhang);
3644 rootLayerConfigurationChanged();
3647 void RenderLayerCompositor::updateOverflowControlsLayers()
3649 #if ENABLE(RUBBER_BANDING)
3650 if (requiresOverhangAreasLayer()) {
3651 if (!m_layerForOverhangAreas) {
3652 m_layerForOverhangAreas = GraphicsLayer::create(graphicsLayerFactory(), *this);
3653 m_layerForOverhangAreas->setName("overhang areas");
3654 m_layerForOverhangAreas->setDrawsContent(false);
3656 float topContentInset = m_renderView.frameView().topContentInset();
3657 IntSize overhangAreaSize = m_renderView.frameView().frameRect().size();
3658 overhangAreaSize.setHeight(overhangAreaSize.height() - topContentInset);
3659 m_layerForOverhangAreas->setSize(overhangAreaSize);
3660 m_layerForOverhangAreas->setPosition(FloatPoint(0, topContentInset));
3661 m_layerForOverhangAreas->setAnchorPoint(FloatPoint3D());
3663 if (m_renderView.settings().backgroundShouldExtendBeyondPage())
3664 m_layerForOverhangAreas->setBackgroundColor(m_renderView.frameView().documentBackgroundColor());
3666 m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::CustomAppearance::ScrollingOverhang);
3668 // We want the overhang areas layer to be positioned below the frame contents,
3669 // so insert it below the clip layer.
3670 m_overflowControlsHostLayer->addChildBelow(*m_layerForOverhangAreas, layerForClipping());
3673 GraphicsLayer::unparentAndClear(m_layerForOverhangAreas);
3675 if (requiresContentShadowLayer()) {
3676 if (!m_contentShadowLayer) {
3677 m_contentShadowLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
3678 m_contentShadowLayer->setName("content shadow");
3679 m_contentShadowLayer->setSize(m_rootContentsLayer->size());
3680 m_contentShadowLayer->setPosition(m_rootContentsLayer->position());
3681 m_contentShadowLayer->setAnchorPoint(FloatPoint3D());
3682 m_contentShadowLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::ScrollingShadow);
3684 m_scrolledContentsLayer->addChildBelow(*m_contentShadowLayer, m_rootContentsLayer.get());
3687 GraphicsLayer::unparentAndClear(m_contentShadowLayer);
3690 if (requiresHorizontalScrollbarLayer()) {
3691 if (!m_layerForHorizontalScrollbar) {
3692 m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this);
3693 m_layerForHorizontalScrollbar->setCanDetachBackingStore(false);
3694 m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
3695 m_layerForHorizontalScrollbar->setName("horizontal scrollbar container");
3696 #if PLATFORM(COCOA) && USE(CA)
3697 m_layerForHorizontalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled());
3699 m_overflowControlsHostLayer->addChild(*m_layerForHorizontalScrollbar);
3701 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3702 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
3704 } else if (m_layerForHorizontalScrollbar) {
3705 GraphicsLayer::unparentAndClear(m_layerForHorizontalScrollbar);
3707 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3708 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar);
3711 if (requiresVerticalScrollbarLayer()) {
3712 if (!m_layerForVerticalScrollbar) {
3713 m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this);
3714 m_layerForVerticalScrollbar->setCanDetachBackingStore(false);
3715 m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
3716 m_layerForVerticalScrollbar->setName("vertical scrollbar container");
3717 #if PLATFORM(COCOA) && USE(CA)
3718 m_layerForVerticalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled());
3720 m_overflowControlsHostLayer->addChild(*m_layerForVerticalScrollbar);
3722 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3723 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
3725 } else if (m_layerForVerticalScrollbar) {
3726 GraphicsLayer::unparentAndClear(m_layerForVerticalScrollbar);
3728 if (auto* scrollingCoordinator = this->scrollingCoordinator())
3729 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar);
3732 if (requiresScrollCornerLayer()) {
3733 if (!m_layerForScrollCorner) {
3734 m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), *this);
3735 m_layerForScrollCorner->setCanDetachBackingStore(false);
3736 m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
3737 m_layerForScrollCorner->setName("scroll corner");
3738 #if PLATFORM(COCOA) && USE(CA)
3739 m_layerForScrollCorner->setAcceleratesDrawing(acceleratedDrawingEnabled());
3741 m_overflowControlsHostLayer->addChild(*m_layerForScrollCorner);
3744 GraphicsLayer::unparentAndClear(m_layerForScrollCorner);
3746 m_renderView.frameView().positionScrollbarLayers();
3749 void RenderLayerCompositor::ensureRootLayer()
3751 RootLayerAttachment expectedAttachment = isMainFrameCompositor() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
3752 if (expectedAttachment == m_rootLayerAttachment)
3755 if (!m_rootContentsLayer) {
3756 m_rootContentsLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
3757 m_rootContentsLayer->setName("content root");
3758 IntRect overflowRect = snappedIntRect(m_renderView.layoutOverflowRect());
3759 m_rootContentsLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
3760 m_rootContentsLayer->setPosition(FloatPoint());
3762 #if PLATFORM(IOS_FAMILY)
3763 // Page scale is applied above this on iOS, so we'll just say that our root layer applies it.
3764 auto& frame = m_renderView.frameView().frame();
3765 if (frame.isMainFrame())
3766 m_rootContentsLayer->setAppliesPageScale();
3769 // Need to clip to prevent transformed content showing outside this frame
3770 updateRootContentLayerClipping();
3773 if (requiresScrollLayer(expectedAttachment)) {
3774 if (!m_overflowControlsHostLayer) {
3775 ASSERT(!m_scrolledContentsLayer);
3776 ASSERT(!m_clipLayer);
3778 // Create a layer to host the clipping layer and the overflow controls layers.
3779 m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
3780 m_overflowControlsHostLayer->setName("overflow controls host");
3782 m_scrolledContentsLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
3783 m_scrolledContentsLayer->setName("scrolled contents");
3784 m_scrolledContentsLayer->setAnchorPoint({ });
3786 #if PLATFORM(IOS_FAMILY)
3787 if (m_renderView.settings().asyncFrameScrollingEnabled()) {
3788 m_scrollContainerLayer = GraphicsLayer::create(graphicsLayerFactory(), *this, GraphicsLayer::Type::ScrollContainer);
3790 m_scrollContainerLayer->setName("scroll container");
3791 m_scrollContainerLayer->setMasksToBounds(true);
3792 m_scrollContainerLayer->setAnchorPoint({ });
3794 m_scrollContainerLayer->addChild(*m_scrolledContentsLayer);
3795 m_overflowControlsHostLayer->addChild(*m_scrollContainerLayer);
3798 if (!m_scrollContainerLayer) {
3799 m_clipLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
3800 m_clipLayer->setName("frame clipping");
3801 m_clipLayer->setMasksToBounds(true);
3802 m_clipLayer->setAnchorPoint({ });
3804 m_clipLayer->addChild(*m_scrolledContentsLayer);
3805 m_overflowControlsHostLayer->addChild(*m_clipLayer);
3808 m_scrolledContentsLayer->addChild(*m_rootContentsLayer);
3810 updateScrollLayerClipping();
3811 updateOverflowControlsLayers();
3813 if (hasCoordinatedScrolling())