2 * Copyright (C) 2009, 2010, 2011 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 "RenderLayerBacking.h"
30 #include "BitmapImage.h"
31 #include "CSSAnimationController.h"
32 #include "CanvasRenderingContext.h"
33 #include "CSSPropertyNames.h"
34 #include "CachedImage.h"
36 #include "DocumentTimeline.h"
38 #include "FrameView.h"
39 #include "GraphicsContext.h"
40 #include "GraphicsLayer.h"
41 #include "HTMLBodyElement.h"
42 #include "HTMLCanvasElement.h"
43 #include "HTMLIFrameElement.h"
44 #include "HTMLMediaElement.h"
45 #include "HTMLNames.h"
46 #include "HTMLPlugInElement.h"
47 #include "InspectorInstrumentation.h"
48 #include "KeyframeList.h"
51 #include "PerformanceLoggingClient.h"
52 #include "PluginViewBase.h"
53 #include "ProgressTracker.h"
54 #include "RenderFragmentContainer.h"
55 #include "RenderFragmentedFlow.h"
56 #include "RenderHTMLCanvas.h"
57 #include "RenderIFrame.h"
58 #include "RenderImage.h"
59 #include "RenderLayerCompositor.h"
60 #include "RenderEmbeddedObject.h"
61 #include "RenderMedia.h"
62 #include "RenderVideo.h"
63 #include "RenderView.h"
64 #include "RuntimeEnabledFeatures.h"
65 #include "ScrollingCoordinator.h"
67 #include "StyleResolver.h"
68 #include "TiledBacking.h"
69 #include <wtf/text/TextStream.h>
72 #include "RuntimeApplicationChecks.h"
76 #include "LocalDefaultSystemAppearance.h"
81 using namespace HTMLNames;
83 CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject& renderer)
85 ASSERT(renderer.isCanvas());
87 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer.node());
88 auto* context = canvas->renderingContext();
89 if (!context || !context->isAccelerated())
90 return UnacceleratedCanvas;
92 if (context->isGPUBased())
93 return CanvasAsLayerContents;
95 #if ENABLE(ACCELERATED_2D_CANVAS)
96 return CanvasAsLayerContents;
98 return CanvasPaintedToLayer; // On Mac and iOS we paint accelerated canvases into their layers.
102 // This acts as a cache of what we know about what is painting into this RenderLayerBacking.
103 class PaintedContentsInfo {
105 enum class ContentsTypeDetermination {
108 DirectlyCompositedImage,
112 PaintedContentsInfo(RenderLayerBacking& inBacking)
113 : m_backing(inBacking)
117 void setWantsSubpixelAntialiasedTextState(bool wantsSubpixelAntialiasedTextState)
119 m_subpixelAntialiasedText = wantsSubpixelAntialiasedTextState ? RequestState::Unknown : RequestState::DontCare;
122 RequestState paintsBoxDecorationsDetermination();
123 bool paintsBoxDecorations()
125 RequestState state = paintsBoxDecorationsDetermination();
126 return state == RequestState::True || state == RequestState::Undetermined;
129 RequestState paintsContentDetermination();
132 RequestState state = paintsContentDetermination();
133 return state == RequestState::True || state == RequestState::Undetermined;
136 RequestState paintsSubpixelAntialiasedTextDetermination();
137 bool paintsSubpixelAntialiasedText()
139 RequestState state = paintsSubpixelAntialiasedTextDetermination();
140 return state == RequestState::True || state == RequestState::Undetermined;
143 ContentsTypeDetermination contentsTypeDetermination();
144 bool isSimpleContainer()
146 return contentsTypeDetermination() == ContentsTypeDetermination::SimpleContainer;
149 bool isDirectlyCompositedImage()
151 return contentsTypeDetermination() == ContentsTypeDetermination::DirectlyCompositedImage;
154 RenderLayerBacking& m_backing;
155 RequestState m_boxDecorations { RequestState::Unknown };
156 RequestState m_content { RequestState::Unknown };
157 RequestState m_subpixelAntialiasedText { RequestState::DontCare };
159 ContentsTypeDetermination m_contentsType { ContentsTypeDetermination::Unknown };
162 RequestState PaintedContentsInfo::paintsBoxDecorationsDetermination()
164 if (m_boxDecorations != RequestState::Unknown)
165 return m_boxDecorations;
167 m_boxDecorations = m_backing.paintsBoxDecorations() ? RequestState::True : RequestState::False;
168 return m_boxDecorations;
171 RequestState PaintedContentsInfo::paintsContentDetermination()
173 if (m_content != RequestState::Unknown && m_subpixelAntialiasedText != RequestState::Unknown)
176 RenderLayer::PaintedContentRequest contentRequest;
177 if (m_subpixelAntialiasedText == RequestState::Unknown)
178 contentRequest.hasSubpixelAntialiasedText = RequestState::Unknown;
180 m_content = m_backing.paintsContent(contentRequest) ? RequestState::True : RequestState::False;
182 if (m_subpixelAntialiasedText == RequestState::Unknown)
183 m_subpixelAntialiasedText = contentRequest.hasSubpixelAntialiasedText;
188 RequestState PaintedContentsInfo::paintsSubpixelAntialiasedTextDetermination()
190 if (m_subpixelAntialiasedText != RequestState::Unknown)
191 return m_subpixelAntialiasedText;
193 paintsContentDetermination();
195 return m_subpixelAntialiasedText;
198 PaintedContentsInfo::ContentsTypeDetermination PaintedContentsInfo::contentsTypeDetermination()
200 if (m_contentsType != ContentsTypeDetermination::Unknown)
201 return m_contentsType;
203 if (m_backing.isSimpleContainerCompositingLayer(*this))
204 m_contentsType = ContentsTypeDetermination::SimpleContainer;
205 else if (m_backing.isDirectlyCompositedImage())
206 m_contentsType = ContentsTypeDetermination::DirectlyCompositedImage;
208 m_contentsType = ContentsTypeDetermination::Painted;
210 return m_contentsType;
214 RenderLayerBacking::RenderLayerBacking(RenderLayer& layer)
215 : m_owningLayer(layer)
217 if (layer.isRenderViewLayer()) {
218 m_isMainFrameRenderViewLayer = renderer().frame().isMainFrame();
219 m_isFrameLayerWithTiledBacking = renderer().page().chrome().client().shouldUseTiledBackingForFrameView(renderer().view().frameView());
222 createPrimaryGraphicsLayer();
223 #if ENABLE(FULLSCREEN_API)
224 setRequiresBackgroundLayer(layer.renderer().isRenderFullScreen());
227 if (auto* tiledBacking = this->tiledBacking()) {
228 tiledBacking->setIsInWindow(renderer().page().isInWindow());
230 if (m_isFrameLayerWithTiledBacking) {
231 tiledBacking->setScrollingPerformanceLoggingEnabled(renderer().settings().scrollingPerformanceLoggingEnabled());
232 adjustTiledBackingCoverage();
237 RenderLayerBacking::~RenderLayerBacking()
239 updateAncestorClippingLayer(false);
240 updateChildClippingStrategy(false);
241 updateDescendantClippingLayer(false);
242 updateOverflowControlsLayers(false, false, false);
243 updateForegroundLayer(false);
244 updateBackgroundLayer(false);
245 updateMaskingLayer(false, false);
246 updateScrollingLayers(false);
247 detachFromScrollingCoordinator({ Scrolling, ViewportConstrained });
248 destroyGraphicsLayers();
251 void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
253 if (layer && layer->type() == GraphicsLayer::Type::Normal && layer->tiledBacking())
254 compositor().layerTiledBackingUsageChanged(layer, false);
257 Ref<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name, GraphicsLayer::Type layerType)
259 auto* graphicsLayerFactory = renderer().page().chrome().client().graphicsLayerFactory();
261 auto graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, *this, layerType);
263 graphicsLayer->setName(name);
265 #if PLATFORM(COCOA) && USE(CA)
266 graphicsLayer->setAcceleratesDrawing(compositor().acceleratedDrawingEnabled());
267 graphicsLayer->setUsesDisplayListDrawing(compositor().displayListDrawingEnabled());
270 return graphicsLayer;
273 void RenderLayerBacking::setUsesDisplayListDrawing(bool usesDisplayListDrawing)
275 // Note that this only affects the primary layer.
276 if (usesDisplayListDrawing == m_graphicsLayer->usesDisplayListDrawing())
279 m_graphicsLayer->setUsesDisplayListDrawing(usesDisplayListDrawing);
280 if (m_graphicsLayer->drawsContent())
281 m_graphicsLayer->setNeedsDisplay();
284 String RenderLayerBacking::displayListAsText(DisplayList::AsTextFlags flags) const
286 return m_graphicsLayer->displayListAsText(flags);
289 void RenderLayerBacking::setIsTrackingDisplayListReplay(bool isTrackingReplay)
291 m_graphicsLayer->setIsTrackingDisplayListReplay(isTrackingReplay);
294 String RenderLayerBacking::replayDisplayListAsText(DisplayList::AsTextFlags flags) const
296 return m_graphicsLayer->replayDisplayListAsText(flags);
299 void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
301 compositor().layerTiledBackingUsageChanged(layer, usingTiledBacking);
304 TiledBacking* RenderLayerBacking::tiledBacking() const
306 return m_graphicsLayer->tiledBacking();
309 static TiledBacking::TileCoverage computePageTiledBackingCoverage(RenderLayerBacking* backing)
311 // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
312 auto& frameView = backing->owningLayer().renderer().view().frameView();
314 // If the page is non-visible, don't incur the cost of keeping extra tiles for scrolling.
315 if (!backing->owningLayer().page().isVisible())
316 return TiledBacking::CoverageForVisibleArea;
318 TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
319 bool useMinimalTilesDuringLiveResize = frameView.inLiveResize();
320 if (frameView.speculativeTilingEnabled() && !useMinimalTilesDuringLiveResize) {
321 bool clipsToExposedRect = static_cast<bool>(frameView.viewExposedRect());
322 if (frameView.horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
323 tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
325 if (frameView.verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
326 tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
331 void RenderLayerBacking::adjustTiledBackingCoverage()
333 if (!m_isFrameLayerWithTiledBacking)
336 TiledBacking::TileCoverage tileCoverage = computePageTiledBackingCoverage(this);
337 tiledBacking()->setTileCoverage(tileCoverage);
340 void RenderLayerBacking::setTiledBackingHasMargins(bool hasExtendedBackgroundOnLeftAndRight, bool hasExtendedBackgroundOnTopAndBottom)
342 if (!m_isFrameLayerWithTiledBacking)
345 tiledBacking()->setHasMargins(hasExtendedBackgroundOnTopAndBottom, hasExtendedBackgroundOnTopAndBottom, hasExtendedBackgroundOnLeftAndRight, hasExtendedBackgroundOnLeftAndRight);
348 void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter)
350 m_graphicsLayer->setShowDebugBorder(showBorder);
351 m_graphicsLayer->setShowRepaintCounter(showRepaintCounter);
353 if (m_ancestorClippingLayer)
354 m_ancestorClippingLayer->setShowDebugBorder(showBorder);
356 if (m_foregroundLayer) {
357 m_foregroundLayer->setShowDebugBorder(showBorder);
358 m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
361 if (m_contentsContainmentLayer)
362 m_contentsContainmentLayer->setShowDebugBorder(showBorder);
364 if (m_backgroundLayer) {
365 m_backgroundLayer->setShowDebugBorder(showBorder);
366 m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
370 m_maskLayer->setShowDebugBorder(showBorder);
371 m_maskLayer->setShowRepaintCounter(showRepaintCounter);
374 if (m_layerForHorizontalScrollbar)
375 m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
377 if (m_layerForVerticalScrollbar)
378 m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
380 if (m_layerForScrollCorner)
381 m_layerForScrollCorner->setShowDebugBorder(showBorder);
383 if (m_scrollingLayer)
384 m_scrollingLayer->setShowDebugBorder(showBorder);
386 if (m_scrollingContentsLayer) {
387 m_scrollingContentsLayer->setShowDebugBorder(showBorder);
388 m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter);
392 void RenderLayerBacking::createPrimaryGraphicsLayer()
394 String layerName = m_owningLayer.name();
395 const unsigned maxLayerNameLength = 100;
396 if (layerName.length() > maxLayerNameLength) {
397 layerName.truncate(maxLayerNameLength);
398 layerName.append("...");
400 m_graphicsLayer = createGraphicsLayer(layerName, m_isFrameLayerWithTiledBacking ? GraphicsLayer::Type::PageTiledBacking : GraphicsLayer::Type::Normal);
402 if (m_isFrameLayerWithTiledBacking) {
403 m_childContainmentLayer = createGraphicsLayer("Page TiledBacking containment");
404 m_graphicsLayer->addChild(*m_childContainmentLayer);
408 if (m_isMainFrameRenderViewLayer) {
409 // Page scale is applied above the RenderView on iOS.
410 m_graphicsLayer->setContentsOpaque(!compositor().viewHasTransparentBackground());
411 m_graphicsLayer->setAppliesPageScale();
415 #if PLATFORM(COCOA) && USE(CA)
416 if (!compositor().acceleratedDrawingEnabled() && renderer().isCanvas()) {
417 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element());
418 if (canvas->shouldAccelerate(canvas->size()))
419 m_graphicsLayer->setAcceleratesDrawing(true);
423 updateOpacity(renderer().style());
424 updateTransform(renderer().style());
425 updateFilters(renderer().style());
426 #if ENABLE(FILTERS_LEVEL_2)
427 updateBackdropFilters(renderer().style());
429 #if ENABLE(CSS_COMPOSITING)
430 updateBlendMode(renderer().style());
432 updateCustomAppearance(renderer().style());
436 void RenderLayerBacking::layerWillBeDestroyed()
438 auto& renderer = this->renderer();
439 if (is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing()) {
440 auto* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer).widget());
441 if (pluginViewBase && m_graphicsLayer->contentsLayerForMedia())
442 pluginViewBase->detachPluginLayer();
446 bool RenderLayerBacking::needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack(const GraphicsLayer& layer) const
448 if (m_isMainFrameRenderViewLayer && IOSApplication::isDumpRenderTree()) {
449 // In iOS WebKit1 the main frame's RenderView layer is always transparent. We lie that it is opaque so that
450 // internals.layerTreeAsText() tests succeed.
451 ASSERT_UNUSED(layer, !layer.contentsOpaque());
458 void RenderLayerBacking::destroyGraphicsLayers()
460 if (m_graphicsLayer) {
461 m_graphicsLayer->setMaskLayer(nullptr);
462 m_graphicsLayer->setReplicatedByLayer(nullptr);
463 willDestroyLayer(m_graphicsLayer.get());
466 GraphicsLayer::clear(m_maskLayer);
468 GraphicsLayer::unparentAndClear(m_ancestorClippingLayer);
469 GraphicsLayer::unparentAndClear(m_contentsContainmentLayer);
470 GraphicsLayer::unparentAndClear(m_foregroundLayer);
471 GraphicsLayer::unparentAndClear(m_backgroundLayer);
472 GraphicsLayer::unparentAndClear(m_childContainmentLayer);
473 GraphicsLayer::unparentAndClear(m_childClippingMaskLayer);
474 GraphicsLayer::unparentAndClear(m_scrollingLayer);
475 GraphicsLayer::unparentAndClear(m_scrollingContentsLayer);
476 GraphicsLayer::unparentAndClear(m_graphicsLayer);
479 void RenderLayerBacking::updateOpacity(const RenderStyle& style)
481 m_graphicsLayer->setOpacity(compositingOpacity(style.opacity()));
484 void RenderLayerBacking::updateTransform(const RenderStyle& style)
486 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
487 // baked into it, and we don't want that.
488 TransformationMatrix t;
489 if (m_owningLayer.hasTransform()) {
490 auto& renderBox = downcast<RenderBox>(renderer());
491 style.applyTransform(t, snapRectToDevicePixels(renderBox.borderBoxRect(), deviceScaleFactor()), RenderStyle::ExcludeTransformOrigin);
492 makeMatrixRenderable(t, compositor().canRender3DTransforms());
495 if (m_contentsContainmentLayer) {
496 m_contentsContainmentLayer->setTransform(t);
497 m_graphicsLayer->setTransform(TransformationMatrix());
499 m_graphicsLayer->setTransform(t);
502 void RenderLayerBacking::updateFilters(const RenderStyle& style)
504 m_canCompositeFilters = m_graphicsLayer->setFilters(style.filter());
507 #if ENABLE(FILTERS_LEVEL_2)
508 void RenderLayerBacking::updateBackdropFilters(const RenderStyle& style)
510 m_canCompositeBackdropFilters = m_graphicsLayer->setBackdropFilters(style.backdropFilter());
513 void RenderLayerBacking::updateBackdropFiltersGeometry()
515 if (!m_canCompositeBackdropFilters)
518 if (!is<RenderBox>(renderer()))
521 auto& renderer = downcast<RenderBox>(this->renderer());
522 LayoutRect boxRect = renderer.borderBoxRect();
523 if (renderer.hasClip())
524 boxRect.intersect(renderer.clipRect(LayoutPoint(), nullptr));
525 boxRect.move(contentOffsetInCompostingLayer());
527 FloatRoundedRect backdropFiltersRect;
528 if (renderer.style().hasBorderRadius() && !renderer.hasClip())
529 backdropFiltersRect = renderer.style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
531 backdropFiltersRect = FloatRoundedRect(snapRectToDevicePixels(boxRect, deviceScaleFactor()));
533 m_graphicsLayer->setBackdropFiltersRect(backdropFiltersRect);
537 #if ENABLE(CSS_COMPOSITING)
538 void RenderLayerBacking::updateBlendMode(const RenderStyle& style)
540 // FIXME: where is the blend mode updated when m_ancestorClippingLayers come and go?
541 if (m_ancestorClippingLayer) {
542 m_ancestorClippingLayer->setBlendMode(style.blendMode());
543 m_graphicsLayer->setBlendMode(BlendMode::Normal);
545 m_graphicsLayer->setBlendMode(style.blendMode());
549 void RenderLayerBacking::updateCustomAppearance(const RenderStyle& style)
551 ControlPart appearance = style.appearance();
552 if (appearance == MediaControlsLightBarBackgroundPart)
553 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::LightBackdrop);
554 else if (appearance == MediaControlsDarkBarBackgroundPart)
555 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::DarkBackdrop);
557 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::None);
560 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
562 for (auto* curr = &layer; curr; curr = curr->parent()) {
563 if (curr->hasTransform() || curr->usesAcceleratedScrolling())
570 bool RenderLayerBacking::shouldClipCompositedBounds() const
573 // Scrollbar layers use this layer for relative positioning, so don't clip.
574 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
578 if (m_isFrameLayerWithTiledBacking)
581 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
587 static bool hasNonZeroTransformOrigin(const RenderObject& renderer)
589 const RenderStyle& style = renderer.style();
590 return (style.transformOriginX().type() == Fixed && style.transformOriginX().value())
591 || (style.transformOriginY().type() == Fixed && style.transformOriginY().value());
594 void RenderLayerBacking::updateCompositedBounds()
596 LayoutRect layerBounds = m_owningLayer.calculateLayerBounds(&m_owningLayer, LayoutSize(), RenderLayer::defaultCalculateLayerBoundsFlags() | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
597 // Clip to the size of the document or enclosing overflow-scroll layer.
598 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
599 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
600 if (shouldClipCompositedBounds()) {
601 auto& view = renderer().view();
602 auto* rootLayer = view.layer();
604 LayoutRect clippingBounds;
605 if (renderer().isFixedPositioned() && renderer().container() == &view)
606 clippingBounds = view.frameView().rectForFixedPositionLayout();
608 clippingBounds = view.unscaledDocumentRect();
610 if (&m_owningLayer != rootLayer)
611 clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
613 LayoutPoint delta = m_owningLayer.convertToLayerCoords(rootLayer, LayoutPoint(), RenderLayer::AdjustForColumns);
614 clippingBounds.move(-delta.x(), -delta.y());
616 layerBounds.intersect(clippingBounds);
619 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
620 // then we need to ensure that the compositing layer has non-zero size so that we can apply
621 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
622 if (layerBounds.isEmpty() && (hasNonZeroTransformOrigin(renderer()) || renderer().style().hasPerspective())) {
623 layerBounds.setWidth(1);
624 layerBounds.setHeight(1);
625 m_artificiallyInflatedBounds = true;
627 m_artificiallyInflatedBounds = false;
629 setCompositedBounds(layerBounds);
632 void RenderLayerBacking::updateAfterWidgetResize()
634 if (!is<RenderWidget>(renderer()))
636 if (auto* innerCompositor = RenderLayerCompositor::frameContentsCompositor(&downcast<RenderWidget>(renderer()))) {
637 innerCompositor->frameViewDidChangeSize();
638 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
642 void RenderLayerBacking::updateAfterLayout(OptionSet<UpdateAfterLayoutFlags> flags)
644 LOG(Compositing, "RenderLayerBacking %p updateAfterLayout (layer %p)", this, &m_owningLayer);
646 if (!compositor().compositingLayersNeedRebuild()) {
647 // Calling updateGeometry() here gives incorrect results, because the
648 // position of this layer's GraphicsLayer depends on the position of our compositing
649 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
650 // RenderLayers of that ancestor have been processed via updateLayerPositions().
652 // The solution is to update compositing children of this layer here,
653 // via updateCompositingChildrenGeometry().
654 updateCompositedBounds();
655 compositor().updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer);
657 if (flags.contains(UpdateAfterLayoutFlags::IsUpdateRoot)) {
659 updateAfterDescendants();
660 compositor().updateRootLayerPosition();
661 auto* stackingContainer = m_owningLayer.enclosingStackingContainer();
662 if (!compositor().compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != &m_owningLayer))
663 compositor().updateCompositingDescendantGeometry(*stackingContainer, *stackingContainer);
667 if (flags.contains(UpdateAfterLayoutFlags::NeedsFullRepaint) && canIssueSetNeedsDisplay())
668 setContentsNeedDisplay();
671 bool RenderLayerBacking::updateConfiguration()
673 m_owningLayer.updateDescendantDependentFlags();
674 m_owningLayer.updateZOrderLists();
676 bool layerConfigChanged = false;
677 setBackgroundLayerPaintsFixedRootBackground(compositor().needsFixedRootBackgroundLayer(m_owningLayer));
679 // The background layer is currently only used for fixed root backgrounds.
680 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground || m_requiresBackgroundLayer))
681 layerConfigChanged = true;
683 if (updateForegroundLayer(compositor().needsContentsCompositingLayer(m_owningLayer)))
684 layerConfigChanged = true;
686 bool needsDescendantsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer);
688 if (!renderer().view().needsLayout()) {
689 bool usesCompositedScrolling = m_owningLayer.usesAcceleratedScrolling();
691 // Our scrolling layer will clip.
692 if (usesCompositedScrolling)
693 needsDescendantsClippingLayer = false;
695 if (updateScrollingLayers(usesCompositedScrolling))
696 layerConfigChanged = true;
698 if (updateDescendantClippingLayer(needsDescendantsClippingLayer))
699 layerConfigChanged = true;
702 if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer)))
703 layerConfigChanged = true;
705 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
706 layerConfigChanged = true;
708 if (layerConfigChanged)
709 updateInternalHierarchy();
711 if (auto* flatteningLayer = tileCacheFlatteningLayer()) {
712 if (layerConfigChanged || flatteningLayer->parent() != m_graphicsLayer.get())
713 m_graphicsLayer->addChild(*flatteningLayer);
716 updateMaskingLayer(renderer().hasMask(), renderer().hasClipPath());
718 updateChildClippingStrategy(needsDescendantsClippingLayer);
720 if (m_owningLayer.hasReflection()) {
721 if (m_owningLayer.reflectionLayer()->backing()) {
722 auto* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
723 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
726 m_graphicsLayer->setReplicatedByLayer(nullptr);
728 PaintedContentsInfo contentsInfo(*this);
730 if (!m_owningLayer.isRenderViewLayer()) {
731 bool didUpdateContentsRect = false;
732 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
734 updateRootLayerConfiguration();
736 if (contentsInfo.isDirectlyCompositedImage())
737 updateImageContents(contentsInfo);
739 if (is<RenderEmbeddedObject>(renderer()) && downcast<RenderEmbeddedObject>(renderer()).allowsAcceleratedCompositing()) {
740 auto* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer()).widget());
742 if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) {
743 pluginViewBase->detachPluginLayer();
744 pluginViewBase->attachPluginLayer();
747 if (!pluginViewBase->shouldNotAddLayer())
748 m_graphicsLayer->setContentsToPlatformLayer(pluginViewBase->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Plugin);
752 else if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo()) {
753 auto* mediaElement = downcast<HTMLMediaElement>(renderer().element());
754 m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Media);
758 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
759 else if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
760 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element());
761 if (auto* context = canvas->renderingContext())
762 m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Canvas);
763 layerConfigChanged = true;
766 if (is<RenderWidget>(renderer()))
767 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(&downcast<RenderWidget>(renderer()));
769 return layerConfigChanged;
772 static LayoutRect clipBox(RenderBox& renderer)
774 LayoutRect result = LayoutRect::infiniteRect();
775 if (renderer.hasOverflowClip())
776 result = renderer.overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
778 if (renderer.hasClip())
779 result.intersect(renderer.clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
784 static bool subpixelOffsetFromRendererChanged(const LayoutSize& oldSubpixelOffsetFromRenderer, const LayoutSize& newSubpixelOffsetFromRenderer, float deviceScaleFactor)
786 FloatSize previous = snapSizeToDevicePixel(oldSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor);
787 FloatSize current = snapSizeToDevicePixel(newSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor);
788 return previous != current;
791 static FloatSize subpixelForLayerPainting(const LayoutPoint& point, float pixelSnappingFactor)
793 LayoutUnit x = point.x();
794 LayoutUnit y = point.y();
795 x = x >= 0 ? floorToDevicePixel(x, pixelSnappingFactor) : ceilToDevicePixel(x, pixelSnappingFactor);
796 y = y >= 0 ? floorToDevicePixel(y, pixelSnappingFactor) : ceilToDevicePixel(y, pixelSnappingFactor);
797 return point - LayoutPoint(x, y);
800 struct OffsetFromRenderer {
801 // 1.2px - > { m_devicePixelOffset = 1px m_subpixelOffset = 0.2px }
802 LayoutSize m_devicePixelOffset;
803 LayoutSize m_subpixelOffset;
806 static OffsetFromRenderer computeOffsetFromRenderer(const LayoutSize& offset, float deviceScaleFactor)
808 OffsetFromRenderer offsetFromRenderer;
809 offsetFromRenderer.m_subpixelOffset = LayoutSize(subpixelForLayerPainting(toLayoutPoint(offset), deviceScaleFactor));
810 offsetFromRenderer.m_devicePixelOffset = offset - offsetFromRenderer.m_subpixelOffset;
811 return offsetFromRenderer;
814 struct SnappedRectInfo {
815 LayoutRect m_snappedRect;
816 LayoutSize m_snapDelta;
819 static SnappedRectInfo snappedGraphicsLayer(const LayoutSize& offset, const LayoutSize& size, float deviceScaleFactor)
821 SnappedRectInfo snappedGraphicsLayer;
822 LayoutRect graphicsLayerRect = LayoutRect(toLayoutPoint(offset), size);
823 snappedGraphicsLayer.m_snappedRect = LayoutRect(snapRectToDevicePixels(graphicsLayerRect, deviceScaleFactor));
824 snappedGraphicsLayer.m_snapDelta = snappedGraphicsLayer.m_snappedRect.location() - toLayoutPoint(offset);
825 return snappedGraphicsLayer;
828 static LayoutSize computeOffsetFromAncestorGraphicsLayer(RenderLayer* compositedAncestor, const LayoutPoint& location, float deviceScaleFactor)
830 if (!compositedAncestor)
831 return toLayoutSize(location);
833 // FIXME: This is a workaround until after webkit.org/162634 gets fixed. ancestorSubpixelOffsetFromRenderer
834 // could be stale when a dynamic composited state change triggers a pre-order updateGeometry() traversal.
835 LayoutSize ancestorSubpixelOffsetFromRenderer = compositedAncestor->backing()->subpixelOffsetFromRenderer();
836 LayoutRect ancestorCompositedBounds = compositedAncestor->backing()->compositedBounds();
837 LayoutSize floored = toLayoutSize(LayoutPoint(floorPointToDevicePixels(ancestorCompositedBounds.location() - ancestorSubpixelOffsetFromRenderer, deviceScaleFactor)));
838 LayoutSize ancestorRendererOffsetFromAncestorGraphicsLayer = -(floored + ancestorSubpixelOffsetFromRenderer);
839 return ancestorRendererOffsetFromAncestorGraphicsLayer + toLayoutSize(location);
842 class ComputedOffsets {
844 ComputedOffsets(const RenderLayer& renderLayer, const LayoutRect& localRect, const LayoutRect& parentGraphicsLayerRect, const LayoutRect& primaryGraphicsLayerRect)
845 : m_renderLayer(renderLayer)
846 , m_location(localRect.location())
847 , m_parentGraphicsLayerOffset(toLayoutSize(parentGraphicsLayerRect.location()))
848 , m_primaryGraphicsLayerOffset(toLayoutSize(primaryGraphicsLayerRect.location()))
849 , m_deviceScaleFactor(renderLayer.renderer().document().deviceScaleFactor())
853 LayoutSize fromParentGraphicsLayer()
855 if (!m_fromParentGraphicsLayer)
856 m_fromParentGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset;
857 return m_fromParentGraphicsLayer.value();
860 LayoutSize fromPrimaryGraphicsLayer()
862 if (!m_fromPrimaryGraphicsLayer)
863 m_fromPrimaryGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset - m_primaryGraphicsLayerOffset;
864 return m_fromPrimaryGraphicsLayer.value();
868 LayoutSize fromAncestorGraphicsLayer()
870 if (!m_fromAncestorGraphicsLayer) {
871 auto* compositedAncestor = m_renderLayer.ancestorCompositingLayer();
872 LayoutPoint localPointInAncestorRenderLayerCoords = m_renderLayer.convertToLayerCoords(compositedAncestor, m_location, RenderLayer::AdjustForColumns);
873 m_fromAncestorGraphicsLayer = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, localPointInAncestorRenderLayerCoords, m_deviceScaleFactor);
875 return m_fromAncestorGraphicsLayer.value();
878 std::optional<LayoutSize> m_fromAncestorGraphicsLayer;
879 std::optional<LayoutSize> m_fromParentGraphicsLayer;
880 std::optional<LayoutSize> m_fromPrimaryGraphicsLayer;
882 const RenderLayer& m_renderLayer;
883 // Location is relative to the renderer.
884 const LayoutPoint m_location;
885 const LayoutSize m_parentGraphicsLayerOffset;
886 const LayoutSize m_primaryGraphicsLayerOffset;
887 float m_deviceScaleFactor;
890 LayoutRect RenderLayerBacking::computePrimaryGraphicsLayerRect(const LayoutRect& parentGraphicsLayerRect) const
892 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, LayoutRect());
893 return LayoutRect(encloseRectToDevicePixels(LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()),
894 deviceScaleFactor()));
897 LayoutRect RenderLayerBacking::computeParentGraphicsLayerRect(RenderLayer* compositedAncestor, LayoutSize& ancestorClippingLayerOffset) const
899 if (!compositedAncestor || !compositedAncestor->backing())
900 return renderer().view().documentRect();
902 auto* ancestorBackingLayer = compositedAncestor->backing();
903 LayoutRect parentGraphicsLayerRect;
904 if (m_owningLayer.isInsideFragmentedFlow()) {
905 // FIXME: flows/columns need work.
906 LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds();
907 ancestorCompositedBounds.setLocation(LayoutPoint());
908 parentGraphicsLayerRect = ancestorCompositedBounds;
911 if (ancestorBackingLayer->hasClippingLayer()) {
912 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore position relative to it.
913 LayoutRect clippingBox = clipBox(downcast<RenderBox>(compositedAncestor->renderer()));
914 LayoutSize clippingBoxOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, clippingBox.location(), deviceScaleFactor());
915 parentGraphicsLayerRect = snappedGraphicsLayer(clippingBoxOffset, clippingBox.size(), deviceScaleFactor()).m_snappedRect;
919 if (compositedAncestor->hasTouchScrollableOverflow()) {
920 LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds();
921 auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer());
922 LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom());
923 ScrollOffset scrollOffset = compositedAncestor->scrollOffset();
924 parentGraphicsLayerRect = LayoutRect((paddingBox.location() - toLayoutSize(ancestorCompositedBounds.location()) - toLayoutSize(scrollOffset)), paddingBox.size());
927 if (compositedAncestor->needsCompositedScrolling()) {
928 auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer());
929 LayoutPoint scrollOrigin(renderBox.borderLeft(), renderBox.borderTop());
930 parentGraphicsLayerRect = LayoutRect(scrollOrigin - toLayoutSize(compositedAncestor->scrollOffset()), renderBox.borderBoxRect().size());
934 if (m_ancestorClippingLayer) {
935 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
936 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
937 // for a compositing layer, rootLayer is the layer itself.
938 ShouldRespectOverflowClip shouldRespectOverflowClip = compositedAncestor->isolatesCompositedBlending() ? RespectOverflowClip : IgnoreOverflowClip;
939 RenderLayer::ClipRectsContext clipRectsContext(compositedAncestor, TemporaryClipRects, IgnoreOverlayScrollbarSize, shouldRespectOverflowClip);
940 LayoutRect parentClipRect = m_owningLayer.backgroundClipRect(clipRectsContext).rect(); // FIXME: Incorrect for CSS regions.
941 ASSERT(!parentClipRect.isInfinite());
942 LayoutSize clippingOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, parentClipRect.location(), deviceScaleFactor());
943 LayoutRect snappedClippingLayerRect = snappedGraphicsLayer(clippingOffset, parentClipRect.size(), deviceScaleFactor()).m_snappedRect;
944 // The primary layer is then parented in, and positioned relative to this clipping layer.
945 ancestorClippingLayerOffset = snappedClippingLayerRect.location() - parentGraphicsLayerRect.location();
946 parentGraphicsLayerRect = snappedClippingLayerRect;
948 return parentGraphicsLayerRect;
951 void RenderLayerBacking::updateGeometry()
953 // If we haven't built z-order lists yet, wait until later.
954 if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
957 const RenderStyle& style = renderer().style();
959 bool isRunningAcceleratedTransformAnimation = false;
960 bool isRunningAcceleratedOpacityAnimation = false;
961 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
962 if (auto* timeline = renderer().documentTimeline()) {
963 isRunningAcceleratedTransformAnimation = timeline->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform);
964 isRunningAcceleratedOpacityAnimation = timeline->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity);
967 isRunningAcceleratedTransformAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused);
968 isRunningAcceleratedOpacityAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused);
971 // Set transform property, if it is not animating. We have to do this here because the transform
972 // is affected by the layer dimensions.
973 if (!isRunningAcceleratedTransformAnimation)
974 updateTransform(style);
976 // Set opacity, if it is not animating.
977 if (!isRunningAcceleratedOpacityAnimation)
978 updateOpacity(style);
980 updateFilters(style);
981 #if ENABLE(FILTERS_LEVEL_2)
982 updateBackdropFilters(style);
984 #if ENABLE(CSS_COMPOSITING)
985 updateBlendMode(style);
987 m_owningLayer.updateDescendantDependentFlags();
989 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
990 bool preserves3D = style.transformStyle3D() == TransformStyle3D::Preserve3D && !renderer().hasReflection();
991 m_graphicsLayer->setPreserves3D(preserves3D);
992 m_graphicsLayer->setBackfaceVisibility(style.backfaceVisibility() == BackfaceVisibility::Visible);
994 auto* compositedAncestor = m_owningLayer.ancestorCompositingLayer();
995 LayoutSize ancestorClippingLayerOffset;
996 LayoutRect parentGraphicsLayerRect = computeParentGraphicsLayerRect(compositedAncestor, ancestorClippingLayerOffset);
997 LayoutRect primaryGraphicsLayerRect = computePrimaryGraphicsLayerRect(parentGraphicsLayerRect);
999 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
1000 m_compositedBoundsOffsetFromGraphicsLayer = compositedBoundsOffset.fromPrimaryGraphicsLayer();
1001 m_graphicsLayer->setPosition(primaryGraphicsLayerRect.location());
1002 m_graphicsLayer->setSize(primaryGraphicsLayerRect.size());
1004 auto computeAnimationExtent = [&] () -> std::optional<FloatRect> {
1005 LayoutRect animatedBounds;
1006 if (isRunningAcceleratedTransformAnimation && m_owningLayer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(animatedBounds, RenderLayer::IncludeCompositedDescendants))
1007 return FloatRect(animatedBounds);
1010 m_graphicsLayer->setAnimationExtent(computeAnimationExtent());
1012 ComputedOffsets rendererOffset(m_owningLayer, LayoutRect(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
1013 if (m_ancestorClippingLayer) {
1014 // Clipping layer is parented in the ancestor layer.
1015 m_ancestorClippingLayer->setPosition(toLayoutPoint(ancestorClippingLayerOffset));
1016 m_ancestorClippingLayer->setSize(parentGraphicsLayerRect.size());
1017 m_ancestorClippingLayer->setOffsetFromRenderer(-rendererOffset.fromParentGraphicsLayer());
1020 if (m_contentsContainmentLayer) {
1021 m_contentsContainmentLayer->setPreserves3D(preserves3D);
1022 m_contentsContainmentLayer->setPosition(primaryGraphicsLayerRect.location());
1023 m_graphicsLayer->setPosition(FloatPoint());
1024 // Use the same size as m_graphicsLayer so transforms behave correctly.
1025 m_contentsContainmentLayer->setSize(primaryGraphicsLayerRect.size());
1028 // Compute renderer offset from primary graphics layer. Note that primaryGraphicsLayerRect is in parentGraphicsLayer's coordidate system which is not necessarily
1029 // the same as the ancestor graphics layer.
1030 OffsetFromRenderer primaryGraphicsLayerOffsetFromRenderer;
1031 LayoutSize oldSubpixelOffsetFromRenderer = m_subpixelOffsetFromRenderer;
1032 primaryGraphicsLayerOffsetFromRenderer = computeOffsetFromRenderer(-rendererOffset.fromPrimaryGraphicsLayer(), deviceScaleFactor());
1033 m_subpixelOffsetFromRenderer = primaryGraphicsLayerOffsetFromRenderer.m_subpixelOffset;
1035 if (primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset != m_graphicsLayer->offsetFromRenderer()) {
1036 m_graphicsLayer->setOffsetFromRenderer(primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset);
1037 positionOverflowControlsLayers();
1040 if (!m_isMainFrameRenderViewLayer && !m_isFrameLayerWithTiledBacking && !m_requiresBackgroundLayer) {
1041 // For non-root layers, background is always painted by the primary graphics layer.
1042 ASSERT(!m_backgroundLayer);
1043 // Subpixel offset from graphics layer or size changed.
1044 bool hadSubpixelRounding = !m_subpixelOffsetFromRenderer.isZero() || compositedBounds().size() != primaryGraphicsLayerRect.size();
1045 m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
1048 // If we have a layer that clips children, position it.
1049 LayoutRect clippingBox;
1050 if (auto* clipLayer = clippingLayer()) {
1051 clippingBox = clipBox(downcast<RenderBox>(renderer()));
1052 // Clipping layer is parented in the primary graphics layer.
1053 LayoutSize clipBoxOffsetFromGraphicsLayer = toLayoutSize(clippingBox.location()) + rendererOffset.fromPrimaryGraphicsLayer();
1054 SnappedRectInfo snappedClippingGraphicsLayer = snappedGraphicsLayer(clipBoxOffsetFromGraphicsLayer, clippingBox.size(), deviceScaleFactor());
1055 clipLayer->setPosition(snappedClippingGraphicsLayer.m_snappedRect.location());
1056 clipLayer->setSize(snappedClippingGraphicsLayer.m_snappedRect.size());
1057 clipLayer->setOffsetFromRenderer(toLayoutSize(clippingBox.location() - snappedClippingGraphicsLayer.m_snapDelta));
1059 if (m_childClippingMaskLayer && !m_scrollingLayer) {
1060 m_childClippingMaskLayer->setSize(clipLayer->size());
1061 m_childClippingMaskLayer->setPosition(FloatPoint());
1062 m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer());
1067 updateMaskingLayerGeometry();
1069 if (renderer().hasTransformRelatedProperty()) {
1070 // Update properties that depend on layer dimensions.
1071 FloatPoint3D transformOrigin = computeTransformOriginForPainting(downcast<RenderBox>(renderer()).borderBoxRect());
1072 FloatPoint layerOffset = roundPointToDevicePixels(toLayoutPoint(rendererOffset.fromParentGraphicsLayer()), deviceScaleFactor());
1073 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
1074 FloatPoint3D anchor(
1075 primaryGraphicsLayerRect.width() ? ((layerOffset.x() - primaryGraphicsLayerRect.x()) + transformOrigin.x()) / primaryGraphicsLayerRect.width() : 0.5,
1076 primaryGraphicsLayerRect.height() ? ((layerOffset.y() - primaryGraphicsLayerRect.y())+ transformOrigin.y()) / primaryGraphicsLayerRect.height() : 0.5,
1077 transformOrigin.z());
1079 if (m_contentsContainmentLayer)
1080 m_contentsContainmentLayer->setAnchorPoint(anchor);
1082 m_graphicsLayer->setAnchorPoint(anchor);
1084 auto* clipLayer = clippingLayer();
1085 if (style.hasPerspective()) {
1086 TransformationMatrix t = owningLayer().perspectiveTransform();
1089 clipLayer->setChildrenTransform(t);
1090 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
1093 m_graphicsLayer->setChildrenTransform(t);
1096 clipLayer->setChildrenTransform(TransformationMatrix());
1098 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
1101 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
1102 if (m_contentsContainmentLayer)
1103 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
1106 if (m_foregroundLayer) {
1107 FloatPoint foregroundPosition;
1108 FloatSize foregroundSize = primaryGraphicsLayerRect.size();
1109 FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
1110 if (hasClippingLayer()) {
1111 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
1112 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
1113 foregroundSize = FloatSize(clippingBox.size());
1114 foregroundOffset = toFloatSize(clippingBox.location());
1117 m_foregroundLayer->setPosition(foregroundPosition);
1118 m_foregroundLayer->setSize(foregroundSize);
1119 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
1122 if (m_backgroundLayer) {
1123 FloatPoint backgroundPosition;
1124 FloatSize backgroundSize = primaryGraphicsLayerRect.size();
1125 if (backgroundLayerPaintsFixedRootBackground()) {
1126 const FrameView& frameView = renderer().view().frameView();
1127 backgroundPosition = frameView.scrollPositionForFixedPosition();
1128 backgroundSize = frameView.layoutSize();
1130 auto boundingBox = renderer().objectBoundingBox();
1131 backgroundPosition = boundingBox.location();
1132 backgroundSize = boundingBox.size();
1134 m_backgroundLayer->setPosition(backgroundPosition);
1135 m_backgroundLayer->setSize(backgroundSize);
1136 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
1139 if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
1140 auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
1141 reflectionBacking->updateGeometry();
1143 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
1144 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
1145 FloatRect layerBounds = this->compositedBounds();
1146 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
1147 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
1150 if (m_scrollingLayer) {
1151 ASSERT(m_scrollingContentsLayer);
1152 auto& renderBox = downcast<RenderBox>(renderer());
1153 LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom());
1154 ScrollOffset scrollOffset = m_owningLayer.scrollOffset();
1156 // FIXME: need to do some pixel snapping here.
1157 m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - compositedBounds().location()));
1159 m_scrollingLayer->setSize(roundedIntSize(LayoutSize(renderBox.clientWidth(), renderBox.clientHeight())));
1161 FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
1162 m_scrollingLayer->setOffsetFromRenderer(FloatPoint() - paddingBox.location());
1163 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
1165 if (m_owningLayer.isInUserScroll()) {
1166 // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause jitter.
1167 m_scrollingLayer->syncBoundsOrigin(scrollOffset);
1168 m_owningLayer.setRequiresScrollBoundsOriginUpdate(true);
1170 // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
1171 m_scrollingLayer->setBoundsOrigin(scrollOffset);
1172 m_owningLayer.setRequiresScrollBoundsOriginUpdate(false);
1175 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
1177 m_scrollingContentsLayer->setPosition(FloatPoint());
1179 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
1180 m_scrollingContentsLayer->setNeedsDisplay();
1182 m_scrollingContentsLayer->setSize(scrollSize);
1183 // Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
1184 // FIXME: The paint offset and the scroll offset should really be separate concepts.
1185 LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - toLayoutSize(scrollOffset));
1186 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
1188 m_scrollingContentsLayer->setPosition(-scrollOffset);
1190 FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
1191 m_scrollingLayer->setOffsetFromRenderer(-toFloatSize(paddingBox.location()));
1193 if (m_childClippingMaskLayer) {
1194 m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
1195 m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
1196 m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBox.location()));
1199 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
1201 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
1202 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
1203 m_scrollingContentsLayer->setNeedsDisplay();
1205 LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - toLayoutSize(scrollOffset));
1206 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
1207 compositor().scrollingLayerDidChange(m_owningLayer);
1209 m_scrollingContentsLayer->setSize(scrollSize);
1210 // FIXME: The paint offset and the scroll offset should really be separate concepts.
1211 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
1214 if (m_foregroundLayer) {
1215 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
1216 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
1220 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
1221 LayoutRect ancestorCompositedBounds = compositedAncestor ? compositedAncestor->backing()->compositedBounds() : LayoutRect();
1222 setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compositedAncestor,
1223 LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()), ancestorCompositedBounds));
1224 #if ENABLE(FILTERS_LEVEL_2)
1225 updateBackdropFiltersGeometry();
1227 updateAfterWidgetResize();
1229 if (subpixelOffsetFromRendererChanged(oldSubpixelOffsetFromRenderer, m_subpixelOffsetFromRenderer, deviceScaleFactor()) && canIssueSetNeedsDisplay())
1230 setContentsNeedDisplay();
1232 compositor().updateScrollCoordinatedStatus(m_owningLayer, { RenderLayerCompositor::ScrollingNodeChangeFlags::Layer, RenderLayerCompositor::ScrollingNodeChangeFlags::LayerGeometry });
1235 void RenderLayerBacking::updateAfterDescendants()
1237 // FIXME: this potentially duplicates work we did in updateConfiguration().
1238 PaintedContentsInfo contentsInfo(*this);
1239 contentsInfo.setWantsSubpixelAntialiasedTextState(GraphicsLayer::supportsSubpixelAntialiasedLayerText());
1241 if (!m_owningLayer.isRenderViewLayer()) {
1242 bool didUpdateContentsRect = false;
1243 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
1244 if (!didUpdateContentsRect && m_graphicsLayer->usesContentsLayer())
1245 resetContentsRect();
1248 updateDrawsContent(contentsInfo);
1250 m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositedDescendants());
1251 if (m_scrollingLayer) {
1252 m_scrollingLayer->setContentsVisible(renderer().style().visibility() == Visibility::Visible);
1253 m_scrollingLayer->setUserInteractionEnabled(renderer().style().pointerEvents() != PointerEvents::None);
1257 // FIXME: Avoid repaints when clip path changes.
1258 void RenderLayerBacking::updateMaskingLayerGeometry()
1260 m_maskLayer->setSize(m_graphicsLayer->size());
1261 m_maskLayer->setPosition(FloatPoint());
1262 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
1264 if (!m_maskLayer->drawsContent()) {
1265 if (renderer().hasClipPath()) {
1266 ASSERT(renderer().style().clipPath()->type() != ClipPathOperation::Reference);
1269 // FIXME: Use correct reference box for inlines: https://bugs.webkit.org/show_bug.cgi?id=129047
1270 LayoutRect boundingBox = m_owningLayer.boundingBox(&m_owningLayer);
1271 LayoutRect referenceBoxForClippedInline = LayoutRect(snapRectToDevicePixels(boundingBox, deviceScaleFactor()));
1272 LayoutSize offset = LayoutSize(snapSizeToDevicePixel(-m_subpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor()));
1273 Path clipPath = m_owningLayer.computeClipPath(offset, referenceBoxForClippedInline, windRule);
1275 FloatSize pathOffset = m_maskLayer->offsetFromRenderer();
1276 if (!pathOffset.isZero())
1277 clipPath.translate(-pathOffset);
1279 m_maskLayer->setShapeLayerPath(clipPath);
1280 m_maskLayer->setShapeLayerWindRule(windRule);
1285 void RenderLayerBacking::updateDirectlyCompositedBoxDecorations(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1287 if (!m_owningLayer.hasVisibleContent())
1290 // The order of operations here matters, since the last valid type of contents needs
1291 // to also update the contentsRect.
1292 updateDirectlyCompositedBackgroundColor(contentsInfo, didUpdateContentsRect);
1293 updateDirectlyCompositedBackgroundImage(contentsInfo, didUpdateContentsRect);
1296 void RenderLayerBacking::updateInternalHierarchy()
1298 // m_foregroundLayer has to be inserted in the correct order with child layers,
1299 // so it's not inserted here.
1300 if (m_ancestorClippingLayer)
1301 m_ancestorClippingLayer->removeAllChildren();
1303 if (m_contentsContainmentLayer) {
1304 m_contentsContainmentLayer->removeAllChildren();
1305 if (m_ancestorClippingLayer)
1306 m_ancestorClippingLayer->addChild(*m_contentsContainmentLayer);
1309 if (m_backgroundLayer)
1310 m_contentsContainmentLayer->addChild(*m_backgroundLayer);
1312 if (m_contentsContainmentLayer)
1313 m_contentsContainmentLayer->addChild(*m_graphicsLayer);
1314 else if (m_ancestorClippingLayer)
1315 m_ancestorClippingLayer->addChild(*m_graphicsLayer);
1317 if (m_childContainmentLayer)
1318 m_graphicsLayer->addChild(*m_childContainmentLayer);
1320 if (m_scrollingLayer) {
1321 auto* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
1322 superlayer->addChild(*m_scrollingLayer);
1325 // The clip for child layers does not include space for overflow controls, so they exist as
1326 // siblings of the clipping layer if we have one. Normal children of this layer are set as
1327 // children of the clipping layer.
1328 if (m_layerForHorizontalScrollbar)
1329 m_graphicsLayer->addChild(*m_layerForHorizontalScrollbar);
1331 if (m_layerForVerticalScrollbar)
1332 m_graphicsLayer->addChild(*m_layerForVerticalScrollbar);
1334 if (m_layerForScrollCorner)
1335 m_graphicsLayer->addChild(*m_layerForScrollCorner);
1338 void RenderLayerBacking::resetContentsRect()
1340 m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
1342 if (is<RenderBox>(renderer())) {
1343 LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
1344 boxRect.move(contentOffsetInCompostingLayer());
1345 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
1346 m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
1349 m_graphicsLayer->setContentsTileSize(IntSize());
1350 m_graphicsLayer->setContentsTilePhase(IntSize());
1353 void RenderLayerBacking::updateDrawsContent()
1355 PaintedContentsInfo contentsInfo(*this);
1356 contentsInfo.setWantsSubpixelAntialiasedTextState(GraphicsLayer::supportsSubpixelAntialiasedLayerText());
1358 updateDrawsContent(contentsInfo);
1361 void RenderLayerBacking::updateDrawsContent(PaintedContentsInfo& contentsInfo)
1363 if (m_scrollingLayer) {
1364 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1365 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1366 // m_scrollingLayer never has backing store.
1367 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1368 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasVisibleBoxDecorationsOrBackground();
1369 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1371 bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || contentsInfo.paintsContent());
1372 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
1376 bool hasPaintedContent = containsPaintedContent(contentsInfo);
1378 m_paintsSubpixelAntialiasedText = renderer().settings().subpixelAntialiasedLayerTextEnabled() && contentsInfo.paintsSubpixelAntialiasedText();
1380 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
1381 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1382 if (m_foregroundLayer) {
1383 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1384 m_foregroundLayer->setSupportsSubpixelAntialiasedText(m_paintsSubpixelAntialiasedText);
1385 // The text content is painted into the foreground layer.
1386 // FIXME: this ignores SVG background images which may contain text.
1387 m_graphicsLayer->setSupportsSubpixelAntialiasedText(false);
1389 m_graphicsLayer->setSupportsSubpixelAntialiasedText(m_paintsSubpixelAntialiasedText);
1391 if (m_backgroundLayer)
1392 m_backgroundLayer->setDrawsContent(m_backgroundLayerPaintsFixedRootBackground ? hasPaintedContent : contentsInfo.paintsBoxDecorations());
1395 // Return true if the layer changed.
1396 bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip)
1398 bool layersChanged = false;
1400 if (needsAncestorClip) {
1401 if (!m_ancestorClippingLayer) {
1402 m_ancestorClippingLayer = createGraphicsLayer("ancestor clipping");
1403 m_ancestorClippingLayer->setMasksToBounds(true);
1404 layersChanged = true;
1406 } else if (hasAncestorClippingLayer()) {
1407 willDestroyLayer(m_ancestorClippingLayer.get());
1408 GraphicsLayer::unparentAndClear(m_ancestorClippingLayer);
1409 layersChanged = true;
1412 return layersChanged;
1415 // Return true if the layer changed.
1416 bool RenderLayerBacking::updateDescendantClippingLayer(bool needsDescendantClip)
1418 bool layersChanged = false;
1420 if (needsDescendantClip) {
1421 if (!m_childContainmentLayer && !m_isFrameLayerWithTiledBacking) {
1422 m_childContainmentLayer = createGraphicsLayer("child clipping");
1423 m_childContainmentLayer->setMasksToBounds(true);
1424 layersChanged = true;
1426 } else if (hasClippingLayer()) {
1427 willDestroyLayer(m_childContainmentLayer.get());
1428 GraphicsLayer::unparentAndClear(m_childContainmentLayer);
1429 layersChanged = true;
1432 return layersChanged;
1435 void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1437 if (backgroundLayerPaintsFixedRootBackground == m_backgroundLayerPaintsFixedRootBackground)
1440 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1442 if (m_backgroundLayerPaintsFixedRootBackground) {
1443 ASSERT(m_isFrameLayerWithTiledBacking);
1444 renderer().view().frameView().removeSlowRepaintObject(*renderer().view().rendererForRootBackground());
1448 void RenderLayerBacking::setRequiresBackgroundLayer(bool requiresBackgroundLayer)
1450 m_requiresBackgroundLayer = requiresBackgroundLayer;
1453 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
1455 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1457 return m_owningLayer.horizontalScrollbar();
1460 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
1462 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1464 return m_owningLayer.verticalScrollbar();
1467 bool RenderLayerBacking::requiresScrollCornerLayer() const
1469 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1471 return !m_owningLayer.scrollCornerAndResizerRect().isEmpty();
1474 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1476 bool horizontalScrollbarLayerChanged = false;
1477 if (needsHorizontalScrollbarLayer) {
1478 if (!m_layerForHorizontalScrollbar) {
1479 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
1480 m_layerForHorizontalScrollbar->setCanDetachBackingStore(false);
1481 horizontalScrollbarLayerChanged = true;
1483 } else if (m_layerForHorizontalScrollbar) {
1484 willDestroyLayer(m_layerForHorizontalScrollbar.get());
1485 GraphicsLayer::unparentAndClear(m_layerForHorizontalScrollbar);
1486 horizontalScrollbarLayerChanged = true;
1489 bool verticalScrollbarLayerChanged = false;
1490 if (needsVerticalScrollbarLayer) {
1491 if (!m_layerForVerticalScrollbar) {
1492 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
1493 m_layerForVerticalScrollbar->setCanDetachBackingStore(false);
1494 verticalScrollbarLayerChanged = true;
1496 } else if (m_layerForVerticalScrollbar) {
1497 willDestroyLayer(m_layerForVerticalScrollbar.get());
1498 GraphicsLayer::unparentAndClear(m_layerForVerticalScrollbar);
1499 verticalScrollbarLayerChanged = true;
1502 bool scrollCornerLayerChanged = false;
1503 if (needsScrollCornerLayer) {
1504 if (!m_layerForScrollCorner) {
1505 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
1506 m_layerForScrollCorner->setCanDetachBackingStore(false);
1507 scrollCornerLayerChanged = true;
1509 } else if (m_layerForScrollCorner) {
1510 willDestroyLayer(m_layerForScrollCorner.get());
1511 GraphicsLayer::unparentAndClear(m_layerForScrollCorner);
1512 scrollCornerLayerChanged = true;
1515 if (auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator()) {
1516 if (horizontalScrollbarLayerChanged)
1517 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar);
1518 if (verticalScrollbarLayerChanged)
1519 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar);
1522 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1525 void RenderLayerBacking::positionOverflowControlsLayers()
1527 if (!m_owningLayer.hasScrollbars())
1530 const IntRect borderBox = snappedIntRect(renderBox()->borderBoxRect());
1532 FloatSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
1533 if (auto* layer = layerForHorizontalScrollbar()) {
1534 IntRect hBarRect = m_owningLayer.rectForHorizontalScrollbar(borderBox);
1535 layer->setPosition(hBarRect.location() - offsetFromRenderer);
1536 layer->setSize(hBarRect.size());
1537 if (layer->usesContentsLayer()) {
1538 IntRect barRect = IntRect(IntPoint(), hBarRect.size());
1539 layer->setContentsRect(barRect);
1540 layer->setContentsClippingRect(FloatRoundedRect(barRect));
1542 layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->usesContentsLayer());
1545 if (auto* layer = layerForVerticalScrollbar()) {
1546 IntRect vBarRect = m_owningLayer.rectForVerticalScrollbar(borderBox);
1547 layer->setPosition(vBarRect.location() - offsetFromRenderer);
1548 layer->setSize(vBarRect.size());
1549 if (layer->usesContentsLayer()) {
1550 IntRect barRect = IntRect(IntPoint(), vBarRect.size());
1551 layer->setContentsRect(barRect);
1552 layer->setContentsClippingRect(FloatRoundedRect(barRect));
1554 layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->usesContentsLayer());
1557 if (auto* layer = layerForScrollCorner()) {
1558 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
1559 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1560 layer->setSize(scrollCornerAndResizer.size());
1561 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1565 bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
1567 if (auto* layer = layerForHorizontalScrollbar()) {
1568 if (!layer->drawsContent())
1572 if (auto* layer = layerForVerticalScrollbar()) {
1573 if (!layer->drawsContent())
1577 if (auto* layer = layerForScrollCorner()) {
1578 if (!layer->drawsContent())
1585 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
1587 bool layerChanged = false;
1588 if (needsForegroundLayer) {
1589 if (!m_foregroundLayer) {
1590 String layerName = m_owningLayer.name() + " (foreground)";
1591 m_foregroundLayer = createGraphicsLayer(layerName);
1592 m_foregroundLayer->setDrawsContent(true);
1593 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1594 layerChanged = true;
1596 } else if (m_foregroundLayer) {
1597 willDestroyLayer(m_foregroundLayer.get());
1598 GraphicsLayer::unparentAndClear(m_foregroundLayer);
1599 layerChanged = true;
1603 m_graphicsLayer->setNeedsDisplay();
1604 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1607 return layerChanged;
1610 bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
1612 bool layerChanged = false;
1613 if (needsBackgroundLayer) {
1614 if (!m_backgroundLayer) {
1615 String layerName = m_owningLayer.name() + " (background)";
1616 m_backgroundLayer = createGraphicsLayer(layerName);
1617 m_backgroundLayer->setDrawsContent(true);
1618 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1619 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1620 layerChanged = true;
1623 if (!m_contentsContainmentLayer) {
1624 String layerName = m_owningLayer.name() + " (contents containment)";
1625 m_contentsContainmentLayer = createGraphicsLayer(layerName);
1626 m_contentsContainmentLayer->setAppliesPageScale(true);
1627 m_graphicsLayer->setAppliesPageScale(false);
1628 layerChanged = true;
1631 if (m_backgroundLayer) {
1632 willDestroyLayer(m_backgroundLayer.get());
1633 GraphicsLayer::unparentAndClear(m_backgroundLayer);
1634 layerChanged = true;
1636 if (m_contentsContainmentLayer) {
1637 willDestroyLayer(m_contentsContainmentLayer.get());
1638 GraphicsLayer::unparentAndClear(m_contentsContainmentLayer);
1639 layerChanged = true;
1640 m_graphicsLayer->setAppliesPageScale(true);
1645 m_graphicsLayer->setNeedsDisplay();
1647 if (m_backgroundLayerPaintsFixedRootBackground)
1648 compositor().fixedRootBackgroundLayerChanged();
1651 return layerChanged;
1654 // Masking layer is used for masks or clip-path.
1655 void RenderLayerBacking::updateMaskingLayer(bool hasMask, bool hasClipPath)
1657 bool layerChanged = false;
1658 if (hasMask || hasClipPath) {
1659 GraphicsLayerPaintingPhase maskPhases = 0;
1661 maskPhases = GraphicsLayerPaintMask;
1664 // If we have a mask, we need to paint the combined clip-path and mask into the mask layer.
1665 if (hasMask || renderer().style().clipPath()->type() == ClipPathOperation::Reference || !GraphicsLayer::supportsLayerType(GraphicsLayer::Type::Shape))
1666 maskPhases |= GraphicsLayerPaintClipPath;
1669 bool paintsContent = maskPhases;
1670 GraphicsLayer::Type requiredLayerType = paintsContent ? GraphicsLayer::Type::Normal : GraphicsLayer::Type::Shape;
1671 if (m_maskLayer && m_maskLayer->type() != requiredLayerType) {
1672 m_graphicsLayer->setMaskLayer(nullptr);
1673 willDestroyLayer(m_maskLayer.get());
1674 GraphicsLayer::clear(m_maskLayer);
1678 m_maskLayer = createGraphicsLayer("mask", requiredLayerType);
1679 m_maskLayer->setDrawsContent(paintsContent);
1680 m_maskLayer->setPaintingPhase(maskPhases);
1681 layerChanged = true;
1682 m_graphicsLayer->setMaskLayer(m_maskLayer.copyRef());
1684 } else if (m_maskLayer) {
1685 m_graphicsLayer->setMaskLayer(nullptr);
1686 willDestroyLayer(m_maskLayer.get());
1687 GraphicsLayer::clear(m_maskLayer);
1688 layerChanged = true;
1692 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1695 void RenderLayerBacking::updateChildClippingStrategy(bool needsDescendantsClippingLayer)
1697 if (hasClippingLayer() && needsDescendantsClippingLayer) {
1698 if (is<RenderBox>(renderer()) && (renderer().style().clipPath() || renderer().style().hasBorderRadius())) {
1699 // FIXME: we shouldn't get geometry here as layout may not have been udpated.
1700 LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
1701 boxRect.move(contentOffsetInCompostingLayer());
1702 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
1703 if (clippingLayer()->setMasksToBoundsRect(contentsClippingRect)) {
1704 clippingLayer()->setMaskLayer(nullptr);
1705 GraphicsLayer::clear(m_childClippingMaskLayer);
1709 if (!m_childClippingMaskLayer) {
1710 m_childClippingMaskLayer = createGraphicsLayer("child clipping mask");
1711 m_childClippingMaskLayer->setDrawsContent(true);
1712 m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
1713 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.copyRef());
1717 if (m_childClippingMaskLayer) {
1718 if (hasClippingLayer())
1719 clippingLayer()->setMaskLayer(nullptr);
1720 GraphicsLayer::clear(m_childClippingMaskLayer);
1722 if (hasClippingLayer())
1723 clippingLayer()->setMasksToBoundsRect(FloatRoundedRect(FloatRect(FloatPoint(), clippingLayer()->size())));
1727 bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
1729 if (needsScrollingLayers == !!m_scrollingLayer)
1732 if (!m_scrollingLayer) {
1733 // Outer layer which corresponds with the scroll view.
1734 m_scrollingLayer = createGraphicsLayer("scrolling container", GraphicsLayer::Type::Scrolling);
1735 m_scrollingLayer->setDrawsContent(false);
1736 m_scrollingLayer->setMasksToBounds(true);
1738 // Inner layer which renders the content that scrolls.
1739 m_scrollingContentsLayer = createGraphicsLayer("scrolled Contents");
1740 m_scrollingContentsLayer->setDrawsContent(true);
1742 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1743 if (!m_foregroundLayer)
1744 paintPhase |= GraphicsLayerPaintForeground;
1745 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1746 m_scrollingLayer->addChild(*m_scrollingContentsLayer);
1748 compositor().willRemoveScrollingLayerWithBacking(m_owningLayer, *this);
1750 willDestroyLayer(m_scrollingLayer.get());
1751 willDestroyLayer(m_scrollingContentsLayer.get());
1753 GraphicsLayer::unparentAndClear(m_scrollingLayer);
1754 GraphicsLayer::unparentAndClear(m_scrollingContentsLayer);
1757 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1758 m_graphicsLayer->setNeedsDisplay(); // Because painting phases changed.
1760 if (m_scrollingLayer)
1761 compositor().didAddScrollingLayer(m_owningLayer);
1766 void RenderLayerBacking::detachFromScrollingCoordinator(OptionSet<LayerScrollCoordinationRole> roles)
1768 if (!m_scrollingNodeID && !m_viewportConstrainedNodeID)
1771 auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator();
1772 if (!scrollingCoordinator)
1775 if ((roles & Scrolling) && m_scrollingNodeID) {
1776 LOG(Compositing, "Detaching Scrolling node %" PRIu64, m_scrollingNodeID);
1777 scrollingCoordinator->detachFromStateTree(m_scrollingNodeID);
1778 m_scrollingNodeID = 0;
1781 if ((roles & ViewportConstrained) && m_viewportConstrainedNodeID) {
1782 LOG(Compositing, "Detaching ViewportConstrained node %" PRIu64, m_viewportConstrainedNodeID);
1783 scrollingCoordinator->detachFromStateTree(m_viewportConstrainedNodeID);
1784 m_viewportConstrainedNodeID = 0;
1788 void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated)
1790 m_graphicsLayer->setIsViewportConstrained(viewportCoordinated);
1793 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
1796 if (!m_backgroundLayer)
1797 phase |= GraphicsLayerPaintBackground;
1798 if (!m_foregroundLayer)
1799 phase |= GraphicsLayerPaintForeground;
1801 if (m_scrollingContentsLayer) {
1802 phase &= ~GraphicsLayerPaintForeground;
1803 phase |= GraphicsLayerPaintCompositedScroll;
1806 return static_cast<GraphicsLayerPaintingPhase>(phase);
1809 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
1811 float finalOpacity = rendererOpacity;
1813 for (auto* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1814 // We only care about parents that are stacking contexts.
1815 // Recall that opacity creates stacking context.
1816 if (!curr->isStackingContainer())
1819 // If we found a compositing layer, we want to compute opacity
1820 // relative to it. So we can break here.
1821 if (curr->isComposited())
1824 finalOpacity *= curr->renderer().opacity();
1827 return finalOpacity;
1830 // FIXME: Code is duplicated in RenderLayer. Also, we should probably not consider filters a box decoration here.
1831 static inline bool hasVisibleBoxDecorations(const RenderStyle& style)
1833 return style.hasVisibleBorder() || style.hasBorderRadius() || style.hasOutline() || style.hasAppearance() || style.boxShadow() || style.hasFilter();
1836 static bool canDirectlyCompositeBackgroundBackgroundImage(const RenderStyle& style)
1838 if (!GraphicsLayer::supportsContentsTiling())
1841 auto& fillLayer = style.backgroundLayers();
1842 if (fillLayer.next())
1845 if (!fillLayer.imagesAreLoaded())
1848 if (fillLayer.attachment() != FillAttachment::ScrollBackground)
1851 // FIXME: Allow color+image compositing when it makes sense.
1852 // For now bailing out.
1853 if (style.visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor).isVisible())
1856 // FIXME: support gradients with isGeneratedImage.
1857 auto* styleImage = fillLayer.image();
1858 if (!styleImage->isCachedImage())
1861 auto* image = styleImage->cachedImage()->image();
1862 if (!image->isBitmapImage())
1868 static bool hasPaintedBoxDecorationsOrBackgroundImage(const RenderStyle& style)
1870 if (hasVisibleBoxDecorations(style))
1873 if (!style.hasBackgroundImage())
1876 return !canDirectlyCompositeBackgroundBackgroundImage(style);
1879 static inline bool hasPerspectiveOrPreserves3D(const RenderStyle& style)
1881 return style.hasPerspective() || style.preserves3D();
1884 Color RenderLayerBacking::rendererBackgroundColor() const
1886 RenderElement* backgroundRenderer = nullptr;
1887 if (renderer().isDocumentElementRenderer())
1888 backgroundRenderer = renderer().view().rendererForRootBackground();
1890 if (!backgroundRenderer)
1891 backgroundRenderer = &renderer();
1893 return backgroundRenderer->style().visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
1896 void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1898 if (m_backgroundLayer && !m_backgroundLayerPaintsFixedRootBackground && !contentsInfo.paintsBoxDecorations()) {
1899 m_graphicsLayer->setContentsToSolidColor(Color());
1900 m_backgroundLayer->setContentsToSolidColor(rendererBackgroundColor());
1902 FloatRect contentsRect = backgroundBoxForSimpleContainerPainting();
1903 // NOTE: This is currently only used by RenderFullScreen, which we want to be
1904 // big enough to hide overflow areas of the root.
1905 contentsRect.inflate(contentsRect.size());
1906 m_backgroundLayer->setContentsRect(contentsRect);
1907 m_backgroundLayer->setContentsClippingRect(FloatRoundedRect(contentsRect));
1911 if (!contentsInfo.isSimpleContainer() || (is<RenderBox>(renderer()) && !downcast<RenderBox>(renderer()).paintsOwnBackground())) {
1912 m_graphicsLayer->setContentsToSolidColor(Color());
1916 Color backgroundColor = rendererBackgroundColor();
1918 // An unset (invalid) color will remove the solid color.
1919 m_graphicsLayer->setContentsToSolidColor(backgroundColor);
1920 FloatRect contentsRect = backgroundBoxForSimpleContainerPainting();
1921 m_graphicsLayer->setContentsRect(contentsRect);
1922 m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(contentsRect));
1923 didUpdateContentsRect = true;
1926 void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1928 if (!GraphicsLayer::supportsContentsTiling())
1931 if (contentsInfo.isDirectlyCompositedImage())
1934 auto& style = renderer().style();
1935 if (!contentsInfo.isSimpleContainer() || !style.hasBackgroundImage()) {
1936 m_graphicsLayer->setContentsToImage(0);
1940 auto destRect = backgroundBoxForSimpleContainerPainting();
1943 // FIXME: Absolute paint location is required here.
1944 downcast<RenderBox>(renderer()).getGeometryForBackgroundImage(&renderer(), LayoutPoint(), destRect, phase, tileSize);
1946 m_graphicsLayer->setContentsTileSize(tileSize);
1947 m_graphicsLayer->setContentsTilePhase(phase);
1948 m_graphicsLayer->setContentsRect(destRect);
1949 m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(destRect));
1950 m_graphicsLayer->setContentsToImage(style.backgroundLayers().image()->cachedImage()->image());
1952 didUpdateContentsRect = true;
1955 void RenderLayerBacking::updateRootLayerConfiguration()
1957 if (!m_isFrameLayerWithTiledBacking)
1960 Color backgroundColor;
1961 bool viewIsTransparent = compositor().viewHasTransparentBackground(&backgroundColor);
1963 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
1964 if (m_isMainFrameRenderViewLayer) {
1965 m_backgroundLayer->setBackgroundColor(backgroundColor);
1966 m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
1969 m_graphicsLayer->setBackgroundColor(Color());
1970 m_graphicsLayer->setContentsOpaque(false);
1971 } else if (m_isMainFrameRenderViewLayer) {
1972 m_graphicsLayer->setBackgroundColor(backgroundColor);
1973 m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
1977 static bool supportsDirectlyCompositedBoxDecorations(const RenderLayerModelObject& renderer)
1979 if (!GraphicsLayer::supportsBackgroundColorContent())
1982 const RenderStyle& style = renderer.style();
1983 if (renderer.hasClip())
1986 if (hasPaintedBoxDecorationsOrBackgroundImage(style))
1989 // FIXME: We can't create a directly composited background if this
1990 // layer will have children that intersect with the background layer.
1991 // A better solution might be to introduce a flattening layer if
1992 // we do direct box decoration composition.
1993 // https://bugs.webkit.org/show_bug.cgi?id=119461
1994 if (hasPerspectiveOrPreserves3D(style))
1997 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
1998 if (style.backgroundComposite() != CompositeSourceOver)
2004 bool RenderLayerBacking::paintsBoxDecorations() const
2006 if (!m_owningLayer.hasVisibleBoxDecorations())
2009 return !supportsDirectlyCompositedBoxDecorations(renderer());
2012 bool RenderLayerBacking::paintsContent(RenderLayer::PaintedContentRequest& request) const
2014 bool paintsContent = false;
2016 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers(request))
2017 paintsContent = true;
2019 if (request.isSatisfied())
2020 return paintsContent;
2022 if (isPaintDestinationForDescendantLayers(request))
2023 paintsContent = true;
2025 if (request.isSatisfied())
2026 return paintsContent;
2028 if (request.hasPaintedContent == RequestState::Unknown)
2029 request.hasPaintedContent = RequestState::False;
2031 if (request.hasSubpixelAntialiasedText == RequestState::Unknown)
2032 request.hasSubpixelAntialiasedText = RequestState::False;
2034 return paintsContent;
2037 static bool isRestartedPlugin(RenderObject& renderer)
2039 if (!is<RenderEmbeddedObject>(renderer))
2042 auto& element = downcast<RenderEmbeddedObject>(renderer).frameOwnerElement();
2043 if (!is<HTMLPlugInElement>(element))
2046 return downcast<HTMLPlugInElement>(element).isRestartedPlugin();
2049 static bool isCompositedPlugin(RenderObject& renderer)
2051 return is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
2054 // A "simple container layer" is a RenderLayer which has no visible content to render.
2055 // It may have no children, or all its children may be themselves composited.
2056 // This is a useful optimization, because it allows us to avoid allocating backing store.
2057 bool RenderLayerBacking::isSimpleContainerCompositingLayer(PaintedContentsInfo& contentsInfo) const
2059 if (renderer().isRenderReplaced() && (!isCompositedPlugin(renderer()) || isRestartedPlugin(renderer())))
2062 if (renderer().isTextControl())
2065 if (contentsInfo.paintsBoxDecorations() || contentsInfo.paintsContent())
2068 if (renderer().style().backgroundClip() == FillBox::Text)
2071 if (renderer().isDocumentElementRenderer() && m_owningLayer.isolatesCompositedBlending())
2074 if (renderer().isRenderView()) {
2075 // Look to see if the root object has a non-simple background
2076 auto* rootObject = renderer().document().documentElement() ? renderer().document().documentElement()->renderer() : nullptr;
2080 // Reject anything that has a border, a border-radius or outline,
2081 // or is not a simple background (no background, or solid color).
2082 if (hasPaintedBoxDecorationsOrBackgroundImage(rootObject->style()))
2085 // Now look at the body's renderer.
2086 auto* body = renderer().document().body();
2089 auto* bodyRenderer = body->renderer();
2093 if (hasPaintedBoxDecorationsOrBackgroundImage(bodyRenderer->style()))
2100 // Returning true stops the traversal.
2101 enum class LayerTraversal { Continue, Stop };
2103 static LayerTraversal traverseVisibleNonCompositedDescendantLayers(RenderLayer& parent, const WTF::Function<LayerTraversal (const RenderLayer&)>& layerFunc)
2105 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
2106 parent.updateLayerListsIfNeeded();
2108 #if !ASSERT_DISABLED
2109 LayerListMutationDetector mutationChecker(&parent);
2112 if (auto* normalFlowList = parent.normalFlowList()) {
2113 for (auto* childLayer : *normalFlowList) {
2114 if (compositedWithOwnBackingStore(*childLayer))
2117 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2118 return LayerTraversal::Stop;
2120 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2121 return LayerTraversal::Stop;
2125 if (parent.isStackingContainer() && !parent.hasVisibleDescendant())
2126 return LayerTraversal::Continue;
2128 // Use the m_hasCompositingDescendant bit to optimize?
2129 if (auto* negZOrderList = parent.negZOrderList()) {
2130 for (auto* childLayer : *negZOrderList) {
2131 if (compositedWithOwnBackingStore(*childLayer))
2134 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2135 return LayerTraversal::Stop;
2137 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2138 return LayerTraversal::Stop;
2142 if (auto* posZOrderList = parent.posZOrderList()) {
2143 for (auto* childLayer : *posZOrderList) {
2144 if (compositedWithOwnBackingStore(*childLayer))
2147 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2148 return LayerTraversal::Stop;
2150 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2151 return LayerTraversal::Stop;
2155 return LayerTraversal::Continue;
2158 // Conservative test for having no rendered children.
2159 bool RenderLayerBacking::isPaintDestinationForDescendantLayers(RenderLayer::PaintedContentRequest& request) const
2161 bool hasPaintingDescendant = false;
2162 traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasPaintingDescendant, &request](const RenderLayer& layer) {
2163 hasPaintingDescendant |= layer.isVisuallyNonEmpty(&request);
2164 return (hasPaintingDescendant && request.isSatisfied()) ? LayerTraversal::Stop : LayerTraversal::Continue;
2167 return hasPaintingDescendant;
2170 bool RenderLayerBacking::hasVisibleNonCompositedDescendants() const
2172 bool hasVisibleDescendant = false;
2173 traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasVisibleDescendant](const RenderLayer& layer) {
2174 hasVisibleDescendant |= layer.hasVisibleContent();
2175 return hasVisibleDescendant ? LayerTraversal::Stop : LayerTraversal::Continue;
2178 return hasVisibleDescendant;
2181 bool RenderLayerBacking::containsPaintedContent(PaintedContentsInfo& contentsInfo) const
2183 if (contentsInfo.isSimpleContainer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer.isReflection())
2186 if (contentsInfo.isDirectlyCompositedImage())
2189 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
2190 // and set background color on the layer in that case, instead of allocating backing store and painting.
2192 if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo())
2193 return m_owningLayer.hasVisibleBoxDecorationsOrBackground() || (!(downcast<RenderVideo>(renderer()).supportsAcceleratedRendering()) && m_requiresOwnBackingStore);
2196 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
2197 if (is<RenderHTMLCanvas>(renderer()) && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents)
2198 return m_owningLayer.hasVisibleBoxDecorationsOrBackground();
2204 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
2205 // that require painting. Direct compositing saves backing store.
2206 bool RenderLayerBacking::isDirectlyCompositedImage() const
2208 if (!is<RenderImage>(renderer()) || m_owningLayer.hasVisibleBoxDecorationsOrBackground() || m_owningLayer.paintsWithFilters() || renderer().hasClip())
2212 if (is<RenderMedia>(renderer()))
2216 auto& imageRenderer = downcast<RenderImage>(renderer());
2217 if (auto* cachedImage = imageRenderer.cachedImage()) {
2218 if (!cachedImage->hasImage())
2221 auto* image = cachedImage->imageForRenderer(&imageRenderer);
2222 if (!is<BitmapImage>(image))
2225 if (downcast<BitmapImage>(*image).orientationForCurrentFrame() != DefaultImageOrientation)
2228 #if (PLATFORM(GTK) || PLATFORM(WPE))
2229 // GTK and WPE ports don't support rounded rect clipping at TextureMapper level, so they cannot
2230 // directly composite images that have border-radius propery. Draw them as non directly composited
2231 // content instead. See https://bugs.webkit.org/show_bug.cgi?id=174157.
2232 if (imageRenderer.style().hasBorderRadius())
2236 return m_graphicsLayer->shouldDirectlyCompositeImage(image);
2242 void RenderLayerBacking::contentChanged(ContentChangeType changeType)
2244 PaintedContentsInfo contentsInfo(*this);
2245 if ((changeType == ImageChanged) && contentsInfo.isDirectlyCompositedImage()) {
2246 updateImageContents(contentsInfo);
2250 if ((changeType == BackgroundImageChanged) && canDirectlyCompositeBackgroundBackgroundImage(renderer().style()))
2253 if ((changeType == MaskImageChanged) && m_maskLayer) {
2254 // The composited layer bounds relies on box->maskClipRect(), which changes
2255 // when the mask image becomes available.
2256 updateAfterLayout(UpdateAfterLayoutFlags::IsUpdateRoot);
2259 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
2260 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
2261 m_graphicsLayer->setContentsNeedsDisplay();
2267 void RenderLayerBacking::updateImageContents(PaintedContentsInfo& contentsInfo)
2269 auto& imageRenderer = downcast<RenderImage>(renderer());
2271 auto* cachedImage = imageRenderer.cachedImage();
2275 auto* image = cachedImage->imageForRenderer(&imageRenderer);
2279 // We have to wait until the image is fully loaded before setting it on the layer.
2280 if (!cachedImage->isLoaded())
2283 // This is a no-op if the layer doesn't have an inner layer for the image.
2284 m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
2286 LayoutRect boxRect(LayoutPoint(), imageRenderer.size());
2287 boxRect.move(contentOffsetInCompostingLayer());
2288 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
2289 m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
2291 m_graphicsLayer->setContentsToImage(image);
2293 updateDrawsContent(contentsInfo);
2295 // Image animation is "lazy", in that it automatically stops unless someone is drawing
2296 // the image. So we have to kick the animation each time; this has the downside that the
2297 // image will keep animating, even if its layer is not visible.
2298 image->startAnimation();
2301 FloatPoint3D RenderLayerBacking::computeTransformOriginForPainting(const LayoutRect& borderBox) const
2303 const RenderStyle& style = renderer().style();
2304 float deviceScaleFactor = this->deviceScaleFactor();
2306 FloatPoint3D origin;
2307 origin.setX(roundToDevicePixel(floatValueForLength(style.transformOriginX(), borderBox.width()), deviceScaleFactor));
2308 origin.setY(roundToDevicePixel(floatValueForLength(style.transformOriginY(), borderBox.height()), deviceScaleFactor));
2309 origin.setZ(style.transformOriginZ());
2314 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
2315 LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const
2317 return LayoutSize(-m_compositedBounds.x() + m_compositedBoundsOffsetFromGraphicsLayer.width(), -m_compositedBounds.y() + m_compositedBoundsOffsetFromGraphicsLayer.height());
2320 LayoutRect RenderLayerBacking::contentsBox() const
2322 if (!is<RenderBox>(renderer()))
2323 return LayoutRect();
2325 auto& renderBox = downcast<RenderBox>(renderer());
2326 LayoutRect contentsRect;
2328 if (is<RenderVideo>(renderBox))
2329 contentsRect = downcast<RenderVideo>(renderBox).videoBox();
2332 if (is<RenderReplaced>(renderBox)) {
2333 RenderReplaced& renderReplaced = downcast<RenderReplaced>(renderBox);
2334 contentsRect = renderReplaced.replacedContentRect();
2336 contentsRect = renderBox.contentBoxRect();
2338 contentsRect.move(contentOffsetInCompostingLayer());
2339 return contentsRect;
2342 static LayoutRect backgroundRectForBox(const RenderBox& box)
2344 switch (box.style().backgroundClip()) {
2345 case FillBox::Border:
2346 return box.borderBoxRect();
2347 case FillBox::Padding:
2348 return box.paddingBoxRect();
2349 case FillBox::Content:
2350 return box.contentBoxRect();
2355 ASSERT_NOT_REACHED();
2356 return LayoutRect();
2359 FloatRect RenderLayerBacking::backgroundBoxForSimpleContainerPainting() const
2361 if (!is<RenderBox>(renderer()))
2364 LayoutRect backgroundBox = backgroundRectForBox(downcast<RenderBox>(renderer()));
2365 backgroundBox.move(contentOffsetInCompostingLayer());
2366 return snapRectToDevicePixels(backgroundBox, deviceScaleFactor());
2369 GraphicsLayer* RenderLayerBacking::parentForSublayers() const
2371 if (m_scrollingContentsLayer)
2372 return m_scrollingContentsLayer.get();
2374 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
2377 GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
2379 if (m_ancestorClippingLayer)
2380 return m_ancestorClippingLayer.get();
2382 if (m_contentsContainmentLayer)
2383 return m_contentsContainmentLayer.get();
2385 return m_graphicsLayer.get();
2388 bool RenderLayerBacking::paintsIntoWindow() const
2390 #if USE(COORDINATED_GRAPHICS_THREADED)
2394 if (m_isFrameLayerWithTiledBacking)
2397 if (m_owningLayer.isRenderViewLayer()) {
2398 #if PLATFORM(IOS) || USE(COORDINATED_GRAPHICS)
2399 if (compositor().inForcedCompositingMode())
2403 return compositor().rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
2409 void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
2411 if (requiresOwnBacking == m_requiresOwnBackingStore)
2414 m_requiresOwnBackingStore = requiresOwnBacking;
2416 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
2417 // cached clip rects, so when it changes we have to clear clip rects on descendants.
2418 m_owningLayer.clearClipRectsIncludingDescendants(PaintingClipRects);
2419 m_owningLayer.computeRepaintRectsIncludingDescendants();
2421 compositor().repaintInCompositedAncestor(m_owningLayer, compositedBounds());
2424 void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer shouldClip)
2426 ASSERT(!paintsIntoCompositedAncestor());
2428 auto& frameView = renderer().view().frameView();
2429 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2430 frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBoxForPainting());
2432 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2433 // By default, setNeedsDisplay will clip to the size of the GraphicsLayer, which does not include margin tiles.
2434 // So if the TiledBacking has a margin that needs to be invalidated, we need to send in a rect to setNeedsDisplayInRect
2435 // that is large enough to include the margin. TiledBacking::bounds() includes the margin.
2436 auto* tiledBacking = this->tiledBacking();
2437 FloatRect rectToRepaint = tiledBacking ? tiledBacking->bounds() : FloatRect(FloatPoint(0, 0), m_graphicsLayer->size());
2438 m_graphicsLayer->setNeedsDisplayInRect(rectToRepaint, shouldClip);
2441 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
2442 m_foregroundLayer->setNeedsDisplay();
2444 if (m_backgroundLayer && m_backgroundLayer->drawsContent())
2445 m_backgroundLayer->setNeedsDisplay();
2447 if (m_maskLayer && m_maskLayer->drawsContent())
2448 m_maskLayer->setNeedsDisplay();
2450 if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent())
2451 m_childClippingMaskLayer->setNeedsDisplay();
2453 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
2454 m_scrollingContentsLayer->setNeedsDisplay();
2457 // r is in the coordinate space of the layer's render object
2458 void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, GraphicsLayer::ShouldClipToLayer shouldClip)
2460 ASSERT(!paintsIntoCompositedAncestor());
2462 FloatRect pixelSnappedRectForPainting = snapRectToDevicePixels(r, deviceScaleFactor());
2463 auto& frameView = renderer().view().frameView();
2464 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2465 frameView.addTrackedRepaintRect(pixelSnappedRectForPainting);
2467 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2468 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2469 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2470 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2473 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
2474 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2475 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2476 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2479 // FIXME: need to split out repaints for the background.
2480 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
2481 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2482 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2483 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2486 if (m_maskLayer && m_maskLayer->drawsContent()) {
2487 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2488 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2489 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2492 if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) {
2493 FloatRect layerDirtyRect = r;
2494 layerDirtyRect.move(-m_childClippingMaskLayer->offsetFromRenderer());
2495 m_childClippingMaskLayer->setNeedsDisplayInRect(layerDirtyRect);
2498 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
2499 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2500 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2502 // Account for the fact that RenderLayerBacking::updateGeometry() bakes scrollOffset into offsetFromRenderer on iOS,
2503 // but the repaint rect is computed without taking the scroll position into account (see shouldApplyClipAndScrollPositionForRepaint()).
2504 layerDirtyRect.moveBy(-m_owningLayer.scrollPosition());
2506 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2510 void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext& context,
2511 const IntRect& paintDirtyRect, // In the coords of rootLayer.
2512 OptionSet<PaintBehavior> paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
2514 if ((paintsIntoWindow() || paintsIntoCompositedAncestor()) && paintingPhase != GraphicsLayerPaintChildClippingMask) {
2515 #if !PLATFORM(IOS) && !OS(WINDOWS)
2516 // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy
2517 // when pages are restored from the PageCache.
2518 // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache
2519 ASSERT_NOT_REACHED();
2524 OptionSet<RenderLayer::PaintLayerFlag> paintFlags;
2525 if (paintingPhase & GraphicsLayerPaintBackground)
2526 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingBackgroundPhase);
2527 if (paintingPhase & GraphicsLayerPaintForeground)
2528 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingForegroundPhase);
2529 if (paintingPhase & GraphicsLayerPaintMask)
2530 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingMaskPhase);
2531 if (paintingPhase & GraphicsLayerPaintClipPath)
2532 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingClipPathPhase);
2533 if (paintingPhase & GraphicsLayerPaintChildClippingMask)
2534 paintFlags.add(RenderLayer::PaintLayerPaintingChildClippingMaskPhase);
2535 if (paintingPhase & GraphicsLayerPaintOverflowContents)
2536 paintFlags.add(RenderLayer::PaintLayerPaintingOverflowContents);
2537 if (paintingPhase & GraphicsLayerPaintCompositedScroll)
2538 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingScrollingPhase);
2540 if (graphicsLayer == m_backgroundLayer.get() && m_backgroundLayerPaintsFixedRootBackground)
2541 paintFlags.add({ RenderLayer::PaintLayerPaintingRootBackgroundOnly, RenderLayer::PaintLayerPaintingCompositingForegroundPhase }); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
2542 else if (compositor().fixedRootBackgroundLayer())
2543 paintFlags.add(RenderLayer::PaintLayerPaintingSkipRootBackground);
2546 RenderElement::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(&renderer());
2549 FrameView::PaintingState paintingState;
2550 if (m_owningLayer.isRenderViewLayer())
2551 renderer().view().frameView().willPaintContents(context, paintDirtyRect, paintingState);
2553 // FIXME: GraphicsLayers need a way to split for RenderFragmentContainers.
2554 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer);
2555 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags);
2557 if (m_owningLayer.containsDirtyOverlayScrollbars())
2558 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
2560 if (m_owningLayer.isRenderViewLayer())
2561 renderer().view().frameView().didPaintContents(context, paintDirtyRect, paintingState);
2563 compositor().didPaintBacking(this);
2565 ASSERT(!m_owningLayer.m_usedTransparency);
2568 // Up-call from compositing layer drawing callback.
2569 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const FloatRect& clip, GraphicsLayerPaintBehavior layerPaintBehavior)
2572 renderer().page().setIsPainting(true);
2576 LocalDefaultSystemAppearance localAppearance(renderer().page().useSystemAppearance(), renderer().page().useDarkAppearance());
2579 // The dirtyRect is in the coords of the painting root.
2580 FloatRect adjustedClipRect = clip;
2581 adjustedClipRect.move(m_subpixelOffsetFromRenderer);
2582 IntRect dirtyRect = enclosingIntRect(adjustedClipRect);
2584 if (!graphicsLayer->repaintCount())
2585 layerPaintBehavior |= GraphicsLayerPaintFirstTilePaint;
2587 if (graphicsLayer == m_graphicsLayer.get()
2588 || graphicsLayer == m_foregroundLayer.get()
2589 || graphicsLayer == m_backgroundLayer.get()
2590 || graphicsLayer == m_maskLayer.get()
2591 || graphicsLayer == m_childClippingMaskLayer.get()
2592 || graphicsLayer == m_scrollingContentsLayer.get()) {
2593 InspectorInstrumentation::willPaint(renderer());
2595 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
2596 dirtyRect.intersect(enclosingIntRect(compositedBoundsIncludingMargin()));
2598 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2599 OptionSet<PaintBehavior> behavior = PaintBehavior::Normal;
2600 if (layerPaintBehavior == GraphicsLayerPaintSnapshotting)
2601 behavior.add(PaintBehavior::Snapshotting);
2603 if (layerPaintBehavior == GraphicsLayerPaintFirstTilePaint)
2604 behavior.add(PaintBehavior::TileFirstPaint);
2606 paintIntoLayer(graphicsLayer, context, dirtyRect, behavior, paintingPhase);
2608 InspectorInstrumentation::didPaint(renderer(), dirtyRect);
2609 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2610 paintScrollbar(m_owningLayer.horizontalScrollbar(), context, dirtyRect);
2611 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2612 paintScrollbar(m_owningLayer.verticalScrollbar(), context, dirtyRect);
2613 } else if (graphicsLayer == layerForScrollCorner()) {
2614 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
2616 context.translate(-scrollCornerAndResizer.location());
2617 LayoutRect transformedClip = LayoutRect(clip);
2618 transformedClip.moveBy(scrollCornerAndResizer.location());
2619 m_owningLayer.paintScrollCorner(context, IntPoint(), snappedIntRect(transformedClip));
2620 m_owningLayer.paintResizer(context, IntPoint(), transformedClip);
2624 renderer().page().setIsPainting(false);
2628 float RenderLayerBacking::pageScaleFactor() const
2630 return compositor().pageScaleFactor();
2633 float RenderLayerBacking::zoomedOutPageScaleFactor() const
2635 return compositor().zoomedOutPageScaleFactor();
2638 float RenderLayerBacking::deviceScaleFactor() const
2640 return compositor().deviceScaleFactor();
2643 float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer* layer) const
2645 return compositor().contentsScaleMultiplierForNewTiles(layer);
2648 bool RenderLayerBacking::paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const
2650 return m_isMainFrameRenderViewLayer;
2653 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
2655 compositor().didFlushChangesForLayer(m_owningLayer, layer);
2658 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
2660 auto* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
2661 if (graphicsLayer != transformedLayer)
2664 if (m_owningLayer.hasTransform()) {
2665 transform = m_owningLayer.currentTransform(RenderStyle::ExcludeTransformOrigin);
2671 bool RenderLayerBacking::isTrackingRepaints() const
2673 return static_cast<GraphicsLayerClient&>(compositor()).isTrackingRepaints();
2676 bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer, LayerTreeAsTextBehavior behavior) const
2678 if (behavior & LayerTreeAsTextDebug)
2681 // Skip the root tile cache's flattening layer.
2682 return m_isMainFrameRenderViewLayer && layer && layer == m_childContainmentLayer.get();
2685 bool RenderLayerBacking::shouldDumpPropertyForLayer(const GraphicsLayer* layer, const char* propertyName) const
2687 // For backwards compatibility with WebKit1 and other platforms,
2688 // skip some properties on the root tile cache.
2689 if (m_isMainFrameRenderViewLayer && layer == m_graphicsLayer.get()) {
2690 if (!strcmp(propertyName, "drawsContent"))
2693 // Background color could be of interest to tests or other dumpers if it's non-white.
2694 if (!strcmp(propertyName, "backgroundColor") && layer->backgroundColor() == Color::white)
2697 // The root tile cache's repaints will show up at the top with FrameView's,
2698 // so don't dump them twice.
2699 if (!strcmp(propertyName, "repaintRects"))
2706 bool RenderLayerBacking::shouldAggressivelyRetainTiles(const GraphicsLayer*) const
2708 // Only the main frame TileController has enough information about in-window state to
2709 // correctly implement aggressive tile retention.
2710 if (!m_isMainFrameRenderViewLayer)
2713 return renderer().settings().aggressiveTileRetentionEnabled();
2716 bool RenderLayerBacking::shouldTemporarilyRetainTileCohorts(const GraphicsLayer*) const
2718 return renderer().settings().temporaryTileCohortRetentionEnabled();
2721 bool RenderLayerBacking::useGiantTiles() const
2723 return renderer().settings().useGiantTiles();
2726 void RenderLayerBacking::logFilledVisibleFreshTile(unsigned blankPixelCount)
2728 if (auto* loggingClient = renderer().page().performanceLoggingClient())
2729 loggingClient->logScrollingEvent(PerformanceLoggingClient::ScrollingEvent::FilledTile, MonotonicTime::now(), blankPixelCount);
2733 void RenderLayerBacking::verifyNotPainting()
2735 ASSERT(!renderer().page().isPainting());
2739 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
2741 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
2742 bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyTransform);
2743 bool hasFilter = keyframes.containsProperty(CSSPropertyFilter);
2745 bool hasBackdropFilter = false;
2746 #if ENABLE(FILTERS_LEVEL_2)
2747 hasBackdropFilter = keyframes.containsProperty(CSSPropertyWebkitBackdropFilter);
2750 if (!hasOpacity && !hasTransform && !hasFilter && !hasBackdropFilter)
2753 KeyframeValueList transformVector(AnimatedPropertyTransform);
2754 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2755 KeyframeValueList filterVector(AnimatedPropertyFilter);
2756 #if ENABLE(FILTERS_LEVEL_2)
2757 KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter);
2760 size_t numKeyframes = keyframes.size();
2761 for (size_t i = 0; i < numKeyframes; ++i) {
2762 const KeyframeValue& currentKeyframe = keyframes[i];
2763 const RenderStyle* keyframeStyle = currentKeyframe.style();
2764 double key = currentKeyframe.key();
2769 auto* tf = currentKeyframe.timingFunction();
2771 bool isFirstOrLastKeyframe = key == 0 || key == 1;
2772 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyTransform))
2773 transformVector.insert(std::make_unique<TransformAnimationValue>(key, keyframeStyle->transform(), tf));
2775 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
2776 opacityVector.insert(std::make_unique<FloatAnimationValue>(key, keyframeStyle->opacity(), tf));
2778 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyFilter))
2779 filterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->filter(), tf));
2781 #if ENABLE(FILTERS_LEVEL_2)
2782 if ((hasBackdropFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitBackdropFilter))
2783 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->backdropFilter(), tf));
2787 if (!renderer().settings().acceleratedCompositedAnimationsEnabled())
2790 bool didAnimate = false;
2792 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), anim, keyframes.animationName(), timeOffset))
2795 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2798 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2801 #if ENABLE(FILTERS_LEVEL_2)
2802 if (hasBackdropFilter && m_graphicsLayer->addAnimation(backdropFilterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2809 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
2811 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
2814 void RenderLayerBacking::animationSeeked(double timeOffset, const String& animationName)
2816 m_graphicsLayer->seekAnimation(animationName, timeOffset);
2819 void RenderLayerBacking::animationFinished(const String& animationName)
2821 m_graphicsLayer->removeAnimation(animationName);
2824 bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
2826 bool didAnimate = false;
2828 ASSERT(property != CSSPropertyInvalid);
2830 if (property == CSSPropertyOpacity) {
2831 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
2832 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
2833 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2834 opacityVector.insert(std::make_unique<FloatAnimationValue>(0, compositingOpacity(fromStyle->opacity())));
2835 opacityVector.insert(std::make_unique<FloatAnimationValue>(1, compositingOpacity(toStyle->opacity())));
2836 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
2837 if (m_graphicsLayer->addAnimation(opacityVector, FloatSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
2838 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
2839 updateOpacity(*toStyle);
2845 if (property == CSSPropertyTransform && m_owningLayer.hasTransform()) {
2846 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyTransform);
2847 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
2848 KeyframeValueList transformVector(AnimatedPropertyTransform);
2849 transformVector.insert(std::make_unique<TransformAnimationValue>(0, fromStyle->transform()));
2850 transformVector.insert(std::make_unique<TransformAnimationValue>(1, toStyle->transform()));
2851 if (m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyTransform), timeOffset)) {
2852 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
2853 updateTransform(*toStyle);
2859 if (property == CSSPropertyFilter && m_owningLayer.hasFilter()) {
2860 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyFilter);
2861 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
2862 KeyframeValueList filterVector(AnimatedPropertyFilter);
2863 filterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->filter()));
2864 filterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->filter()));
2865 if (m_graphicsLayer->addAnimation(filterVector, FloatSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyFilter), timeOffset)) {
2866 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
2867 updateFilters(*toStyle);
2873 #if ENABLE(FILTERS_LEVEL_2)
2874 if (property == CSSPropertyWebkitBackdropFilter && m_owningLayer.hasBackdropFilter()) {
2875 const Animation* backdropFilterAnim = toStyle->transitionForProperty(CSSPropertyWebkitBackdropFilter);
2876 if (backdropFilterAnim && !backdropFilterAnim->isEmptyOrZeroDuration()) {
2877 KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter);
2878 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->backdropFilter()));
2879 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->backdropFilter()));
2880 if (m_graphicsLayer->addAnimation(backdropFilterVector, FloatSize(), backdropFilterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitBackdropFilter), timeOffset)) {
2881 // To ensure that the correct backdrop filter is visible when the animation ends, also set the final backdrop filter.
2882 updateBackdropFilters(*toStyle);
2892 void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
2894 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2895 if (animatedProperty != AnimatedPropertyInvalid)
2896 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
2899 void RenderLayerBacking::transitionFinished(CSSPropertyID property)
2901 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2902 if (animatedProperty != AnimatedPropertyInvalid)
2903 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
2906 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, const String&, MonotonicTime time)
2908 renderer().animation().notifyAnimationStarted(renderer(), time);
2911 void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer)
2913 if (renderer().renderTreeBeingDestroyed())
2915 compositor().scheduleLayerFlush(layer->canThrottleLayerFlush());
2918 void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
2920 compositor().notifyFlushBeforeDisplayRefresh(layer);
2923 // This is used for the 'freeze' API, for testing only.
2924 void RenderLayerBacking::suspendAnimations(MonotonicTime time)
2926 m_graphicsLayer->suspendAnimations(time);
2929 void RenderLayerBacking::resumeAnimations()
2931 m_graphicsLayer->resumeAnimations();
2934 LayoutRect RenderLayerBacking::compositedBounds() const
2936 return m_compositedBounds;
2939 void RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds)
2941 m_compositedBounds = bounds;
2944 LayoutRect RenderLayerBacking::compositedBoundsIncludingMargin() const
2946 auto* tiledBacking = this->tiledBacking();
2947 if (!tiledBacking || !tiledBacking->hasMargins())
2948 return compositedBounds();
2950 LayoutRect boundsIncludingMargin = compositedBounds();
2951 LayoutUnit leftMarginWidth = tiledBacking->leftMarginWidth();
2952 LayoutUnit topMarginHeight = tiledBacking->topMarginHeight();
2954 boundsIncludingMargin.moveBy(LayoutPoint(-leftMarginWidth, -topMarginHeight));
2955 boundsIncludingMargin.expand(leftMarginWidth + tiledBacking->rightMarginWidth(), topMarginHeight + tiledBacking->bottomMarginHeight());
2957 return boundsIncludingMargin;
2960 CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
2962 CSSPropertyID cssProperty = CSSPropertyInvalid;
2964 case AnimatedPropertyTransform:
2965 cssProperty = CSSPropertyTransform;
2967 case AnimatedPropertyOpacity:
2968 cssProperty = CSSPropertyOpacity;
2970 case AnimatedPropertyBackgroundColor:
2971 cssProperty = CSSPropertyBackgroundColor;
2973 case AnimatedPropertyFilter:
2974 cssProperty = CSSPropertyFilter;
2976 #if ENABLE(FILTERS_LEVEL_2)
2977 case AnimatedPropertyWebkitBackdropFilter:
2978 cssProperty = CSSPropertyWebkitBackdropFilter;
2981 case AnimatedPropertyInvalid:
2982 ASSERT_NOT_REACHED();
2987 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
2989 switch (cssProperty) {
2990 case CSSPropertyTransform:
2991 return AnimatedPropertyTransform;
2992 case CSSPropertyOpacity:
2993 return AnimatedPropertyOpacity;
2994 case CSSPropertyBackgroundColor:
2995 return AnimatedPropertyBackgroundColor;
2996 case CSSPropertyFilter:
2997 return AnimatedPropertyFilter;
2998 #if ENABLE(FILTERS_LEVEL_2)
2999 case CSSPropertyWebkitBackdropFilter:
3000 return AnimatedPropertyWebkitBackdropFilter;
3003 // It's fine if we see other css properties here; they are just not accelerated.
3006 return AnimatedPropertyInvalid;
3009 CompositingLayerType RenderLayerBacking::compositingLayerType() const
3011 if (m_graphicsLayer->usesContentsLayer())
3012 return MediaCompositingLayer;
3014 if (m_graphicsLayer->drawsContent())
3015 return m_graphicsLayer->tiledBacking() ? TiledCompositingLayer : NormalCompositingLayer;
3017 return ContainerCompositingLayer;
3020 double RenderLayerBacking::backingStoreMemoryEstimate() const
3022 double backingMemory;
3024 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
3025 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
3026 if (m_foregroundLayer)
3027 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
3028 if (m_backgroundLayer)
3029 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
3031 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
3032 if (m_childClippingMaskLayer)
3033 backingMemory += m_childClippingMaskLayer->backingStoreMemoryEstimate();
3035 if (m_scrollingContentsLayer)
3036 backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
3038 if (m_layerForHorizontalScrollbar)
3039 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
3041 if (m_layerForVerticalScrollbar)
3042 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
3044 if (m_layerForScrollCorner)
3045 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
3047 return backingMemory;
3050 TextStream& operator<<(TextStream& ts, const RenderLayerBacking& backing)
3052 ts << "RenderLayerBacking " << &backing << " bounds " << backing.compositedBounds();
3054 if (backing.isFrameLayerWithTiledBacking())
3055 ts << " frame layer tiled backing";
3056 if (backing.paintsIntoWindow())
3057 ts << " paintsIntoWindow";
3058 if (backing.paintsIntoCompositedAncestor())
3059 ts << " paintsIntoCompositedAncestor";
3061 ts << " primary layer ID " << backing.graphicsLayer()->primaryLayerID();
3062 if (auto nodeID = backing.scrollingNodeIDForRole(ViewportConstrained))
3063 ts << " viewport constrained scrolling node " << nodeID;
3064 if (auto nodeID = backing.scrollingNodeIDForRole(Scrolling))
3065 ts << " scrolling node " << nodeID;
3069 } // namespace WebCore