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 willDestroyLayer(m_graphicsLayer.get());
462 m_graphicsLayer->removeFromParent();
465 m_ancestorClippingLayer = nullptr;
466 m_contentsContainmentLayer = nullptr;
467 m_graphicsLayer = nullptr;
468 m_foregroundLayer = nullptr;
469 m_backgroundLayer = nullptr;
470 m_childContainmentLayer = nullptr;
471 m_maskLayer = nullptr;
472 m_childClippingMaskLayer = nullptr;
474 m_scrollingLayer = nullptr;
475 m_scrollingContentsLayer = nullptr;
478 void RenderLayerBacking::updateOpacity(const RenderStyle& style)
480 m_graphicsLayer->setOpacity(compositingOpacity(style.opacity()));
483 void RenderLayerBacking::updateTransform(const RenderStyle& style)
485 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
486 // baked into it, and we don't want that.
487 TransformationMatrix t;
488 if (m_owningLayer.hasTransform()) {
489 auto& renderBox = downcast<RenderBox>(renderer());
490 style.applyTransform(t, snapRectToDevicePixels(renderBox.borderBoxRect(), deviceScaleFactor()), RenderStyle::ExcludeTransformOrigin);
491 makeMatrixRenderable(t, compositor().canRender3DTransforms());
494 if (m_contentsContainmentLayer) {
495 m_contentsContainmentLayer->setTransform(t);
496 m_graphicsLayer->setTransform(TransformationMatrix());
498 m_graphicsLayer->setTransform(t);
501 void RenderLayerBacking::updateFilters(const RenderStyle& style)
503 m_canCompositeFilters = m_graphicsLayer->setFilters(style.filter());
506 #if ENABLE(FILTERS_LEVEL_2)
507 void RenderLayerBacking::updateBackdropFilters(const RenderStyle& style)
509 m_canCompositeBackdropFilters = m_graphicsLayer->setBackdropFilters(style.backdropFilter());
512 void RenderLayerBacking::updateBackdropFiltersGeometry()
514 if (!m_canCompositeBackdropFilters)
517 if (!is<RenderBox>(renderer()))
520 auto& renderer = downcast<RenderBox>(this->renderer());
521 LayoutRect boxRect = renderer.borderBoxRect();
522 if (renderer.hasClip())
523 boxRect.intersect(renderer.clipRect(LayoutPoint(), nullptr));
524 boxRect.move(contentOffsetInCompostingLayer());
526 FloatRoundedRect backdropFiltersRect;
527 if (renderer.style().hasBorderRadius() && !renderer.hasClip())
528 backdropFiltersRect = renderer.style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
530 backdropFiltersRect = FloatRoundedRect(snapRectToDevicePixels(boxRect, deviceScaleFactor()));
532 m_graphicsLayer->setBackdropFiltersRect(backdropFiltersRect);
536 #if ENABLE(CSS_COMPOSITING)
537 void RenderLayerBacking::updateBlendMode(const RenderStyle& style)
539 // FIXME: where is the blend mode updated when m_ancestorClippingLayers come and go?
540 if (m_ancestorClippingLayer) {
541 m_ancestorClippingLayer->setBlendMode(style.blendMode());
542 m_graphicsLayer->setBlendMode(BlendMode::Normal);
544 m_graphicsLayer->setBlendMode(style.blendMode());
548 void RenderLayerBacking::updateCustomAppearance(const RenderStyle& style)
550 ControlPart appearance = style.appearance();
551 if (appearance == MediaControlsLightBarBackgroundPart)
552 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::LightBackdrop);
553 else if (appearance == MediaControlsDarkBarBackgroundPart)
554 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::DarkBackdrop);
556 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::None);
559 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
561 for (auto* curr = &layer; curr; curr = curr->parent()) {
562 if (curr->hasTransform() || curr->usesAcceleratedScrolling())
569 bool RenderLayerBacking::shouldClipCompositedBounds() const
572 // Scrollbar layers use this layer for relative positioning, so don't clip.
573 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
577 if (m_isFrameLayerWithTiledBacking)
580 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
586 static bool hasNonZeroTransformOrigin(const RenderObject& renderer)
588 const RenderStyle& style = renderer.style();
589 return (style.transformOriginX().type() == Fixed && style.transformOriginX().value())
590 || (style.transformOriginY().type() == Fixed && style.transformOriginY().value());
593 void RenderLayerBacking::updateCompositedBounds()
595 LayoutRect layerBounds = m_owningLayer.calculateLayerBounds(&m_owningLayer, LayoutSize(), RenderLayer::defaultCalculateLayerBoundsFlags() | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
596 // Clip to the size of the document or enclosing overflow-scroll layer.
597 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
598 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
599 if (shouldClipCompositedBounds()) {
600 auto& view = renderer().view();
601 auto* rootLayer = view.layer();
603 LayoutRect clippingBounds;
604 if (renderer().isFixedPositioned() && renderer().container() == &view)
605 clippingBounds = view.frameView().rectForFixedPositionLayout();
607 clippingBounds = view.unscaledDocumentRect();
609 if (&m_owningLayer != rootLayer)
610 clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
612 LayoutPoint delta = m_owningLayer.convertToLayerCoords(rootLayer, LayoutPoint(), RenderLayer::AdjustForColumns);
613 clippingBounds.move(-delta.x(), -delta.y());
615 layerBounds.intersect(clippingBounds);
618 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
619 // then we need to ensure that the compositing layer has non-zero size so that we can apply
620 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
621 if (layerBounds.isEmpty() && (hasNonZeroTransformOrigin(renderer()) || renderer().style().hasPerspective())) {
622 layerBounds.setWidth(1);
623 layerBounds.setHeight(1);
624 m_artificiallyInflatedBounds = true;
626 m_artificiallyInflatedBounds = false;
628 setCompositedBounds(layerBounds);
631 void RenderLayerBacking::updateAfterWidgetResize()
633 if (!is<RenderWidget>(renderer()))
635 if (auto* innerCompositor = RenderLayerCompositor::frameContentsCompositor(&downcast<RenderWidget>(renderer()))) {
636 innerCompositor->frameViewDidChangeSize();
637 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
641 void RenderLayerBacking::updateAfterLayout(OptionSet<UpdateAfterLayoutFlags> flags)
643 LOG(Compositing, "RenderLayerBacking %p updateAfterLayout (layer %p)", this, &m_owningLayer);
645 if (!compositor().compositingLayersNeedRebuild()) {
646 // Calling updateGeometry() here gives incorrect results, because the
647 // position of this layer's GraphicsLayer depends on the position of our compositing
648 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
649 // RenderLayers of that ancestor have been processed via updateLayerPositions().
651 // The solution is to update compositing children of this layer here,
652 // via updateCompositingChildrenGeometry().
653 updateCompositedBounds();
654 compositor().updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer);
656 if (flags.contains(UpdateAfterLayoutFlags::IsUpdateRoot)) {
658 updateAfterDescendants();
659 compositor().updateRootLayerPosition();
660 auto* stackingContainer = m_owningLayer.enclosingStackingContainer();
661 if (!compositor().compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != &m_owningLayer))
662 compositor().updateCompositingDescendantGeometry(*stackingContainer, *stackingContainer);
666 if (flags.contains(UpdateAfterLayoutFlags::NeedsFullRepaint) && canIssueSetNeedsDisplay())
667 setContentsNeedDisplay();
670 bool RenderLayerBacking::updateConfiguration()
672 m_owningLayer.updateDescendantDependentFlags();
673 m_owningLayer.updateZOrderLists();
675 bool layerConfigChanged = false;
676 setBackgroundLayerPaintsFixedRootBackground(compositor().needsFixedRootBackgroundLayer(m_owningLayer));
678 // The background layer is currently only used for fixed root backgrounds.
679 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground || m_requiresBackgroundLayer))
680 layerConfigChanged = true;
682 if (updateForegroundLayer(compositor().needsContentsCompositingLayer(m_owningLayer)))
683 layerConfigChanged = true;
685 bool needsDescendantsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer);
687 if (!renderer().view().needsLayout()) {
688 bool usesCompositedScrolling = m_owningLayer.usesAcceleratedScrolling();
690 // Our scrolling layer will clip.
691 if (usesCompositedScrolling)
692 needsDescendantsClippingLayer = false;
694 if (updateScrollingLayers(usesCompositedScrolling))
695 layerConfigChanged = true;
697 if (updateDescendantClippingLayer(needsDescendantsClippingLayer))
698 layerConfigChanged = true;
701 if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer)))
702 layerConfigChanged = true;
704 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
705 layerConfigChanged = true;
707 if (layerConfigChanged)
708 updateInternalHierarchy();
710 if (auto* flatteningLayer = tileCacheFlatteningLayer()) {
711 if (layerConfigChanged || flatteningLayer->parent() != m_graphicsLayer.get())
712 m_graphicsLayer->addChild(*flatteningLayer);
715 updateMaskingLayer(renderer().hasMask(), renderer().hasClipPath());
717 updateChildClippingStrategy(needsDescendantsClippingLayer);
719 if (m_owningLayer.hasReflection()) {
720 if (m_owningLayer.reflectionLayer()->backing()) {
721 auto* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
722 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
725 m_graphicsLayer->setReplicatedByLayer(nullptr);
727 PaintedContentsInfo contentsInfo(*this);
729 if (!m_owningLayer.isRenderViewLayer()) {
730 bool didUpdateContentsRect = false;
731 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
733 updateRootLayerConfiguration();
735 if (contentsInfo.isDirectlyCompositedImage())
736 updateImageContents(contentsInfo);
738 if (is<RenderEmbeddedObject>(renderer()) && downcast<RenderEmbeddedObject>(renderer()).allowsAcceleratedCompositing()) {
739 auto* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer()).widget());
741 if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) {
742 pluginViewBase->detachPluginLayer();
743 pluginViewBase->attachPluginLayer();
746 if (!pluginViewBase->shouldNotAddLayer())
747 m_graphicsLayer->setContentsToPlatformLayer(pluginViewBase->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Plugin);
751 else if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo()) {
752 auto* mediaElement = downcast<HTMLMediaElement>(renderer().element());
753 m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Media);
757 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
758 else if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
759 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element());
760 if (auto* context = canvas->renderingContext())
761 m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Canvas);
762 layerConfigChanged = true;
765 if (is<RenderWidget>(renderer()))
766 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(&downcast<RenderWidget>(renderer()));
768 return layerConfigChanged;
771 static LayoutRect clipBox(RenderBox& renderer)
773 LayoutRect result = LayoutRect::infiniteRect();
774 if (renderer.hasOverflowClip())
775 result = renderer.overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
777 if (renderer.hasClip())
778 result.intersect(renderer.clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
783 static bool subpixelOffsetFromRendererChanged(const LayoutSize& oldSubpixelOffsetFromRenderer, const LayoutSize& newSubpixelOffsetFromRenderer, float deviceScaleFactor)
785 FloatSize previous = snapSizeToDevicePixel(oldSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor);
786 FloatSize current = snapSizeToDevicePixel(newSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor);
787 return previous != current;
790 static FloatSize subpixelForLayerPainting(const LayoutPoint& point, float pixelSnappingFactor)
792 LayoutUnit x = point.x();
793 LayoutUnit y = point.y();
794 x = x >= 0 ? floorToDevicePixel(x, pixelSnappingFactor) : ceilToDevicePixel(x, pixelSnappingFactor);
795 y = y >= 0 ? floorToDevicePixel(y, pixelSnappingFactor) : ceilToDevicePixel(y, pixelSnappingFactor);
796 return point - LayoutPoint(x, y);
799 struct OffsetFromRenderer {
800 // 1.2px - > { m_devicePixelOffset = 1px m_subpixelOffset = 0.2px }
801 LayoutSize m_devicePixelOffset;
802 LayoutSize m_subpixelOffset;
805 static OffsetFromRenderer computeOffsetFromRenderer(const LayoutSize& offset, float deviceScaleFactor)
807 OffsetFromRenderer offsetFromRenderer;
808 offsetFromRenderer.m_subpixelOffset = LayoutSize(subpixelForLayerPainting(toLayoutPoint(offset), deviceScaleFactor));
809 offsetFromRenderer.m_devicePixelOffset = offset - offsetFromRenderer.m_subpixelOffset;
810 return offsetFromRenderer;
813 struct SnappedRectInfo {
814 LayoutRect m_snappedRect;
815 LayoutSize m_snapDelta;
818 static SnappedRectInfo snappedGraphicsLayer(const LayoutSize& offset, const LayoutSize& size, float deviceScaleFactor)
820 SnappedRectInfo snappedGraphicsLayer;
821 LayoutRect graphicsLayerRect = LayoutRect(toLayoutPoint(offset), size);
822 snappedGraphicsLayer.m_snappedRect = LayoutRect(snapRectToDevicePixels(graphicsLayerRect, deviceScaleFactor));
823 snappedGraphicsLayer.m_snapDelta = snappedGraphicsLayer.m_snappedRect.location() - toLayoutPoint(offset);
824 return snappedGraphicsLayer;
827 static LayoutSize computeOffsetFromAncestorGraphicsLayer(RenderLayer* compositedAncestor, const LayoutPoint& location, float deviceScaleFactor)
829 if (!compositedAncestor)
830 return toLayoutSize(location);
832 // FIXME: This is a workaround until after webkit.org/162634 gets fixed. ancestorSubpixelOffsetFromRenderer
833 // could be stale when a dynamic composited state change triggers a pre-order updateGeometry() traversal.
834 LayoutSize ancestorSubpixelOffsetFromRenderer = compositedAncestor->backing()->subpixelOffsetFromRenderer();
835 LayoutRect ancestorCompositedBounds = compositedAncestor->backing()->compositedBounds();
836 LayoutSize floored = toLayoutSize(LayoutPoint(floorPointToDevicePixels(ancestorCompositedBounds.location() - ancestorSubpixelOffsetFromRenderer, deviceScaleFactor)));
837 LayoutSize ancestorRendererOffsetFromAncestorGraphicsLayer = -(floored + ancestorSubpixelOffsetFromRenderer);
838 return ancestorRendererOffsetFromAncestorGraphicsLayer + toLayoutSize(location);
841 class ComputedOffsets {
843 ComputedOffsets(const RenderLayer& renderLayer, const LayoutRect& localRect, const LayoutRect& parentGraphicsLayerRect, const LayoutRect& primaryGraphicsLayerRect)
844 : m_renderLayer(renderLayer)
845 , m_location(localRect.location())
846 , m_parentGraphicsLayerOffset(toLayoutSize(parentGraphicsLayerRect.location()))
847 , m_primaryGraphicsLayerOffset(toLayoutSize(primaryGraphicsLayerRect.location()))
848 , m_deviceScaleFactor(renderLayer.renderer().document().deviceScaleFactor())
852 LayoutSize fromParentGraphicsLayer()
854 if (!m_fromParentGraphicsLayer)
855 m_fromParentGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset;
856 return m_fromParentGraphicsLayer.value();
859 LayoutSize fromPrimaryGraphicsLayer()
861 if (!m_fromPrimaryGraphicsLayer)
862 m_fromPrimaryGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset - m_primaryGraphicsLayerOffset;
863 return m_fromPrimaryGraphicsLayer.value();
867 LayoutSize fromAncestorGraphicsLayer()
869 if (!m_fromAncestorGraphicsLayer) {
870 auto* compositedAncestor = m_renderLayer.ancestorCompositingLayer();
871 LayoutPoint localPointInAncestorRenderLayerCoords = m_renderLayer.convertToLayerCoords(compositedAncestor, m_location, RenderLayer::AdjustForColumns);
872 m_fromAncestorGraphicsLayer = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, localPointInAncestorRenderLayerCoords, m_deviceScaleFactor);
874 return m_fromAncestorGraphicsLayer.value();
877 std::optional<LayoutSize> m_fromAncestorGraphicsLayer;
878 std::optional<LayoutSize> m_fromParentGraphicsLayer;
879 std::optional<LayoutSize> m_fromPrimaryGraphicsLayer;
881 const RenderLayer& m_renderLayer;
882 // Location is relative to the renderer.
883 const LayoutPoint m_location;
884 const LayoutSize m_parentGraphicsLayerOffset;
885 const LayoutSize m_primaryGraphicsLayerOffset;
886 float m_deviceScaleFactor;
889 LayoutRect RenderLayerBacking::computePrimaryGraphicsLayerRect(const LayoutRect& parentGraphicsLayerRect) const
891 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, LayoutRect());
892 return LayoutRect(encloseRectToDevicePixels(LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()),
893 deviceScaleFactor()));
896 LayoutRect RenderLayerBacking::computeParentGraphicsLayerRect(RenderLayer* compositedAncestor, LayoutSize& ancestorClippingLayerOffset) const
898 if (!compositedAncestor || !compositedAncestor->backing())
899 return renderer().view().documentRect();
901 auto* ancestorBackingLayer = compositedAncestor->backing();
902 LayoutRect parentGraphicsLayerRect;
903 if (m_owningLayer.isInsideFragmentedFlow()) {
904 // FIXME: flows/columns need work.
905 LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds();
906 ancestorCompositedBounds.setLocation(LayoutPoint());
907 parentGraphicsLayerRect = ancestorCompositedBounds;
910 if (ancestorBackingLayer->hasClippingLayer()) {
911 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore position relative to it.
912 LayoutRect clippingBox = clipBox(downcast<RenderBox>(compositedAncestor->renderer()));
913 LayoutSize clippingBoxOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, clippingBox.location(), deviceScaleFactor());
914 parentGraphicsLayerRect = snappedGraphicsLayer(clippingBoxOffset, clippingBox.size(), deviceScaleFactor()).m_snappedRect;
918 if (compositedAncestor->hasTouchScrollableOverflow()) {
919 LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds();
920 auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer());
921 LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom());
922 ScrollOffset scrollOffset = compositedAncestor->scrollOffset();
923 parentGraphicsLayerRect = LayoutRect((paddingBox.location() - toLayoutSize(ancestorCompositedBounds.location()) - toLayoutSize(scrollOffset)), paddingBox.size());
926 if (compositedAncestor->needsCompositedScrolling()) {
927 auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer());
928 LayoutPoint scrollOrigin(renderBox.borderLeft(), renderBox.borderTop());
929 parentGraphicsLayerRect = LayoutRect(scrollOrigin - toLayoutSize(compositedAncestor->scrollOffset()), renderBox.borderBoxRect().size());
933 if (m_ancestorClippingLayer) {
934 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
935 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
936 // for a compositing layer, rootLayer is the layer itself.
937 ShouldRespectOverflowClip shouldRespectOverflowClip = compositedAncestor->isolatesCompositedBlending() ? RespectOverflowClip : IgnoreOverflowClip;
938 RenderLayer::ClipRectsContext clipRectsContext(compositedAncestor, TemporaryClipRects, IgnoreOverlayScrollbarSize, shouldRespectOverflowClip);
939 LayoutRect parentClipRect = m_owningLayer.backgroundClipRect(clipRectsContext).rect(); // FIXME: Incorrect for CSS regions.
940 ASSERT(!parentClipRect.isInfinite());
941 LayoutSize clippingOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, parentClipRect.location(), deviceScaleFactor());
942 LayoutRect snappedClippingLayerRect = snappedGraphicsLayer(clippingOffset, parentClipRect.size(), deviceScaleFactor()).m_snappedRect;
943 // The primary layer is then parented in, and positioned relative to this clipping layer.
944 ancestorClippingLayerOffset = snappedClippingLayerRect.location() - parentGraphicsLayerRect.location();
945 parentGraphicsLayerRect = snappedClippingLayerRect;
947 return parentGraphicsLayerRect;
950 void RenderLayerBacking::updateGeometry()
952 // If we haven't built z-order lists yet, wait until later.
953 if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
956 const RenderStyle& style = renderer().style();
958 bool isRunningAcceleratedTransformAnimation = false;
959 bool isRunningAcceleratedOpacityAnimation = false;
960 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
961 if (auto* timeline = renderer().documentTimeline()) {
962 isRunningAcceleratedTransformAnimation = timeline->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform);
963 isRunningAcceleratedOpacityAnimation = timeline->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity);
966 isRunningAcceleratedTransformAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform, AnimationBase::Running | AnimationBase::Paused);
967 isRunningAcceleratedOpacityAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused);
970 // Set transform property, if it is not animating. We have to do this here because the transform
971 // is affected by the layer dimensions.
972 if (!isRunningAcceleratedTransformAnimation)
973 updateTransform(style);
975 // Set opacity, if it is not animating.
976 if (!isRunningAcceleratedOpacityAnimation)
977 updateOpacity(style);
979 updateFilters(style);
980 #if ENABLE(FILTERS_LEVEL_2)
981 updateBackdropFilters(style);
983 #if ENABLE(CSS_COMPOSITING)
984 updateBlendMode(style);
986 m_owningLayer.updateDescendantDependentFlags();
988 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
989 bool preserves3D = style.transformStyle3D() == TransformStyle3D::Preserve3D && !renderer().hasReflection();
990 m_graphicsLayer->setPreserves3D(preserves3D);
991 m_graphicsLayer->setBackfaceVisibility(style.backfaceVisibility() == BackfaceVisibility::Visible);
993 auto* compositedAncestor = m_owningLayer.ancestorCompositingLayer();
994 LayoutSize ancestorClippingLayerOffset;
995 LayoutRect parentGraphicsLayerRect = computeParentGraphicsLayerRect(compositedAncestor, ancestorClippingLayerOffset);
996 LayoutRect primaryGraphicsLayerRect = computePrimaryGraphicsLayerRect(parentGraphicsLayerRect);
998 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
999 m_compositedBoundsOffsetFromGraphicsLayer = compositedBoundsOffset.fromPrimaryGraphicsLayer();
1000 m_graphicsLayer->setPosition(primaryGraphicsLayerRect.location());
1001 m_graphicsLayer->setSize(primaryGraphicsLayerRect.size());
1003 auto computeAnimationExtent = [&] () -> std::optional<FloatRect> {
1004 LayoutRect animatedBounds;
1005 if (isRunningAcceleratedTransformAnimation && m_owningLayer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(animatedBounds, RenderLayer::IncludeCompositedDescendants))
1006 return FloatRect(animatedBounds);
1009 m_graphicsLayer->setAnimationExtent(computeAnimationExtent());
1011 ComputedOffsets rendererOffset(m_owningLayer, LayoutRect(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
1012 if (m_ancestorClippingLayer) {
1013 // Clipping layer is parented in the ancestor layer.
1014 m_ancestorClippingLayer->setPosition(toLayoutPoint(ancestorClippingLayerOffset));
1015 m_ancestorClippingLayer->setSize(parentGraphicsLayerRect.size());
1016 m_ancestorClippingLayer->setOffsetFromRenderer(-rendererOffset.fromParentGraphicsLayer());
1019 if (m_contentsContainmentLayer) {
1020 m_contentsContainmentLayer->setPreserves3D(preserves3D);
1021 m_contentsContainmentLayer->setPosition(primaryGraphicsLayerRect.location());
1022 m_graphicsLayer->setPosition(FloatPoint());
1023 // Use the same size as m_graphicsLayer so transforms behave correctly.
1024 m_contentsContainmentLayer->setSize(primaryGraphicsLayerRect.size());
1027 // Compute renderer offset from primary graphics layer. Note that primaryGraphicsLayerRect is in parentGraphicsLayer's coordidate system which is not necessarily
1028 // the same as the ancestor graphics layer.
1029 OffsetFromRenderer primaryGraphicsLayerOffsetFromRenderer;
1030 LayoutSize oldSubpixelOffsetFromRenderer = m_subpixelOffsetFromRenderer;
1031 primaryGraphicsLayerOffsetFromRenderer = computeOffsetFromRenderer(-rendererOffset.fromPrimaryGraphicsLayer(), deviceScaleFactor());
1032 m_subpixelOffsetFromRenderer = primaryGraphicsLayerOffsetFromRenderer.m_subpixelOffset;
1034 if (primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset != m_graphicsLayer->offsetFromRenderer()) {
1035 m_graphicsLayer->setOffsetFromRenderer(primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset);
1036 positionOverflowControlsLayers();
1039 if (!m_isMainFrameRenderViewLayer && !m_isFrameLayerWithTiledBacking && !m_requiresBackgroundLayer) {
1040 // For non-root layers, background is always painted by the primary graphics layer.
1041 ASSERT(!m_backgroundLayer);
1042 // Subpixel offset from graphics layer or size changed.
1043 bool hadSubpixelRounding = !m_subpixelOffsetFromRenderer.isZero() || compositedBounds().size() != primaryGraphicsLayerRect.size();
1044 m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
1047 // If we have a layer that clips children, position it.
1048 LayoutRect clippingBox;
1049 if (auto* clipLayer = clippingLayer()) {
1050 clippingBox = clipBox(downcast<RenderBox>(renderer()));
1051 // Clipping layer is parented in the primary graphics layer.
1052 LayoutSize clipBoxOffsetFromGraphicsLayer = toLayoutSize(clippingBox.location()) + rendererOffset.fromPrimaryGraphicsLayer();
1053 SnappedRectInfo snappedClippingGraphicsLayer = snappedGraphicsLayer(clipBoxOffsetFromGraphicsLayer, clippingBox.size(), deviceScaleFactor());
1054 clipLayer->setPosition(snappedClippingGraphicsLayer.m_snappedRect.location());
1055 clipLayer->setSize(snappedClippingGraphicsLayer.m_snappedRect.size());
1056 clipLayer->setOffsetFromRenderer(toLayoutSize(clippingBox.location() - snappedClippingGraphicsLayer.m_snapDelta));
1058 if (m_childClippingMaskLayer && !m_scrollingLayer) {
1059 m_childClippingMaskLayer->setSize(clipLayer->size());
1060 m_childClippingMaskLayer->setPosition(FloatPoint());
1061 m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer());
1066 updateMaskingLayerGeometry();
1068 if (renderer().hasTransformRelatedProperty()) {
1069 // Update properties that depend on layer dimensions.
1070 FloatPoint3D transformOrigin = computeTransformOriginForPainting(downcast<RenderBox>(renderer()).borderBoxRect());
1071 FloatPoint layerOffset = roundPointToDevicePixels(toLayoutPoint(rendererOffset.fromParentGraphicsLayer()), deviceScaleFactor());
1072 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
1073 FloatPoint3D anchor(
1074 primaryGraphicsLayerRect.width() ? ((layerOffset.x() - primaryGraphicsLayerRect.x()) + transformOrigin.x()) / primaryGraphicsLayerRect.width() : 0.5,
1075 primaryGraphicsLayerRect.height() ? ((layerOffset.y() - primaryGraphicsLayerRect.y())+ transformOrigin.y()) / primaryGraphicsLayerRect.height() : 0.5,
1076 transformOrigin.z());
1078 if (m_contentsContainmentLayer)
1079 m_contentsContainmentLayer->setAnchorPoint(anchor);
1081 m_graphicsLayer->setAnchorPoint(anchor);
1083 auto* clipLayer = clippingLayer();
1084 if (style.hasPerspective()) {
1085 TransformationMatrix t = owningLayer().perspectiveTransform();
1088 clipLayer->setChildrenTransform(t);
1089 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
1092 m_graphicsLayer->setChildrenTransform(t);
1095 clipLayer->setChildrenTransform(TransformationMatrix());
1097 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
1100 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
1101 if (m_contentsContainmentLayer)
1102 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
1105 if (m_foregroundLayer) {
1106 FloatPoint foregroundPosition;
1107 FloatSize foregroundSize = primaryGraphicsLayerRect.size();
1108 FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
1109 if (hasClippingLayer()) {
1110 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
1111 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
1112 foregroundSize = FloatSize(clippingBox.size());
1113 foregroundOffset = toFloatSize(clippingBox.location());
1116 m_foregroundLayer->setPosition(foregroundPosition);
1117 m_foregroundLayer->setSize(foregroundSize);
1118 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
1121 if (m_backgroundLayer) {
1122 FloatPoint backgroundPosition;
1123 FloatSize backgroundSize = primaryGraphicsLayerRect.size();
1124 if (backgroundLayerPaintsFixedRootBackground()) {
1125 const FrameView& frameView = renderer().view().frameView();
1126 backgroundPosition = frameView.scrollPositionForFixedPosition();
1127 backgroundSize = frameView.layoutSize();
1129 auto boundingBox = renderer().objectBoundingBox();
1130 backgroundPosition = boundingBox.location();
1131 backgroundSize = boundingBox.size();
1133 m_backgroundLayer->setPosition(backgroundPosition);
1134 m_backgroundLayer->setSize(backgroundSize);
1135 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
1138 if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
1139 auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
1140 reflectionBacking->updateGeometry();
1142 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
1143 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
1144 FloatRect layerBounds = this->compositedBounds();
1145 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
1146 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
1149 if (m_scrollingLayer) {
1150 ASSERT(m_scrollingContentsLayer);
1151 auto& renderBox = downcast<RenderBox>(renderer());
1152 LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom());
1153 ScrollOffset scrollOffset = m_owningLayer.scrollOffset();
1155 // FIXME: need to do some pixel snapping here.
1156 m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - compositedBounds().location()));
1158 m_scrollingLayer->setSize(roundedIntSize(LayoutSize(renderBox.clientWidth(), renderBox.clientHeight())));
1160 FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
1161 m_scrollingLayer->setOffsetFromRenderer(FloatPoint() - paddingBox.location());
1162 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
1164 if (m_owningLayer.isInUserScroll()) {
1165 // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause jitter.
1166 m_scrollingLayer->syncBoundsOrigin(scrollOffset);
1167 m_owningLayer.setRequiresScrollBoundsOriginUpdate(true);
1169 // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
1170 m_scrollingLayer->setBoundsOrigin(scrollOffset);
1171 m_owningLayer.setRequiresScrollBoundsOriginUpdate(false);
1174 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
1176 m_scrollingContentsLayer->setPosition(FloatPoint());
1178 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
1179 m_scrollingContentsLayer->setNeedsDisplay();
1181 m_scrollingContentsLayer->setSize(scrollSize);
1182 // Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
1183 // FIXME: The paint offset and the scroll offset should really be separate concepts.
1184 LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - toLayoutSize(scrollOffset));
1185 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
1187 m_scrollingContentsLayer->setPosition(-scrollOffset);
1189 FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
1190 m_scrollingLayer->setOffsetFromRenderer(-toFloatSize(paddingBox.location()));
1192 if (m_childClippingMaskLayer) {
1193 m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
1194 m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
1195 m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBox.location()));
1198 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
1200 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
1201 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
1202 m_scrollingContentsLayer->setNeedsDisplay();
1204 LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - toLayoutSize(scrollOffset));
1205 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
1206 compositor().scrollingLayerDidChange(m_owningLayer);
1208 m_scrollingContentsLayer->setSize(scrollSize);
1209 // FIXME: The paint offset and the scroll offset should really be separate concepts.
1210 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
1213 if (m_foregroundLayer) {
1214 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
1215 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
1219 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
1220 LayoutRect ancestorCompositedBounds = compositedAncestor ? compositedAncestor->backing()->compositedBounds() : LayoutRect();
1221 setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compositedAncestor,
1222 LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()), ancestorCompositedBounds));
1223 #if ENABLE(FILTERS_LEVEL_2)
1224 updateBackdropFiltersGeometry();
1226 updateAfterWidgetResize();
1228 if (subpixelOffsetFromRendererChanged(oldSubpixelOffsetFromRenderer, m_subpixelOffsetFromRenderer, deviceScaleFactor()) && canIssueSetNeedsDisplay())
1229 setContentsNeedDisplay();
1231 compositor().updateScrollCoordinatedStatus(m_owningLayer, { RenderLayerCompositor::ScrollingNodeChangeFlags::Layer, RenderLayerCompositor::ScrollingNodeChangeFlags::LayerGeometry });
1234 void RenderLayerBacking::updateAfterDescendants()
1236 // FIXME: this potentially duplicates work we did in updateConfiguration().
1237 PaintedContentsInfo contentsInfo(*this);
1238 contentsInfo.setWantsSubpixelAntialiasedTextState(GraphicsLayer::supportsSubpixelAntialiasedLayerText());
1240 if (!m_owningLayer.isRenderViewLayer()) {
1241 bool didUpdateContentsRect = false;
1242 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
1243 if (!didUpdateContentsRect && m_graphicsLayer->usesContentsLayer())
1244 resetContentsRect();
1247 updateDrawsContent(contentsInfo);
1249 m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositedDescendants());
1250 if (m_scrollingLayer) {
1251 m_scrollingLayer->setContentsVisible(renderer().style().visibility() == Visibility::Visible);
1252 m_scrollingLayer->setUserInteractionEnabled(renderer().style().pointerEvents() != PointerEvents::None);
1256 // FIXME: Avoid repaints when clip path changes.
1257 void RenderLayerBacking::updateMaskingLayerGeometry()
1259 m_maskLayer->setSize(m_graphicsLayer->size());
1260 m_maskLayer->setPosition(FloatPoint());
1261 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
1263 if (!m_maskLayer->drawsContent()) {
1264 if (renderer().hasClipPath()) {
1265 ASSERT(renderer().style().clipPath()->type() != ClipPathOperation::Reference);
1268 // FIXME: Use correct reference box for inlines: https://bugs.webkit.org/show_bug.cgi?id=129047
1269 LayoutRect boundingBox = m_owningLayer.boundingBox(&m_owningLayer);
1270 LayoutRect referenceBoxForClippedInline = LayoutRect(snapRectToDevicePixels(boundingBox, deviceScaleFactor()));
1271 LayoutSize offset = LayoutSize(snapSizeToDevicePixel(-m_subpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor()));
1272 Path clipPath = m_owningLayer.computeClipPath(offset, referenceBoxForClippedInline, windRule);
1274 FloatSize pathOffset = m_maskLayer->offsetFromRenderer();
1275 if (!pathOffset.isZero())
1276 clipPath.translate(-pathOffset);
1278 m_maskLayer->setShapeLayerPath(clipPath);
1279 m_maskLayer->setShapeLayerWindRule(windRule);
1284 void RenderLayerBacking::updateDirectlyCompositedBoxDecorations(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1286 if (!m_owningLayer.hasVisibleContent())
1289 // The order of operations here matters, since the last valid type of contents needs
1290 // to also update the contentsRect.
1291 updateDirectlyCompositedBackgroundColor(contentsInfo, didUpdateContentsRect);
1292 updateDirectlyCompositedBackgroundImage(contentsInfo, didUpdateContentsRect);
1295 void RenderLayerBacking::updateInternalHierarchy()
1297 // m_foregroundLayer has to be inserted in the correct order with child layers,
1298 // so it's not inserted here.
1299 if (m_ancestorClippingLayer)
1300 m_ancestorClippingLayer->removeAllChildren();
1302 if (m_contentsContainmentLayer) {
1303 m_contentsContainmentLayer->removeAllChildren();
1304 if (m_ancestorClippingLayer)
1305 m_ancestorClippingLayer->addChild(*m_contentsContainmentLayer);
1308 if (m_backgroundLayer)
1309 m_contentsContainmentLayer->addChild(*m_backgroundLayer);
1311 if (m_contentsContainmentLayer)
1312 m_contentsContainmentLayer->addChild(*m_graphicsLayer);
1313 else if (m_ancestorClippingLayer)
1314 m_ancestorClippingLayer->addChild(*m_graphicsLayer);
1316 if (m_childContainmentLayer) {
1317 m_childContainmentLayer->removeFromParent();
1318 m_graphicsLayer->addChild(*m_childContainmentLayer);
1321 if (m_scrollingLayer) {
1322 auto* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
1323 m_scrollingLayer->removeFromParent();
1324 superlayer->addChild(*m_scrollingLayer);
1327 // The clip for child layers does not include space for overflow controls, so they exist as
1328 // siblings of the clipping layer if we have one. Normal children of this layer are set as
1329 // children of the clipping layer.
1330 if (m_layerForHorizontalScrollbar) {
1331 m_layerForHorizontalScrollbar->removeFromParent();
1332 m_graphicsLayer->addChild(*m_layerForHorizontalScrollbar);
1334 if (m_layerForVerticalScrollbar) {
1335 m_layerForVerticalScrollbar->removeFromParent();
1336 m_graphicsLayer->addChild(*m_layerForVerticalScrollbar);
1338 if (m_layerForScrollCorner) {
1339 m_layerForScrollCorner->removeFromParent();
1340 m_graphicsLayer->addChild(*m_layerForScrollCorner);
1344 void RenderLayerBacking::resetContentsRect()
1346 m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
1348 if (is<RenderBox>(renderer())) {
1349 LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
1350 boxRect.move(contentOffsetInCompostingLayer());
1351 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
1352 m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
1355 m_graphicsLayer->setContentsTileSize(IntSize());
1356 m_graphicsLayer->setContentsTilePhase(IntSize());
1359 void RenderLayerBacking::updateDrawsContent()
1361 PaintedContentsInfo contentsInfo(*this);
1362 contentsInfo.setWantsSubpixelAntialiasedTextState(GraphicsLayer::supportsSubpixelAntialiasedLayerText());
1364 updateDrawsContent(contentsInfo);
1367 void RenderLayerBacking::updateDrawsContent(PaintedContentsInfo& contentsInfo)
1369 if (m_scrollingLayer) {
1370 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1371 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1372 // m_scrollingLayer never has backing store.
1373 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1374 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasVisibleBoxDecorationsOrBackground();
1375 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1377 bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || contentsInfo.paintsContent());
1378 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
1382 bool hasPaintedContent = containsPaintedContent(contentsInfo);
1384 m_paintsSubpixelAntialiasedText = renderer().settings().subpixelAntialiasedLayerTextEnabled() && contentsInfo.paintsSubpixelAntialiasedText();
1386 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
1387 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1388 if (m_foregroundLayer) {
1389 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1390 m_foregroundLayer->setSupportsSubpixelAntialiasedText(m_paintsSubpixelAntialiasedText);
1391 // The text content is painted into the foreground layer.
1392 // FIXME: this ignores SVG background images which may contain text.
1393 m_graphicsLayer->setSupportsSubpixelAntialiasedText(false);
1395 m_graphicsLayer->setSupportsSubpixelAntialiasedText(m_paintsSubpixelAntialiasedText);
1397 if (m_backgroundLayer)
1398 m_backgroundLayer->setDrawsContent(m_backgroundLayerPaintsFixedRootBackground ? hasPaintedContent : contentsInfo.paintsBoxDecorations());
1401 // Return true if the layer changed.
1402 bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip)
1404 bool layersChanged = false;
1406 if (needsAncestorClip) {
1407 if (!m_ancestorClippingLayer) {
1408 m_ancestorClippingLayer = createGraphicsLayer("ancestor clipping");
1409 m_ancestorClippingLayer->setMasksToBounds(true);
1410 layersChanged = true;
1412 } else if (hasAncestorClippingLayer()) {
1413 willDestroyLayer(m_ancestorClippingLayer.get());
1414 m_ancestorClippingLayer->removeFromParent();
1415 m_ancestorClippingLayer = nullptr;
1416 layersChanged = true;
1419 return layersChanged;
1422 // Return true if the layer changed.
1423 bool RenderLayerBacking::updateDescendantClippingLayer(bool needsDescendantClip)
1425 bool layersChanged = false;
1427 if (needsDescendantClip) {
1428 if (!m_childContainmentLayer && !m_isFrameLayerWithTiledBacking) {
1429 m_childContainmentLayer = createGraphicsLayer("child clipping");
1430 m_childContainmentLayer->setMasksToBounds(true);
1431 layersChanged = true;
1433 } else if (hasClippingLayer()) {
1434 willDestroyLayer(m_childContainmentLayer.get());
1435 m_childContainmentLayer->removeFromParent();
1436 m_childContainmentLayer = nullptr;
1437 layersChanged = true;
1440 return layersChanged;
1443 void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1445 if (backgroundLayerPaintsFixedRootBackground == m_backgroundLayerPaintsFixedRootBackground)
1448 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1450 if (m_backgroundLayerPaintsFixedRootBackground) {
1451 ASSERT(m_isFrameLayerWithTiledBacking);
1452 renderer().view().frameView().removeSlowRepaintObject(*renderer().view().rendererForRootBackground());
1456 void RenderLayerBacking::setRequiresBackgroundLayer(bool requiresBackgroundLayer)
1458 m_requiresBackgroundLayer = requiresBackgroundLayer;
1461 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
1463 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1465 return m_owningLayer.horizontalScrollbar();
1468 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
1470 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1472 return m_owningLayer.verticalScrollbar();
1475 bool RenderLayerBacking::requiresScrollCornerLayer() const
1477 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1479 return !m_owningLayer.scrollCornerAndResizerRect().isEmpty();
1482 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1484 bool horizontalScrollbarLayerChanged = false;
1485 if (needsHorizontalScrollbarLayer) {
1486 if (!m_layerForHorizontalScrollbar) {
1487 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
1488 m_layerForHorizontalScrollbar->setCanDetachBackingStore(false);
1489 horizontalScrollbarLayerChanged = true;
1491 } else if (m_layerForHorizontalScrollbar) {
1492 willDestroyLayer(m_layerForHorizontalScrollbar.get());
1493 m_layerForHorizontalScrollbar = nullptr;
1494 horizontalScrollbarLayerChanged = true;
1497 bool verticalScrollbarLayerChanged = false;
1498 if (needsVerticalScrollbarLayer) {
1499 if (!m_layerForVerticalScrollbar) {
1500 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
1501 m_layerForVerticalScrollbar->setCanDetachBackingStore(false);
1502 verticalScrollbarLayerChanged = true;
1504 } else if (m_layerForVerticalScrollbar) {
1505 willDestroyLayer(m_layerForVerticalScrollbar.get());
1506 m_layerForVerticalScrollbar = nullptr;
1507 verticalScrollbarLayerChanged = true;
1510 bool scrollCornerLayerChanged = false;
1511 if (needsScrollCornerLayer) {
1512 if (!m_layerForScrollCorner) {
1513 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
1514 m_layerForScrollCorner->setCanDetachBackingStore(false);
1515 scrollCornerLayerChanged = true;
1517 } else if (m_layerForScrollCorner) {
1518 willDestroyLayer(m_layerForScrollCorner.get());
1519 m_layerForScrollCorner = nullptr;
1520 scrollCornerLayerChanged = true;
1523 if (auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator()) {
1524 if (horizontalScrollbarLayerChanged)
1525 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar);
1526 if (verticalScrollbarLayerChanged)
1527 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar);
1530 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1533 void RenderLayerBacking::positionOverflowControlsLayers()
1535 if (!m_owningLayer.hasScrollbars())
1538 const IntRect borderBox = snappedIntRect(renderBox()->borderBoxRect());
1540 FloatSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
1541 if (auto* layer = layerForHorizontalScrollbar()) {
1542 IntRect hBarRect = m_owningLayer.rectForHorizontalScrollbar(borderBox);
1543 layer->setPosition(hBarRect.location() - offsetFromRenderer);
1544 layer->setSize(hBarRect.size());
1545 if (layer->usesContentsLayer()) {
1546 IntRect barRect = IntRect(IntPoint(), hBarRect.size());
1547 layer->setContentsRect(barRect);
1548 layer->setContentsClippingRect(FloatRoundedRect(barRect));
1550 layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->usesContentsLayer());
1553 if (auto* layer = layerForVerticalScrollbar()) {
1554 IntRect vBarRect = m_owningLayer.rectForVerticalScrollbar(borderBox);
1555 layer->setPosition(vBarRect.location() - offsetFromRenderer);
1556 layer->setSize(vBarRect.size());
1557 if (layer->usesContentsLayer()) {
1558 IntRect barRect = IntRect(IntPoint(), vBarRect.size());
1559 layer->setContentsRect(barRect);
1560 layer->setContentsClippingRect(FloatRoundedRect(barRect));
1562 layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->usesContentsLayer());
1565 if (auto* layer = layerForScrollCorner()) {
1566 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
1567 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1568 layer->setSize(scrollCornerAndResizer.size());
1569 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1573 bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
1575 if (auto* layer = layerForHorizontalScrollbar()) {
1576 if (!layer->drawsContent())
1580 if (auto* layer = layerForVerticalScrollbar()) {
1581 if (!layer->drawsContent())
1585 if (auto* layer = layerForScrollCorner()) {
1586 if (!layer->drawsContent())
1593 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
1595 bool layerChanged = false;
1596 if (needsForegroundLayer) {
1597 if (!m_foregroundLayer) {
1598 String layerName = m_owningLayer.name() + " (foreground)";
1599 m_foregroundLayer = createGraphicsLayer(layerName);
1600 m_foregroundLayer->setDrawsContent(true);
1601 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1602 layerChanged = true;
1604 } else if (m_foregroundLayer) {
1605 willDestroyLayer(m_foregroundLayer.get());
1606 m_foregroundLayer->removeFromParent();
1607 m_foregroundLayer = nullptr;
1608 layerChanged = true;
1612 m_graphicsLayer->setNeedsDisplay();
1613 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1616 return layerChanged;
1619 bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
1621 bool layerChanged = false;
1622 if (needsBackgroundLayer) {
1623 if (!m_backgroundLayer) {
1624 String layerName = m_owningLayer.name() + " (background)";
1625 m_backgroundLayer = createGraphicsLayer(layerName);
1626 m_backgroundLayer->setDrawsContent(true);
1627 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1628 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1629 layerChanged = true;
1632 if (!m_contentsContainmentLayer) {
1633 String layerName = m_owningLayer.name() + " (contents containment)";
1634 m_contentsContainmentLayer = createGraphicsLayer(layerName);
1635 m_contentsContainmentLayer->setAppliesPageScale(true);
1636 m_graphicsLayer->setAppliesPageScale(false);
1637 layerChanged = true;
1640 if (m_backgroundLayer) {
1641 willDestroyLayer(m_backgroundLayer.get());
1642 m_backgroundLayer->removeFromParent();
1643 m_backgroundLayer = nullptr;
1644 layerChanged = true;
1646 if (m_contentsContainmentLayer) {
1647 willDestroyLayer(m_contentsContainmentLayer.get());
1648 m_contentsContainmentLayer->removeFromParent();
1649 m_contentsContainmentLayer = nullptr;
1650 layerChanged = true;
1651 m_graphicsLayer->setAppliesPageScale(true);
1656 m_graphicsLayer->setNeedsDisplay();
1658 if (m_backgroundLayerPaintsFixedRootBackground)
1659 compositor().fixedRootBackgroundLayerChanged();
1662 return layerChanged;
1665 // Masking layer is used for masks or clip-path.
1666 void RenderLayerBacking::updateMaskingLayer(bool hasMask, bool hasClipPath)
1668 bool layerChanged = false;
1669 if (hasMask || hasClipPath) {
1670 GraphicsLayerPaintingPhase maskPhases = 0;
1672 maskPhases = GraphicsLayerPaintMask;
1675 // If we have a mask, we need to paint the combined clip-path and mask into the mask layer.
1676 if (hasMask || renderer().style().clipPath()->type() == ClipPathOperation::Reference || !GraphicsLayer::supportsLayerType(GraphicsLayer::Type::Shape))
1677 maskPhases |= GraphicsLayerPaintClipPath;
1680 bool paintsContent = maskPhases;
1681 GraphicsLayer::Type requiredLayerType = paintsContent ? GraphicsLayer::Type::Normal : GraphicsLayer::Type::Shape;
1682 if (m_maskLayer && m_maskLayer->type() != requiredLayerType) {
1683 m_graphicsLayer->setMaskLayer(nullptr);
1684 willDestroyLayer(m_maskLayer.get());
1685 m_maskLayer = nullptr;
1689 m_maskLayer = createGraphicsLayer("mask", requiredLayerType);
1690 m_maskLayer->setDrawsContent(paintsContent);
1691 m_maskLayer->setPaintingPhase(maskPhases);
1692 layerChanged = true;
1693 m_graphicsLayer->setMaskLayer(m_maskLayer.copyRef());
1695 } else if (m_maskLayer) {
1696 m_graphicsLayer->setMaskLayer(nullptr);
1697 willDestroyLayer(m_maskLayer.get());
1698 m_maskLayer = nullptr;
1699 layerChanged = true;
1703 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1706 void RenderLayerBacking::updateChildClippingStrategy(bool needsDescendantsClippingLayer)
1708 if (hasClippingLayer() && needsDescendantsClippingLayer) {
1709 if (is<RenderBox>(renderer()) && (renderer().style().clipPath() || renderer().style().hasBorderRadius())) {
1710 // FIXME: we shouldn't get geometry here as layout may not have been udpated.
1711 LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
1712 boxRect.move(contentOffsetInCompostingLayer());
1713 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
1714 if (clippingLayer()->setMasksToBoundsRect(contentsClippingRect)) {
1715 if (m_childClippingMaskLayer)
1716 m_childClippingMaskLayer = nullptr;
1720 if (!m_childClippingMaskLayer) {
1721 m_childClippingMaskLayer = createGraphicsLayer("child clipping mask");
1722 m_childClippingMaskLayer->setDrawsContent(true);
1723 m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
1724 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.copyRef());
1728 if (m_childClippingMaskLayer) {
1729 if (hasClippingLayer())
1730 clippingLayer()->setMaskLayer(nullptr);
1731 m_childClippingMaskLayer = nullptr;
1733 if (hasClippingLayer())
1734 clippingLayer()->setMasksToBoundsRect(FloatRoundedRect(FloatRect(FloatPoint(), clippingLayer()->size())));
1738 bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
1740 if (needsScrollingLayers == !!m_scrollingLayer)
1743 if (!m_scrollingLayer) {
1744 // Outer layer which corresponds with the scroll view.
1745 m_scrollingLayer = createGraphicsLayer("scrolling container", GraphicsLayer::Type::Scrolling);
1746 m_scrollingLayer->setDrawsContent(false);
1747 m_scrollingLayer->setMasksToBounds(true);
1749 // Inner layer which renders the content that scrolls.
1750 m_scrollingContentsLayer = createGraphicsLayer("scrolled Contents");
1751 m_scrollingContentsLayer->setDrawsContent(true);
1753 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1754 if (!m_foregroundLayer)
1755 paintPhase |= GraphicsLayerPaintForeground;
1756 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1757 m_scrollingLayer->addChild(*m_scrollingContentsLayer);
1759 compositor().willRemoveScrollingLayerWithBacking(m_owningLayer, *this);
1761 willDestroyLayer(m_scrollingLayer.get());
1762 willDestroyLayer(m_scrollingContentsLayer.get());
1763 m_scrollingLayer = nullptr;
1764 m_scrollingContentsLayer = nullptr;
1767 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1768 m_graphicsLayer->setNeedsDisplay(); // Because painting phases changed.
1770 if (m_scrollingLayer)
1771 compositor().didAddScrollingLayer(m_owningLayer);
1776 void RenderLayerBacking::detachFromScrollingCoordinator(OptionSet<LayerScrollCoordinationRole> roles)
1778 if (!m_scrollingNodeID && !m_viewportConstrainedNodeID)
1781 auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator();
1782 if (!scrollingCoordinator)
1785 if ((roles & Scrolling) && m_scrollingNodeID) {
1786 LOG(Compositing, "Detaching Scrolling node %" PRIu64, m_scrollingNodeID);
1787 scrollingCoordinator->detachFromStateTree(m_scrollingNodeID);
1788 m_scrollingNodeID = 0;
1791 if ((roles & ViewportConstrained) && m_viewportConstrainedNodeID) {
1792 LOG(Compositing, "Detaching ViewportConstrained node %" PRIu64, m_viewportConstrainedNodeID);
1793 scrollingCoordinator->detachFromStateTree(m_viewportConstrainedNodeID);
1794 m_viewportConstrainedNodeID = 0;
1798 void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated)
1800 m_graphicsLayer->setIsViewportConstrained(viewportCoordinated);
1803 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
1806 if (!m_backgroundLayer)
1807 phase |= GraphicsLayerPaintBackground;
1808 if (!m_foregroundLayer)
1809 phase |= GraphicsLayerPaintForeground;
1811 if (m_scrollingContentsLayer) {
1812 phase &= ~GraphicsLayerPaintForeground;
1813 phase |= GraphicsLayerPaintCompositedScroll;
1816 return static_cast<GraphicsLayerPaintingPhase>(phase);
1819 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
1821 float finalOpacity = rendererOpacity;
1823 for (auto* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1824 // We only care about parents that are stacking contexts.
1825 // Recall that opacity creates stacking context.
1826 if (!curr->isStackingContainer())
1829 // If we found a compositing layer, we want to compute opacity
1830 // relative to it. So we can break here.
1831 if (curr->isComposited())
1834 finalOpacity *= curr->renderer().opacity();
1837 return finalOpacity;
1840 // FIXME: Code is duplicated in RenderLayer. Also, we should probably not consider filters a box decoration here.
1841 static inline bool hasVisibleBoxDecorations(const RenderStyle& style)
1843 return style.hasVisibleBorder() || style.hasBorderRadius() || style.hasOutline() || style.hasAppearance() || style.boxShadow() || style.hasFilter();
1846 static bool canDirectlyCompositeBackgroundBackgroundImage(const RenderStyle& style)
1848 if (!GraphicsLayer::supportsContentsTiling())
1851 auto& fillLayer = style.backgroundLayers();
1852 if (fillLayer.next())
1855 if (!fillLayer.imagesAreLoaded())
1858 if (fillLayer.attachment() != FillAttachment::ScrollBackground)
1861 // FIXME: Allow color+image compositing when it makes sense.
1862 // For now bailing out.
1863 if (style.visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor).isVisible())
1866 // FIXME: support gradients with isGeneratedImage.
1867 auto* styleImage = fillLayer.image();
1868 if (!styleImage->isCachedImage())
1871 auto* image = styleImage->cachedImage()->image();
1872 if (!image->isBitmapImage())
1878 static bool hasPaintedBoxDecorationsOrBackgroundImage(const RenderStyle& style)
1880 if (hasVisibleBoxDecorations(style))
1883 if (!style.hasBackgroundImage())
1886 return !canDirectlyCompositeBackgroundBackgroundImage(style);
1889 static inline bool hasPerspectiveOrPreserves3D(const RenderStyle& style)
1891 return style.hasPerspective() || style.preserves3D();
1894 Color RenderLayerBacking::rendererBackgroundColor() const
1896 RenderElement* backgroundRenderer = nullptr;
1897 if (renderer().isDocumentElementRenderer())
1898 backgroundRenderer = renderer().view().rendererForRootBackground();
1900 if (!backgroundRenderer)
1901 backgroundRenderer = &renderer();
1903 return backgroundRenderer->style().visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
1906 void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1908 if (m_backgroundLayer && !m_backgroundLayerPaintsFixedRootBackground && !contentsInfo.paintsBoxDecorations()) {
1909 m_graphicsLayer->setContentsToSolidColor(Color());
1910 m_backgroundLayer->setContentsToSolidColor(rendererBackgroundColor());
1912 FloatRect contentsRect = backgroundBoxForSimpleContainerPainting();
1913 // NOTE: This is currently only used by RenderFullScreen, which we want to be
1914 // big enough to hide overflow areas of the root.
1915 contentsRect.inflate(contentsRect.size());
1916 m_backgroundLayer->setContentsRect(contentsRect);
1917 m_backgroundLayer->setContentsClippingRect(FloatRoundedRect(contentsRect));
1921 if (!contentsInfo.isSimpleContainer() || (is<RenderBox>(renderer()) && !downcast<RenderBox>(renderer()).paintsOwnBackground())) {
1922 m_graphicsLayer->setContentsToSolidColor(Color());
1926 Color backgroundColor = rendererBackgroundColor();
1928 // An unset (invalid) color will remove the solid color.
1929 m_graphicsLayer->setContentsToSolidColor(backgroundColor);
1930 FloatRect contentsRect = backgroundBoxForSimpleContainerPainting();
1931 m_graphicsLayer->setContentsRect(contentsRect);
1932 m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(contentsRect));
1933 didUpdateContentsRect = true;
1936 void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1938 if (!GraphicsLayer::supportsContentsTiling())
1941 if (contentsInfo.isDirectlyCompositedImage())
1944 auto& style = renderer().style();
1945 if (!contentsInfo.isSimpleContainer() || !style.hasBackgroundImage()) {
1946 m_graphicsLayer->setContentsToImage(0);
1950 auto destRect = backgroundBoxForSimpleContainerPainting();
1953 // FIXME: Absolute paint location is required here.
1954 downcast<RenderBox>(renderer()).getGeometryForBackgroundImage(&renderer(), LayoutPoint(), destRect, phase, tileSize);
1956 m_graphicsLayer->setContentsTileSize(tileSize);
1957 m_graphicsLayer->setContentsTilePhase(phase);
1958 m_graphicsLayer->setContentsRect(destRect);
1959 m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(destRect));
1960 m_graphicsLayer->setContentsToImage(style.backgroundLayers().image()->cachedImage()->image());
1962 didUpdateContentsRect = true;
1965 void RenderLayerBacking::updateRootLayerConfiguration()
1967 if (!m_isFrameLayerWithTiledBacking)
1970 Color backgroundColor;
1971 bool viewIsTransparent = compositor().viewHasTransparentBackground(&backgroundColor);
1973 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
1974 if (m_isMainFrameRenderViewLayer) {
1975 m_backgroundLayer->setBackgroundColor(backgroundColor);
1976 m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
1979 m_graphicsLayer->setBackgroundColor(Color());
1980 m_graphicsLayer->setContentsOpaque(false);
1981 } else if (m_isMainFrameRenderViewLayer) {
1982 m_graphicsLayer->setBackgroundColor(backgroundColor);
1983 m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
1987 static bool supportsDirectlyCompositedBoxDecorations(const RenderLayerModelObject& renderer)
1989 if (!GraphicsLayer::supportsBackgroundColorContent())
1992 const RenderStyle& style = renderer.style();
1993 if (renderer.hasClip())
1996 if (hasPaintedBoxDecorationsOrBackgroundImage(style))
1999 // FIXME: We can't create a directly composited background if this
2000 // layer will have children that intersect with the background layer.
2001 // A better solution might be to introduce a flattening layer if
2002 // we do direct box decoration composition.
2003 // https://bugs.webkit.org/show_bug.cgi?id=119461
2004 if (hasPerspectiveOrPreserves3D(style))
2007 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
2008 if (style.backgroundComposite() != CompositeSourceOver)
2014 bool RenderLayerBacking::paintsBoxDecorations() const
2016 if (!m_owningLayer.hasVisibleBoxDecorations())
2019 return !supportsDirectlyCompositedBoxDecorations(renderer());
2022 bool RenderLayerBacking::paintsContent(RenderLayer::PaintedContentRequest& request) const
2024 bool paintsContent = false;
2026 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers(request))
2027 paintsContent = true;
2029 if (request.isSatisfied())
2030 return paintsContent;
2032 if (isPaintDestinationForDescendantLayers(request))
2033 paintsContent = true;
2035 if (request.isSatisfied())
2036 return paintsContent;
2038 if (request.hasPaintedContent == RequestState::Unknown)
2039 request.hasPaintedContent = RequestState::False;
2041 if (request.hasSubpixelAntialiasedText == RequestState::Unknown)
2042 request.hasSubpixelAntialiasedText = RequestState::False;
2044 return paintsContent;
2047 static bool isRestartedPlugin(RenderObject& renderer)
2049 if (!is<RenderEmbeddedObject>(renderer))
2052 auto& element = downcast<RenderEmbeddedObject>(renderer).frameOwnerElement();
2053 if (!is<HTMLPlugInElement>(element))
2056 return downcast<HTMLPlugInElement>(element).isRestartedPlugin();
2059 static bool isCompositedPlugin(RenderObject& renderer)
2061 return is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
2064 // A "simple container layer" is a RenderLayer which has no visible content to render.
2065 // It may have no children, or all its children may be themselves composited.
2066 // This is a useful optimization, because it allows us to avoid allocating backing store.
2067 bool RenderLayerBacking::isSimpleContainerCompositingLayer(PaintedContentsInfo& contentsInfo) const
2069 if (renderer().isRenderReplaced() && (!isCompositedPlugin(renderer()) || isRestartedPlugin(renderer())))
2072 if (renderer().isTextControl())
2075 if (contentsInfo.paintsBoxDecorations() || contentsInfo.paintsContent())
2078 if (renderer().style().backgroundClip() == FillBox::Text)
2081 if (renderer().isDocumentElementRenderer() && m_owningLayer.isolatesCompositedBlending())
2084 if (renderer().isRenderView()) {
2085 // Look to see if the root object has a non-simple background
2086 auto* rootObject = renderer().document().documentElement() ? renderer().document().documentElement()->renderer() : nullptr;
2090 // Reject anything that has a border, a border-radius or outline,
2091 // or is not a simple background (no background, or solid color).
2092 if (hasPaintedBoxDecorationsOrBackgroundImage(rootObject->style()))
2095 // Now look at the body's renderer.
2096 auto* body = renderer().document().body();
2099 auto* bodyRenderer = body->renderer();
2103 if (hasPaintedBoxDecorationsOrBackgroundImage(bodyRenderer->style()))
2110 // Returning true stops the traversal.
2111 enum class LayerTraversal { Continue, Stop };
2113 static LayerTraversal traverseVisibleNonCompositedDescendantLayers(RenderLayer& parent, const WTF::Function<LayerTraversal (const RenderLayer&)>& layerFunc)
2115 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
2116 parent.updateLayerListsIfNeeded();
2118 #if !ASSERT_DISABLED
2119 LayerListMutationDetector mutationChecker(&parent);
2122 if (auto* normalFlowList = parent.normalFlowList()) {
2123 for (auto* childLayer : *normalFlowList) {
2124 if (compositedWithOwnBackingStore(*childLayer))
2127 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2128 return LayerTraversal::Stop;
2130 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2131 return LayerTraversal::Stop;
2135 if (parent.isStackingContainer() && !parent.hasVisibleDescendant())
2136 return LayerTraversal::Continue;
2138 // Use the m_hasCompositingDescendant bit to optimize?
2139 if (auto* negZOrderList = parent.negZOrderList()) {
2140 for (auto* childLayer : *negZOrderList) {
2141 if (compositedWithOwnBackingStore(*childLayer))
2144 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2145 return LayerTraversal::Stop;
2147 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2148 return LayerTraversal::Stop;
2152 if (auto* posZOrderList = parent.posZOrderList()) {
2153 for (auto* childLayer : *posZOrderList) {
2154 if (compositedWithOwnBackingStore(*childLayer))
2157 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2158 return LayerTraversal::Stop;
2160 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2161 return LayerTraversal::Stop;
2165 return LayerTraversal::Continue;
2168 // Conservative test for having no rendered children.
2169 bool RenderLayerBacking::isPaintDestinationForDescendantLayers(RenderLayer::PaintedContentRequest& request) const
2171 bool hasPaintingDescendant = false;
2172 traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasPaintingDescendant, &request](const RenderLayer& layer) {
2173 hasPaintingDescendant |= layer.isVisuallyNonEmpty(&request);
2174 return (hasPaintingDescendant && request.isSatisfied()) ? LayerTraversal::Stop : LayerTraversal::Continue;
2177 return hasPaintingDescendant;
2180 bool RenderLayerBacking::hasVisibleNonCompositedDescendants() const
2182 bool hasVisibleDescendant = false;
2183 traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasVisibleDescendant](const RenderLayer& layer) {
2184 hasVisibleDescendant |= layer.hasVisibleContent();
2185 return hasVisibleDescendant ? LayerTraversal::Stop : LayerTraversal::Continue;
2188 return hasVisibleDescendant;
2191 bool RenderLayerBacking::containsPaintedContent(PaintedContentsInfo& contentsInfo) const
2193 if (contentsInfo.isSimpleContainer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer.isReflection())
2196 if (contentsInfo.isDirectlyCompositedImage())
2199 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
2200 // and set background color on the layer in that case, instead of allocating backing store and painting.
2202 if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo())
2203 return m_owningLayer.hasVisibleBoxDecorationsOrBackground() || (!(downcast<RenderVideo>(renderer()).supportsAcceleratedRendering()) && m_requiresOwnBackingStore);
2206 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
2207 if (is<RenderHTMLCanvas>(renderer()) && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents)
2208 return m_owningLayer.hasVisibleBoxDecorationsOrBackground();
2214 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
2215 // that require painting. Direct compositing saves backing store.
2216 bool RenderLayerBacking::isDirectlyCompositedImage() const
2218 if (!is<RenderImage>(renderer()) || m_owningLayer.hasVisibleBoxDecorationsOrBackground() || m_owningLayer.paintsWithFilters() || renderer().hasClip())
2222 if (is<RenderMedia>(renderer()))
2226 auto& imageRenderer = downcast<RenderImage>(renderer());
2227 if (auto* cachedImage = imageRenderer.cachedImage()) {
2228 if (!cachedImage->hasImage())
2231 auto* image = cachedImage->imageForRenderer(&imageRenderer);
2232 if (!is<BitmapImage>(image))
2235 if (downcast<BitmapImage>(*image).orientationForCurrentFrame() != DefaultImageOrientation)
2238 #if (PLATFORM(GTK) || PLATFORM(WPE))
2239 // GTK and WPE ports don't support rounded rect clipping at TextureMapper level, so they cannot
2240 // directly composite images that have border-radius propery. Draw them as non directly composited
2241 // content instead. See https://bugs.webkit.org/show_bug.cgi?id=174157.
2242 if (imageRenderer.style().hasBorderRadius())
2246 return m_graphicsLayer->shouldDirectlyCompositeImage(image);
2252 void RenderLayerBacking::contentChanged(ContentChangeType changeType)
2254 PaintedContentsInfo contentsInfo(*this);
2255 if ((changeType == ImageChanged) && contentsInfo.isDirectlyCompositedImage()) {
2256 updateImageContents(contentsInfo);
2260 if ((changeType == BackgroundImageChanged) && canDirectlyCompositeBackgroundBackgroundImage(renderer().style()))
2263 if ((changeType == MaskImageChanged) && m_maskLayer) {
2264 // The composited layer bounds relies on box->maskClipRect(), which changes
2265 // when the mask image becomes available.
2266 updateAfterLayout(UpdateAfterLayoutFlags::IsUpdateRoot);
2269 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
2270 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
2271 m_graphicsLayer->setContentsNeedsDisplay();
2277 void RenderLayerBacking::updateImageContents(PaintedContentsInfo& contentsInfo)
2279 auto& imageRenderer = downcast<RenderImage>(renderer());
2281 auto* cachedImage = imageRenderer.cachedImage();
2285 auto* image = cachedImage->imageForRenderer(&imageRenderer);
2289 // We have to wait until the image is fully loaded before setting it on the layer.
2290 if (!cachedImage->isLoaded())
2293 // This is a no-op if the layer doesn't have an inner layer for the image.
2294 m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
2296 LayoutRect boxRect(LayoutPoint(), imageRenderer.size());
2297 boxRect.move(contentOffsetInCompostingLayer());
2298 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
2299 m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
2301 m_graphicsLayer->setContentsToImage(image);
2303 updateDrawsContent(contentsInfo);
2305 // Image animation is "lazy", in that it automatically stops unless someone is drawing
2306 // the image. So we have to kick the animation each time; this has the downside that the
2307 // image will keep animating, even if its layer is not visible.
2308 image->startAnimation();
2311 FloatPoint3D RenderLayerBacking::computeTransformOriginForPainting(const LayoutRect& borderBox) const
2313 const RenderStyle& style = renderer().style();
2314 float deviceScaleFactor = this->deviceScaleFactor();
2316 FloatPoint3D origin;
2317 origin.setX(roundToDevicePixel(floatValueForLength(style.transformOriginX(), borderBox.width()), deviceScaleFactor));
2318 origin.setY(roundToDevicePixel(floatValueForLength(style.transformOriginY(), borderBox.height()), deviceScaleFactor));
2319 origin.setZ(style.transformOriginZ());
2324 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
2325 LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const
2327 return LayoutSize(-m_compositedBounds.x() + m_compositedBoundsOffsetFromGraphicsLayer.width(), -m_compositedBounds.y() + m_compositedBoundsOffsetFromGraphicsLayer.height());
2330 LayoutRect RenderLayerBacking::contentsBox() const
2332 if (!is<RenderBox>(renderer()))
2333 return LayoutRect();
2335 auto& renderBox = downcast<RenderBox>(renderer());
2336 LayoutRect contentsRect;
2338 if (is<RenderVideo>(renderBox))
2339 contentsRect = downcast<RenderVideo>(renderBox).videoBox();
2342 if (is<RenderReplaced>(renderBox)) {
2343 RenderReplaced& renderReplaced = downcast<RenderReplaced>(renderBox);
2344 contentsRect = renderReplaced.replacedContentRect();
2346 contentsRect = renderBox.contentBoxRect();
2348 contentsRect.move(contentOffsetInCompostingLayer());
2349 return contentsRect;
2352 static LayoutRect backgroundRectForBox(const RenderBox& box)
2354 switch (box.style().backgroundClip()) {
2355 case FillBox::Border:
2356 return box.borderBoxRect();
2357 case FillBox::Padding:
2358 return box.paddingBoxRect();
2359 case FillBox::Content:
2360 return box.contentBoxRect();
2365 ASSERT_NOT_REACHED();
2366 return LayoutRect();
2369 FloatRect RenderLayerBacking::backgroundBoxForSimpleContainerPainting() const
2371 if (!is<RenderBox>(renderer()))
2374 LayoutRect backgroundBox = backgroundRectForBox(downcast<RenderBox>(renderer()));
2375 backgroundBox.move(contentOffsetInCompostingLayer());
2376 return snapRectToDevicePixels(backgroundBox, deviceScaleFactor());
2379 GraphicsLayer* RenderLayerBacking::parentForSublayers() const
2381 if (m_scrollingContentsLayer)
2382 return m_scrollingContentsLayer.get();
2384 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
2387 GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
2389 if (m_ancestorClippingLayer)
2390 return m_ancestorClippingLayer.get();
2392 if (m_contentsContainmentLayer)
2393 return m_contentsContainmentLayer.get();
2395 return m_graphicsLayer.get();
2398 bool RenderLayerBacking::paintsIntoWindow() const
2400 #if USE(COORDINATED_GRAPHICS_THREADED)
2404 if (m_isFrameLayerWithTiledBacking)
2407 if (m_owningLayer.isRenderViewLayer()) {
2408 #if PLATFORM(IOS) || USE(COORDINATED_GRAPHICS)
2409 if (compositor().inForcedCompositingMode())
2413 return compositor().rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
2419 void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
2421 if (requiresOwnBacking == m_requiresOwnBackingStore)
2424 m_requiresOwnBackingStore = requiresOwnBacking;
2426 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
2427 // cached clip rects, so when it changes we have to clear clip rects on descendants.
2428 m_owningLayer.clearClipRectsIncludingDescendants(PaintingClipRects);
2429 m_owningLayer.computeRepaintRectsIncludingDescendants();
2431 compositor().repaintInCompositedAncestor(m_owningLayer, compositedBounds());
2434 void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer shouldClip)
2436 ASSERT(!paintsIntoCompositedAncestor());
2438 auto& frameView = renderer().view().frameView();
2439 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2440 frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBoxForPainting());
2442 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2443 // By default, setNeedsDisplay will clip to the size of the GraphicsLayer, which does not include margin tiles.
2444 // So if the TiledBacking has a margin that needs to be invalidated, we need to send in a rect to setNeedsDisplayInRect
2445 // that is large enough to include the margin. TiledBacking::bounds() includes the margin.
2446 auto* tiledBacking = this->tiledBacking();
2447 FloatRect rectToRepaint = tiledBacking ? tiledBacking->bounds() : FloatRect(FloatPoint(0, 0), m_graphicsLayer->size());
2448 m_graphicsLayer->setNeedsDisplayInRect(rectToRepaint, shouldClip);
2451 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
2452 m_foregroundLayer->setNeedsDisplay();
2454 if (m_backgroundLayer && m_backgroundLayer->drawsContent())
2455 m_backgroundLayer->setNeedsDisplay();
2457 if (m_maskLayer && m_maskLayer->drawsContent())
2458 m_maskLayer->setNeedsDisplay();
2460 if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent())
2461 m_childClippingMaskLayer->setNeedsDisplay();
2463 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
2464 m_scrollingContentsLayer->setNeedsDisplay();
2467 // r is in the coordinate space of the layer's render object
2468 void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, GraphicsLayer::ShouldClipToLayer shouldClip)
2470 ASSERT(!paintsIntoCompositedAncestor());
2472 FloatRect pixelSnappedRectForPainting = snapRectToDevicePixels(r, deviceScaleFactor());
2473 auto& frameView = renderer().view().frameView();
2474 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2475 frameView.addTrackedRepaintRect(pixelSnappedRectForPainting);
2477 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2478 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2479 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2480 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2483 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
2484 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2485 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2486 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2489 // FIXME: need to split out repaints for the background.
2490 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
2491 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2492 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2493 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2496 if (m_maskLayer && m_maskLayer->drawsContent()) {
2497 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2498 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2499 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2502 if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) {
2503 FloatRect layerDirtyRect = r;
2504 layerDirtyRect.move(-m_childClippingMaskLayer->offsetFromRenderer());
2505 m_childClippingMaskLayer->setNeedsDisplayInRect(layerDirtyRect);
2508 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
2509 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2510 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2512 // Account for the fact that RenderLayerBacking::updateGeometry() bakes scrollOffset into offsetFromRenderer on iOS,
2513 // but the repaint rect is computed without taking the scroll position into account (see shouldApplyClipAndScrollPositionForRepaint()).
2514 layerDirtyRect.moveBy(-m_owningLayer.scrollPosition());
2516 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2520 void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext& context,
2521 const IntRect& paintDirtyRect, // In the coords of rootLayer.
2522 OptionSet<PaintBehavior> paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
2524 if ((paintsIntoWindow() || paintsIntoCompositedAncestor()) && paintingPhase != GraphicsLayerPaintChildClippingMask) {
2525 #if !PLATFORM(IOS) && !OS(WINDOWS)
2526 // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy
2527 // when pages are restored from the PageCache.
2528 // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache
2529 ASSERT_NOT_REACHED();
2534 OptionSet<RenderLayer::PaintLayerFlag> paintFlags;
2535 if (paintingPhase & GraphicsLayerPaintBackground)
2536 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingBackgroundPhase);
2537 if (paintingPhase & GraphicsLayerPaintForeground)
2538 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingForegroundPhase);
2539 if (paintingPhase & GraphicsLayerPaintMask)
2540 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingMaskPhase);
2541 if (paintingPhase & GraphicsLayerPaintClipPath)
2542 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingClipPathPhase);
2543 if (paintingPhase & GraphicsLayerPaintChildClippingMask)
2544 paintFlags.add(RenderLayer::PaintLayerPaintingChildClippingMaskPhase);
2545 if (paintingPhase & GraphicsLayerPaintOverflowContents)
2546 paintFlags.add(RenderLayer::PaintLayerPaintingOverflowContents);
2547 if (paintingPhase & GraphicsLayerPaintCompositedScroll)
2548 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingScrollingPhase);
2550 if (graphicsLayer == m_backgroundLayer.get() && m_backgroundLayerPaintsFixedRootBackground)
2551 paintFlags.add({ RenderLayer::PaintLayerPaintingRootBackgroundOnly, RenderLayer::PaintLayerPaintingCompositingForegroundPhase }); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
2552 else if (compositor().fixedRootBackgroundLayer())
2553 paintFlags.add(RenderLayer::PaintLayerPaintingSkipRootBackground);
2556 RenderElement::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(&renderer());
2559 FrameView::PaintingState paintingState;
2560 if (m_owningLayer.isRenderViewLayer())
2561 renderer().view().frameView().willPaintContents(context, paintDirtyRect, paintingState);
2563 // FIXME: GraphicsLayers need a way to split for RenderFragmentContainers.
2564 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer);
2565 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags);
2567 if (m_owningLayer.containsDirtyOverlayScrollbars())
2568 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
2570 if (m_owningLayer.isRenderViewLayer())
2571 renderer().view().frameView().didPaintContents(context, paintDirtyRect, paintingState);
2573 compositor().didPaintBacking(this);
2575 ASSERT(!m_owningLayer.m_usedTransparency);
2578 // Up-call from compositing layer drawing callback.
2579 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const FloatRect& clip, GraphicsLayerPaintBehavior layerPaintBehavior)
2582 renderer().page().setIsPainting(true);
2586 LocalDefaultSystemAppearance localAppearance(renderer().page().useSystemAppearance(), renderer().page().useDarkAppearance());
2589 // The dirtyRect is in the coords of the painting root.
2590 FloatRect adjustedClipRect = clip;
2591 adjustedClipRect.move(m_subpixelOffsetFromRenderer);
2592 IntRect dirtyRect = enclosingIntRect(adjustedClipRect);
2594 if (!graphicsLayer->repaintCount())
2595 layerPaintBehavior |= GraphicsLayerPaintFirstTilePaint;
2597 if (graphicsLayer == m_graphicsLayer.get()
2598 || graphicsLayer == m_foregroundLayer.get()
2599 || graphicsLayer == m_backgroundLayer.get()
2600 || graphicsLayer == m_maskLayer.get()
2601 || graphicsLayer == m_childClippingMaskLayer.get()
2602 || graphicsLayer == m_scrollingContentsLayer.get()) {
2603 InspectorInstrumentation::willPaint(renderer());
2605 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
2606 dirtyRect.intersect(enclosingIntRect(compositedBoundsIncludingMargin()));
2608 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2609 OptionSet<PaintBehavior> behavior = PaintBehavior::Normal;
2610 if (layerPaintBehavior == GraphicsLayerPaintSnapshotting)
2611 behavior.add(PaintBehavior::Snapshotting);
2613 if (layerPaintBehavior == GraphicsLayerPaintFirstTilePaint)
2614 behavior.add(PaintBehavior::TileFirstPaint);
2616 paintIntoLayer(graphicsLayer, context, dirtyRect, behavior, paintingPhase);
2618 InspectorInstrumentation::didPaint(renderer(), dirtyRect);
2619 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2620 paintScrollbar(m_owningLayer.horizontalScrollbar(), context, dirtyRect);
2621 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2622 paintScrollbar(m_owningLayer.verticalScrollbar(), context, dirtyRect);
2623 } else if (graphicsLayer == layerForScrollCorner()) {
2624 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
2626 context.translate(-scrollCornerAndResizer.location());
2627 LayoutRect transformedClip = LayoutRect(clip);
2628 transformedClip.moveBy(scrollCornerAndResizer.location());
2629 m_owningLayer.paintScrollCorner(context, IntPoint(), snappedIntRect(transformedClip));
2630 m_owningLayer.paintResizer(context, IntPoint(), transformedClip);
2634 renderer().page().setIsPainting(false);
2638 float RenderLayerBacking::pageScaleFactor() const
2640 return compositor().pageScaleFactor();
2643 float RenderLayerBacking::zoomedOutPageScaleFactor() const
2645 return compositor().zoomedOutPageScaleFactor();
2648 float RenderLayerBacking::deviceScaleFactor() const
2650 return compositor().deviceScaleFactor();
2653 float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer* layer) const
2655 return compositor().contentsScaleMultiplierForNewTiles(layer);
2658 bool RenderLayerBacking::paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const
2660 return m_isMainFrameRenderViewLayer;
2663 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
2665 compositor().didFlushChangesForLayer(m_owningLayer, layer);
2668 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
2670 auto* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
2671 if (graphicsLayer != transformedLayer)
2674 if (m_owningLayer.hasTransform()) {
2675 transform = m_owningLayer.currentTransform(RenderStyle::ExcludeTransformOrigin);
2681 bool RenderLayerBacking::isTrackingRepaints() const
2683 return static_cast<GraphicsLayerClient&>(compositor()).isTrackingRepaints();
2686 bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer, LayerTreeAsTextBehavior behavior) const
2688 if (behavior & LayerTreeAsTextDebug)
2691 // Skip the root tile cache's flattening layer.
2692 return m_isMainFrameRenderViewLayer && layer && layer == m_childContainmentLayer.get();
2695 bool RenderLayerBacking::shouldDumpPropertyForLayer(const GraphicsLayer* layer, const char* propertyName) const
2697 // For backwards compatibility with WebKit1 and other platforms,
2698 // skip some properties on the root tile cache.
2699 if (m_isMainFrameRenderViewLayer && layer == m_graphicsLayer.get()) {
2700 if (!strcmp(propertyName, "drawsContent"))
2703 // Background color could be of interest to tests or other dumpers if it's non-white.
2704 if (!strcmp(propertyName, "backgroundColor") && layer->backgroundColor() == Color::white)
2707 // The root tile cache's repaints will show up at the top with FrameView's,
2708 // so don't dump them twice.
2709 if (!strcmp(propertyName, "repaintRects"))
2716 bool RenderLayerBacking::shouldAggressivelyRetainTiles(const GraphicsLayer*) const
2718 // Only the main frame TileController has enough information about in-window state to
2719 // correctly implement aggressive tile retention.
2720 if (!m_isMainFrameRenderViewLayer)
2723 return renderer().settings().aggressiveTileRetentionEnabled();
2726 bool RenderLayerBacking::shouldTemporarilyRetainTileCohorts(const GraphicsLayer*) const
2728 return renderer().settings().temporaryTileCohortRetentionEnabled();
2731 bool RenderLayerBacking::useGiantTiles() const
2733 return renderer().settings().useGiantTiles();
2736 void RenderLayerBacking::logFilledVisibleFreshTile(unsigned blankPixelCount)
2738 if (auto* loggingClient = renderer().page().performanceLoggingClient())
2739 loggingClient->logScrollingEvent(PerformanceLoggingClient::ScrollingEvent::FilledTile, MonotonicTime::now(), blankPixelCount);
2743 void RenderLayerBacking::verifyNotPainting()
2745 ASSERT(!renderer().page().isPainting());
2749 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
2751 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
2752 bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyTransform);
2753 bool hasFilter = keyframes.containsProperty(CSSPropertyFilter);
2755 bool hasBackdropFilter = false;
2756 #if ENABLE(FILTERS_LEVEL_2)
2757 hasBackdropFilter = keyframes.containsProperty(CSSPropertyWebkitBackdropFilter);
2760 if (!hasOpacity && !hasTransform && !hasFilter && !hasBackdropFilter)
2763 KeyframeValueList transformVector(AnimatedPropertyTransform);
2764 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2765 KeyframeValueList filterVector(AnimatedPropertyFilter);
2766 #if ENABLE(FILTERS_LEVEL_2)
2767 KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter);
2770 size_t numKeyframes = keyframes.size();
2771 for (size_t i = 0; i < numKeyframes; ++i) {
2772 const KeyframeValue& currentKeyframe = keyframes[i];
2773 const RenderStyle* keyframeStyle = currentKeyframe.style();
2774 double key = currentKeyframe.key();
2779 auto* tf = currentKeyframe.timingFunction();
2781 bool isFirstOrLastKeyframe = key == 0 || key == 1;
2782 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyTransform))
2783 transformVector.insert(std::make_unique<TransformAnimationValue>(key, keyframeStyle->transform(), tf));
2785 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
2786 opacityVector.insert(std::make_unique<FloatAnimationValue>(key, keyframeStyle->opacity(), tf));
2788 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyFilter))
2789 filterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->filter(), tf));
2791 #if ENABLE(FILTERS_LEVEL_2)
2792 if ((hasBackdropFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitBackdropFilter))
2793 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->backdropFilter(), tf));
2797 if (!renderer().settings().acceleratedCompositedAnimationsEnabled())
2800 bool didAnimate = false;
2802 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), anim, keyframes.animationName(), timeOffset))
2805 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2808 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2811 #if ENABLE(FILTERS_LEVEL_2)
2812 if (hasBackdropFilter && m_graphicsLayer->addAnimation(backdropFilterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2819 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
2821 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
2824 void RenderLayerBacking::animationSeeked(double timeOffset, const String& animationName)
2826 m_graphicsLayer->seekAnimation(animationName, timeOffset);
2829 void RenderLayerBacking::animationFinished(const String& animationName)
2831 m_graphicsLayer->removeAnimation(animationName);
2834 bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
2836 bool didAnimate = false;
2838 ASSERT(property != CSSPropertyInvalid);
2840 if (property == CSSPropertyOpacity) {
2841 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
2842 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
2843 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2844 opacityVector.insert(std::make_unique<FloatAnimationValue>(0, compositingOpacity(fromStyle->opacity())));
2845 opacityVector.insert(std::make_unique<FloatAnimationValue>(1, compositingOpacity(toStyle->opacity())));
2846 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
2847 if (m_graphicsLayer->addAnimation(opacityVector, FloatSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
2848 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
2849 updateOpacity(*toStyle);
2855 if (property == CSSPropertyTransform && m_owningLayer.hasTransform()) {
2856 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyTransform);
2857 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
2858 KeyframeValueList transformVector(AnimatedPropertyTransform);
2859 transformVector.insert(std::make_unique<TransformAnimationValue>(0, fromStyle->transform()));
2860 transformVector.insert(std::make_unique<TransformAnimationValue>(1, toStyle->transform()));
2861 if (m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyTransform), timeOffset)) {
2862 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
2863 updateTransform(*toStyle);
2869 if (property == CSSPropertyFilter && m_owningLayer.hasFilter()) {
2870 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyFilter);
2871 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
2872 KeyframeValueList filterVector(AnimatedPropertyFilter);
2873 filterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->filter()));
2874 filterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->filter()));
2875 if (m_graphicsLayer->addAnimation(filterVector, FloatSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyFilter), timeOffset)) {
2876 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
2877 updateFilters(*toStyle);
2883 #if ENABLE(FILTERS_LEVEL_2)
2884 if (property == CSSPropertyWebkitBackdropFilter && m_owningLayer.hasBackdropFilter()) {
2885 const Animation* backdropFilterAnim = toStyle->transitionForProperty(CSSPropertyWebkitBackdropFilter);
2886 if (backdropFilterAnim && !backdropFilterAnim->isEmptyOrZeroDuration()) {
2887 KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter);
2888 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->backdropFilter()));
2889 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->backdropFilter()));
2890 if (m_graphicsLayer->addAnimation(backdropFilterVector, FloatSize(), backdropFilterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitBackdropFilter), timeOffset)) {
2891 // To ensure that the correct backdrop filter is visible when the animation ends, also set the final backdrop filter.
2892 updateBackdropFilters(*toStyle);
2902 void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
2904 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2905 if (animatedProperty != AnimatedPropertyInvalid)
2906 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
2909 void RenderLayerBacking::transitionFinished(CSSPropertyID property)
2911 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2912 if (animatedProperty != AnimatedPropertyInvalid)
2913 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
2916 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, const String&, MonotonicTime time)
2918 renderer().animation().notifyAnimationStarted(renderer(), time);
2921 void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer)
2923 if (renderer().renderTreeBeingDestroyed())
2925 compositor().scheduleLayerFlush(layer->canThrottleLayerFlush());
2928 void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
2930 compositor().notifyFlushBeforeDisplayRefresh(layer);
2933 // This is used for the 'freeze' API, for testing only.
2934 void RenderLayerBacking::suspendAnimations(MonotonicTime time)
2936 m_graphicsLayer->suspendAnimations(time);
2939 void RenderLayerBacking::resumeAnimations()
2941 m_graphicsLayer->resumeAnimations();
2944 LayoutRect RenderLayerBacking::compositedBounds() const
2946 return m_compositedBounds;
2949 void RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds)
2951 m_compositedBounds = bounds;
2954 LayoutRect RenderLayerBacking::compositedBoundsIncludingMargin() const
2956 auto* tiledBacking = this->tiledBacking();
2957 if (!tiledBacking || !tiledBacking->hasMargins())
2958 return compositedBounds();
2960 LayoutRect boundsIncludingMargin = compositedBounds();
2961 LayoutUnit leftMarginWidth = tiledBacking->leftMarginWidth();
2962 LayoutUnit topMarginHeight = tiledBacking->topMarginHeight();
2964 boundsIncludingMargin.moveBy(LayoutPoint(-leftMarginWidth, -topMarginHeight));
2965 boundsIncludingMargin.expand(leftMarginWidth + tiledBacking->rightMarginWidth(), topMarginHeight + tiledBacking->bottomMarginHeight());
2967 return boundsIncludingMargin;
2970 CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
2972 CSSPropertyID cssProperty = CSSPropertyInvalid;
2974 case AnimatedPropertyTransform:
2975 cssProperty = CSSPropertyTransform;
2977 case AnimatedPropertyOpacity:
2978 cssProperty = CSSPropertyOpacity;
2980 case AnimatedPropertyBackgroundColor:
2981 cssProperty = CSSPropertyBackgroundColor;
2983 case AnimatedPropertyFilter:
2984 cssProperty = CSSPropertyFilter;
2986 #if ENABLE(FILTERS_LEVEL_2)
2987 case AnimatedPropertyWebkitBackdropFilter:
2988 cssProperty = CSSPropertyWebkitBackdropFilter;
2991 case AnimatedPropertyInvalid:
2992 ASSERT_NOT_REACHED();
2997 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
2999 switch (cssProperty) {
3000 case CSSPropertyTransform:
3001 return AnimatedPropertyTransform;
3002 case CSSPropertyOpacity:
3003 return AnimatedPropertyOpacity;
3004 case CSSPropertyBackgroundColor:
3005 return AnimatedPropertyBackgroundColor;
3006 case CSSPropertyFilter:
3007 return AnimatedPropertyFilter;
3008 #if ENABLE(FILTERS_LEVEL_2)
3009 case CSSPropertyWebkitBackdropFilter:
3010 return AnimatedPropertyWebkitBackdropFilter;
3013 // It's fine if we see other css properties here; they are just not accelerated.
3016 return AnimatedPropertyInvalid;
3019 CompositingLayerType RenderLayerBacking::compositingLayerType() const
3021 if (m_graphicsLayer->usesContentsLayer())
3022 return MediaCompositingLayer;
3024 if (m_graphicsLayer->drawsContent())
3025 return m_graphicsLayer->tiledBacking() ? TiledCompositingLayer : NormalCompositingLayer;
3027 return ContainerCompositingLayer;
3030 double RenderLayerBacking::backingStoreMemoryEstimate() const
3032 double backingMemory;
3034 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
3035 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
3036 if (m_foregroundLayer)
3037 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
3038 if (m_backgroundLayer)
3039 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
3041 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
3042 if (m_childClippingMaskLayer)
3043 backingMemory += m_childClippingMaskLayer->backingStoreMemoryEstimate();
3045 if (m_scrollingContentsLayer)
3046 backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
3048 if (m_layerForHorizontalScrollbar)
3049 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
3051 if (m_layerForVerticalScrollbar)
3052 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
3054 if (m_layerForScrollCorner)
3055 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
3057 return backingMemory;
3060 TextStream& operator<<(TextStream& ts, const RenderLayerBacking& backing)
3062 ts << "RenderLayerBacking " << &backing << " bounds " << backing.compositedBounds();
3064 if (backing.isFrameLayerWithTiledBacking())
3065 ts << " frame layer tiled backing";
3066 if (backing.paintsIntoWindow())
3067 ts << " paintsIntoWindow";
3068 if (backing.paintsIntoCompositedAncestor())
3069 ts << " paintsIntoCompositedAncestor";
3071 ts << " primary layer ID " << backing.graphicsLayer()->primaryLayerID();
3072 if (auto nodeID = backing.scrollingNodeIDForRole(ViewportConstrained))
3073 ts << " viewport constrained scrolling node " << nodeID;
3074 if (auto nodeID = backing.scrollingNodeIDForRole(Scrolling))
3075 ts << " scrolling node " << nodeID;
3079 } // namespace WebCore