1/*
2 * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#include "config.h"
27
28#include "RenderLayerBacking.h"
29
30#include "BitmapImage.h"
31#include "CSSAnimationController.h"
32#include "CanvasRenderingContext.h"
33#include "CSSPropertyNames.h"
34#include "CachedImage.h"
35#include "Chrome.h"
36#include "DocumentTimeline.h"
37#include "EventRegion.h"
38#include "Frame.h"
39#include "FrameView.h"
40#include "GraphicsContext.h"
41#include "GraphicsLayer.h"
42#include "HTMLBodyElement.h"
43#include "HTMLCanvasElement.h"
44#include "HTMLIFrameElement.h"
45#include "HTMLMediaElement.h"
46#include "HTMLNames.h"
47#include "HTMLPlugInElement.h"
48#include "InspectorInstrumentation.h"
49#include "KeyframeList.h"
50#include "Logging.h"
51#include "Page.h"
52#include "PerformanceLoggingClient.h"
53#include "PluginViewBase.h"
54#include "ProgressTracker.h"
55#include "RenderFragmentContainer.h"
56#include "RenderFragmentedFlow.h"
57#include "RenderHTMLCanvas.h"
58#include "RenderIFrame.h"
59#include "RenderImage.h"
60#include "RenderLayerCompositor.h"
61#include "RenderEmbeddedObject.h"
62#include "RenderMedia.h"
63#include "RenderVideo.h"
64#include "RenderView.h"
65#include "RuntimeEnabledFeatures.h"
66#include "ScrollingCoordinator.h"
67#include "Settings.h"
68#include "StyleResolver.h"
69#include "TiledBacking.h"
70#include <wtf/text/TextStream.h>
71
72#if PLATFORM(IOS_FAMILY)
73#include "RuntimeApplicationChecks.h"
74#endif
75
76#if PLATFORM(MAC)
77#include "LocalDefaultSystemAppearance.h"
78#endif
79
80namespace WebCore {
81
82using namespace HTMLNames;
83
84CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject& renderer)
85{
86 ASSERT(renderer.isCanvas());
87
88 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer.node());
89 auto* context = canvas->renderingContext();
90 if (!context || !context->isAccelerated())
91 return UnacceleratedCanvas;
92
93 if (context->isGPUBased())
94 return CanvasAsLayerContents;
95
96#if ENABLE(ACCELERATED_2D_CANVAS)
97 return CanvasAsLayerContents;
98#else
99 return CanvasPaintedToLayer; // On Mac and iOS we paint accelerated canvases into their layers.
100#endif
101}
102
103// This acts as a cache of what we know about what is painting into this RenderLayerBacking.
104class PaintedContentsInfo {
105public:
106 enum class ContentsTypeDetermination {
107 Unknown,
108 SimpleContainer,
109 DirectlyCompositedImage,
110 Painted
111 };
112
113 PaintedContentsInfo(RenderLayerBacking& inBacking)
114 : m_backing(inBacking)
115 {
116 }
117
118 void setWantsSubpixelAntialiasedTextState(bool wantsSubpixelAntialiasedTextState)
119 {
120 m_subpixelAntialiasedText = wantsSubpixelAntialiasedTextState ? RequestState::Unknown : RequestState::DontCare;
121 }
122
123 RequestState paintsBoxDecorationsDetermination();
124 bool paintsBoxDecorations()
125 {
126 RequestState state = paintsBoxDecorationsDetermination();
127 return state == RequestState::True || state == RequestState::Undetermined;
128 }
129
130 RequestState paintsContentDetermination();
131 bool paintsContent()
132 {
133 RequestState state = paintsContentDetermination();
134 return state == RequestState::True || state == RequestState::Undetermined;
135 }
136
137 RequestState paintsSubpixelAntialiasedTextDetermination();
138 bool paintsSubpixelAntialiasedText()
139 {
140 RequestState state = paintsSubpixelAntialiasedTextDetermination();
141 return state == RequestState::True || state == RequestState::Undetermined;
142 }
143
144 ContentsTypeDetermination contentsTypeDetermination();
145 bool isSimpleContainer()
146 {
147 return contentsTypeDetermination() == ContentsTypeDetermination::SimpleContainer;
148 }
149
150 bool isDirectlyCompositedImage()
151 {
152 return contentsTypeDetermination() == ContentsTypeDetermination::DirectlyCompositedImage;
153 }
154
155 RenderLayerBacking& m_backing;
156 RequestState m_boxDecorations { RequestState::Unknown };
157 RequestState m_content { RequestState::Unknown };
158 RequestState m_subpixelAntialiasedText { RequestState::DontCare };
159
160 ContentsTypeDetermination m_contentsType { ContentsTypeDetermination::Unknown };
161};
162
163RequestState PaintedContentsInfo::paintsBoxDecorationsDetermination()
164{
165 if (m_boxDecorations != RequestState::Unknown)
166 return m_boxDecorations;
167
168 m_boxDecorations = m_backing.paintsBoxDecorations() ? RequestState::True : RequestState::False;
169 return m_boxDecorations;
170}
171
172RequestState PaintedContentsInfo::paintsContentDetermination()
173{
174 if (m_content != RequestState::Unknown && m_subpixelAntialiasedText != RequestState::Unknown)
175 return m_content;
176
177 RenderLayer::PaintedContentRequest contentRequest;
178 if (m_subpixelAntialiasedText == RequestState::Unknown)
179 contentRequest.hasSubpixelAntialiasedText = RequestState::Unknown;
180
181 m_content = m_backing.paintsContent(contentRequest) ? RequestState::True : RequestState::False;
182
183 if (m_subpixelAntialiasedText == RequestState::Unknown)
184 m_subpixelAntialiasedText = contentRequest.hasSubpixelAntialiasedText;
185
186 return m_content;
187}
188
189RequestState PaintedContentsInfo::paintsSubpixelAntialiasedTextDetermination()
190{
191 if (m_subpixelAntialiasedText != RequestState::Unknown)
192 return m_subpixelAntialiasedText;
193
194 paintsContentDetermination();
195
196 return m_subpixelAntialiasedText;
197}
198
199PaintedContentsInfo::ContentsTypeDetermination PaintedContentsInfo::contentsTypeDetermination()
200{
201 if (m_contentsType != ContentsTypeDetermination::Unknown)
202 return m_contentsType;
203
204 if (m_backing.isSimpleContainerCompositingLayer(*this))
205 m_contentsType = ContentsTypeDetermination::SimpleContainer;
206 else if (m_backing.isDirectlyCompositedImage())
207 m_contentsType = ContentsTypeDetermination::DirectlyCompositedImage;
208 else
209 m_contentsType = ContentsTypeDetermination::Painted;
210
211 return m_contentsType;
212}
213
214
215RenderLayerBacking::RenderLayerBacking(RenderLayer& layer)
216 : m_owningLayer(layer)
217{
218 if (layer.isRenderViewLayer()) {
219 m_isMainFrameRenderViewLayer = renderer().frame().isMainFrame();
220 m_isFrameLayerWithTiledBacking = renderer().page().chrome().client().shouldUseTiledBackingForFrameView(renderer().view().frameView());
221 }
222
223 createPrimaryGraphicsLayer();
224#if ENABLE(FULLSCREEN_API)
225 setRequiresBackgroundLayer(layer.renderer().isRenderFullScreen());
226#endif
227
228 if (auto* tiledBacking = this->tiledBacking()) {
229 tiledBacking->setIsInWindow(renderer().page().isInWindow());
230
231 if (m_isFrameLayerWithTiledBacking) {
232 tiledBacking->setScrollingPerformanceLoggingEnabled(renderer().settings().scrollingPerformanceLoggingEnabled());
233 adjustTiledBackingCoverage();
234 }
235 }
236}
237
238RenderLayerBacking::~RenderLayerBacking()
239{
240 // Note that m_owningLayer->backing() is null here.
241 updateAncestorClippingLayer(false);
242 updateChildClippingStrategy(false);
243 updateDescendantClippingLayer(false);
244 updateOverflowControlsLayers(false, false, false);
245 updateForegroundLayer(false);
246 updateBackgroundLayer(false);
247 updateMaskingLayer(false, false);
248 updateScrollingLayers(false);
249
250 ASSERT(!m_viewportConstrainedNodeID);
251 ASSERT(!m_scrollingNodeID);
252 ASSERT(!m_frameHostingNodeID);
253 ASSERT(!m_positioningNodeID);
254
255 destroyGraphicsLayers();
256}
257
258void RenderLayerBacking::willBeDestroyed()
259{
260 ASSERT(m_owningLayer.backing() == this);
261 compositor().removeFromScrollCoordinatedLayers(m_owningLayer);
262
263 clearBackingSharingLayers();
264}
265
266void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
267{
268 if (layer && layer->type() == GraphicsLayer::Type::Normal && layer->tiledBacking())
269 compositor().layerTiledBackingUsageChanged(layer, false);
270}
271
272static void clearBackingSharingLayerProviders(Vector<WeakPtr<RenderLayer>>& sharingLayers)
273{
274 for (auto& layerWeakPtr : sharingLayers) {
275 if (!layerWeakPtr)
276 continue;
277 layerWeakPtr->setBackingProviderLayer(nullptr);
278 }
279}
280
281void RenderLayerBacking::setBackingSharingLayers(Vector<WeakPtr<RenderLayer>>&& sharingLayers)
282{
283 clearBackingSharingLayerProviders(m_backingSharingLayers);
284
285 if (sharingLayers != m_backingSharingLayers)
286 setContentsNeedDisplay(); // This could be optimize to only repaint rects for changed layers.
287
288 m_backingSharingLayers = WTFMove(sharingLayers);
289
290 for (auto& layerWeakPtr : m_backingSharingLayers)
291 layerWeakPtr->setBackingProviderLayer(&m_owningLayer);
292}
293
294void RenderLayerBacking::removeBackingSharingLayer(RenderLayer& layer)
295{
296 layer.setBackingProviderLayer(nullptr);
297 m_backingSharingLayers.removeAll(&layer);
298}
299
300void RenderLayerBacking::clearBackingSharingLayers()
301{
302 clearBackingSharingLayerProviders(m_backingSharingLayers);
303 m_backingSharingLayers.clear();
304}
305
306Ref<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name, GraphicsLayer::Type layerType)
307{
308 auto* graphicsLayerFactory = renderer().page().chrome().client().graphicsLayerFactory();
309
310 auto graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, *this, layerType);
311
312 graphicsLayer->setName(name);
313
314#if PLATFORM(COCOA) && USE(CA)
315 graphicsLayer->setAcceleratesDrawing(compositor().acceleratedDrawingEnabled());
316 graphicsLayer->setUsesDisplayListDrawing(compositor().displayListDrawingEnabled());
317#endif
318
319 return graphicsLayer;
320}
321
322void RenderLayerBacking::setUsesDisplayListDrawing(bool usesDisplayListDrawing)
323{
324 // Note that this only affects the primary layer.
325 if (usesDisplayListDrawing == m_graphicsLayer->usesDisplayListDrawing())
326 return;
327
328 m_graphicsLayer->setUsesDisplayListDrawing(usesDisplayListDrawing);
329 if (m_graphicsLayer->drawsContent())
330 m_graphicsLayer->setNeedsDisplay();
331}
332
333String RenderLayerBacking::displayListAsText(DisplayList::AsTextFlags flags) const
334{
335 return m_graphicsLayer->displayListAsText(flags);
336}
337
338void RenderLayerBacking::setIsTrackingDisplayListReplay(bool isTrackingReplay)
339{
340 m_graphicsLayer->setIsTrackingDisplayListReplay(isTrackingReplay);
341}
342
343String RenderLayerBacking::replayDisplayListAsText(DisplayList::AsTextFlags flags) const
344{
345 return m_graphicsLayer->replayDisplayListAsText(flags);
346}
347
348void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
349{
350 compositor().layerTiledBackingUsageChanged(layer, usingTiledBacking);
351}
352
353TiledBacking* RenderLayerBacking::tiledBacking() const
354{
355 return m_graphicsLayer->tiledBacking();
356}
357
358static TiledBacking::TileCoverage computePageTiledBackingCoverage(RenderLayerBacking* backing)
359{
360 // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
361 auto& frameView = backing->owningLayer().renderer().view().frameView();
362
363 // If the page is non-visible, don't incur the cost of keeping extra tiles for scrolling.
364 if (!backing->owningLayer().page().isVisible())
365 return TiledBacking::CoverageForVisibleArea;
366
367 TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
368 bool useMinimalTilesDuringLiveResize = frameView.inLiveResize();
369 if (frameView.speculativeTilingEnabled() && !useMinimalTilesDuringLiveResize) {
370 bool clipsToExposedRect = static_cast<bool>(frameView.viewExposedRect());
371 if (frameView.horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
372 tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
373
374 if (frameView.verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
375 tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
376 }
377 return tileCoverage;
378}
379
380void RenderLayerBacking::adjustTiledBackingCoverage()
381{
382 if (!m_isFrameLayerWithTiledBacking)
383 return;
384
385 TiledBacking::TileCoverage tileCoverage = computePageTiledBackingCoverage(this);
386 tiledBacking()->setTileCoverage(tileCoverage);
387}
388
389void RenderLayerBacking::setTiledBackingHasMargins(bool hasExtendedBackgroundOnLeftAndRight, bool hasExtendedBackgroundOnTopAndBottom)
390{
391 if (!m_isFrameLayerWithTiledBacking)
392 return;
393
394 tiledBacking()->setHasMargins(hasExtendedBackgroundOnTopAndBottom, hasExtendedBackgroundOnTopAndBottom, hasExtendedBackgroundOnLeftAndRight, hasExtendedBackgroundOnLeftAndRight);
395}
396
397void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter)
398{
399 m_graphicsLayer->setShowDebugBorder(showBorder);
400 m_graphicsLayer->setShowRepaintCounter(showRepaintCounter);
401
402 if (m_ancestorClippingLayer)
403 m_ancestorClippingLayer->setShowDebugBorder(showBorder);
404
405 if (m_foregroundLayer) {
406 m_foregroundLayer->setShowDebugBorder(showBorder);
407 m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
408 }
409
410 if (m_contentsContainmentLayer)
411 m_contentsContainmentLayer->setShowDebugBorder(showBorder);
412
413 if (m_backgroundLayer) {
414 m_backgroundLayer->setShowDebugBorder(showBorder);
415 m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
416 }
417
418 if (m_maskLayer) {
419 m_maskLayer->setShowDebugBorder(showBorder);
420 m_maskLayer->setShowRepaintCounter(showRepaintCounter);
421 }
422
423 if (m_layerForHorizontalScrollbar)
424 m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
425
426 if (m_layerForVerticalScrollbar)
427 m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
428
429 if (m_layerForScrollCorner)
430 m_layerForScrollCorner->setShowDebugBorder(showBorder);
431
432 if (m_scrollContainerLayer)
433 m_scrollContainerLayer->setShowDebugBorder(showBorder);
434
435 if (m_scrolledContentsLayer) {
436 m_scrolledContentsLayer->setShowDebugBorder(showBorder);
437 m_scrolledContentsLayer->setShowRepaintCounter(showRepaintCounter);
438 }
439}
440
441void RenderLayerBacking::createPrimaryGraphicsLayer()
442{
443 String layerName = m_owningLayer.name();
444 const unsigned maxLayerNameLength = 100;
445 if (layerName.length() > maxLayerNameLength) {
446 layerName.truncate(maxLayerNameLength);
447 layerName.append("...");
448 }
449 m_graphicsLayer = createGraphicsLayer(layerName, m_isFrameLayerWithTiledBacking ? GraphicsLayer::Type::PageTiledBacking : GraphicsLayer::Type::Normal);
450
451 if (m_isFrameLayerWithTiledBacking) {
452 m_childContainmentLayer = createGraphicsLayer("Page TiledBacking containment");
453 m_graphicsLayer->addChild(*m_childContainmentLayer);
454 }
455
456#if !PLATFORM(IOS_FAMILY)
457 if (m_isMainFrameRenderViewLayer) {
458 // Page scale is applied above the RenderView on iOS.
459 m_graphicsLayer->setContentsOpaque(!compositor().viewHasTransparentBackground());
460 m_graphicsLayer->setAppliesPageScale();
461 }
462#endif
463
464#if PLATFORM(COCOA) && USE(CA)
465 if (!compositor().acceleratedDrawingEnabled() && renderer().isCanvas()) {
466 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element());
467 if (canvas->shouldAccelerate(canvas->size()))
468 m_graphicsLayer->setAcceleratesDrawing(true);
469 }
470#endif
471
472 updateOpacity(renderer().style());
473 updateTransform(renderer().style());
474 updateFilters(renderer().style());
475#if ENABLE(FILTERS_LEVEL_2)
476 updateBackdropFilters(renderer().style());
477#endif
478#if ENABLE(CSS_COMPOSITING)
479 updateBlendMode(renderer().style());
480#endif
481 updateCustomAppearance(renderer().style());
482}
483
484#if PLATFORM(IOS_FAMILY)
485void RenderLayerBacking::layerWillBeDestroyed()
486{
487 auto& renderer = this->renderer();
488 if (is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing()) {
489 auto* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer).widget());
490 if (pluginViewBase && m_graphicsLayer->contentsLayerForMedia())
491 pluginViewBase->detachPluginLayer();
492 }
493}
494
495bool RenderLayerBacking::needsIOSDumpRenderTreeMainFrameRenderViewLayerIsAlwaysOpaqueHack(const GraphicsLayer& layer) const
496{
497 if (m_isMainFrameRenderViewLayer && IOSApplication::isDumpRenderTree()) {
498 // In iOS WebKit1 the main frame's RenderView layer is always transparent. We lie that it is opaque so that
499 // internals.layerTreeAsText() tests succeed.
500 ASSERT_UNUSED(layer, !layer.contentsOpaque());
501 return true;
502 }
503 return false;
504}
505#endif
506
507void RenderLayerBacking::destroyGraphicsLayers()
508{
509 if (m_graphicsLayer) {
510 m_graphicsLayer->setMaskLayer(nullptr);
511 m_graphicsLayer->setReplicatedByLayer(nullptr);
512 willDestroyLayer(m_graphicsLayer.get());
513 }
514
515 GraphicsLayer::clear(m_maskLayer);
516
517 GraphicsLayer::unparentAndClear(m_ancestorClippingLayer);
518 GraphicsLayer::unparentAndClear(m_contentsContainmentLayer);
519 GraphicsLayer::unparentAndClear(m_foregroundLayer);
520 GraphicsLayer::unparentAndClear(m_backgroundLayer);
521 GraphicsLayer::unparentAndClear(m_childContainmentLayer);
522 GraphicsLayer::unparentAndClear(m_childClippingMaskLayer);
523 GraphicsLayer::unparentAndClear(m_scrollContainerLayer);
524 GraphicsLayer::unparentAndClear(m_scrolledContentsLayer);
525 GraphicsLayer::unparentAndClear(m_graphicsLayer);
526}
527
528void RenderLayerBacking::updateOpacity(const RenderStyle& style)
529{
530 m_graphicsLayer->setOpacity(compositingOpacity(style.opacity()));
531}
532
533void RenderLayerBacking::updateTransform(const RenderStyle& style)
534{
535 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
536 // baked into it, and we don't want that.
537 TransformationMatrix t;
538 if (m_owningLayer.hasTransform()) {
539 auto& renderBox = downcast<RenderBox>(renderer());
540 style.applyTransform(t, snapRectToDevicePixels(renderBox.borderBoxRect(), deviceScaleFactor()), RenderStyle::ExcludeTransformOrigin);
541 makeMatrixRenderable(t, compositor().canRender3DTransforms());
542 }
543
544 if (m_contentsContainmentLayer) {
545 m_contentsContainmentLayer->setTransform(t);
546 m_graphicsLayer->setTransform(TransformationMatrix());
547 } else
548 m_graphicsLayer->setTransform(t);
549}
550
551void RenderLayerBacking::updateFilters(const RenderStyle& style)
552{
553 m_canCompositeFilters = m_graphicsLayer->setFilters(style.filter());
554}
555
556#if ENABLE(FILTERS_LEVEL_2)
557void RenderLayerBacking::updateBackdropFilters(const RenderStyle& style)
558{
559 m_canCompositeBackdropFilters = m_graphicsLayer->setBackdropFilters(style.backdropFilter());
560}
561
562void RenderLayerBacking::updateBackdropFiltersGeometry()
563{
564 if (!m_canCompositeBackdropFilters)
565 return;
566
567 if (!is<RenderBox>(renderer()))
568 return;
569
570 auto& renderer = downcast<RenderBox>(this->renderer());
571 LayoutRect boxRect = renderer.borderBoxRect();
572 if (renderer.hasClip())
573 boxRect.intersect(renderer.clipRect(LayoutPoint(), nullptr));
574 boxRect.move(contentOffsetInCompositingLayer());
575
576 FloatRoundedRect backdropFiltersRect;
577 if (renderer.style().hasBorderRadius() && !renderer.hasClip())
578 backdropFiltersRect = renderer.style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
579 else
580 backdropFiltersRect = FloatRoundedRect(snapRectToDevicePixels(boxRect, deviceScaleFactor()));
581
582 m_graphicsLayer->setBackdropFiltersRect(backdropFiltersRect);
583}
584#endif
585
586#if ENABLE(CSS_COMPOSITING)
587void RenderLayerBacking::updateBlendMode(const RenderStyle& style)
588{
589 // FIXME: where is the blend mode updated when m_ancestorClippingLayers come and go?
590 if (m_ancestorClippingLayer) {
591 m_ancestorClippingLayer->setBlendMode(style.blendMode());
592 m_graphicsLayer->setBlendMode(BlendMode::Normal);
593 } else
594 m_graphicsLayer->setBlendMode(style.blendMode());
595}
596#endif
597
598void RenderLayerBacking::updateCustomAppearance(const RenderStyle& style)
599{
600 ControlPart appearance = style.appearance();
601 if (appearance == MediaControlsLightBarBackgroundPart)
602 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::LightBackdrop);
603 else if (appearance == MediaControlsDarkBarBackgroundPart)
604 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::DarkBackdrop);
605 else
606 m_graphicsLayer->setCustomAppearance(GraphicsLayer::CustomAppearance::None);
607}
608
609static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
610{
611 for (auto* curr = &layer; curr; curr = curr->parent()) {
612 if (curr->hasTransform() || curr->hasCompositedScrollableOverflow())
613 return true;
614 }
615
616 return false;
617}
618
619bool RenderLayerBacking::shouldClipCompositedBounds() const
620{
621#if !PLATFORM(IOS_FAMILY)
622 // Scrollbar layers use this layer for relative positioning, so don't clip.
623 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
624 return false;
625#endif
626
627 if (m_isFrameLayerWithTiledBacking)
628 return false;
629
630 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
631 return false;
632
633 return true;
634}
635
636static bool hasNonZeroTransformOrigin(const RenderObject& renderer)
637{
638 const RenderStyle& style = renderer.style();
639 return (style.transformOriginX().type() == Fixed && style.transformOriginX().value())
640 || (style.transformOriginY().type() == Fixed && style.transformOriginY().value());
641}
642
643bool RenderLayerBacking::updateCompositedBounds()
644{
645 LayoutRect layerBounds = m_owningLayer.calculateLayerBounds(&m_owningLayer, { }, RenderLayer::defaultCalculateLayerBoundsFlags() | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
646 // Clip to the size of the document or enclosing overflow-scroll layer.
647 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
648 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
649 if (shouldClipCompositedBounds()) {
650 auto& view = renderer().view();
651 auto* rootLayer = view.layer();
652
653 LayoutRect clippingBounds;
654 if (renderer().isFixedPositioned() && renderer().container() == &view)
655 clippingBounds = view.frameView().rectForFixedPositionLayout();
656 else
657 clippingBounds = view.unscaledDocumentRect();
658
659 if (&m_owningLayer != rootLayer)
660 clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
661
662 LayoutPoint delta = m_owningLayer.convertToLayerCoords(rootLayer, LayoutPoint(), RenderLayer::AdjustForColumns);
663 clippingBounds.move(-delta.x(), -delta.y());
664
665 layerBounds.intersect(clippingBounds);
666 }
667
668 // If the backing provider has overflow:clip, we know all sharing layers are affected by the clip because they are containing-block descendants.
669 if (!renderer().hasOverflowClip()) {
670 for (auto& layerWeakPtr : m_backingSharingLayers) {
671 auto* boundsRootLayer = &m_owningLayer;
672 ASSERT(layerWeakPtr->isDescendantOf(m_owningLayer));
673 auto offset = layerWeakPtr->offsetFromAncestor(&m_owningLayer);
674 auto bounds = layerWeakPtr->calculateLayerBounds(boundsRootLayer, offset, RenderLayer::defaultCalculateLayerBoundsFlags() | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask);
675 layerBounds.unite(bounds);
676 }
677 }
678
679 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
680 // then we need to ensure that the compositing layer has non-zero size so that we can apply
681 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
682 if (layerBounds.isEmpty() && (hasNonZeroTransformOrigin(renderer()) || renderer().style().hasPerspective())) {
683 layerBounds.setWidth(1);
684 layerBounds.setHeight(1);
685 m_artificiallyInflatedBounds = true;
686 } else
687 m_artificiallyInflatedBounds = false;
688
689 return setCompositedBounds(layerBounds);
690}
691
692void RenderLayerBacking::updateAfterWidgetResize()
693{
694 if (!is<RenderWidget>(renderer()))
695 return;
696
697 if (auto* innerCompositor = RenderLayerCompositor::frameContentsCompositor(downcast<RenderWidget>(renderer()))) {
698 innerCompositor->frameViewDidChangeSize();
699 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
700 }
701}
702
703void RenderLayerBacking::updateAfterLayout(bool needsClippingUpdate, bool needsFullRepaint)
704{
705 LOG(Compositing, "RenderLayerBacking %p updateAfterLayout (layer %p)", this, &m_owningLayer);
706
707 // This is the main trigger for layout changing layer geometry, but we have to do the work again in updateBackingAndHierarchy()
708 // when we know the final compositing hierarchy. We can't just set dirty bits from RenderLayer::setSize() because that doesn't
709 // take overflow into account.
710 if (updateCompositedBounds()) {
711 m_owningLayer.setNeedsCompositingGeometryUpdate();
712 // This layer's geometry affects those of its children.
713 m_owningLayer.setChildrenNeedCompositingGeometryUpdate();
714 } else if (needsClippingUpdate)
715 m_owningLayer.setNeedsCompositingGeometryUpdate();
716
717 if (needsFullRepaint && canIssueSetNeedsDisplay())
718 setContentsNeedDisplay();
719}
720
721// This can only update things that don't require up-to-date layout.
722void RenderLayerBacking::updateConfigurationAfterStyleChange()
723{
724 updateMaskingLayer(renderer().hasMask(), renderer().hasClipPath());
725
726 if (m_owningLayer.hasReflection()) {
727 if (m_owningLayer.reflectionLayer()->backing()) {
728 auto* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
729 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
730 }
731 } else
732 m_graphicsLayer->setReplicatedByLayer(nullptr);
733
734 // FIXME: do we care if opacity is animating?
735 auto& style = renderer().style();
736 updateOpacity(style);
737 updateFilters(style);
738
739#if ENABLE(FILTERS_LEVEL_2)
740 updateBackdropFilters(style);
741#endif
742#if ENABLE(CSS_COMPOSITING)
743 updateBlendMode(style);
744#endif
745 updateCustomAppearance(style);
746}
747
748bool RenderLayerBacking::updateConfiguration()
749{
750 ASSERT(!m_owningLayer.normalFlowListDirty());
751 ASSERT(!m_owningLayer.zOrderListsDirty());
752 ASSERT(!renderer().view().needsLayout());
753
754 bool layerConfigChanged = false;
755 auto& compositor = this->compositor();
756
757 setBackgroundLayerPaintsFixedRootBackground(compositor.needsFixedRootBackgroundLayer(m_owningLayer));
758
759 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground || m_requiresBackgroundLayer))
760 layerConfigChanged = true;
761
762 if (updateForegroundLayer(compositor.needsContentsCompositingLayer(m_owningLayer)))
763 layerConfigChanged = true;
764
765 bool needsDescendantsClippingLayer = false;
766 bool usesCompositedScrolling = m_owningLayer.hasCompositedScrollableOverflow();
767
768 if (usesCompositedScrolling) {
769 // If it's scrollable, it has to be a box.
770 auto& renderBox = downcast<RenderBox>(renderer());
771 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(renderBox.borderBoxRect()).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
772 needsDescendantsClippingLayer = contentsClippingRect.isRounded();
773 } else
774 needsDescendantsClippingLayer = RenderLayerCompositor::clipsCompositingDescendants(m_owningLayer);
775
776 if (updateScrollingLayers(usesCompositedScrolling))
777 layerConfigChanged = true;
778
779 if (updateDescendantClippingLayer(needsDescendantsClippingLayer))
780 layerConfigChanged = true;
781
782 // clippedByAncestor() does a tree walk.
783 if (updateAncestorClippingLayer(compositor.clippedByAncestor(m_owningLayer)))
784 layerConfigChanged = true;
785
786 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
787 layerConfigChanged = true;
788
789 if (layerConfigChanged)
790 updateInternalHierarchy();
791
792 if (auto* flatteningLayer = tileCacheFlatteningLayer()) {
793 if (layerConfigChanged || flatteningLayer->parent() != m_graphicsLayer.get())
794 m_graphicsLayer->addChild(*flatteningLayer);
795 }
796
797 updateMaskingLayer(renderer().hasMask(), renderer().hasClipPath());
798
799 updateChildClippingStrategy(needsDescendantsClippingLayer);
800
801 if (m_owningLayer.hasReflection()) {
802 if (m_owningLayer.reflectionLayer()->backing()) {
803 auto* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
804 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
805 }
806 } else
807 m_graphicsLayer->setReplicatedByLayer(nullptr);
808
809 PaintedContentsInfo contentsInfo(*this);
810
811 // Requires layout.
812 if (!m_owningLayer.isRenderViewLayer()) {
813 bool didUpdateContentsRect = false;
814 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
815 } else
816 updateRootLayerConfiguration();
817
818 updateEventRegion();
819
820 // Requires layout.
821 if (contentsInfo.isDirectlyCompositedImage())
822 updateImageContents(contentsInfo);
823
824 if (is<RenderEmbeddedObject>(renderer()) && downcast<RenderEmbeddedObject>(renderer()).allowsAcceleratedCompositing()) {
825 auto* pluginViewBase = downcast<PluginViewBase>(downcast<RenderWidget>(renderer()).widget());
826#if PLATFORM(IOS_FAMILY)
827 if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) {
828 pluginViewBase->detachPluginLayer();
829 pluginViewBase->attachPluginLayer();
830 }
831#else
832 if (!pluginViewBase->shouldNotAddLayer())
833 m_graphicsLayer->setContentsToPlatformLayer(pluginViewBase->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Plugin);
834#endif
835 }
836#if ENABLE(VIDEO)
837 else if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo()) {
838 auto* mediaElement = downcast<HTMLMediaElement>(renderer().element());
839 m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Media);
840 // Requires layout.
841 resetContentsRect();
842 }
843#endif
844#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
845 else if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
846 const HTMLCanvasElement* canvas = downcast<HTMLCanvasElement>(renderer().element());
847 if (auto* context = canvas->renderingContext())
848 m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Canvas);
849
850 layerConfigChanged = true;
851 }
852#endif
853 if (is<RenderWidget>(renderer()) && compositor.parentFrameContentLayers(downcast<RenderWidget>(renderer()))) {
854 m_owningLayer.setNeedsCompositingGeometryUpdate();
855 layerConfigChanged = true;
856 }
857
858 if (is<RenderImage>(renderer()) && downcast<RenderImage>(renderer()).isEditableImage()) {
859 auto element = renderer().element();
860 if (is<HTMLImageElement>(element)) {
861 m_graphicsLayer->setContentsToEmbeddedView(GraphicsLayer::ContentsLayerEmbeddedViewType::EditableImage, downcast<HTMLImageElement>(element)->editableImageViewID());
862 layerConfigChanged = true;
863 }
864 }
865
866 return layerConfigChanged;
867}
868
869static LayoutRect clipBox(RenderBox& renderer)
870{
871 LayoutRect result = LayoutRect::infiniteRect();
872 if (renderer.hasOverflowClip())
873 result = renderer.overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
874
875 if (renderer.hasClip())
876 result.intersect(renderer.clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
877
878 return result;
879}
880
881static bool subpixelOffsetFromRendererChanged(const LayoutSize& oldSubpixelOffsetFromRenderer, const LayoutSize& newSubpixelOffsetFromRenderer, float deviceScaleFactor)
882{
883 FloatSize previous = snapSizeToDevicePixel(oldSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor);
884 FloatSize current = snapSizeToDevicePixel(newSubpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor);
885 return previous != current;
886}
887
888static FloatSize subpixelForLayerPainting(const LayoutPoint& point, float pixelSnappingFactor)
889{
890 LayoutUnit x = point.x();
891 LayoutUnit y = point.y();
892 x = x >= 0 ? floorToDevicePixel(x, pixelSnappingFactor) : ceilToDevicePixel(x, pixelSnappingFactor);
893 y = y >= 0 ? floorToDevicePixel(y, pixelSnappingFactor) : ceilToDevicePixel(y, pixelSnappingFactor);
894 return point - LayoutPoint(x, y);
895}
896
897struct OffsetFromRenderer {
898 // 1.2px - > { m_devicePixelOffset = 1px m_subpixelOffset = 0.2px }
899 LayoutSize m_devicePixelOffset;
900 LayoutSize m_subpixelOffset;
901};
902
903static OffsetFromRenderer computeOffsetFromRenderer(const LayoutSize& offset, float deviceScaleFactor)
904{
905 OffsetFromRenderer offsetFromRenderer;
906 offsetFromRenderer.m_subpixelOffset = LayoutSize(subpixelForLayerPainting(toLayoutPoint(offset), deviceScaleFactor));
907 offsetFromRenderer.m_devicePixelOffset = offset - offsetFromRenderer.m_subpixelOffset;
908 return offsetFromRenderer;
909}
910
911struct SnappedRectInfo {
912 LayoutRect m_snappedRect;
913 LayoutSize m_snapDelta;
914};
915
916static SnappedRectInfo snappedGraphicsLayer(const LayoutSize& offset, const LayoutSize& size, float deviceScaleFactor)
917{
918 SnappedRectInfo snappedGraphicsLayer;
919 LayoutRect graphicsLayerRect = LayoutRect(toLayoutPoint(offset), size);
920 snappedGraphicsLayer.m_snappedRect = LayoutRect(snapRectToDevicePixels(graphicsLayerRect, deviceScaleFactor));
921 snappedGraphicsLayer.m_snapDelta = snappedGraphicsLayer.m_snappedRect.location() - toLayoutPoint(offset);
922 return snappedGraphicsLayer;
923}
924
925static LayoutSize computeOffsetFromAncestorGraphicsLayer(RenderLayer* compositedAncestor, const LayoutPoint& location, float deviceScaleFactor)
926{
927 if (!compositedAncestor)
928 return toLayoutSize(location);
929
930 // FIXME: This is a workaround until after webkit.org/162634 gets fixed. ancestorSubpixelOffsetFromRenderer
931 // could be stale when a dynamic composited state change triggers a pre-order updateGeometry() traversal.
932 LayoutSize ancestorSubpixelOffsetFromRenderer = compositedAncestor->backing()->subpixelOffsetFromRenderer();
933 LayoutRect ancestorCompositedBounds = compositedAncestor->backing()->compositedBounds();
934 LayoutSize floored = toLayoutSize(LayoutPoint(floorPointToDevicePixels(ancestorCompositedBounds.location() - ancestorSubpixelOffsetFromRenderer, deviceScaleFactor)));
935 LayoutSize ancestorRendererOffsetFromAncestorGraphicsLayer = -(floored + ancestorSubpixelOffsetFromRenderer);
936 return ancestorRendererOffsetFromAncestorGraphicsLayer + toLayoutSize(location);
937}
938
939class ComputedOffsets {
940public:
941 ComputedOffsets(const RenderLayer& renderLayer, const LayoutRect& localRect, const LayoutRect& parentGraphicsLayerRect, const LayoutRect& primaryGraphicsLayerRect)
942 : m_renderLayer(renderLayer)
943 , m_location(localRect.location())
944 , m_parentGraphicsLayerOffset(toLayoutSize(parentGraphicsLayerRect.location()))
945 , m_primaryGraphicsLayerOffset(toLayoutSize(primaryGraphicsLayerRect.location()))
946 , m_deviceScaleFactor(renderLayer.renderer().document().deviceScaleFactor())
947 {
948 }
949
950 LayoutSize fromParentGraphicsLayer()
951 {
952 if (!m_fromParentGraphicsLayer)
953 m_fromParentGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset;
954 return m_fromParentGraphicsLayer.value();
955 }
956
957 LayoutSize fromPrimaryGraphicsLayer()
958 {
959 if (!m_fromPrimaryGraphicsLayer)
960 m_fromPrimaryGraphicsLayer = fromAncestorGraphicsLayer() - m_parentGraphicsLayerOffset - m_primaryGraphicsLayerOffset;
961 return m_fromPrimaryGraphicsLayer.value();
962 }
963
964private:
965 LayoutSize fromAncestorGraphicsLayer()
966 {
967 if (!m_fromAncestorGraphicsLayer) {
968 auto* compositedAncestor = m_renderLayer.ancestorCompositingLayer();
969 LayoutPoint localPointInAncestorRenderLayerCoords = m_renderLayer.convertToLayerCoords(compositedAncestor, m_location, RenderLayer::AdjustForColumns);
970 m_fromAncestorGraphicsLayer = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, localPointInAncestorRenderLayerCoords, m_deviceScaleFactor);
971 }
972 return m_fromAncestorGraphicsLayer.value();
973 }
974
975 Optional<LayoutSize> m_fromAncestorGraphicsLayer;
976 Optional<LayoutSize> m_fromParentGraphicsLayer;
977 Optional<LayoutSize> m_fromPrimaryGraphicsLayer;
978
979 const RenderLayer& m_renderLayer;
980 // Location is relative to the renderer.
981 const LayoutPoint m_location;
982 const LayoutSize m_parentGraphicsLayerOffset;
983 const LayoutSize m_primaryGraphicsLayerOffset;
984 float m_deviceScaleFactor;
985};
986
987LayoutRect RenderLayerBacking::computePrimaryGraphicsLayerRect(const LayoutRect& parentGraphicsLayerRect) const
988{
989 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, LayoutRect());
990 return LayoutRect(encloseRectToDevicePixels(LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()),
991 deviceScaleFactor()));
992}
993
994// FIXME: See if we need this now that updateGeometry() is always called in post-order traversal.
995LayoutRect RenderLayerBacking::computeParentGraphicsLayerRect(RenderLayer* compositedAncestor, LayoutSize& ancestorClippingLayerOffset) const
996{
997 if (!compositedAncestor || !compositedAncestor->backing())
998 return renderer().view().documentRect();
999
1000 auto* ancestorBackingLayer = compositedAncestor->backing();
1001 LayoutRect parentGraphicsLayerRect;
1002 if (m_owningLayer.isInsideFragmentedFlow()) {
1003 // FIXME: flows/columns need work.
1004 LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds();
1005 ancestorCompositedBounds.setLocation(LayoutPoint());
1006 parentGraphicsLayerRect = ancestorCompositedBounds;
1007 }
1008
1009 if (ancestorBackingLayer->hasClippingLayer()) {
1010 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore position relative to it.
1011 LayoutRect clippingBox = clipBox(downcast<RenderBox>(compositedAncestor->renderer()));
1012 LayoutSize clippingBoxOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, clippingBox.location(), deviceScaleFactor());
1013 parentGraphicsLayerRect = snappedGraphicsLayer(clippingBoxOffset, clippingBox.size(), deviceScaleFactor()).m_snappedRect;
1014 }
1015
1016 if (compositedAncestor->hasCompositedScrollableOverflow()) {
1017 LayoutRect ancestorCompositedBounds = ancestorBackingLayer->compositedBounds();
1018 auto& renderBox = downcast<RenderBox>(compositedAncestor->renderer());
1019 LayoutRect paddingBoxIncludingScrollbar = renderBox.paddingBoxRectIncludingScrollbar();
1020 ScrollOffset scrollOffset = compositedAncestor->scrollOffset();
1021 parentGraphicsLayerRect = LayoutRect((paddingBoxIncludingScrollbar.location() - toLayoutSize(ancestorCompositedBounds.location()) - toLayoutSize(scrollOffset)), paddingBoxIncludingScrollbar.size());
1022 }
1023
1024 if (m_ancestorClippingLayer) {
1025 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
1026 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
1027 // for a compositing layer, rootLayer is the layer itself.
1028 ShouldRespectOverflowClip shouldRespectOverflowClip = compositedAncestor->isolatesCompositedBlending() ? RespectOverflowClip : IgnoreOverflowClip;
1029 RenderLayer::ClipRectsContext clipRectsContext(compositedAncestor, TemporaryClipRects, IgnoreOverlayScrollbarSize, shouldRespectOverflowClip);
1030 LayoutRect parentClipRect = m_owningLayer.backgroundClipRect(clipRectsContext).rect(); // FIXME: Incorrect for CSS regions.
1031 ASSERT(!parentClipRect.isInfinite());
1032 LayoutSize clippingOffset = computeOffsetFromAncestorGraphicsLayer(compositedAncestor, parentClipRect.location(), deviceScaleFactor());
1033 LayoutRect snappedClippingLayerRect = snappedGraphicsLayer(clippingOffset, parentClipRect.size(), deviceScaleFactor()).m_snappedRect;
1034 // The primary layer is then parented in, and positioned relative to this clipping layer.
1035 ancestorClippingLayerOffset = snappedClippingLayerRect.location() - parentGraphicsLayerRect.location();
1036 parentGraphicsLayerRect = snappedClippingLayerRect;
1037 }
1038 return parentGraphicsLayerRect;
1039}
1040
1041void RenderLayerBacking::updateGeometry()
1042{
1043 ASSERT(!m_owningLayer.normalFlowListDirty());
1044 ASSERT(!m_owningLayer.zOrderListsDirty());
1045 ASSERT(!m_owningLayer.descendantDependentFlagsAreDirty());
1046 ASSERT(!renderer().view().needsLayout());
1047
1048 const RenderStyle& style = renderer().style();
1049
1050 bool isRunningAcceleratedTransformAnimation = false;
1051 if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1052 if (auto* timeline = renderer().documentTimeline())
1053 isRunningAcceleratedTransformAnimation = timeline->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform);
1054 } else
1055 isRunningAcceleratedTransformAnimation = renderer().animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyTransform);
1056
1057 updateTransform(style);
1058 updateOpacity(style);
1059 updateFilters(style);
1060#if ENABLE(FILTERS_LEVEL_2)
1061 updateBackdropFilters(style);
1062#endif
1063#if ENABLE(CSS_COMPOSITING)
1064 updateBlendMode(style);
1065#endif
1066
1067 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
1068 bool preserves3D = style.transformStyle3D() == TransformStyle3D::Preserve3D && !renderer().hasReflection();
1069 m_graphicsLayer->setPreserves3D(preserves3D);
1070 m_graphicsLayer->setBackfaceVisibility(style.backfaceVisibility() == BackfaceVisibility::Visible);
1071
1072 auto* compositedAncestor = m_owningLayer.ancestorCompositingLayer();
1073 LayoutSize ancestorClippingLayerOffset;
1074 LayoutRect parentGraphicsLayerRect = computeParentGraphicsLayerRect(compositedAncestor, ancestorClippingLayerOffset);
1075 LayoutRect primaryGraphicsLayerRect = computePrimaryGraphicsLayerRect(parentGraphicsLayerRect);
1076
1077 ComputedOffsets compositedBoundsOffset(m_owningLayer, compositedBounds(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
1078 m_compositedBoundsOffsetFromGraphicsLayer = compositedBoundsOffset.fromPrimaryGraphicsLayer();
1079 m_graphicsLayer->setPosition(primaryGraphicsLayerRect.location());
1080 m_graphicsLayer->setSize(primaryGraphicsLayerRect.size());
1081
1082 auto computeAnimationExtent = [&] () -> Optional<FloatRect> {
1083 LayoutRect animatedBounds;
1084 if (isRunningAcceleratedTransformAnimation && m_owningLayer.getOverlapBoundsIncludingChildrenAccountingForTransformAnimations(animatedBounds, RenderLayer::IncludeCompositedDescendants))
1085 return FloatRect(animatedBounds);
1086 return { };
1087 };
1088 m_graphicsLayer->setAnimationExtent(computeAnimationExtent());
1089
1090 ComputedOffsets rendererOffset(m_owningLayer, LayoutRect(), parentGraphicsLayerRect, primaryGraphicsLayerRect);
1091 if (m_ancestorClippingLayer) {
1092 // Clipping layer is parented in the ancestor layer.
1093 m_ancestorClippingLayer->setPosition(toLayoutPoint(ancestorClippingLayerOffset));
1094 m_ancestorClippingLayer->setSize(parentGraphicsLayerRect.size());
1095 m_ancestorClippingLayer->setOffsetFromRenderer(-rendererOffset.fromParentGraphicsLayer());
1096 }
1097
1098 if (m_contentsContainmentLayer) {
1099 m_contentsContainmentLayer->setPreserves3D(preserves3D);
1100 m_contentsContainmentLayer->setPosition(primaryGraphicsLayerRect.location());
1101 m_graphicsLayer->setPosition(FloatPoint());
1102 // Use the same size as m_graphicsLayer so transforms behave correctly.
1103 m_contentsContainmentLayer->setSize(primaryGraphicsLayerRect.size());
1104 }
1105
1106 // Compute renderer offset from primary graphics layer. Note that primaryGraphicsLayerRect is in parentGraphicsLayer's coordinate system which is not necessarily
1107 // the same as the ancestor graphics layer.
1108 OffsetFromRenderer primaryGraphicsLayerOffsetFromRenderer;
1109 LayoutSize oldSubpixelOffsetFromRenderer = m_subpixelOffsetFromRenderer;
1110 primaryGraphicsLayerOffsetFromRenderer = computeOffsetFromRenderer(-rendererOffset.fromPrimaryGraphicsLayer(), deviceScaleFactor());
1111 m_subpixelOffsetFromRenderer = primaryGraphicsLayerOffsetFromRenderer.m_subpixelOffset;
1112 m_hasSubpixelRounding = !m_subpixelOffsetFromRenderer.isZero() || compositedBounds().size() != primaryGraphicsLayerRect.size();
1113
1114 if (primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset != m_graphicsLayer->offsetFromRenderer()) {
1115 m_graphicsLayer->setOffsetFromRenderer(primaryGraphicsLayerOffsetFromRenderer.m_devicePixelOffset);
1116 positionOverflowControlsLayers();
1117 }
1118
1119 // If we have a layer that clips children, position it.
1120 LayoutRect clippingBox;
1121 if (auto* clipLayer = clippingLayer()) {
1122 // clipLayer is the m_childContainmentLayer.
1123 clippingBox = clipBox(downcast<RenderBox>(renderer()));
1124 // Clipping layer is parented in the primary graphics layer.
1125 LayoutSize clipBoxOffsetFromGraphicsLayer = toLayoutSize(clippingBox.location()) + rendererOffset.fromPrimaryGraphicsLayer();
1126 SnappedRectInfo snappedClippingGraphicsLayer = snappedGraphicsLayer(clipBoxOffsetFromGraphicsLayer, clippingBox.size(), deviceScaleFactor());
1127 clipLayer->setPosition(snappedClippingGraphicsLayer.m_snappedRect.location());
1128 clipLayer->setSize(snappedClippingGraphicsLayer.m_snappedRect.size());
1129 clipLayer->setOffsetFromRenderer(toLayoutSize(clippingBox.location() - snappedClippingGraphicsLayer.m_snapDelta));
1130
1131 if (m_childClippingMaskLayer && !m_scrollContainerLayer) {
1132 m_childClippingMaskLayer->setSize(clipLayer->size());
1133 m_childClippingMaskLayer->setPosition(FloatPoint());
1134 m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer());
1135 }
1136 }
1137
1138 if (m_maskLayer)
1139 updateMaskingLayerGeometry();
1140
1141 if (renderer().hasTransformRelatedProperty()) {
1142 // Update properties that depend on layer dimensions.
1143 FloatPoint3D transformOrigin = computeTransformOriginForPainting(downcast<RenderBox>(renderer()).borderBoxRect());
1144 FloatPoint layerOffset = roundPointToDevicePixels(toLayoutPoint(rendererOffset.fromParentGraphicsLayer()), deviceScaleFactor());
1145 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
1146 FloatPoint3D anchor(
1147 primaryGraphicsLayerRect.width() ? ((layerOffset.x() - primaryGraphicsLayerRect.x()) + transformOrigin.x()) / primaryGraphicsLayerRect.width() : 0.5,
1148 primaryGraphicsLayerRect.height() ? ((layerOffset.y() - primaryGraphicsLayerRect.y())+ transformOrigin.y()) / primaryGraphicsLayerRect.height() : 0.5,
1149 transformOrigin.z());
1150
1151 if (m_contentsContainmentLayer)
1152 m_contentsContainmentLayer->setAnchorPoint(anchor);
1153 else
1154 m_graphicsLayer->setAnchorPoint(anchor);
1155
1156 auto* clipLayer = clippingLayer();
1157 if (style.hasPerspective()) {
1158 TransformationMatrix t = owningLayer().perspectiveTransform();
1159
1160 if (clipLayer) {
1161 clipLayer->setChildrenTransform(t);
1162 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
1163 }
1164 else
1165 m_graphicsLayer->setChildrenTransform(t);
1166 } else {
1167 if (clipLayer)
1168 clipLayer->setChildrenTransform(TransformationMatrix());
1169 else
1170 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
1171 }
1172 } else {
1173 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
1174 if (m_contentsContainmentLayer)
1175 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
1176 }
1177
1178 if (m_foregroundLayer) {
1179 FloatPoint foregroundPosition;
1180 FloatSize foregroundSize = primaryGraphicsLayerRect.size();
1181 FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
1182 if (hasClippingLayer()) {
1183 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
1184 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
1185 foregroundSize = FloatSize(clippingBox.size());
1186 foregroundOffset = toFloatSize(clippingBox.location());
1187 }
1188
1189 m_foregroundLayer->setPosition(foregroundPosition);
1190 m_foregroundLayer->setSize(foregroundSize);
1191 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
1192 }
1193
1194 if (m_backgroundLayer) {
1195 FloatPoint backgroundPosition;
1196 FloatSize backgroundSize = primaryGraphicsLayerRect.size();
1197 if (backgroundLayerPaintsFixedRootBackground()) {
1198 const FrameView& frameView = renderer().view().frameView();
1199 backgroundPosition = frameView.scrollPositionForFixedPosition();
1200 backgroundSize = frameView.layoutSize();
1201 } else {
1202 auto boundingBox = renderer().objectBoundingBox();
1203 backgroundPosition = boundingBox.location();
1204 backgroundSize = boundingBox.size();
1205 }
1206 m_backgroundLayer->setPosition(backgroundPosition);
1207 m_backgroundLayer->setSize(backgroundSize);
1208 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
1209 }
1210
1211 if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
1212 auto* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
1213 reflectionBacking->updateGeometry();
1214
1215 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
1216 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
1217 FloatRect layerBounds = this->compositedBounds();
1218 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
1219 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
1220 }
1221
1222 if (m_scrollContainerLayer) {
1223 ASSERT(m_scrolledContentsLayer);
1224 auto& renderBox = downcast<RenderBox>(renderer());
1225 LayoutRect paddingBoxIncludingScrollbar = renderBox.paddingBoxRectIncludingScrollbar();
1226 LayoutRect parentLayerBounds = clippingLayer() ? clippingBox : compositedBounds();
1227
1228 // FIXME: need to do some pixel snapping here.
1229 m_scrollContainerLayer->setPosition(FloatPoint(paddingBoxIncludingScrollbar.location() - parentLayerBounds.location()));
1230 m_scrollContainerLayer->setSize(roundedIntSize(LayoutSize(renderBox.paddingBoxWidth(), renderBox.paddingBoxHeight())));
1231
1232 ScrollOffset scrollOffset = m_owningLayer.scrollOffset();
1233 updateScrollOffset(scrollOffset);
1234#if PLATFORM(IOS_FAMILY)
1235 m_scrolledContentsLayer->setPosition({ }); // FIXME: necessary?
1236#endif
1237
1238 FloatSize oldScrollingLayerOffset = m_scrollContainerLayer->offsetFromRenderer();
1239 m_scrollContainerLayer->setOffsetFromRenderer(toFloatSize(paddingBoxIncludingScrollbar.location()));
1240
1241 if (m_childClippingMaskLayer) {
1242 m_childClippingMaskLayer->setPosition(m_scrollContainerLayer->position());
1243 m_childClippingMaskLayer->setSize(m_scrollContainerLayer->size());
1244 m_childClippingMaskLayer->setOffsetFromRenderer(toFloatSize(paddingBoxIncludingScrollbar.location()));
1245 }
1246
1247 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollContainerLayer->offsetFromRenderer();
1248
1249 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
1250 if (scrollSize != m_scrolledContentsLayer->size() || paddingBoxOffsetChanged)
1251 m_scrolledContentsLayer->setNeedsDisplay();
1252
1253 m_scrolledContentsLayer->setSize(scrollSize);
1254 m_scrolledContentsLayer->setScrollOffset(scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
1255 m_scrolledContentsLayer->setOffsetFromRenderer(toLayoutSize(paddingBoxIncludingScrollbar.location()), GraphicsLayer::DontSetNeedsDisplay);
1256
1257 if (m_foregroundLayer) {
1258 m_foregroundLayer->setSize(m_scrolledContentsLayer->size());
1259 m_foregroundLayer->setOffsetFromRenderer(m_scrolledContentsLayer->offsetFromRenderer() - toLayoutSize(m_scrolledContentsLayer->scrollOffset()));
1260 }
1261 }
1262
1263 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
1264 LayoutRect ancestorCompositedBounds = compositedAncestor ? compositedAncestor->backing()->compositedBounds() : LayoutRect();
1265 setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compositedAncestor,
1266 LayoutRect(toLayoutPoint(compositedBoundsOffset.fromParentGraphicsLayer()), compositedBounds().size()), ancestorCompositedBounds));
1267#if ENABLE(FILTERS_LEVEL_2)
1268 updateBackdropFiltersGeometry();
1269#endif
1270 updateAfterWidgetResize();
1271
1272 if (subpixelOffsetFromRendererChanged(oldSubpixelOffsetFromRenderer, m_subpixelOffsetFromRenderer, deviceScaleFactor()) && canIssueSetNeedsDisplay())
1273 setContentsNeedDisplay();
1274}
1275
1276void RenderLayerBacking::setLocationOfScrolledContents(ScrollOffset scrollOffset, ScrollingLayerPositionAction setOrSync)
1277{
1278#if PLATFORM(IOS_FAMILY)
1279 if (setOrSync == ScrollingLayerPositionAction::Sync)
1280 m_scrollContainerLayer->syncBoundsOrigin(scrollOffset);
1281 else
1282 m_scrollContainerLayer->setBoundsOrigin(scrollOffset);
1283#else
1284 if (setOrSync == ScrollingLayerPositionAction::Sync)
1285 m_scrolledContentsLayer->syncPosition(-scrollOffset);
1286 else
1287 m_scrolledContentsLayer->setPosition(-scrollOffset);
1288#endif
1289}
1290
1291void RenderLayerBacking::updateScrollOffset(ScrollOffset scrollOffset)
1292{
1293 if (m_owningLayer.currentScrollType() == ScrollType::User) {
1294 // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause jitter.
1295 setLocationOfScrolledContents(scrollOffset, ScrollingLayerPositionAction::Sync);
1296 m_owningLayer.setRequiresScrollPositionReconciliation(true);
1297 } else {
1298 // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
1299 setLocationOfScrolledContents(scrollOffset, ScrollingLayerPositionAction::Set);
1300 m_owningLayer.setRequiresScrollPositionReconciliation(false);
1301 }
1302}
1303
1304void RenderLayerBacking::updateAfterDescendants()
1305{
1306 // FIXME: this potentially duplicates work we did in updateConfiguration().
1307 PaintedContentsInfo contentsInfo(*this);
1308 contentsInfo.setWantsSubpixelAntialiasedTextState(GraphicsLayer::supportsSubpixelAntialiasedLayerText() && FontCascade::isSubpixelAntialiasingAvailable());
1309
1310 if (!m_owningLayer.isRenderViewLayer()) {
1311 bool didUpdateContentsRect = false;
1312 updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
1313 if (!didUpdateContentsRect && m_graphicsLayer->usesContentsLayer())
1314 resetContentsRect();
1315 }
1316
1317 updateDrawsContent(contentsInfo);
1318
1319 if (!m_isMainFrameRenderViewLayer && !m_isFrameLayerWithTiledBacking && !m_requiresBackgroundLayer) {
1320 // For non-root layers, background is always painted by the primary graphics layer.
1321 ASSERT(!m_backgroundLayer);
1322 m_graphicsLayer->setContentsOpaque(!m_hasSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
1323 }
1324
1325 m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositedDescendants());
1326 if (m_scrollContainerLayer) {
1327 m_scrollContainerLayer->setContentsVisible(renderer().style().visibility() == Visibility::Visible);
1328 m_scrollContainerLayer->setUserInteractionEnabled(renderer().style().pointerEvents() != PointerEvents::None);
1329 }
1330}
1331
1332// FIXME: Avoid repaints when clip path changes.
1333void RenderLayerBacking::updateMaskingLayerGeometry()
1334{
1335 m_maskLayer->setSize(m_graphicsLayer->size());
1336 m_maskLayer->setPosition(FloatPoint());
1337 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
1338
1339 if (!m_maskLayer->drawsContent()) {
1340 if (renderer().hasClipPath()) {
1341 ASSERT(renderer().style().clipPath()->type() != ClipPathOperation::Reference);
1342
1343 WindRule windRule;
1344 // FIXME: Use correct reference box for inlines: https://bugs.webkit.org/show_bug.cgi?id=129047
1345 LayoutRect boundingBox = m_owningLayer.boundingBox(&m_owningLayer);
1346 LayoutRect referenceBoxForClippedInline = LayoutRect(snapRectToDevicePixels(boundingBox, deviceScaleFactor()));
1347 LayoutSize offset = LayoutSize(snapSizeToDevicePixel(-m_subpixelOffsetFromRenderer, LayoutPoint(), deviceScaleFactor()));
1348 Path clipPath = m_owningLayer.computeClipPath(offset, referenceBoxForClippedInline, windRule);
1349
1350 FloatSize pathOffset = m_maskLayer->offsetFromRenderer();
1351 if (!pathOffset.isZero())
1352 clipPath.translate(-pathOffset);
1353
1354 m_maskLayer->setShapeLayerPath(clipPath);
1355 m_maskLayer->setShapeLayerWindRule(windRule);
1356 }
1357 }
1358}
1359
1360void RenderLayerBacking::updateDirectlyCompositedBoxDecorations(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
1361{
1362 if (!m_owningLayer.hasVisibleContent())
1363 return;
1364
1365 // The order of operations here matters, since the last valid type of contents needs
1366 // to also update the contentsRect.
1367 updateDirectlyCompositedBackgroundColor(contentsInfo, didUpdateContentsRect);
1368 updateDirectlyCompositedBackgroundImage(contentsInfo, didUpdateContentsRect);
1369}
1370
1371void RenderLayerBacking::updateInternalHierarchy()
1372{
1373 // m_foregroundLayer has to be inserted in the correct order with child layers,
1374 // so it's not inserted here.
1375 if (m_ancestorClippingLayer)
1376 m_ancestorClippingLayer->removeAllChildren();
1377
1378 if (m_contentsContainmentLayer) {
1379 m_contentsContainmentLayer->removeAllChildren();
1380 if (m_ancestorClippingLayer)
1381 m_ancestorClippingLayer->addChild(*m_contentsContainmentLayer);
1382 }
1383
1384 if (m_backgroundLayer)
1385 m_contentsContainmentLayer->addChild(*m_backgroundLayer);
1386
1387 if (m_contentsContainmentLayer)
1388 m_contentsContainmentLayer->addChild(*m_graphicsLayer);
1389 else if (m_ancestorClippingLayer)
1390 m_ancestorClippingLayer->addChild(*m_graphicsLayer);
1391
1392 if (m_childContainmentLayer)
1393 m_graphicsLayer->addChild(*m_childContainmentLayer);
1394
1395 if (m_scrollContainerLayer) {
1396 auto* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
1397 superlayer->addChild(*m_scrollContainerLayer);
1398 }
1399
1400 // The clip for child layers does not include space for overflow controls, so they exist as
1401 // siblings of the clipping layer if we have one. Normal children of this layer are set as
1402 // children of the clipping layer.
1403 if (m_layerForHorizontalScrollbar)
1404 m_graphicsLayer->addChild(*m_layerForHorizontalScrollbar);
1405
1406 if (m_layerForVerticalScrollbar)
1407 m_graphicsLayer->addChild(*m_layerForVerticalScrollbar);
1408
1409 if (m_layerForScrollCorner)
1410 m_graphicsLayer->addChild(*m_layerForScrollCorner);
1411}
1412
1413void RenderLayerBacking::resetContentsRect()
1414{
1415 m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
1416
1417 if (is<RenderBox>(renderer())) {
1418 LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
1419 boxRect.move(contentOffsetInCompositingLayer());
1420 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
1421 m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
1422 }
1423
1424 m_graphicsLayer->setContentsTileSize(IntSize());
1425 m_graphicsLayer->setContentsTilePhase(IntSize());
1426}
1427
1428void RenderLayerBacking::updateDrawsContent()
1429{
1430 PaintedContentsInfo contentsInfo(*this);
1431 contentsInfo.setWantsSubpixelAntialiasedTextState(GraphicsLayer::supportsSubpixelAntialiasedLayerText());
1432
1433 updateDrawsContent(contentsInfo);
1434}
1435
1436void RenderLayerBacking::updateDrawsContent(PaintedContentsInfo& contentsInfo)
1437{
1438 if (m_scrollContainerLayer) {
1439 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1440 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1441 // m_scrollContainerLayer never has backing store.
1442 // m_scrolledContentsLayer only needs backing store if the scrolled contents need to paint.
1443 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasVisibleBoxDecorationsOrBackground();
1444 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1445
1446 bool hasScrollingPaintedContent = hasBackingSharingLayers() || (m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || contentsInfo.paintsContent()));
1447 m_scrolledContentsLayer->setDrawsContent(hasScrollingPaintedContent);
1448 return;
1449 }
1450
1451 bool hasPaintedContent = containsPaintedContent(contentsInfo);
1452
1453 m_paintsSubpixelAntialiasedText = renderer().settings().subpixelAntialiasedLayerTextEnabled() && contentsInfo.paintsSubpixelAntialiasedText();
1454
1455 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
1456 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1457 if (m_foregroundLayer) {
1458 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1459 m_foregroundLayer->setSupportsSubpixelAntialiasedText(m_paintsSubpixelAntialiasedText);
1460 // The text content is painted into the foreground layer.
1461 // FIXME: this ignores SVG background images which may contain text.
1462 m_graphicsLayer->setSupportsSubpixelAntialiasedText(false);
1463 } else
1464 m_graphicsLayer->setSupportsSubpixelAntialiasedText(m_paintsSubpixelAntialiasedText);
1465
1466 if (m_backgroundLayer)
1467 m_backgroundLayer->setDrawsContent(m_backgroundLayerPaintsFixedRootBackground ? hasPaintedContent : contentsInfo.paintsBoxDecorations());
1468}
1469
1470void RenderLayerBacking::updateEventRegion()
1471{
1472#if PLATFORM(IOS_FAMILY)
1473 if (paintsIntoCompositedAncestor())
1474 return;
1475
1476 bool hasTouchActionElements = false;
1477#if ENABLE(POINTER_EVENTS)
1478 hasTouchActionElements = !!renderer().document().touchActionElements();
1479#endif
1480 if (m_owningLayer.isRenderViewLayer() && !hasTouchActionElements)
1481 return;
1482
1483 GraphicsContext nullContext(nullptr);
1484 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, compositedBounds(), { }, LayoutSize());
1485
1486 EventRegion eventRegion;
1487 auto eventRegionContext = eventRegion.makeContext();
1488 paintingInfo.eventRegionContext = &eventRegionContext;
1489
1490 auto paintFlags = RenderLayer::paintLayerPaintingCompositingAllPhasesFlags() | RenderLayer::PaintLayerCollectingEventRegion;
1491 m_owningLayer.paintLayerContents(nullContext, paintingInfo, paintFlags);
1492
1493 for (auto& layer : m_backingSharingLayers)
1494 layer->paintLayerWithEffects(nullContext, paintingInfo, paintFlags);
1495
1496 auto contentOffset = roundedIntSize(contentOffsetInCompositingLayer());
1497 eventRegion.translate(contentOffset);
1498 m_graphicsLayer->setEventRegion(WTFMove(eventRegion));
1499
1500#endif
1501}
1502
1503// Return true if the layer changed.
1504bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip)
1505{
1506 bool layersChanged = false;
1507
1508 if (needsAncestorClip) {
1509 if (!m_ancestorClippingLayer) {
1510 m_ancestorClippingLayer = createGraphicsLayer("ancestor clipping");
1511 m_ancestorClippingLayer->setMasksToBounds(true);
1512 layersChanged = true;
1513 }
1514 } else if (hasAncestorClippingLayer()) {
1515 willDestroyLayer(m_ancestorClippingLayer.get());
1516 GraphicsLayer::unparentAndClear(m_ancestorClippingLayer);
1517 layersChanged = true;
1518 }
1519
1520 return layersChanged;
1521}
1522
1523// Return true if the layer changed.
1524bool RenderLayerBacking::updateDescendantClippingLayer(bool needsDescendantClip)
1525{
1526 bool layersChanged = false;
1527
1528 if (needsDescendantClip) {
1529 if (!m_childContainmentLayer && !m_isFrameLayerWithTiledBacking) {
1530 m_childContainmentLayer = createGraphicsLayer("child clipping");
1531 m_childContainmentLayer->setMasksToBounds(true);
1532 layersChanged = true;
1533 }
1534 } else if (hasClippingLayer()) {
1535 willDestroyLayer(m_childContainmentLayer.get());
1536 GraphicsLayer::unparentAndClear(m_childContainmentLayer);
1537 layersChanged = true;
1538 }
1539
1540 return layersChanged;
1541}
1542
1543void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1544{
1545 if (backgroundLayerPaintsFixedRootBackground == m_backgroundLayerPaintsFixedRootBackground)
1546 return;
1547
1548 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1549
1550 if (m_backgroundLayerPaintsFixedRootBackground) {
1551 ASSERT(m_isFrameLayerWithTiledBacking);
1552 renderer().view().frameView().removeSlowRepaintObject(*renderer().view().rendererForRootBackground());
1553 }
1554}
1555
1556void RenderLayerBacking::setRequiresBackgroundLayer(bool requiresBackgroundLayer)
1557{
1558 if (requiresBackgroundLayer == m_requiresBackgroundLayer)
1559 return;
1560
1561 m_requiresBackgroundLayer = requiresBackgroundLayer;
1562 m_owningLayer.setNeedsCompositingConfigurationUpdate();
1563}
1564
1565bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
1566{
1567 if (!m_owningLayer.hasOverlayScrollbars())
1568 return false;
1569 return m_owningLayer.horizontalScrollbar();
1570}
1571
1572bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
1573{
1574 if (!m_owningLayer.hasOverlayScrollbars())
1575 return false;
1576 return m_owningLayer.verticalScrollbar();
1577}
1578
1579bool RenderLayerBacking::requiresScrollCornerLayer() const
1580{
1581 if (!m_owningLayer.hasOverlayScrollbars())
1582 return false;
1583 return !m_owningLayer.scrollCornerAndResizerRect().isEmpty();
1584}
1585
1586bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1587{
1588 bool horizontalScrollbarLayerChanged = false;
1589 if (needsHorizontalScrollbarLayer) {
1590 if (!m_layerForHorizontalScrollbar) {
1591 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
1592 m_layerForHorizontalScrollbar->setCanDetachBackingStore(false);
1593 horizontalScrollbarLayerChanged = true;
1594 }
1595 } else if (m_layerForHorizontalScrollbar) {
1596 willDestroyLayer(m_layerForHorizontalScrollbar.get());
1597 GraphicsLayer::unparentAndClear(m_layerForHorizontalScrollbar);
1598 horizontalScrollbarLayerChanged = true;
1599 }
1600
1601 bool verticalScrollbarLayerChanged = false;
1602 if (needsVerticalScrollbarLayer) {
1603 if (!m_layerForVerticalScrollbar) {
1604 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
1605 m_layerForVerticalScrollbar->setCanDetachBackingStore(false);
1606 verticalScrollbarLayerChanged = true;
1607 }
1608 } else if (m_layerForVerticalScrollbar) {
1609 willDestroyLayer(m_layerForVerticalScrollbar.get());
1610 GraphicsLayer::unparentAndClear(m_layerForVerticalScrollbar);
1611 verticalScrollbarLayerChanged = true;
1612 }
1613
1614 bool scrollCornerLayerChanged = false;
1615 if (needsScrollCornerLayer) {
1616 if (!m_layerForScrollCorner) {
1617 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
1618 m_layerForScrollCorner->setCanDetachBackingStore(false);
1619 scrollCornerLayerChanged = true;
1620 }
1621 } else if (m_layerForScrollCorner) {
1622 willDestroyLayer(m_layerForScrollCorner.get());
1623 GraphicsLayer::unparentAndClear(m_layerForScrollCorner);
1624 scrollCornerLayerChanged = true;
1625 }
1626
1627 if (auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator()) {
1628 if (horizontalScrollbarLayerChanged)
1629 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar);
1630 if (verticalScrollbarLayerChanged)
1631 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar);
1632 }
1633
1634 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1635}
1636
1637void RenderLayerBacking::positionOverflowControlsLayers()
1638{
1639 if (!m_owningLayer.hasScrollbars())
1640 return;
1641
1642 const IntRect borderBox = snappedIntRect(renderBox()->borderBoxRect());
1643
1644 FloatSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
1645 if (auto* layer = layerForHorizontalScrollbar()) {
1646 IntRect hBarRect = m_owningLayer.rectForHorizontalScrollbar(borderBox);
1647 layer->setPosition(hBarRect.location() - offsetFromRenderer);
1648 layer->setSize(hBarRect.size());
1649 if (layer->usesContentsLayer()) {
1650 IntRect barRect = IntRect(IntPoint(), hBarRect.size());
1651 layer->setContentsRect(barRect);
1652 layer->setContentsClippingRect(FloatRoundedRect(barRect));
1653 }
1654 layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->usesContentsLayer());
1655 }
1656
1657 if (auto* layer = layerForVerticalScrollbar()) {
1658 IntRect vBarRect = m_owningLayer.rectForVerticalScrollbar(borderBox);
1659 layer->setPosition(vBarRect.location() - offsetFromRenderer);
1660 layer->setSize(vBarRect.size());
1661 if (layer->usesContentsLayer()) {
1662 IntRect barRect = IntRect(IntPoint(), vBarRect.size());
1663 layer->setContentsRect(barRect);
1664 layer->setContentsClippingRect(FloatRoundedRect(barRect));
1665 }
1666 layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->usesContentsLayer());
1667 }
1668
1669 if (auto* layer = layerForScrollCorner()) {
1670 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
1671 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1672 layer->setSize(scrollCornerAndResizer.size());
1673 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1674 }
1675}
1676
1677bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
1678{
1679 bool layerChanged = false;
1680 if (needsForegroundLayer) {
1681 if (!m_foregroundLayer) {
1682 String layerName = m_owningLayer.name() + " (foreground)";
1683 m_foregroundLayer = createGraphicsLayer(layerName);
1684 m_foregroundLayer->setDrawsContent(true);
1685 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1686 layerChanged = true;
1687 }
1688 } else if (m_foregroundLayer) {
1689 willDestroyLayer(m_foregroundLayer.get());
1690 GraphicsLayer::unparentAndClear(m_foregroundLayer);
1691 layerChanged = true;
1692 }
1693
1694 if (layerChanged) {
1695 m_graphicsLayer->setNeedsDisplay();
1696 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1697 }
1698
1699 return layerChanged;
1700}
1701
1702bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
1703{
1704 bool layerChanged = false;
1705 if (needsBackgroundLayer) {
1706 if (!m_backgroundLayer) {
1707 String layerName = m_owningLayer.name() + " (background)";
1708 m_backgroundLayer = createGraphicsLayer(layerName);
1709 m_backgroundLayer->setDrawsContent(true);
1710 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1711 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1712 layerChanged = true;
1713 }
1714
1715 if (!m_contentsContainmentLayer) {
1716 String layerName = m_owningLayer.name() + " (contents containment)";
1717 m_contentsContainmentLayer = createGraphicsLayer(layerName);
1718 m_contentsContainmentLayer->setAppliesPageScale(true);
1719 m_graphicsLayer->setAppliesPageScale(false);
1720 layerChanged = true;
1721 }
1722 } else {
1723 if (m_backgroundLayer) {
1724 willDestroyLayer(m_backgroundLayer.get());
1725 GraphicsLayer::unparentAndClear(m_backgroundLayer);
1726 layerChanged = true;
1727 }
1728 if (m_contentsContainmentLayer) {
1729 willDestroyLayer(m_contentsContainmentLayer.get());
1730 GraphicsLayer::unparentAndClear(m_contentsContainmentLayer);
1731 layerChanged = true;
1732 m_graphicsLayer->setAppliesPageScale(true);
1733 }
1734 }
1735
1736 if (layerChanged)
1737 m_graphicsLayer->setNeedsDisplay();
1738
1739 return layerChanged;
1740}
1741
1742// Masking layer is used for masks or clip-path.
1743void RenderLayerBacking::updateMaskingLayer(bool hasMask, bool hasClipPath)
1744{
1745 bool layerChanged = false;
1746 if (hasMask || hasClipPath) {
1747 GraphicsLayerPaintingPhase maskPhases = 0;
1748 if (hasMask)
1749 maskPhases = GraphicsLayerPaintMask;
1750
1751 if (hasClipPath) {
1752 // If we have a mask, we need to paint the combined clip-path and mask into the mask layer.
1753 if (hasMask || renderer().style().clipPath()->type() == ClipPathOperation::Reference || !GraphicsLayer::supportsLayerType(GraphicsLayer::Type::Shape))
1754 maskPhases |= GraphicsLayerPaintClipPath;
1755 }
1756
1757 bool paintsContent = maskPhases;
1758 GraphicsLayer::Type requiredLayerType = paintsContent ? GraphicsLayer::Type::Normal : GraphicsLayer::Type::Shape;
1759 if (m_maskLayer && m_maskLayer->type() != requiredLayerType) {
1760 m_graphicsLayer->setMaskLayer(nullptr);
1761 willDestroyLayer(m_maskLayer.get());
1762 GraphicsLayer::clear(m_maskLayer);
1763 }
1764
1765 if (!m_maskLayer) {
1766 m_maskLayer = createGraphicsLayer("mask", requiredLayerType);
1767 m_maskLayer->setDrawsContent(paintsContent);
1768 m_maskLayer->setPaintingPhase(maskPhases);
1769 layerChanged = true;
1770 m_graphicsLayer->setMaskLayer(m_maskLayer.copyRef());
1771 // We need a geometry update to size the new mask layer.
1772 m_owningLayer.setNeedsCompositingGeometryUpdate();
1773 }
1774 } else if (m_maskLayer) {
1775 m_graphicsLayer->setMaskLayer(nullptr);
1776 willDestroyLayer(m_maskLayer.get());
1777 GraphicsLayer::clear(m_maskLayer);
1778 layerChanged = true;
1779 }
1780
1781 if (layerChanged)
1782 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1783}
1784
1785void RenderLayerBacking::updateChildClippingStrategy(bool needsDescendantsClippingLayer)
1786{
1787 if (hasClippingLayer() && needsDescendantsClippingLayer) {
1788 if (is<RenderBox>(renderer()) && (renderer().style().clipPath() || renderer().style().hasBorderRadius())) {
1789 LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
1790 boxRect.move(contentOffsetInCompositingLayer());
1791 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
1792 if (clippingLayer()->setMasksToBoundsRect(contentsClippingRect)) {
1793 clippingLayer()->setMaskLayer(nullptr);
1794 GraphicsLayer::clear(m_childClippingMaskLayer);
1795 return;
1796 }
1797
1798 if (!m_childClippingMaskLayer) {
1799 m_childClippingMaskLayer = createGraphicsLayer("child clipping mask");
1800 m_childClippingMaskLayer->setDrawsContent(true);
1801 m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
1802 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.copyRef());
1803 }
1804 }
1805 } else {
1806 if (m_childClippingMaskLayer) {
1807 if (hasClippingLayer())
1808 clippingLayer()->setMaskLayer(nullptr);
1809 GraphicsLayer::clear(m_childClippingMaskLayer);
1810 } else
1811 if (hasClippingLayer())
1812 clippingLayer()->setMasksToBoundsRect(FloatRoundedRect(FloatRect(FloatPoint(), clippingLayer()->size())));
1813 }
1814}
1815
1816bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
1817{
1818 if (needsScrollingLayers == !!m_scrollContainerLayer)
1819 return false;
1820
1821 if (!m_scrollContainerLayer) {
1822 // Outer layer which corresponds with the scroll view.
1823 m_scrollContainerLayer = createGraphicsLayer("scroll container", GraphicsLayer::Type::ScrollContainer);
1824 m_scrollContainerLayer->setDrawsContent(false);
1825 m_scrollContainerLayer->setMasksToBounds(true);
1826
1827 // Inner layer which renders the content that scrolls.
1828 m_scrolledContentsLayer = createGraphicsLayer("scrolled contents");
1829 m_scrolledContentsLayer->setDrawsContent(true);
1830 m_scrolledContentsLayer->setAnchorPoint({ });
1831
1832 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1833 if (!m_foregroundLayer)
1834 paintPhase |= GraphicsLayerPaintForeground;
1835 m_scrolledContentsLayer->setPaintingPhase(paintPhase);
1836 m_scrollContainerLayer->addChild(*m_scrolledContentsLayer);
1837 } else {
1838 compositor().willRemoveScrollingLayerWithBacking(m_owningLayer, *this);
1839
1840 willDestroyLayer(m_scrollContainerLayer.get());
1841 willDestroyLayer(m_scrolledContentsLayer.get());
1842
1843 GraphicsLayer::unparentAndClear(m_scrollContainerLayer);
1844 GraphicsLayer::unparentAndClear(m_scrolledContentsLayer);
1845 }
1846
1847 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1848 m_graphicsLayer->setNeedsDisplay(); // Because painting phases changed.
1849
1850 if (m_scrollContainerLayer)
1851 compositor().didAddScrollingLayer(m_owningLayer);
1852
1853 return true;
1854}
1855
1856OptionSet<ScrollCoordinationRole> RenderLayerBacking::coordinatedScrollingRoles() const
1857{
1858 auto& compositor = this->compositor();
1859
1860 OptionSet<ScrollCoordinationRole> coordinationRoles;
1861 if (compositor.isViewportConstrainedFixedOrStickyLayer(m_owningLayer))
1862 coordinationRoles.add(ScrollCoordinationRole::ViewportConstrained);
1863
1864 if (compositor.useCoordinatedScrollingForLayer(m_owningLayer))
1865 coordinationRoles.add(ScrollCoordinationRole::Scrolling);
1866
1867 if (compositor.isLayerForIFrameWithScrollCoordinatedContents(m_owningLayer))
1868 coordinationRoles.add(ScrollCoordinationRole::FrameHosting);
1869
1870 if (compositor.computeCoordinatedPositioningForLayer(m_owningLayer) != ScrollPositioningBehavior::None)
1871 coordinationRoles.add(ScrollCoordinationRole::Positioning);
1872
1873 return coordinationRoles;
1874}
1875
1876void RenderLayerBacking::detachFromScrollingCoordinator(OptionSet<ScrollCoordinationRole> roles)
1877{
1878 if (!m_scrollingNodeID && !m_frameHostingNodeID && !m_viewportConstrainedNodeID && !m_positioningNodeID)
1879 return;
1880
1881 auto* scrollingCoordinator = m_owningLayer.page().scrollingCoordinator();
1882 if (!scrollingCoordinator)
1883 return;
1884
1885 if (roles.contains(ScrollCoordinationRole::Scrolling) && m_scrollingNodeID) {
1886 LOG(Compositing, "Detaching Scrolling node %" PRIu64, m_scrollingNodeID);
1887 scrollingCoordinator->unparentChildrenAndDestroyNode(m_scrollingNodeID);
1888 m_scrollingNodeID = 0;
1889 }
1890
1891 if (roles.contains(ScrollCoordinationRole::FrameHosting) && m_frameHostingNodeID) {
1892 LOG(Compositing, "Detaching FrameHosting node %" PRIu64, m_frameHostingNodeID);
1893 scrollingCoordinator->unparentChildrenAndDestroyNode(m_frameHostingNodeID);
1894 m_frameHostingNodeID = 0;
1895 }
1896
1897 if (roles.contains(ScrollCoordinationRole::ViewportConstrained) && m_viewportConstrainedNodeID) {
1898 LOG(Compositing, "Detaching ViewportConstrained node %" PRIu64, m_viewportConstrainedNodeID);
1899 scrollingCoordinator->unparentChildrenAndDestroyNode(m_viewportConstrainedNodeID);
1900 m_viewportConstrainedNodeID = 0;
1901 }
1902
1903 if (roles.contains(ScrollCoordinationRole::Positioning) && m_positioningNodeID) {
1904 LOG(Compositing, "Detaching Positioned node %" PRIu64, m_positioningNodeID);
1905 scrollingCoordinator->unparentChildrenAndDestroyNode(m_positioningNodeID);
1906 m_positioningNodeID = 0;
1907 }
1908}
1909
1910void RenderLayerBacking::setIsScrollCoordinatedWithViewportConstrainedRole(bool viewportCoordinated)
1911{
1912 m_graphicsLayer->setIsViewportConstrained(viewportCoordinated);
1913}
1914
1915GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
1916{
1917 unsigned phase = 0;
1918 if (!m_backgroundLayer)
1919 phase |= GraphicsLayerPaintBackground;
1920 if (!m_foregroundLayer)
1921 phase |= GraphicsLayerPaintForeground;
1922
1923 if (m_scrolledContentsLayer) {
1924 phase &= ~GraphicsLayerPaintForeground;
1925 phase |= GraphicsLayerPaintCompositedScroll;
1926 }
1927
1928 return static_cast<GraphicsLayerPaintingPhase>(phase);
1929}
1930
1931float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
1932{
1933 float finalOpacity = rendererOpacity;
1934
1935 for (auto* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1936 // We only care about parents that are stacking contexts.
1937 // Recall that opacity creates stacking context.
1938 if (!curr->isCSSStackingContext())
1939 continue;
1940
1941 // If we found a compositing layer, we want to compute opacity
1942 // relative to it. So we can break here.
1943 if (curr->isComposited())
1944 break;
1945
1946 finalOpacity *= curr->renderer().opacity();
1947 }
1948
1949 return finalOpacity;
1950}
1951
1952// FIXME: Code is duplicated in RenderLayer. Also, we should probably not consider filters a box decoration here.
1953static inline bool hasVisibleBoxDecorations(const RenderStyle& style)
1954{
1955 return style.hasVisibleBorder() || style.hasBorderRadius() || style.hasOutline() || style.hasAppearance() || style.boxShadow() || style.hasFilter();
1956}
1957
1958static bool canDirectlyCompositeBackgroundBackgroundImage(const RenderStyle& style)
1959{
1960 if (!GraphicsLayer::supportsContentsTiling())
1961 return false;
1962
1963 auto& fillLayer = style.backgroundLayers();
1964 if (fillLayer.next())
1965 return false;
1966
1967 if (!fillLayer.imagesAreLoaded())
1968 return false;
1969
1970 if (fillLayer.attachment() != FillAttachment::ScrollBackground)
1971 return false;
1972
1973 // FIXME: Allow color+image compositing when it makes sense.
1974 // For now bailing out.
1975 if (style.visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor).isVisible())
1976 return false;
1977
1978 // FIXME: support gradients with isGeneratedImage.
1979 auto* styleImage = fillLayer.image();
1980 if (!styleImage->isCachedImage())
1981 return false;
1982
1983 auto* image = styleImage->cachedImage()->image();
1984 if (!image->isBitmapImage())
1985 return false;
1986
1987 return true;
1988}
1989
1990static bool hasPaintedBoxDecorationsOrBackgroundImage(const RenderStyle& style)
1991{
1992 if (hasVisibleBoxDecorations(style))
1993 return true;
1994
1995 if (!style.hasBackgroundImage())
1996 return false;
1997
1998 return !canDirectlyCompositeBackgroundBackgroundImage(style);
1999}
2000
2001static inline bool hasPerspectiveOrPreserves3D(const RenderStyle& style)
2002{
2003 return style.hasPerspective() || style.preserves3D();
2004}
2005
2006Color RenderLayerBacking::rendererBackgroundColor() const
2007{
2008 RenderElement* backgroundRenderer = nullptr;
2009 if (renderer().isDocumentElementRenderer())
2010 backgroundRenderer = renderer().view().rendererForRootBackground();
2011
2012 if (!backgroundRenderer)
2013 backgroundRenderer = &renderer();
2014
2015 return backgroundRenderer->style().visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);
2016}
2017
2018void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
2019{
2020 if (m_backgroundLayer && !m_backgroundLayerPaintsFixedRootBackground && !contentsInfo.paintsBoxDecorations()) {
2021 m_graphicsLayer->setContentsToSolidColor(Color());
2022 m_backgroundLayer->setContentsToSolidColor(rendererBackgroundColor());
2023
2024 FloatRect contentsRect = backgroundBoxForSimpleContainerPainting();
2025 // NOTE: This is currently only used by RenderFullScreen, which we want to be
2026 // big enough to hide overflow areas of the root.
2027 contentsRect.inflate(contentsRect.size());
2028 m_backgroundLayer->setContentsRect(contentsRect);
2029 m_backgroundLayer->setContentsClippingRect(FloatRoundedRect(contentsRect));
2030 return;
2031 }
2032
2033 if (!contentsInfo.isSimpleContainer() || (is<RenderBox>(renderer()) && !downcast<RenderBox>(renderer()).paintsOwnBackground())) {
2034 m_graphicsLayer->setContentsToSolidColor(Color());
2035 return;
2036 }
2037
2038 Color backgroundColor = rendererBackgroundColor();
2039
2040 // An unset (invalid) color will remove the solid color.
2041 m_graphicsLayer->setContentsToSolidColor(backgroundColor);
2042 FloatRect contentsRect = backgroundBoxForSimpleContainerPainting();
2043 m_graphicsLayer->setContentsRect(contentsRect);
2044 m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(contentsRect));
2045 didUpdateContentsRect = true;
2046}
2047
2048void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(PaintedContentsInfo& contentsInfo, bool& didUpdateContentsRect)
2049{
2050 if (!GraphicsLayer::supportsContentsTiling())
2051 return;
2052
2053 if (contentsInfo.isDirectlyCompositedImage())
2054 return;
2055
2056 auto& style = renderer().style();
2057 if (!contentsInfo.isSimpleContainer() || !style.hasBackgroundImage()) {
2058 m_graphicsLayer->setContentsToImage(0);
2059 return;
2060 }
2061
2062 auto destRect = backgroundBoxForSimpleContainerPainting();
2063 FloatSize phase;
2064 FloatSize tileSize;
2065 // FIXME: Absolute paint location is required here.
2066 downcast<RenderBox>(renderer()).getGeometryForBackgroundImage(&renderer(), LayoutPoint(), destRect, phase, tileSize);
2067
2068 m_graphicsLayer->setContentsTileSize(tileSize);
2069 m_graphicsLayer->setContentsTilePhase(phase);
2070 m_graphicsLayer->setContentsRect(destRect);
2071 m_graphicsLayer->setContentsClippingRect(FloatRoundedRect(destRect));
2072 m_graphicsLayer->setContentsToImage(style.backgroundLayers().image()->cachedImage()->image());
2073
2074 didUpdateContentsRect = true;
2075}
2076
2077void RenderLayerBacking::updateRootLayerConfiguration()
2078{
2079 if (!m_isFrameLayerWithTiledBacking)
2080 return;
2081
2082 Color backgroundColor;
2083 bool viewIsTransparent = compositor().viewHasTransparentBackground(&backgroundColor);
2084
2085 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
2086 if (m_isMainFrameRenderViewLayer) {
2087 m_backgroundLayer->setBackgroundColor(backgroundColor);
2088 m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
2089 }
2090
2091 m_graphicsLayer->setBackgroundColor(Color());
2092 m_graphicsLayer->setContentsOpaque(false);
2093 } else if (m_isMainFrameRenderViewLayer) {
2094 m_graphicsLayer->setBackgroundColor(backgroundColor);
2095 m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
2096 }
2097}
2098
2099static bool supportsDirectlyCompositedBoxDecorations(const RenderLayerModelObject& renderer)
2100{
2101 if (!GraphicsLayer::supportsBackgroundColorContent())
2102 return false;
2103
2104 const RenderStyle& style = renderer.style();
2105 if (renderer.hasClip())
2106 return false;
2107
2108 if (hasPaintedBoxDecorationsOrBackgroundImage(style))
2109 return false;
2110
2111 // FIXME: We can't create a directly composited background if this
2112 // layer will have children that intersect with the background layer.
2113 // A better solution might be to introduce a flattening layer if
2114 // we do direct box decoration composition.
2115 // https://bugs.webkit.org/show_bug.cgi?id=119461
2116 if (hasPerspectiveOrPreserves3D(style))
2117 return false;
2118
2119 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
2120 if (style.backgroundComposite() != CompositeSourceOver)
2121 return false;
2122
2123 return true;
2124}
2125
2126bool RenderLayerBacking::paintsBoxDecorations() const
2127{
2128 if (!m_owningLayer.hasVisibleBoxDecorations())
2129 return false;
2130
2131 return !supportsDirectlyCompositedBoxDecorations(renderer());
2132}
2133
2134bool RenderLayerBacking::paintsContent(RenderLayer::PaintedContentRequest& request) const
2135{
2136 m_owningLayer.updateDescendantDependentFlags();
2137
2138 bool paintsContent = false;
2139
2140 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers(request))
2141 paintsContent = true;
2142
2143 if (request.isSatisfied())
2144 return paintsContent;
2145
2146 if (isPaintDestinationForDescendantLayers(request))
2147 paintsContent = true;
2148
2149 if (request.isSatisfied())
2150 return paintsContent;
2151
2152 if (request.hasPaintedContent == RequestState::Unknown)
2153 request.hasPaintedContent = RequestState::False;
2154
2155 if (request.hasSubpixelAntialiasedText == RequestState::Unknown)
2156 request.hasSubpixelAntialiasedText = RequestState::False;
2157
2158 return paintsContent;
2159}
2160
2161static bool isRestartedPlugin(RenderObject& renderer)
2162{
2163 if (!is<RenderEmbeddedObject>(renderer))
2164 return false;
2165
2166 auto& element = downcast<RenderEmbeddedObject>(renderer).frameOwnerElement();
2167 if (!is<HTMLPlugInElement>(element))
2168 return false;
2169
2170 return downcast<HTMLPlugInElement>(element).isRestartedPlugin();
2171}
2172
2173static bool isCompositedPlugin(RenderObject& renderer)
2174{
2175 return is<RenderEmbeddedObject>(renderer) && downcast<RenderEmbeddedObject>(renderer).allowsAcceleratedCompositing();
2176}
2177
2178// A "simple container layer" is a RenderLayer which has no visible content to render.
2179// It may have no children, or all its children may be themselves composited.
2180// This is a useful optimization, because it allows us to avoid allocating backing store.
2181bool RenderLayerBacking::isSimpleContainerCompositingLayer(PaintedContentsInfo& contentsInfo) const
2182{
2183 if (m_owningLayer.isRenderViewLayer())
2184 return false;
2185
2186 if (hasBackingSharingLayers())
2187 return false;
2188
2189 if (renderer().isRenderReplaced() && (!isCompositedPlugin(renderer()) || isRestartedPlugin(renderer())))
2190 return false;
2191
2192 if (renderer().isTextControl())
2193 return false;
2194
2195 if (contentsInfo.paintsBoxDecorations() || contentsInfo.paintsContent())
2196 return false;
2197
2198 if (renderer().style().backgroundClip() == FillBox::Text)
2199 return false;
2200
2201 if (renderer().isDocumentElementRenderer() && m_owningLayer.isolatesCompositedBlending())
2202 return false;
2203
2204 return true;
2205}
2206
2207// Returning true stops the traversal.
2208enum class LayerTraversal { Continue, Stop };
2209
2210static LayerTraversal traverseVisibleNonCompositedDescendantLayers(RenderLayer& parent, const WTF::Function<LayerTraversal (const RenderLayer&)>& layerFunc)
2211{
2212 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
2213 parent.updateLayerListsIfNeeded();
2214
2215#if !ASSERT_DISABLED
2216 LayerListMutationDetector mutationChecker(parent);
2217#endif
2218
2219 for (auto* childLayer : parent.normalFlowLayers()) {
2220 if (compositedWithOwnBackingStore(*childLayer))
2221 continue;
2222
2223 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2224 return LayerTraversal::Stop;
2225
2226 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2227 return LayerTraversal::Stop;
2228 }
2229
2230 if (parent.isStackingContext() && !parent.hasVisibleDescendant())
2231 return LayerTraversal::Continue;
2232
2233 // Use the m_hasCompositingDescendant bit to optimize?
2234 for (auto* childLayer : parent.negativeZOrderLayers()) {
2235 if (compositedWithOwnBackingStore(*childLayer))
2236 continue;
2237
2238 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2239 return LayerTraversal::Stop;
2240
2241 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2242 return LayerTraversal::Stop;
2243 }
2244
2245 for (auto* childLayer : parent.positiveZOrderLayers()) {
2246 if (compositedWithOwnBackingStore(*childLayer))
2247 continue;
2248
2249 if (layerFunc(*childLayer) == LayerTraversal::Stop)
2250 return LayerTraversal::Stop;
2251
2252 if (traverseVisibleNonCompositedDescendantLayers(*childLayer, layerFunc) == LayerTraversal::Stop)
2253 return LayerTraversal::Stop;
2254 }
2255
2256 return LayerTraversal::Continue;
2257}
2258
2259// Conservative test for having no rendered children.
2260bool RenderLayerBacking::isPaintDestinationForDescendantLayers(RenderLayer::PaintedContentRequest& request) const
2261{
2262 bool hasPaintingDescendant = false;
2263 traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasPaintingDescendant, &request](const RenderLayer& layer) {
2264 hasPaintingDescendant |= layer.isVisuallyNonEmpty(&request);
2265 return (hasPaintingDescendant && request.isSatisfied()) ? LayerTraversal::Stop : LayerTraversal::Continue;
2266 });
2267
2268 return hasPaintingDescendant;
2269}
2270
2271bool RenderLayerBacking::hasVisibleNonCompositedDescendants() const
2272{
2273 bool hasVisibleDescendant = false;
2274 traverseVisibleNonCompositedDescendantLayers(m_owningLayer, [&hasVisibleDescendant](const RenderLayer& layer) {
2275 hasVisibleDescendant |= layer.hasVisibleContent();
2276 return hasVisibleDescendant ? LayerTraversal::Stop : LayerTraversal::Continue;
2277 });
2278
2279 return hasVisibleDescendant;
2280}
2281
2282bool RenderLayerBacking::containsPaintedContent(PaintedContentsInfo& contentsInfo) const
2283{
2284 if (contentsInfo.isSimpleContainer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer.isReflection())
2285 return false;
2286
2287 if (contentsInfo.isDirectlyCompositedImage())
2288 return false;
2289
2290 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
2291 // and set background color on the layer in that case, instead of allocating backing store and painting.
2292#if ENABLE(VIDEO)
2293 if (is<RenderVideo>(renderer()) && downcast<RenderVideo>(renderer()).shouldDisplayVideo())
2294 return m_owningLayer.hasVisibleBoxDecorationsOrBackground() || (!(downcast<RenderVideo>(renderer()).supportsAcceleratedRendering()) && m_requiresOwnBackingStore);
2295#endif
2296
2297#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
2298 if (is<RenderHTMLCanvas>(renderer()) && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents)
2299 return m_owningLayer.hasVisibleBoxDecorationsOrBackground();
2300#endif
2301
2302 return true;
2303}
2304
2305// An image can be directly compositing if it's the sole content of the layer, and has no box decorations
2306// that require painting. Direct compositing saves backing store.
2307bool RenderLayerBacking::isDirectlyCompositedImage() const
2308{
2309 if (!is<RenderImage>(renderer()) || m_owningLayer.hasVisibleBoxDecorationsOrBackground() || m_owningLayer.paintsWithFilters() || renderer().hasClip())
2310 return false;
2311
2312#if ENABLE(VIDEO)
2313 if (is<RenderMedia>(renderer()))
2314 return false;
2315#endif
2316
2317 auto& imageRenderer = downcast<RenderImage>(renderer());
2318 if (auto* cachedImage = imageRenderer.cachedImage()) {
2319 if (!cachedImage->hasImage())
2320 return false;
2321
2322 auto* image = cachedImage->imageForRenderer(&imageRenderer);
2323 if (!is<BitmapImage>(image))
2324 return false;
2325
2326 if (downcast<BitmapImage>(*image).orientationForCurrentFrame() != DefaultImageOrientation)
2327 return false;
2328
2329#if (PLATFORM(GTK) || PLATFORM(WPE))
2330 // GTK and WPE ports don't support rounded rect clipping at TextureMapper level, so they cannot
2331 // directly composite images that have border-radius propery. Draw them as non directly composited
2332 // content instead. See https://bugs.webkit.org/show_bug.cgi?id=174157.
2333 if (imageRenderer.style().hasBorderRadius())
2334 return false;
2335#endif
2336
2337 return m_graphicsLayer->shouldDirectlyCompositeImage(image);
2338 }
2339
2340 return false;
2341}
2342
2343void RenderLayerBacking::contentChanged(ContentChangeType changeType)
2344{
2345 PaintedContentsInfo contentsInfo(*this);
2346 if ((changeType == ImageChanged) && contentsInfo.isDirectlyCompositedImage()) {
2347 updateImageContents(contentsInfo);
2348 return;
2349 }
2350
2351 if ((changeType == BackgroundImageChanged) && canDirectlyCompositeBackgroundBackgroundImage(renderer().style()))
2352 m_owningLayer.setNeedsCompositingConfigurationUpdate();
2353
2354 if ((changeType == MaskImageChanged) && m_maskLayer)
2355 m_owningLayer.setNeedsCompositingConfigurationUpdate();
2356
2357#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
2358 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
2359 m_graphicsLayer->setContentsNeedsDisplay();
2360 return;
2361 }
2362#endif
2363}
2364
2365void RenderLayerBacking::updateImageContents(PaintedContentsInfo& contentsInfo)
2366{
2367 auto& imageRenderer = downcast<RenderImage>(renderer());
2368
2369 auto* cachedImage = imageRenderer.cachedImage();
2370 if (!cachedImage)
2371 return;
2372
2373 auto* image = cachedImage->imageForRenderer(&imageRenderer);
2374 if (!image)
2375 return;
2376
2377 // We have to wait until the image is fully loaded before setting it on the layer.
2378 if (!cachedImage->isLoaded())
2379 return;
2380
2381 // This is a no-op if the layer doesn't have an inner layer for the image.
2382 m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
2383
2384 LayoutRect boxRect(LayoutPoint(), imageRenderer.size());
2385 boxRect.move(contentOffsetInCompositingLayer());
2386 FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
2387 m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
2388
2389 m_graphicsLayer->setContentsToImage(image);
2390
2391 updateDrawsContent(contentsInfo);
2392
2393 // Image animation is "lazy", in that it automatically stops unless someone is drawing
2394 // the image. So we have to kick the animation each time; this has the downside that the
2395 // image will keep animating, even if its layer is not visible.
2396 image->startAnimation();
2397}
2398
2399FloatPoint3D RenderLayerBacking::computeTransformOriginForPainting(const LayoutRect& borderBox) const
2400{
2401 const RenderStyle& style = renderer().style();
2402 float deviceScaleFactor = this->deviceScaleFactor();
2403
2404 FloatPoint3D origin;
2405 origin.setX(roundToDevicePixel(floatValueForLength(style.transformOriginX(), borderBox.width()), deviceScaleFactor));
2406 origin.setY(roundToDevicePixel(floatValueForLength(style.transformOriginY(), borderBox.height()), deviceScaleFactor));
2407 origin.setZ(style.transformOriginZ());
2408
2409 return origin;
2410}
2411
2412// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
2413LayoutSize RenderLayerBacking::contentOffsetInCompositingLayer() const
2414{
2415 return LayoutSize(-m_compositedBounds.x() + m_compositedBoundsOffsetFromGraphicsLayer.width(), -m_compositedBounds.y() + m_compositedBoundsOffsetFromGraphicsLayer.height());
2416}
2417
2418LayoutRect RenderLayerBacking::contentsBox() const
2419{
2420 if (!is<RenderBox>(renderer()))
2421 return LayoutRect();
2422
2423 auto& renderBox = downcast<RenderBox>(renderer());
2424 LayoutRect contentsRect;
2425#if ENABLE(VIDEO)
2426 if (is<RenderVideo>(renderBox))
2427 contentsRect = downcast<RenderVideo>(renderBox).videoBox();
2428 else
2429#endif
2430 if (is<RenderReplaced>(renderBox)) {
2431 RenderReplaced& renderReplaced = downcast<RenderReplaced>(renderBox);
2432 contentsRect = renderReplaced.replacedContentRect();
2433 } else
2434 contentsRect = renderBox.contentBoxRect();
2435
2436 contentsRect.move(contentOffsetInCompositingLayer());
2437 return contentsRect;
2438}
2439
2440static LayoutRect backgroundRectForBox(const RenderBox& box)
2441{
2442 switch (box.style().backgroundClip()) {
2443 case FillBox::Border:
2444 return box.borderBoxRect();
2445 case FillBox::Padding:
2446 return box.paddingBoxRect();
2447 case FillBox::Content:
2448 return box.contentBoxRect();
2449 default:
2450 break;
2451 }
2452
2453 ASSERT_NOT_REACHED();
2454 return LayoutRect();
2455}
2456
2457FloatRect RenderLayerBacking::backgroundBoxForSimpleContainerPainting() const
2458{
2459 if (!is<RenderBox>(renderer()))
2460 return FloatRect();
2461
2462 LayoutRect backgroundBox = backgroundRectForBox(downcast<RenderBox>(renderer()));
2463 backgroundBox.move(contentOffsetInCompositingLayer());
2464 return snapRectToDevicePixels(backgroundBox, deviceScaleFactor());
2465}
2466
2467GraphicsLayer* RenderLayerBacking::parentForSublayers() const
2468{
2469 if (m_scrolledContentsLayer)
2470 return m_scrolledContentsLayer.get();
2471
2472 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
2473}
2474
2475GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
2476{
2477 if (m_ancestorClippingLayer)
2478 return m_ancestorClippingLayer.get();
2479
2480 if (m_contentsContainmentLayer)
2481 return m_contentsContainmentLayer.get();
2482
2483 return m_graphicsLayer.get();
2484}
2485
2486bool RenderLayerBacking::paintsIntoWindow() const
2487{
2488#if USE(COORDINATED_GRAPHICS)
2489 return false;
2490#endif
2491
2492 if (m_isFrameLayerWithTiledBacking)
2493 return false;
2494
2495 if (m_owningLayer.isRenderViewLayer()) {
2496#if PLATFORM(IOS_FAMILY) || USE(COORDINATED_GRAPHICS)
2497 if (compositor().inForcedCompositingMode())
2498 return false;
2499#endif
2500
2501 return compositor().rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
2502 }
2503
2504 return false;
2505}
2506
2507void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
2508{
2509 if (requiresOwnBacking == m_requiresOwnBackingStore)
2510 return;
2511
2512 m_requiresOwnBackingStore = requiresOwnBacking;
2513
2514 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
2515 // cached clip rects, so when it changes we have to clear clip rects on descendants.
2516 m_owningLayer.clearClipRectsIncludingDescendants(PaintingClipRects);
2517 m_owningLayer.computeRepaintRectsIncludingDescendants();
2518
2519 compositor().repaintInCompositedAncestor(m_owningLayer, compositedBounds());
2520}
2521
2522void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer shouldClip)
2523{
2524 ASSERT(!paintsIntoCompositedAncestor());
2525
2526 // Use the repaint as a trigger to re-evaluate direct compositing (which is never used on the root layer).
2527 if (!m_owningLayer.isRenderViewLayer())
2528 m_owningLayer.setNeedsCompositingConfigurationUpdate();
2529
2530 m_owningLayer.invalidateEventRegion();
2531
2532 auto& frameView = renderer().view().frameView();
2533 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2534 frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBoxForPainting());
2535
2536 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2537 // By default, setNeedsDisplay will clip to the size of the GraphicsLayer, which does not include margin tiles.
2538 // So if the TiledBacking has a margin that needs to be invalidated, we need to send in a rect to setNeedsDisplayInRect
2539 // that is large enough to include the margin. TiledBacking::bounds() includes the margin.
2540 auto* tiledBacking = this->tiledBacking();
2541 FloatRect rectToRepaint = tiledBacking ? tiledBacking->bounds() : FloatRect(FloatPoint(0, 0), m_graphicsLayer->size());
2542 m_graphicsLayer->setNeedsDisplayInRect(rectToRepaint, shouldClip);
2543 }
2544
2545 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
2546 m_foregroundLayer->setNeedsDisplay();
2547
2548 if (m_backgroundLayer && m_backgroundLayer->drawsContent())
2549 m_backgroundLayer->setNeedsDisplay();
2550
2551 if (m_maskLayer && m_maskLayer->drawsContent())
2552 m_maskLayer->setNeedsDisplay();
2553
2554 if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent())
2555 m_childClippingMaskLayer->setNeedsDisplay();
2556
2557 if (m_scrolledContentsLayer && m_scrolledContentsLayer->drawsContent())
2558 m_scrolledContentsLayer->setNeedsDisplay();
2559}
2560
2561// r is in the coordinate space of the layer's render object
2562void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, GraphicsLayer::ShouldClipToLayer shouldClip)
2563{
2564 ASSERT(!paintsIntoCompositedAncestor());
2565
2566 // Use the repaint as a trigger to re-evaluate direct compositing (which is never used on the root layer).
2567 if (!m_owningLayer.isRenderViewLayer())
2568 m_owningLayer.setNeedsCompositingConfigurationUpdate();
2569
2570 m_owningLayer.invalidateEventRegion();
2571
2572 FloatRect pixelSnappedRectForPainting = snapRectToDevicePixels(r, deviceScaleFactor());
2573 auto& frameView = renderer().view().frameView();
2574 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2575 frameView.addTrackedRepaintRect(pixelSnappedRectForPainting);
2576
2577 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2578 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2579 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2580 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2581 }
2582
2583 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
2584 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2585 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2586 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2587 }
2588
2589 // FIXME: need to split out repaints for the background.
2590 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
2591 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2592 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2593 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2594 }
2595
2596 if (m_maskLayer && m_maskLayer->drawsContent()) {
2597 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2598 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer() - m_subpixelOffsetFromRenderer);
2599 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2600 }
2601
2602 if (m_childClippingMaskLayer && m_childClippingMaskLayer->drawsContent()) {
2603 FloatRect layerDirtyRect = r;
2604 layerDirtyRect.move(-m_childClippingMaskLayer->offsetFromRenderer());
2605 m_childClippingMaskLayer->setNeedsDisplayInRect(layerDirtyRect);
2606 }
2607
2608 if (m_scrolledContentsLayer && m_scrolledContentsLayer->drawsContent()) {
2609 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2610 layerDirtyRect.move(-m_scrolledContentsLayer->offsetFromRenderer() + toLayoutSize(m_scrolledContentsLayer->scrollOffset()) - m_subpixelOffsetFromRenderer);
2611#if PLATFORM(IOS_FAMILY)
2612 // Account for the fact that RenderLayerBacking::updateGeometry() bakes scrollOffset into offsetFromRenderer on iOS,
2613 // but the repaint rect is computed without taking the scroll position into account (see shouldApplyClipAndScrollPositionForRepaint()).
2614 layerDirtyRect.moveBy(-m_owningLayer.scrollPosition());
2615#endif
2616 m_scrolledContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2617 }
2618}
2619
2620void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext& context,
2621 const IntRect& paintDirtyRect, // In the coords of rootLayer.
2622 OptionSet<PaintBehavior> paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
2623{
2624 if ((paintsIntoWindow() || paintsIntoCompositedAncestor()) && paintingPhase != GraphicsLayerPaintChildClippingMask) {
2625#if !PLATFORM(IOS_FAMILY) && !OS(WINDOWS)
2626 // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy
2627 // when pages are restored from the PageCache.
2628 // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache
2629 ASSERT_NOT_REACHED();
2630#endif
2631 return;
2632 }
2633
2634 OptionSet<RenderLayer::PaintLayerFlag> paintFlags;
2635 if (paintingPhase & GraphicsLayerPaintBackground)
2636 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingBackgroundPhase);
2637 if (paintingPhase & GraphicsLayerPaintForeground)
2638 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingForegroundPhase);
2639 if (paintingPhase & GraphicsLayerPaintMask)
2640 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingMaskPhase);
2641 if (paintingPhase & GraphicsLayerPaintClipPath)
2642 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingClipPathPhase);
2643 if (paintingPhase & GraphicsLayerPaintChildClippingMask)
2644 paintFlags.add(RenderLayer::PaintLayerPaintingChildClippingMaskPhase);
2645 if (paintingPhase & GraphicsLayerPaintOverflowContents)
2646 paintFlags.add(RenderLayer::PaintLayerPaintingOverflowContents);
2647 if (paintingPhase & GraphicsLayerPaintCompositedScroll)
2648 paintFlags.add(RenderLayer::PaintLayerPaintingCompositingScrollingPhase);
2649
2650 if (graphicsLayer == m_backgroundLayer.get() && m_backgroundLayerPaintsFixedRootBackground)
2651 paintFlags.add({ RenderLayer::PaintLayerPaintingRootBackgroundOnly, RenderLayer::PaintLayerPaintingCompositingForegroundPhase }); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
2652 else if (compositor().fixedRootBackgroundLayer())
2653 paintFlags.add(RenderLayer::PaintLayerPaintingSkipRootBackground);
2654
2655#ifndef NDEBUG
2656 RenderElement::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(&renderer());
2657#endif
2658
2659 auto paintOneLayer = [&](RenderLayer& layer, OptionSet<RenderLayer::PaintLayerFlag> paintFlags) {
2660 InspectorInstrumentation::willPaint(layer.renderer());
2661
2662 FrameView::PaintingState paintingState;
2663 if (layer.isRenderViewLayer())
2664 renderer().view().frameView().willPaintContents(context, paintDirtyRect, paintingState);
2665
2666 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, -m_subpixelOffsetFromRenderer);
2667
2668 if (&layer == &m_owningLayer) {
2669 layer.paintLayerContents(context, paintingInfo, paintFlags);
2670
2671 if (layer.containsDirtyOverlayScrollbars())
2672 layer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
2673 } else
2674 layer.paintLayerWithEffects(context, paintingInfo, paintFlags);
2675
2676 if (layer.isRenderViewLayer())
2677 renderer().view().frameView().didPaintContents(context, paintDirtyRect, paintingState);
2678
2679 ASSERT(!m_owningLayer.m_usedTransparency);
2680
2681 InspectorInstrumentation::didPaint(layer.renderer(), paintDirtyRect);
2682 };
2683
2684 paintOneLayer(m_owningLayer, paintFlags);
2685
2686 // FIXME: Need to check m_foregroundLayer, masking etc. webkit.org/b/197565.
2687 GraphicsLayer* destinationForSharingLayers = m_scrolledContentsLayer ? m_scrolledContentsLayer.get() : m_graphicsLayer.get();
2688
2689 if (graphicsLayer == destinationForSharingLayers) {
2690 OptionSet<RenderLayer::PaintLayerFlag> sharingLayerPaintFlags = {
2691 RenderLayer::PaintLayerPaintingCompositingBackgroundPhase,
2692 RenderLayer::PaintLayerPaintingCompositingForegroundPhase };
2693
2694 if (paintingPhase & GraphicsLayerPaintOverflowContents)
2695 sharingLayerPaintFlags.add(RenderLayer::PaintLayerPaintingOverflowContents);
2696
2697 for (auto& layerWeakPtr : m_backingSharingLayers)
2698 paintOneLayer(*layerWeakPtr, sharingLayerPaintFlags);
2699 }
2700
2701 compositor().didPaintBacking(this);
2702}
2703
2704// Up-call from compositing layer drawing callback.
2705void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const FloatRect& clip, GraphicsLayerPaintBehavior layerPaintBehavior)
2706{
2707#ifndef NDEBUG
2708 renderer().page().setIsPainting(true);
2709#endif
2710
2711#if PLATFORM(MAC)
2712 LocalDefaultSystemAppearance localAppearance(renderer().useDarkAppearance());
2713#endif
2714
2715 // The dirtyRect is in the coords of the painting root.
2716 FloatRect adjustedClipRect = clip;
2717 adjustedClipRect.move(m_subpixelOffsetFromRenderer);
2718 IntRect dirtyRect = enclosingIntRect(adjustedClipRect);
2719
2720 if (!graphicsLayer->repaintCount())
2721 layerPaintBehavior |= GraphicsLayerPaintFirstTilePaint;
2722
2723 if (graphicsLayer == m_graphicsLayer.get()
2724 || graphicsLayer == m_foregroundLayer.get()
2725 || graphicsLayer == m_backgroundLayer.get()
2726 || graphicsLayer == m_maskLayer.get()
2727 || graphicsLayer == m_childClippingMaskLayer.get()
2728 || graphicsLayer == m_scrolledContentsLayer.get()) {
2729
2730 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
2731 dirtyRect.intersect(enclosingIntRect(compositedBoundsIncludingMargin()));
2732
2733 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2734 OptionSet<PaintBehavior> behavior = PaintBehavior::Normal;
2735 if (layerPaintBehavior == GraphicsLayerPaintSnapshotting)
2736 behavior.add(PaintBehavior::Snapshotting);
2737
2738 if (layerPaintBehavior == GraphicsLayerPaintFirstTilePaint)
2739 behavior.add(PaintBehavior::TileFirstPaint);
2740
2741 paintIntoLayer(graphicsLayer, context, dirtyRect, behavior, paintingPhase);
2742 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2743 paintScrollbar(m_owningLayer.horizontalScrollbar(), context, dirtyRect);
2744 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2745 paintScrollbar(m_owningLayer.verticalScrollbar(), context, dirtyRect);
2746 } else if (graphicsLayer == layerForScrollCorner()) {
2747 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
2748 GraphicsContextStateSaver stateSaver(context);
2749 context.translate(-scrollCornerAndResizer.location());
2750 LayoutRect transformedClip = LayoutRect(clip);
2751 transformedClip.moveBy(scrollCornerAndResizer.location());
2752 m_owningLayer.paintScrollCorner(context, IntPoint(), snappedIntRect(transformedClip));
2753 m_owningLayer.paintResizer(context, IntPoint(), transformedClip);
2754 }
2755#ifndef NDEBUG
2756 renderer().page().setIsPainting(false);
2757#endif
2758}
2759
2760float RenderLayerBacking::pageScaleFactor() const
2761{
2762 return compositor().pageScaleFactor();
2763}
2764
2765float RenderLayerBacking::zoomedOutPageScaleFactor() const
2766{
2767 return compositor().zoomedOutPageScaleFactor();
2768}
2769
2770float RenderLayerBacking::deviceScaleFactor() const
2771{
2772 return compositor().deviceScaleFactor();
2773}
2774
2775float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer* layer) const
2776{
2777 return compositor().contentsScaleMultiplierForNewTiles(layer);
2778}
2779
2780bool RenderLayerBacking::paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const
2781{
2782 return m_isMainFrameRenderViewLayer;
2783}
2784
2785void RenderLayerBacking::didChangePlatformLayerForLayer(const GraphicsLayer* layer)
2786{
2787 compositor().didChangePlatformLayerForLayer(m_owningLayer, layer);
2788}
2789
2790bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
2791{
2792 auto* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
2793 if (graphicsLayer != transformedLayer)
2794 return false;
2795
2796 if (m_owningLayer.hasTransform()) {
2797 transform = m_owningLayer.currentTransform(RenderStyle::ExcludeTransformOrigin);
2798 return true;
2799 }
2800 return false;
2801}
2802
2803bool RenderLayerBacking::isTrackingRepaints() const
2804{
2805 return static_cast<GraphicsLayerClient&>(compositor()).isTrackingRepaints();
2806}
2807
2808bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer, LayerTreeAsTextBehavior behavior) const
2809{
2810 if (behavior & LayerTreeAsTextDebug)
2811 return false;
2812
2813 // Skip the root tile cache's flattening layer.
2814 return m_isMainFrameRenderViewLayer && layer && layer == m_childContainmentLayer.get();
2815}
2816
2817bool RenderLayerBacking::shouldDumpPropertyForLayer(const GraphicsLayer* layer, const char* propertyName, LayerTreeAsTextBehavior flags) const
2818{
2819 // For backwards compatibility with WebKit1 and other platforms,
2820 // skip some properties on the root tile cache.
2821 if (m_isMainFrameRenderViewLayer && layer == m_graphicsLayer.get() && !(flags & LayerTreeAsTextIncludeRootLayerProperties)) {
2822 if (!strcmp(propertyName, "drawsContent"))
2823 return false;
2824
2825 // Background color could be of interest to tests or other dumpers if it's non-white.
2826 if (!strcmp(propertyName, "backgroundColor") && Color::isWhiteColor(layer->backgroundColor()))
2827 return false;
2828
2829 // The root tile cache's repaints will show up at the top with FrameView's,
2830 // so don't dump them twice.
2831 if (!strcmp(propertyName, "repaintRects"))
2832 return false;
2833 }
2834
2835 return true;
2836}
2837
2838bool RenderLayerBacking::shouldAggressivelyRetainTiles(const GraphicsLayer*) const
2839{
2840 // Only the main frame TileController has enough information about in-window state to
2841 // correctly implement aggressive tile retention.
2842 if (!m_isMainFrameRenderViewLayer)
2843 return false;
2844
2845 return renderer().settings().aggressiveTileRetentionEnabled();
2846}
2847
2848bool RenderLayerBacking::shouldTemporarilyRetainTileCohorts(const GraphicsLayer*) const
2849{
2850 return renderer().settings().temporaryTileCohortRetentionEnabled();
2851}
2852
2853bool RenderLayerBacking::useGiantTiles() const
2854{
2855 return renderer().settings().useGiantTiles();
2856}
2857
2858void RenderLayerBacking::logFilledVisibleFreshTile(unsigned blankPixelCount)
2859{
2860 if (auto* loggingClient = renderer().page().performanceLoggingClient())
2861 loggingClient->logScrollingEvent(PerformanceLoggingClient::ScrollingEvent::FilledTile, MonotonicTime::now(), blankPixelCount);
2862}
2863
2864#ifndef NDEBUG
2865void RenderLayerBacking::verifyNotPainting()
2866{
2867 ASSERT(!renderer().page().isPainting());
2868}
2869#endif
2870
2871bool RenderLayerBacking::startAnimation(double timeOffset, const Animation& animation, const KeyframeList& keyframes)
2872{
2873 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
2874 bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyTransform);
2875 bool hasFilter = keyframes.containsProperty(CSSPropertyFilter);
2876
2877 bool hasBackdropFilter = false;
2878#if ENABLE(FILTERS_LEVEL_2)
2879 hasBackdropFilter = keyframes.containsProperty(CSSPropertyWebkitBackdropFilter);
2880#endif
2881
2882 if (!hasOpacity && !hasTransform && !hasFilter && !hasBackdropFilter)
2883 return false;
2884
2885 KeyframeValueList transformVector(AnimatedPropertyTransform);
2886 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2887 KeyframeValueList filterVector(AnimatedPropertyFilter);
2888#if ENABLE(FILTERS_LEVEL_2)
2889 KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter);
2890#endif
2891
2892 size_t numKeyframes = keyframes.size();
2893 for (size_t i = 0; i < numKeyframes; ++i) {
2894 const KeyframeValue& currentKeyframe = keyframes[i];
2895 const RenderStyle* keyframeStyle = currentKeyframe.style();
2896 double key = currentKeyframe.key();
2897
2898 if (!keyframeStyle)
2899 continue;
2900
2901 auto* tf = currentKeyframe.timingFunction();
2902
2903 bool isFirstOrLastKeyframe = key == 0 || key == 1;
2904 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyTransform))
2905 transformVector.insert(std::make_unique<TransformAnimationValue>(key, keyframeStyle->transform(), tf));
2906
2907 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
2908 opacityVector.insert(std::make_unique<FloatAnimationValue>(key, keyframeStyle->opacity(), tf));
2909
2910 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyFilter))
2911 filterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->filter(), tf));
2912
2913#if ENABLE(FILTERS_LEVEL_2)
2914 if ((hasBackdropFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitBackdropFilter))
2915 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(key, keyframeStyle->backdropFilter(), tf));
2916#endif
2917 }
2918
2919 if (!renderer().settings().acceleratedCompositedAnimationsEnabled())
2920 return false;
2921
2922 bool didAnimate = false;
2923
2924 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), &animation, keyframes.animationName(), timeOffset))
2925 didAnimate = true;
2926
2927 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize { }, &animation, keyframes.animationName(), timeOffset))
2928 didAnimate = true;
2929
2930 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize { }, &animation, keyframes.animationName(), timeOffset))
2931 didAnimate = true;
2932
2933#if ENABLE(FILTERS_LEVEL_2)
2934 if (hasBackdropFilter && m_graphicsLayer->addAnimation(backdropFilterVector, IntSize { }, &animation, keyframes.animationName(), timeOffset))
2935 didAnimate = true;
2936#endif
2937
2938 if (didAnimate)
2939 m_owningLayer.setNeedsPostLayoutCompositingUpdate();
2940
2941 return didAnimate;
2942}
2943
2944void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
2945{
2946 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
2947}
2948
2949void RenderLayerBacking::animationSeeked(double timeOffset, const String& animationName)
2950{
2951 m_graphicsLayer->seekAnimation(animationName, timeOffset);
2952}
2953
2954void RenderLayerBacking::animationFinished(const String& animationName)
2955{
2956 m_graphicsLayer->removeAnimation(animationName);
2957 m_owningLayer.setNeedsPostLayoutCompositingUpdate();
2958}
2959
2960bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
2961{
2962 bool didAnimate = false;
2963
2964 ASSERT(property != CSSPropertyInvalid);
2965
2966 if (property == CSSPropertyOpacity) {
2967 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
2968 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
2969 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2970 opacityVector.insert(std::make_unique<FloatAnimationValue>(0, compositingOpacity(fromStyle->opacity())));
2971 opacityVector.insert(std::make_unique<FloatAnimationValue>(1, compositingOpacity(toStyle->opacity())));
2972 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
2973 if (m_graphicsLayer->addAnimation(opacityVector, FloatSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
2974 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
2975 updateOpacity(*toStyle);
2976 didAnimate = true;
2977 }
2978 }
2979 }
2980
2981 if (property == CSSPropertyTransform && m_owningLayer.hasTransform()) {
2982 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyTransform);
2983 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
2984 KeyframeValueList transformVector(AnimatedPropertyTransform);
2985 transformVector.insert(std::make_unique<TransformAnimationValue>(0, fromStyle->transform()));
2986 transformVector.insert(std::make_unique<TransformAnimationValue>(1, toStyle->transform()));
2987 if (m_graphicsLayer->addAnimation(transformVector, snappedIntRect(renderBox()->borderBoxRect()).size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyTransform), timeOffset)) {
2988 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
2989 updateTransform(*toStyle);
2990 didAnimate = true;
2991 }
2992 }
2993 }
2994
2995 if (property == CSSPropertyFilter && m_owningLayer.hasFilter()) {
2996 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyFilter);
2997 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
2998 KeyframeValueList filterVector(AnimatedPropertyFilter);
2999 filterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->filter()));
3000 filterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->filter()));
3001 if (m_graphicsLayer->addAnimation(filterVector, FloatSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyFilter), timeOffset)) {
3002 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
3003 updateFilters(*toStyle);
3004 didAnimate = true;
3005 }
3006 }
3007 }
3008
3009#if ENABLE(FILTERS_LEVEL_2)
3010 if (property == CSSPropertyWebkitBackdropFilter && m_owningLayer.hasBackdropFilter()) {
3011 const Animation* backdropFilterAnim = toStyle->transitionForProperty(CSSPropertyWebkitBackdropFilter);
3012 if (backdropFilterAnim && !backdropFilterAnim->isEmptyOrZeroDuration()) {
3013 KeyframeValueList backdropFilterVector(AnimatedPropertyWebkitBackdropFilter);
3014 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(0, fromStyle->backdropFilter()));
3015 backdropFilterVector.insert(std::make_unique<FilterAnimationValue>(1, toStyle->backdropFilter()));
3016 if (m_graphicsLayer->addAnimation(backdropFilterVector, FloatSize(), backdropFilterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitBackdropFilter), timeOffset)) {
3017 // To ensure that the correct backdrop filter is visible when the animation ends, also set the final backdrop filter.
3018 updateBackdropFilters(*toStyle);
3019 didAnimate = true;
3020 }
3021 }
3022 }
3023#endif
3024
3025 if (didAnimate)
3026 m_owningLayer.setNeedsPostLayoutCompositingUpdate();
3027
3028 return didAnimate;
3029}
3030
3031void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
3032{
3033 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
3034 if (animatedProperty != AnimatedPropertyInvalid)
3035 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
3036}
3037
3038void RenderLayerBacking::transitionFinished(CSSPropertyID property)
3039{
3040 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
3041 if (animatedProperty != AnimatedPropertyInvalid) {
3042 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
3043 m_owningLayer.setNeedsPostLayoutCompositingUpdate();
3044 }
3045}
3046
3047void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, const String&, MonotonicTime time)
3048{
3049 renderer().animation().notifyAnimationStarted(renderer(), time);
3050}
3051
3052void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer)
3053{
3054 if (renderer().renderTreeBeingDestroyed())
3055 return;
3056 compositor().scheduleLayerFlush(layer->canThrottleLayerFlush());
3057}
3058
3059void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
3060{
3061 compositor().notifyFlushBeforeDisplayRefresh(layer);
3062}
3063
3064// This is used for the 'freeze' API, for testing only.
3065void RenderLayerBacking::suspendAnimations(MonotonicTime time)
3066{
3067 m_graphicsLayer->suspendAnimations(time);
3068}
3069
3070void RenderLayerBacking::resumeAnimations()
3071{
3072 m_graphicsLayer->resumeAnimations();
3073}
3074
3075LayoutRect RenderLayerBacking::compositedBounds() const
3076{
3077 return m_compositedBounds;
3078}
3079
3080bool RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds)
3081{
3082 if (bounds == m_compositedBounds)
3083 return false;
3084
3085 m_compositedBounds = bounds;
3086 return true;
3087}
3088
3089LayoutRect RenderLayerBacking::compositedBoundsIncludingMargin() const
3090{
3091 auto* tiledBacking = this->tiledBacking();
3092 if (!tiledBacking || !tiledBacking->hasMargins())
3093 return compositedBounds();
3094
3095 LayoutRect boundsIncludingMargin = compositedBounds();
3096 LayoutUnit leftMarginWidth = tiledBacking->leftMarginWidth();
3097 LayoutUnit topMarginHeight = tiledBacking->topMarginHeight();
3098
3099 boundsIncludingMargin.moveBy(LayoutPoint(-leftMarginWidth, -topMarginHeight));
3100 boundsIncludingMargin.expand(leftMarginWidth + tiledBacking->rightMarginWidth(), topMarginHeight + tiledBacking->bottomMarginHeight());
3101
3102 return boundsIncludingMargin;
3103}
3104
3105CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
3106{
3107 CSSPropertyID cssProperty = CSSPropertyInvalid;
3108 switch (property) {
3109 case AnimatedPropertyTransform:
3110 cssProperty = CSSPropertyTransform;
3111 break;
3112 case AnimatedPropertyOpacity:
3113 cssProperty = CSSPropertyOpacity;
3114 break;
3115 case AnimatedPropertyBackgroundColor:
3116 cssProperty = CSSPropertyBackgroundColor;
3117 break;
3118 case AnimatedPropertyFilter:
3119 cssProperty = CSSPropertyFilter;
3120 break;
3121#if ENABLE(FILTERS_LEVEL_2)
3122 case AnimatedPropertyWebkitBackdropFilter:
3123 cssProperty = CSSPropertyWebkitBackdropFilter;
3124 break;
3125#endif
3126 case AnimatedPropertyInvalid:
3127 ASSERT_NOT_REACHED();
3128 }
3129 return cssProperty;
3130}
3131
3132AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
3133{
3134 switch (cssProperty) {
3135 case CSSPropertyTransform:
3136 return AnimatedPropertyTransform;
3137 case CSSPropertyOpacity:
3138 return AnimatedPropertyOpacity;
3139 case CSSPropertyBackgroundColor:
3140 return AnimatedPropertyBackgroundColor;
3141 case CSSPropertyFilter:
3142 return AnimatedPropertyFilter;
3143#if ENABLE(FILTERS_LEVEL_2)
3144 case CSSPropertyWebkitBackdropFilter:
3145 return AnimatedPropertyWebkitBackdropFilter;
3146#endif
3147 default:
3148 // It's fine if we see other css properties here; they are just not accelerated.
3149 break;
3150 }
3151 return AnimatedPropertyInvalid;
3152}
3153
3154CompositingLayerType RenderLayerBacking::compositingLayerType() const
3155{
3156 if (m_graphicsLayer->usesContentsLayer())
3157 return MediaCompositingLayer;
3158
3159 if (m_graphicsLayer->drawsContent())
3160 return m_graphicsLayer->tiledBacking() ? TiledCompositingLayer : NormalCompositingLayer;
3161
3162 return ContainerCompositingLayer;
3163}
3164
3165double RenderLayerBacking::backingStoreMemoryEstimate() const
3166{
3167 double backingMemory;
3168
3169 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
3170 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
3171 if (m_foregroundLayer)
3172 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
3173 if (m_backgroundLayer)
3174 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
3175 if (m_maskLayer)
3176 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
3177 if (m_childClippingMaskLayer)
3178 backingMemory += m_childClippingMaskLayer->backingStoreMemoryEstimate();
3179
3180 if (m_scrolledContentsLayer)
3181 backingMemory += m_scrolledContentsLayer->backingStoreMemoryEstimate();
3182
3183 if (m_layerForHorizontalScrollbar)
3184 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
3185
3186 if (m_layerForVerticalScrollbar)
3187 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
3188
3189 if (m_layerForScrollCorner)
3190 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
3191
3192 return backingMemory;
3193}
3194
3195TextStream& operator<<(TextStream& ts, const RenderLayerBacking& backing)
3196{
3197 ts << "RenderLayerBacking " << &backing << " bounds " << backing.compositedBounds();
3198
3199 if (backing.isFrameLayerWithTiledBacking())
3200 ts << " frame layer tiled backing";
3201 if (backing.paintsIntoWindow())
3202 ts << " paintsIntoWindow";
3203 if (backing.paintsIntoCompositedAncestor())
3204 ts << " paintsIntoCompositedAncestor";
3205
3206 ts << " primary layer ID " << backing.graphicsLayer()->primaryLayerID();
3207 if (auto nodeID = backing.scrollingNodeIDForRole(ScrollCoordinationRole::ViewportConstrained))
3208 ts << " viewport constrained scrolling node " << nodeID;
3209 if (auto nodeID = backing.scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling))
3210 ts << " scrolling node " << nodeID;
3211 if (auto nodeID = backing.scrollingNodeIDForRole(ScrollCoordinationRole::FrameHosting))
3212 ts << " frame hosting node " << nodeID;
3213 if (auto nodeID = backing.scrollingNodeIDForRole(ScrollCoordinationRole::Positioning))
3214 ts << " positioning node " << nodeID;
3215 return ts;
3216}
3217
3218} // namespace WebCore
3219