2 * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "RenderLayerBacking.h"
30 #include "AnimationController.h"
31 #include "CanvasRenderingContext.h"
32 #include "CSSPropertyNames.h"
33 #include "CachedImage.h"
35 #include "FontCache.h"
36 #include "FrameView.h"
37 #include "GraphicsContext.h"
38 #include "GraphicsLayer.h"
39 #include "HTMLCanvasElement.h"
40 #include "HTMLIFrameElement.h"
41 #include "HTMLMediaElement.h"
42 #include "HTMLNames.h"
43 #include "HTMLPlugInElement.h"
44 #include "InspectorInstrumentation.h"
45 #include "KeyframeList.h"
46 #include "MainFrame.h"
47 #include "PluginViewBase.h"
48 #include "ProgressTracker.h"
49 #include "RenderFlowThread.h"
50 #include "RenderIFrame.h"
51 #include "RenderImage.h"
52 #include "RenderLayerCompositor.h"
53 #include "RenderEmbeddedObject.h"
54 #include "RenderNamedFlowFragment.h"
55 #include "RenderRegion.h"
56 #include "RenderVideo.h"
57 #include "RenderView.h"
58 #include "ScrollingCoordinator.h"
60 #include "StyleResolver.h"
61 #include "TiledBacking.h"
62 #include <wtf/text/StringBuilder.h>
64 #if ENABLE(CSS_FILTERS)
65 #include "FilterEffectRenderer.h"
68 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
69 #include "GraphicsContext3D.h"
74 using namespace HTMLNames;
76 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
77 static LayoutRect clipBox(RenderBox& renderer);
79 CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject& renderer)
81 ASSERT(renderer.isCanvas());
83 const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer.node());
84 CanvasRenderingContext* context = canvas->renderingContext();
85 if (!context || !context->isAccelerated())
86 return UnacceleratedCanvas;
89 return CanvasAsLayerContents;
91 #if ENABLE(ACCELERATED_2D_CANVAS)
92 return CanvasAsLayerContents;
94 return CanvasPaintedToLayer; // On Mac and iOS we paint accelerated canvases into their layers.
98 // Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor.
99 static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer)
101 Page* page = layer.renderer().frame().page();
105 return page->scrollingCoordinator();
108 bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
110 RenderLayerBacking::RenderLayerBacking(RenderLayer& layer)
111 : m_owningLayer(layer)
112 , m_viewportConstrainedNodeID(0)
113 , m_scrollingNodeID(0)
114 , m_artificiallyInflatedBounds(false)
115 , m_isMainFrameRenderViewLayer(false)
116 , m_usingTiledCacheLayer(false)
117 , m_requiresOwnBackingStore(true)
118 #if ENABLE(CSS_FILTERS)
119 , m_canCompositeFilters(false)
121 , m_backgroundLayerPaintsFixedRootBackground(false)
123 Page* page = renderer().frame().page();
125 if (layer.isRootLayer() && page) {
126 if (renderer().frame().isMainFrame())
127 m_isMainFrameRenderViewLayer = true;
129 m_usingTiledCacheLayer = page->chrome().client().shouldUseTiledBackingForFrameView(renderer().frame().view());
132 createPrimaryGraphicsLayer();
134 if (m_usingTiledCacheLayer && page) {
135 TiledBacking* tiledBacking = this->tiledBacking();
137 tiledBacking->setIsInWindow(page->isInWindow());
139 if (m_isMainFrameRenderViewLayer) {
140 tiledBacking->setExposedRect(renderer().frame().view()->exposedRect());
141 tiledBacking->setUnparentsOffscreenTiles(true);
144 tiledBacking->setScrollingPerformanceLoggingEnabled(page->settings().scrollingPerformanceLoggingEnabled());
145 adjustTiledBackingCoverage();
149 RenderLayerBacking::~RenderLayerBacking()
151 updateAncestorClippingLayer(false);
152 updateDescendantClippingLayer(false);
153 updateOverflowControlsLayers(false, false, false);
154 updateForegroundLayer(false);
155 updateBackgroundLayer(false);
156 updateMaskLayer(false);
157 updateScrollingLayers(false);
158 detachFromScrollingCoordinator();
159 destroyGraphicsLayers();
162 void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
164 if (layer && layer->usingTiledBacking())
165 compositor().layerTiledBackingUsageChanged(layer, false);
168 std::unique_ptr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name)
170 GraphicsLayerFactory* graphicsLayerFactory = 0;
171 if (Page* page = renderer().frame().page())
172 graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
174 std::unique_ptr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
177 graphicsLayer->setName(name);
181 graphicsLayer->setMaintainsPixelAlignment(compositor().keepLayersPixelAligned());
183 #if PLATFORM(COCOA) && USE(CA)
184 graphicsLayer->setAcceleratesDrawing(compositor().acceleratedDrawingEnabled());
187 return graphicsLayer;
190 bool RenderLayerBacking::shouldUseTiledBacking(const GraphicsLayer*) const
192 return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
195 void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
197 compositor().layerTiledBackingUsageChanged(layer, usingTiledBacking);
200 TiledBacking* RenderLayerBacking::tiledBacking() const
202 return m_graphicsLayer->tiledBacking();
205 static TiledBacking::TileCoverage computeTileCoverage(RenderLayerBacking* backing)
207 // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
208 FrameView& frameView = backing->owningLayer().renderer().view().frameView();
210 TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
211 bool useMinimalTilesDuringLiveResize = frameView.inLiveResize();
212 if (frameView.speculativeTilingEnabled() && !useMinimalTilesDuringLiveResize) {
213 bool clipsToExposedRect = !frameView.exposedRect().isInfinite();
214 if (frameView.horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
215 tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
217 if (frameView.verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
218 tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
223 void RenderLayerBacking::adjustTiledBackingCoverage()
225 if (!m_usingTiledCacheLayer)
228 TiledBacking::TileCoverage tileCoverage = computeTileCoverage(this);
229 tiledBacking()->setTileCoverage(tileCoverage);
232 void RenderLayerBacking::setTiledBackingHasMargins(bool hasExtendedBackgroundRect)
234 if (!m_usingTiledCacheLayer)
237 int marginLeftAndRightSize = hasExtendedBackgroundRect ? defaultTileWidth : 0;
238 int marginTopAndBottomSize = hasExtendedBackgroundRect ? defaultTileHeight : 0;
239 tiledBacking()->setTileMargins(marginTopAndBottomSize, marginTopAndBottomSize, marginLeftAndRightSize, marginLeftAndRightSize);
242 void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter)
244 m_graphicsLayer->setShowDebugBorder(showBorder);
245 m_graphicsLayer->setShowRepaintCounter(showRepaintCounter);
247 if (m_ancestorClippingLayer)
248 m_ancestorClippingLayer->setShowDebugBorder(showBorder);
250 if (m_foregroundLayer) {
251 m_foregroundLayer->setShowDebugBorder(showBorder);
252 m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
255 if (m_contentsContainmentLayer)
256 m_contentsContainmentLayer->setShowDebugBorder(showBorder);
258 if (m_backgroundLayer) {
259 m_backgroundLayer->setShowDebugBorder(showBorder);
260 m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
264 m_maskLayer->setShowDebugBorder(showBorder);
265 m_maskLayer->setShowRepaintCounter(showRepaintCounter);
268 if (m_layerForHorizontalScrollbar)
269 m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
271 if (m_layerForVerticalScrollbar)
272 m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
274 if (m_layerForScrollCorner)
275 m_layerForScrollCorner->setShowDebugBorder(showBorder);
277 if (m_scrollingLayer)
278 m_scrollingLayer->setShowDebugBorder(showBorder);
280 if (m_scrollingContentsLayer) {
281 m_scrollingContentsLayer->setShowDebugBorder(showBorder);
282 m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter);
286 void RenderLayerBacking::createPrimaryGraphicsLayer()
290 layerName = m_owningLayer.name();
293 // The call to createGraphicsLayer ends calling back into here as
294 // a GraphicsLayerClient to ask if it shouldUseTiledBacking(). We only want
295 // the tile cache on our main layer. This is pretty ugly, but saves us from
296 // exposing the API to all clients.
298 m_creatingPrimaryGraphicsLayer = true;
299 m_graphicsLayer = createGraphicsLayer(layerName);
300 m_creatingPrimaryGraphicsLayer = false;
302 if (m_usingTiledCacheLayer) {
303 m_childContainmentLayer = createGraphicsLayer("TiledBacking Flattening Layer");
304 m_graphicsLayer->addChild(m_childContainmentLayer.get());
307 #if !PLATFORM(IOS) && !PLATFORM(EFL)
308 if (m_isMainFrameRenderViewLayer) {
309 // Page scale is applied above the RenderView on iOS.
310 m_graphicsLayer->setContentsOpaque(true);
311 m_graphicsLayer->setAppliesPageScale();
315 #if PLATFORM(COCOA) && USE(CA)
316 if (!compositor().acceleratedDrawingEnabled() && renderer().isCanvas()) {
317 const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer().element());
318 if (canvas->shouldAccelerate(canvas->size()))
319 m_graphicsLayer->setAcceleratesDrawing(true);
323 updateOpacity(&renderer().style());
324 updateTransform(&renderer().style());
325 #if ENABLE(CSS_FILTERS)
326 updateFilters(&renderer().style());
328 #if ENABLE(CSS_COMPOSITING)
329 updateBlendMode(&renderer().style());
334 void RenderLayerBacking::layerWillBeDestroyed()
336 RenderObject& renderer = this->renderer();
337 if (renderer.isEmbeddedObject() && toRenderEmbeddedObject(renderer).allowsAcceleratedCompositing()) {
338 PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(renderer).widget());
339 if (pluginViewBase && m_graphicsLayer->contentsLayerForMedia())
340 pluginViewBase->detachPluginLayer();
345 void RenderLayerBacking::destroyGraphicsLayers()
347 if (m_graphicsLayer) {
348 willDestroyLayer(m_graphicsLayer.get());
349 m_graphicsLayer->removeFromParent();
352 m_ancestorClippingLayer = nullptr;
353 m_contentsContainmentLayer = nullptr;
354 m_graphicsLayer = nullptr;
355 m_foregroundLayer = nullptr;
356 m_backgroundLayer = nullptr;
357 m_childContainmentLayer = nullptr;
358 m_maskLayer = nullptr;
360 m_scrollingLayer = nullptr;
361 m_scrollingContentsLayer = nullptr;
364 void RenderLayerBacking::updateOpacity(const RenderStyle* style)
366 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
369 void RenderLayerBacking::updateTransform(const RenderStyle* style)
371 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
372 // baked into it, and we don't want that.
373 TransformationMatrix t;
374 if (m_owningLayer.hasTransform()) {
375 RenderBox& renderBox = toRenderBox(renderer());
376 style->applyTransform(t, pixelSnappedForPainting(renderBox.borderBoxRect(), renderBox.document().deviceScaleFactor()), RenderStyle::ExcludeTransformOrigin);
377 makeMatrixRenderable(t, compositor().canRender3DTransforms());
380 if (m_contentsContainmentLayer) {
381 m_contentsContainmentLayer->setTransform(t);
382 m_graphicsLayer->setTransform(TransformationMatrix());
384 m_graphicsLayer->setTransform(t);
387 #if ENABLE(CSS_FILTERS)
388 void RenderLayerBacking::updateFilters(const RenderStyle* style)
390 m_canCompositeFilters = m_graphicsLayer->setFilters(style->filter());
394 #if ENABLE(CSS_COMPOSITING)
395 void RenderLayerBacking::updateBlendMode(const RenderStyle* style)
397 if (m_ancestorClippingLayer) {
398 m_ancestorClippingLayer->setBlendMode(style->blendMode());
399 m_graphicsLayer->setBlendMode(BlendModeNormal);
401 m_graphicsLayer->setBlendMode(style->blendMode());
405 static bool hasNonZeroTransformOrigin(const RenderObject& renderer)
407 const RenderStyle& style = renderer.style();
408 return (style.transformOriginX().type() == Fixed && style.transformOriginX().value())
409 || (style.transformOriginY().type() == Fixed && style.transformOriginY().value());
413 // FIXME: We should merge the concept of RenderLayer::{hasAcceleratedTouchScrolling, needsCompositedScrolling}()
414 // so that we can remove this iOS-specific variant.
415 static bool layerOrAncestorIsTransformedOrScrolling(RenderLayer& layer)
417 for (RenderLayer* curr = &layer; curr; curr = curr->parent()) {
418 if (curr->hasTransform() || curr->hasAcceleratedTouchScrolling())
425 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
427 for (RenderLayer* curr = &layer; curr; curr = curr->parent()) {
428 if (curr->hasTransform() || curr->needsCompositedScrolling())
436 bool RenderLayerBacking::shouldClipCompositedBounds() const
439 // Scrollbar layers use this layer for relative positioning, so don't clip.
440 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
444 if (m_usingTiledCacheLayer)
448 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
451 if (layerOrAncestorIsTransformedOrScrolling(m_owningLayer))
455 if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions())
461 void RenderLayerBacking::updateCompositedBounds()
463 LayoutRect layerBounds = compositor().calculateCompositedBounds(m_owningLayer, m_owningLayer);
465 // Clip to the size of the document or enclosing overflow-scroll layer.
466 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
467 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
468 if (shouldClipCompositedBounds()) {
469 RenderView& view = m_owningLayer.renderer().view();
470 RenderLayer* rootLayer = view.layer();
472 LayoutRect clippingBounds;
473 if (renderer().style().position() == FixedPosition && renderer().container() == &view)
474 clippingBounds = view.frameView().viewportConstrainedExtentRect();
476 clippingBounds = view.unscaledDocumentRect();
478 if (&m_owningLayer != rootLayer)
479 clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
482 m_owningLayer.convertToLayerCoords(rootLayer, delta, RenderLayer::AdjustForColumns);
483 clippingBounds.move(-delta.x(), -delta.y());
485 layerBounds.intersect(clippingBounds);
488 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
489 // then we need to ensure that the compositing layer has non-zero size so that we can apply
490 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
491 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
492 layerBounds.setWidth(1);
493 layerBounds.setHeight(1);
494 m_artificiallyInflatedBounds = true;
496 m_artificiallyInflatedBounds = false;
498 setCompositedBounds(layerBounds);
501 void RenderLayerBacking::updateAfterWidgetResize()
503 if (!renderer().isWidget())
505 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderWidget(&renderer()))) {
506 innerCompositor->frameViewDidChangeSize();
507 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
511 void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags)
513 if (!compositor().compositingLayersNeedRebuild()) {
514 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
515 // position of this layer's GraphicsLayer depends on the position of our compositing
516 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
517 // RenderLayers of that ancestor have been processed via updateLayerPositions().
519 // The solution is to update compositing children of this layer here,
520 // via updateCompositingChildrenGeometry().
521 updateCompositedBounds();
522 compositor().updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly);
524 if (flags & IsUpdateRoot) {
525 updateGraphicsLayerGeometry();
526 compositor().updateRootLayerPosition();
527 RenderLayer* stackingContainer = m_owningLayer.enclosingStackingContainer();
528 if (!compositor().compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != &m_owningLayer))
529 compositor().updateCompositingDescendantGeometry(*stackingContainer, *stackingContainer, flags & CompositingChildrenOnly);
533 if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor())
534 setContentsNeedDisplay();
537 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
539 m_owningLayer.updateDescendantDependentFlags();
540 m_owningLayer.updateZOrderLists();
542 bool layerConfigChanged = false;
543 setBackgroundLayerPaintsFixedRootBackground(compositor().needsFixedRootBackgroundLayer(m_owningLayer));
545 // The background layer is currently only used for fixed root backgrounds.
546 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
547 layerConfigChanged = true;
549 if (updateForegroundLayer(compositor().needsContentsCompositingLayer(m_owningLayer)))
550 layerConfigChanged = true;
552 bool needsDescendentsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer);
555 // Our scrolling layer will clip.
556 if (m_owningLayer.hasAcceleratedTouchScrolling())
557 needsDescendentsClippingLayer = false;
559 // Our scrolling layer will clip.
560 if (m_owningLayer.needsCompositedScrolling())
561 needsDescendentsClippingLayer = false;
562 #endif // PLATFORM(IOS)
564 if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer)))
565 layerConfigChanged = true;
567 if (updateDescendantClippingLayer(needsDescendentsClippingLayer))
568 layerConfigChanged = true;
570 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
571 layerConfigChanged = true;
574 if (updateScrollingLayers(m_owningLayer.hasAcceleratedTouchScrolling()))
575 layerConfigChanged = true;
577 if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling()))
578 layerConfigChanged = true;
579 #endif // PLATFORM(IOS)
581 if (layerConfigChanged)
582 updateInternalHierarchy();
584 if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) {
585 if (layerConfigChanged || flatteningLayer->parent() != m_graphicsLayer.get())
586 m_graphicsLayer->addChild(flatteningLayer);
589 if (updateMaskLayer(renderer().hasMask()))
590 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
592 if (m_owningLayer.hasReflection()) {
593 if (m_owningLayer.reflectionLayer()->backing()) {
594 GraphicsLayer* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
595 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
598 m_graphicsLayer->setReplicatedByLayer(0);
600 bool isSimpleContainer = isSimpleContainerCompositingLayer();
601 bool didUpdateContentsRect = false;
602 updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect);
604 updateRootLayerConfiguration();
606 if (isDirectlyCompositedImage())
607 updateImageContents();
609 if (renderer().isEmbeddedObject() && toRenderEmbeddedObject(&renderer())->allowsAcceleratedCompositing()) {
610 PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(&renderer())->widget());
612 if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) {
613 pluginViewBase->detachPluginLayer();
614 pluginViewBase->attachPluginLayer();
617 if (!pluginViewBase->shouldNotAddLayer())
618 m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
622 else if (renderer().isVideo()) {
623 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer().element());
624 m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
627 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
628 else if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
629 const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer().element());
630 if (CanvasRenderingContext* context = canvas->renderingContext())
631 m_graphicsLayer->setContentsToCanvas(context->platformLayer());
632 layerConfigChanged = true;
635 if (renderer().isWidget())
636 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderWidget(&renderer()));
638 return layerConfigChanged;
641 static LayoutRect clipBox(RenderBox& renderer)
643 LayoutRect result = LayoutRect::infiniteRect();
644 if (renderer.hasOverflowClip())
645 result = renderer.overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
647 if (renderer.hasClip())
648 result.intersect(renderer.clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
653 static FloatSize pixelFractionForLayerPainting(const LayoutPoint& point, float pixelSnappingFactor)
655 LayoutUnit x = point.x();
656 LayoutUnit y = point.y();
657 x = x >= 0 ? floorToDevicePixel(x, pixelSnappingFactor) : ceilToDevicePixel(x, pixelSnappingFactor);
658 y = y >= 0 ? floorToDevicePixel(y, pixelSnappingFactor) : ceilToDevicePixel(y, pixelSnappingFactor);
659 return point - LayoutPoint(x, y);
662 static void calculateDevicePixelOffsetFromRenderer(const LayoutSize& rendererOffsetFromGraphicsLayer, FloatSize& devicePixelOffsetFromRenderer,
663 LayoutSize& devicePixelFractionFromRenderer, float deviceScaleFactor)
665 devicePixelFractionFromRenderer = LayoutSize(pixelFractionForLayerPainting(toLayoutPoint(rendererOffsetFromGraphicsLayer), deviceScaleFactor));
666 devicePixelOffsetFromRenderer = rendererOffsetFromGraphicsLayer - devicePixelFractionFromRenderer;
669 void RenderLayerBacking::updateGraphicsLayerGeometry()
671 // If we haven't built z-order lists yet, wait until later.
672 if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
675 // Set transform property, if it is not animating. We have to do this here because the transform
676 // is affected by the layer dimensions.
677 if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(&renderer(), CSSPropertyWebkitTransform, AnimationBase::Running | AnimationBase::Paused | AnimationBase::FillingFowards))
678 updateTransform(&renderer().style());
680 // Set opacity, if it is not animating.
681 if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(&renderer(), CSSPropertyOpacity, AnimationBase::Running | AnimationBase::Paused | AnimationBase::FillingFowards))
682 updateOpacity(&renderer().style());
684 #if ENABLE(CSS_FILTERS)
685 updateFilters(&renderer().style());
688 #if ENABLE(CSS_COMPOSITING)
689 updateBlendMode(&renderer().style());
692 bool isSimpleContainer = isSimpleContainerCompositingLayer();
694 m_owningLayer.updateDescendantDependentFlags();
696 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
697 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
698 // non-compositing visible layers.
699 m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
701 const RenderStyle& style = renderer().style();
702 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
703 bool preserves3D = style.transformStyle3D() == TransformStyle3DPreserve3D && !renderer().hasReflection();
704 m_graphicsLayer->setPreserves3D(preserves3D);
705 m_graphicsLayer->setBackfaceVisibility(style.backfaceVisibility() == BackfaceVisibilityVisible);
707 RenderLayer* compAncestor = m_owningLayer.ancestorCompositingLayer();
709 // We compute everything relative to the enclosing compositing layer.
710 LayoutRect ancestorCompositingBounds;
712 ASSERT(compAncestor->backing());
713 ancestorCompositingBounds = compAncestor->backing()->compositedBounds();
717 * GraphicsLayer: device pixel positioned. Floored, enclosing rect.
718 * RenderLayer: subpixel positioned.
719 * Offset from renderer (GraphicsLayer <-> RenderLayer::renderer()): subpixel based offset.
721 * relativeCompositingBounds
722 * _______________________________________
725 * | \ offset from renderer: (device pixel + subpixel)
727 * | \______________________________ |
728 * | | localCompositingBounds | |
730 * | | RenderLayer::renderer() | |
733 * localCompositingBounds: this RenderLayer relative to its renderer().
734 * relativeCompositingBounds: this RenderLayer relative to its parent compositing layer.
735 * enclosingRelativeCompositingBounds: this RenderLayer relative to its parent but floored to device pixel position.
736 * rendererOffsetFromGraphicsLayer: RenderLayer::renderer()'s offset from its enclosing GraphicsLayer.
737 * devicePixelOffsetFromRenderer: rendererOffsetFromGraphicsLayer's device pixel part. (6.9px -> 6.5px in case of 2x display)
738 * devicePixelFractionFromRenderer: rendererOffsetFromGraphicsLayer's fractional part (6.9px -> 0.4px in case of 2x display)
740 float deviceScaleFactor = this->deviceScaleFactor();
741 LayoutRect localCompositingBounds = compositedBounds();
742 LayoutRect relativeCompositingBounds(localCompositingBounds);
744 LayoutPoint offsetFromParent;
745 m_owningLayer.convertToLayerCoords(compAncestor, offsetFromParent, RenderLayer::AdjustForColumns);
746 // Device pixel fractions get accumulated through ancestor layers. Our painting offset is layout offset + parent's painting offset.
747 offsetFromParent = offsetFromParent + (compAncestor ? compAncestor->backing()->devicePixelFractionFromRenderer() : LayoutSize());
748 relativeCompositingBounds.moveBy(offsetFromParent);
750 LayoutRect enclosingRelativeCompositingBounds = LayoutRect(enclosingRectForPainting(relativeCompositingBounds, deviceScaleFactor));
751 LayoutSize subpixelOffsetAdjustment = enclosingRelativeCompositingBounds.location() - relativeCompositingBounds.location();
752 LayoutSize rendererOffsetFromGraphicsLayer = toLayoutSize(localCompositingBounds.location()) + subpixelOffsetAdjustment;
754 FloatSize devicePixelOffsetFromRenderer;
755 LayoutSize devicePixelFractionFromRenderer;
756 calculateDevicePixelOffsetFromRenderer(rendererOffsetFromGraphicsLayer, devicePixelOffsetFromRenderer, devicePixelFractionFromRenderer, deviceScaleFactor);
757 m_devicePixelFractionFromRenderer = LayoutSize(fabs(devicePixelFractionFromRenderer.width().toFloat()), fabs(devicePixelFractionFromRenderer.height().toFloat()));
759 adjustAncestorCompositingBoundsForFlowThread(ancestorCompositingBounds, compAncestor);
761 LayoutPoint graphicsLayerParentLocation;
762 if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
763 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
764 // position relative to it.
765 LayoutRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
766 graphicsLayerParentLocation = clippingBox.location();
767 } else if (compAncestor)
768 graphicsLayerParentLocation = ancestorCompositingBounds.location();
770 graphicsLayerParentLocation = renderer().view().documentRect().location();
773 if (compAncestor && compAncestor->hasAcceleratedTouchScrolling()) {
774 RenderBox* renderBox = toRenderBox(&compAncestor->renderer());
775 LayoutRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(),
776 renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(),
777 renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
779 LayoutSize scrollOffset = compAncestor->scrolledContentOffset();
780 graphicsLayerParentLocation = paddingBox.location() - scrollOffset;
784 if (compAncestor && compAncestor->needsCompositedScrolling()) {
785 RenderBox& renderBox = toRenderBox(compAncestor->renderer());
786 LayoutSize scrollOffset = compAncestor->scrolledContentOffset();
787 LayoutPoint scrollOrigin(renderBox.borderLeft(), renderBox.borderTop());
788 graphicsLayerParentLocation = scrollOrigin - scrollOffset;
791 if (compAncestor && m_ancestorClippingLayer) {
792 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
793 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
794 // for a compositing layer, rootLayer is the layer itself.
795 RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
796 LayoutRect parentClipRect = m_owningLayer.backgroundClipRect(clipRectsContext).rect(); // FIXME: Incorrect for CSS regions.
797 ASSERT(parentClipRect != LayoutRect::infiniteRect());
798 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
799 m_ancestorClippingLayer->setSize(parentClipRect.size());
801 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
802 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - offsetFromParent);
804 // The primary layer is then parented in, and positioned relative to this clipping layer.
805 graphicsLayerParentLocation = parentClipRect.location();
808 LayoutSize contentsSize = enclosingRelativeCompositingBounds.size();
810 if (m_contentsContainmentLayer) {
811 m_contentsContainmentLayer->setPreserves3D(preserves3D);
812 m_contentsContainmentLayer->setPosition(FloatPoint(enclosingRelativeCompositingBounds.location() - graphicsLayerParentLocation));
813 // Use the same size as m_graphicsLayer so transforms behave correctly.
814 m_contentsContainmentLayer->setSize(contentsSize);
815 graphicsLayerParentLocation = enclosingRelativeCompositingBounds.location();
818 m_graphicsLayer->setPosition(FloatPoint(enclosingRelativeCompositingBounds.location() - graphicsLayerParentLocation));
819 m_graphicsLayer->setSize(contentsSize);
820 if (devicePixelOffsetFromRenderer != m_graphicsLayer->offsetFromRenderer()) {
821 m_graphicsLayer->setOffsetFromRenderer(devicePixelOffsetFromRenderer);
822 positionOverflowControlsLayers();
825 if (!m_isMainFrameRenderViewLayer) {
826 // For non-root layers, background is always painted by the primary graphics layer.
827 ASSERT(!m_backgroundLayer);
828 bool hadSubpixelRounding = !m_devicePixelFractionFromRenderer.isZero();
829 m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(localCompositingBounds));
832 // If we have a layer that clips children, position it.
833 LayoutRect clippingBox;
834 if (GraphicsLayer* clipLayer = clippingLayer()) {
835 clippingBox = clipBox(toRenderBox(renderer()));
836 clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
837 clipLayer->setSize(clippingBox.size());
838 clipLayer->setOffsetFromRenderer(toFloatSize(clippingBox.location()));
842 m_maskLayer->setSize(m_graphicsLayer->size());
843 m_maskLayer->setPosition(FloatPoint());
844 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
847 if (m_owningLayer.hasTransform()) {
848 // Update properties that depend on layer dimensions.
849 FloatPoint3D transformOrigin = computeTransformOriginForPainting(toRenderBox(renderer()).borderBoxRect());
850 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
851 FloatPoint layerOffset = roundedForPainting(offsetFromParent, deviceScaleFactor);
852 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
853 FloatPoint3D anchor(enclosingRelativeCompositingBounds.width() ? ((layerOffset.x() - enclosingRelativeCompositingBounds.x()) + transformOrigin.x())
854 / enclosingRelativeCompositingBounds.width() : 0.5, enclosingRelativeCompositingBounds.height() ? ((layerOffset.y() - enclosingRelativeCompositingBounds.y())
855 + transformOrigin.y()) / enclosingRelativeCompositingBounds.height() : 0.5, transformOrigin.z());
857 if (m_contentsContainmentLayer)
858 m_contentsContainmentLayer->setAnchorPoint(anchor);
860 m_graphicsLayer->setAnchorPoint(anchor);
862 const RenderStyle& style = renderer().style();
863 GraphicsLayer* clipLayer = clippingLayer();
864 if (style.hasPerspective()) {
865 TransformationMatrix t = owningLayer().perspectiveTransform();
868 clipLayer->setChildrenTransform(t);
869 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
872 m_graphicsLayer->setChildrenTransform(t);
875 clipLayer->setChildrenTransform(TransformationMatrix());
877 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
880 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
881 if (m_contentsContainmentLayer)
882 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5, 0.5, 0));
885 if (m_foregroundLayer) {
886 FloatPoint foregroundPosition;
887 FloatSize foregroundSize = contentsSize;
888 FloatSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
889 if (hasClippingLayer()) {
890 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
891 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
892 foregroundSize = FloatSize(clippingBox.size());
893 foregroundOffset = toFloatSize(clippingBox.location());
896 m_foregroundLayer->setPosition(foregroundPosition);
897 m_foregroundLayer->setSize(foregroundSize);
898 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
901 if (m_backgroundLayer) {
902 FloatPoint backgroundPosition;
903 FloatSize backgroundSize = contentsSize;
904 if (backgroundLayerPaintsFixedRootBackground()) {
905 const FrameView& frameView = renderer().view().frameView();
906 backgroundPosition = toLayoutPoint(frameView.scrollOffsetForFixedPosition());
907 backgroundSize = frameView.visibleContentRect().size();
909 m_backgroundLayer->setPosition(backgroundPosition);
910 m_backgroundLayer->setSize(backgroundSize);
911 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
914 if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
915 RenderLayerBacking* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
916 reflectionBacking->updateGraphicsLayerGeometry();
918 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
919 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
920 FloatRect layerBounds = compositedBounds();
921 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
922 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
925 if (m_scrollingLayer) {
926 ASSERT(m_scrollingContentsLayer);
927 RenderBox& renderBox = toRenderBox(renderer());
928 LayoutRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom());
929 LayoutSize scrollOffset = m_owningLayer.scrollOffset();
931 m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location()));
933 m_scrollingLayer->setSize(paddingBox.size());
935 FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
936 m_scrollingLayer->setOffsetFromRenderer(FloatPoint() - paddingBox.location());
937 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
939 if (m_owningLayer.isInUserScroll()) {
940 // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause
941 // jitter. Set a flag to ensure that we sync up later.
942 m_owningLayer.setRequiresScrollBoundsOriginUpdate(true);
944 // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
945 m_scrollingLayer->setBoundsOrigin(FloatPoint(scrollOffset.width(), scrollOffset.height()));
946 m_owningLayer.setRequiresScrollBoundsOriginUpdate(false);
949 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
951 m_scrollingContentsLayer->setPosition(FloatPoint());
953 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
954 m_scrollingContentsLayer->setNeedsDisplay();
956 m_scrollingContentsLayer->setSize(scrollSize);
957 // Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
958 // FIXME: The paint offset and the scroll offset should really be separate concepts.
959 m_scrollingContentsLayer->setOffsetFromRenderer(paddingBox.location() - IntPoint() - scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
961 m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
963 FloatSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
964 m_scrollingLayer->setOffsetFromRenderer(-toFloatSize(paddingBox.location()));
966 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
968 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
969 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
970 m_scrollingContentsLayer->setNeedsDisplay();
972 LayoutSize scrollingContentsOffset = toLayoutSize(paddingBox.location() - scrollOffset);
973 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
974 compositor().scrollingLayerDidChange(m_owningLayer);
976 m_scrollingContentsLayer->setSize(scrollSize);
977 // FIXME: The paint offset and the scroll offset should really be separate concepts.
978 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
981 if (m_foregroundLayer) {
982 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
983 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
987 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
988 setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compAncestor, enclosingRelativeCompositingBounds, ancestorCompositingBounds));
990 bool didUpdateContentsRect = false;
991 updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect);
992 if (!didUpdateContentsRect && m_graphicsLayer->hasContentsLayer())
995 updateDrawsContent(isSimpleContainer);
996 updateAfterWidgetResize();
998 compositor().updateScrollCoordinatedStatus(m_owningLayer);
1001 void RenderLayerBacking::adjustAncestorCompositingBoundsForFlowThread(LayoutRect& ancestorCompositingBounds, const RenderLayer* compositingAncestor) const
1003 if (!m_owningLayer.isInsideFlowThread())
1006 RenderLayer* flowThreadLayer = m_owningLayer.isInsideOutOfFlowThread() ? m_owningLayer.stackingContainer() : m_owningLayer.enclosingFlowThreadAncestor();
1007 if (flowThreadLayer && flowThreadLayer->isRenderFlowThread()) {
1008 if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions()) {
1009 // The RenderNamedFlowThread is not composited, as we need it to paint the
1010 // background layer of the regions. We need to compensate for that by manually
1011 // subtracting the position of the flow-thread.
1012 IntPoint flowPosition;
1013 flowThreadLayer->convertToPixelSnappedLayerCoords(compositingAncestor, flowPosition);
1014 ancestorCompositingBounds.moveBy(flowPosition);
1017 // Move the ancestor position at the top of the region where the composited layer is going to display.
1018 RenderFlowThread& flowThread = toRenderFlowThread(flowThreadLayer->renderer());
1019 RenderNamedFlowFragment* parentRegion = flowThread.cachedRegionForCompositedLayer(m_owningLayer);
1024 m_owningLayer.convertToPixelSnappedLayerCoords(flowThreadLayer, flowDelta);
1025 parentRegion->adjustRegionBoundsFromFlowThreadPortionRect(flowDelta, ancestorCompositingBounds);
1026 RenderBoxModelObject& layerOwner = toRenderBoxModelObject(parentRegion->layerOwner());
1027 RenderLayerBacking* layerOwnerBacking = layerOwner.layer()->backing();
1028 if (!layerOwnerBacking)
1031 // Make sure that the region propagates its borders, paddings, outlines or box-shadows to layers inside it.
1032 // Note that the composited bounds of the RenderRegion are already calculated because
1033 // RenderLayerCompositor::rebuildCompositingLayerTree will only iterate on the content of the region after the
1034 // region itself is computed.
1035 ancestorCompositingBounds.moveBy(roundedIntPoint(layerOwnerBacking->compositedBounds().location()));
1036 ancestorCompositingBounds.move(-layerOwner.borderAndPaddingStart(), -layerOwner.borderAndPaddingBefore());
1038 // If there's a clipping GraphicsLayer on the hierarchy (region graphics layer -> clipping graphics layer ->
1039 // composited content graphics layer), substract the offset of the clipping layer, since it's its parent
1040 // that positions us (the graphics layer of the region).
1041 if (layerOwnerBacking->clippingLayer())
1042 ancestorCompositingBounds.moveBy(roundedIntPoint(layerOwnerBacking->clippingLayer()->position()));
1046 void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer, bool& didUpdateContentsRect)
1048 if (!m_owningLayer.hasVisibleContent())
1051 // The order of operations here matters, since the last valid type of contents needs
1052 // to also update the contentsRect.
1053 updateDirectlyCompositedBackgroundColor(isSimpleContainer, didUpdateContentsRect);
1054 updateDirectlyCompositedBackgroundImage(isSimpleContainer, didUpdateContentsRect);
1057 void RenderLayerBacking::updateInternalHierarchy()
1059 // m_foregroundLayer has to be inserted in the correct order with child layers,
1060 // so it's not inserted here.
1061 if (m_ancestorClippingLayer)
1062 m_ancestorClippingLayer->removeAllChildren();
1064 if (m_contentsContainmentLayer) {
1065 m_contentsContainmentLayer->removeAllChildren();
1066 if (m_ancestorClippingLayer)
1067 m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get());
1070 if (m_backgroundLayer)
1071 m_contentsContainmentLayer->addChild(m_backgroundLayer.get());
1073 if (m_contentsContainmentLayer)
1074 m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
1075 else if (m_ancestorClippingLayer)
1076 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
1078 if (m_childContainmentLayer) {
1079 m_childContainmentLayer->removeFromParent();
1080 m_graphicsLayer->addChild(m_childContainmentLayer.get());
1083 if (m_scrollingLayer) {
1084 GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
1085 m_scrollingLayer->removeFromParent();
1086 superlayer->addChild(m_scrollingLayer.get());
1089 // The clip for child layers does not include space for overflow controls, so they exist as
1090 // siblings of the clipping layer if we have one. Normal children of this layer are set as
1091 // children of the clipping layer.
1092 if (m_layerForHorizontalScrollbar) {
1093 m_layerForHorizontalScrollbar->removeFromParent();
1094 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
1096 if (m_layerForVerticalScrollbar) {
1097 m_layerForVerticalScrollbar->removeFromParent();
1098 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
1100 if (m_layerForScrollCorner) {
1101 m_layerForScrollCorner->removeFromParent();
1102 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
1106 void RenderLayerBacking::resetContentsRect()
1108 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
1110 LayoutRect contentsClippingRect;
1111 if (renderer().isBox())
1112 contentsClippingRect = toRenderBox(renderer()).contentBoxRect();
1114 contentsClippingRect.move(contentOffsetInCompostingLayer());
1115 m_graphicsLayer->setContentsClippingRect(pixelSnappedIntRect(contentsClippingRect));
1117 m_graphicsLayer->setContentsTileSize(IntSize());
1118 m_graphicsLayer->setContentsTilePhase(IntPoint());
1121 void RenderLayerBacking::updateDrawsContent()
1123 updateDrawsContent(isSimpleContainerCompositingLayer());
1126 void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer)
1128 if (m_scrollingLayer) {
1129 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1130 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1131 // m_scrollingLayer never has backing store.
1132 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1133 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground();
1134 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1136 bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || paintsChildren());
1137 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
1141 bool hasPaintedContent = containsPaintedContent(isSimpleContainer);
1143 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
1144 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1145 if (m_foregroundLayer)
1146 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1148 if (m_backgroundLayer)
1149 m_backgroundLayer->setDrawsContent(hasPaintedContent);
1152 // Return true if the layer changed.
1153 bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip)
1155 bool layersChanged = false;
1157 if (needsAncestorClip) {
1158 if (!m_ancestorClippingLayer) {
1159 m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer");
1160 m_ancestorClippingLayer->setMasksToBounds(true);
1161 layersChanged = true;
1163 } else if (hasAncestorClippingLayer()) {
1164 willDestroyLayer(m_ancestorClippingLayer.get());
1165 m_ancestorClippingLayer->removeFromParent();
1166 m_ancestorClippingLayer = nullptr;
1167 layersChanged = true;
1170 return layersChanged;
1173 // Return true if the layer changed.
1174 bool RenderLayerBacking::updateDescendantClippingLayer(bool needsDescendantClip)
1176 bool layersChanged = false;
1178 if (needsDescendantClip) {
1179 if (!m_childContainmentLayer && !m_usingTiledCacheLayer) {
1180 m_childContainmentLayer = createGraphicsLayer("Child clipping Layer");
1181 m_childContainmentLayer->setMasksToBounds(true);
1182 layersChanged = true;
1184 } else if (hasClippingLayer()) {
1185 willDestroyLayer(m_childContainmentLayer.get());
1186 m_childContainmentLayer->removeFromParent();
1187 m_childContainmentLayer = nullptr;
1188 layersChanged = true;
1191 return layersChanged;
1194 void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1196 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1199 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
1201 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1203 return m_owningLayer.horizontalScrollbar();
1206 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
1208 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1210 return m_owningLayer.verticalScrollbar();
1213 bool RenderLayerBacking::requiresScrollCornerLayer() const
1215 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1217 return !m_owningLayer.scrollCornerAndResizerRect().isEmpty();
1220 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1222 bool horizontalScrollbarLayerChanged = false;
1223 if (needsHorizontalScrollbarLayer) {
1224 if (!m_layerForHorizontalScrollbar) {
1225 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
1226 horizontalScrollbarLayerChanged = true;
1228 } else if (m_layerForHorizontalScrollbar) {
1229 willDestroyLayer(m_layerForHorizontalScrollbar.get());
1230 m_layerForHorizontalScrollbar = nullptr;
1231 horizontalScrollbarLayerChanged = true;
1234 bool verticalScrollbarLayerChanged = false;
1235 if (needsVerticalScrollbarLayer) {
1236 if (!m_layerForVerticalScrollbar) {
1237 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
1238 verticalScrollbarLayerChanged = true;
1240 } else if (m_layerForVerticalScrollbar) {
1241 willDestroyLayer(m_layerForVerticalScrollbar.get());
1242 m_layerForVerticalScrollbar = nullptr;
1243 verticalScrollbarLayerChanged = true;
1246 bool scrollCornerLayerChanged = false;
1247 if (needsScrollCornerLayer) {
1248 if (!m_layerForScrollCorner) {
1249 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
1250 scrollCornerLayerChanged = true;
1252 } else if (m_layerForScrollCorner) {
1253 willDestroyLayer(m_layerForScrollCorner.get());
1254 m_layerForScrollCorner = nullptr;
1255 scrollCornerLayerChanged = true;
1258 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1259 if (horizontalScrollbarLayerChanged)
1260 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_owningLayer, HorizontalScrollbar);
1261 if (verticalScrollbarLayerChanged)
1262 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_owningLayer, VerticalScrollbar);
1265 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1268 void RenderLayerBacking::positionOverflowControlsLayers()
1270 if (!m_owningLayer.hasScrollbars())
1273 const IntRect borderBox = toRenderBox(renderer()).pixelSnappedBorderBoxRect();
1275 FloatSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
1276 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1277 IntRect hBarRect = m_owningLayer.rectForHorizontalScrollbar(borderBox);
1278 layer->setPosition(hBarRect.location() - offsetFromRenderer);
1279 layer->setSize(hBarRect.size());
1280 if (layer->hasContentsLayer()) {
1281 IntRect barRect = IntRect(IntPoint(), hBarRect.size());
1282 layer->setContentsRect(barRect);
1283 layer->setContentsClippingRect(barRect);
1285 layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->hasContentsLayer());
1288 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1289 IntRect vBarRect = m_owningLayer.rectForVerticalScrollbar(borderBox);
1290 layer->setPosition(vBarRect.location() - offsetFromRenderer);
1291 layer->setSize(vBarRect.size());
1292 if (layer->hasContentsLayer()) {
1293 IntRect barRect = IntRect(IntPoint(), vBarRect.size());
1294 layer->setContentsRect(barRect);
1295 layer->setContentsClippingRect(barRect);
1297 layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->hasContentsLayer());
1300 if (GraphicsLayer* layer = layerForScrollCorner()) {
1301 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
1302 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1303 layer->setSize(scrollCornerAndResizer.size());
1304 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1308 bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
1310 if (GraphicsLayer* layer = layerForHorizontalScrollbar())
1311 if (!layer->drawsContent())
1314 if (GraphicsLayer* layer = layerForVerticalScrollbar())
1315 if (!layer->drawsContent())
1318 if (GraphicsLayer* layer = layerForScrollCorner())
1319 if (!layer->drawsContent())
1325 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
1327 bool layerChanged = false;
1328 if (needsForegroundLayer) {
1329 if (!m_foregroundLayer) {
1332 layerName = m_owningLayer.name() + " (foreground)";
1334 m_foregroundLayer = createGraphicsLayer(layerName);
1335 m_foregroundLayer->setDrawsContent(true);
1336 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1337 layerChanged = true;
1339 } else if (m_foregroundLayer) {
1340 willDestroyLayer(m_foregroundLayer.get());
1341 m_foregroundLayer->removeFromParent();
1342 m_foregroundLayer = nullptr;
1343 layerChanged = true;
1347 m_graphicsLayer->setNeedsDisplay();
1348 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1351 return layerChanged;
1354 bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
1356 bool layerChanged = false;
1357 if (needsBackgroundLayer) {
1358 if (!m_backgroundLayer) {
1361 layerName = m_owningLayer.name() + " (background)";
1363 m_backgroundLayer = createGraphicsLayer(layerName);
1364 m_backgroundLayer->setDrawsContent(true);
1365 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1366 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1367 layerChanged = true;
1370 if (!m_contentsContainmentLayer) {
1373 layerName = m_owningLayer.name() + " (contents containment)";
1375 m_contentsContainmentLayer = createGraphicsLayer(layerName);
1376 m_contentsContainmentLayer->setAppliesPageScale(true);
1377 m_graphicsLayer->setAppliesPageScale(false);
1378 layerChanged = true;
1381 if (m_backgroundLayer) {
1382 willDestroyLayer(m_backgroundLayer.get());
1383 m_backgroundLayer->removeFromParent();
1384 m_backgroundLayer = nullptr;
1385 layerChanged = true;
1387 if (m_contentsContainmentLayer) {
1388 willDestroyLayer(m_contentsContainmentLayer.get());
1389 m_contentsContainmentLayer->removeFromParent();
1390 m_contentsContainmentLayer = nullptr;
1391 layerChanged = true;
1392 m_graphicsLayer->setAppliesPageScale(true);
1397 m_graphicsLayer->setNeedsDisplay();
1398 // This assumes that the background layer is only used for fixed backgrounds, which is currently a correct assumption.
1399 compositor().fixedRootBackgroundLayerChanged();
1402 return layerChanged;
1405 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
1407 bool layerChanged = false;
1408 if (needsMaskLayer) {
1410 m_maskLayer = createGraphicsLayer("Mask");
1411 m_maskLayer->setDrawsContent(true);
1412 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
1413 layerChanged = true;
1415 } else if (m_maskLayer) {
1416 willDestroyLayer(m_maskLayer.get());
1417 m_maskLayer = nullptr;
1418 layerChanged = true;
1422 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1424 return layerChanged;
1427 bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
1429 if (needsScrollingLayers == !!m_scrollingLayer)
1432 if (!m_scrollingLayer) {
1433 // Outer layer which corresponds with the scroll view.
1434 m_scrollingLayer = createGraphicsLayer("Scrolling container");
1435 m_scrollingLayer->setDrawsContent(false);
1436 m_scrollingLayer->setMasksToBounds(true);
1438 m_scrollingLayer->setCustomBehavior(GraphicsLayer::CustomScrollingBehavior);
1440 // Inner layer which renders the content that scrolls.
1441 m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
1442 m_scrollingContentsLayer->setDrawsContent(true);
1443 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1444 if (!m_foregroundLayer)
1445 paintPhase |= GraphicsLayerPaintForeground;
1446 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1447 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
1449 compositor().willRemoveScrollingLayer(m_owningLayer);
1451 willDestroyLayer(m_scrollingLayer.get());
1452 willDestroyLayer(m_scrollingContentsLayer.get());
1453 m_scrollingLayer = nullptr;
1454 m_scrollingContentsLayer = nullptr;
1457 updateInternalHierarchy();
1458 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1459 m_graphicsLayer->setNeedsDisplay(); // Because painting phases changed.
1461 if (m_scrollingLayer)
1462 compositor().didAddScrollingLayer(m_owningLayer);
1467 void RenderLayerBacking::detachFromScrollingCoordinator()
1469 if (!m_scrollingNodeID && !m_viewportConstrainedNodeID)
1472 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1473 if (!scrollingCoordinator)
1476 if (m_scrollingNodeID)
1477 scrollingCoordinator->detachFromStateTree(m_scrollingNodeID);
1479 if (m_viewportConstrainedNodeID)
1480 scrollingCoordinator->detachFromStateTree(m_viewportConstrainedNodeID);
1482 m_scrollingNodeID = 0;
1483 m_viewportConstrainedNodeID = 0;
1486 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
1489 if (!m_backgroundLayer)
1490 phase |= GraphicsLayerPaintBackground;
1491 if (!m_foregroundLayer)
1492 phase |= GraphicsLayerPaintForeground;
1494 phase |= GraphicsLayerPaintMask;
1496 if (m_scrollingContentsLayer) {
1497 phase &= ~GraphicsLayerPaintForeground;
1498 phase |= GraphicsLayerPaintCompositedScroll;
1501 return static_cast<GraphicsLayerPaintingPhase>(phase);
1504 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
1506 float finalOpacity = rendererOpacity;
1508 for (RenderLayer* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1509 // We only care about parents that are stacking contexts.
1510 // Recall that opacity creates stacking context.
1511 if (!curr->isStackingContainer())
1514 // If we found a compositing layer, we want to compute opacity
1515 // relative to it. So we can break here.
1516 if (curr->isComposited())
1519 finalOpacity *= curr->renderer().opacity();
1522 return finalOpacity;
1525 static bool hasBoxDecorations(const RenderStyle* style)
1527 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
1530 static bool canCreateTiledImage(const RenderStyle*);
1532 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
1534 if (hasBoxDecorations(style))
1537 if (!style->hasBackgroundImage())
1540 return !GraphicsLayer::supportsContentsTiling() || !canCreateTiledImage(style);
1543 static bool hasPerspectiveOrPreserves3D(const RenderStyle* style)
1545 return style->hasPerspective() || style->preserves3D();
1548 Color RenderLayerBacking::rendererBackgroundColor() const
1550 const auto& backgroundRenderer = renderer().isRoot() ? renderer().rendererForRootBackground() : renderer();
1551 return backgroundRenderer.style().visitedDependentColor(CSSPropertyBackgroundColor);
1554 void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(bool isSimpleContainer, bool& didUpdateContentsRect)
1556 if (!isSimpleContainer) {
1557 m_graphicsLayer->setContentsToSolidColor(Color());
1561 Color backgroundColor = rendererBackgroundColor();
1563 // An unset (invalid) color will remove the solid color.
1564 m_graphicsLayer->setContentsToSolidColor(backgroundColor);
1565 FloatRect contentsRect = backgroundBoxForPainting();
1566 m_graphicsLayer->setContentsRect(contentsRect);
1567 m_graphicsLayer->setContentsClippingRect(contentsRect);
1568 didUpdateContentsRect = true;
1571 bool canCreateTiledImage(const RenderStyle* style)
1573 const FillLayer* fillLayer = style->backgroundLayers();
1574 if (fillLayer->next())
1577 if (!fillLayer->imagesAreLoaded())
1580 if (fillLayer->attachment() != ScrollBackgroundAttachment)
1583 Color color = style->visitedDependentColor(CSSPropertyBackgroundColor);
1585 // FIXME: Allow color+image compositing when it makes sense.
1586 // For now bailing out.
1587 if (color.isValid() && color.alpha())
1590 StyleImage* styleImage = fillLayer->image();
1592 // FIXME: support gradients with isGeneratedImage.
1593 if (!styleImage->isCachedImage())
1596 Image* image = styleImage->cachedImage()->image();
1597 if (!image->isBitmapImage())
1603 void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(bool isSimpleContainer, bool& didUpdateContentsRect)
1605 if (!GraphicsLayer::supportsContentsTiling())
1608 if (isDirectlyCompositedImage())
1611 const RenderStyle& style = renderer().style();
1613 if (!isSimpleContainer || !style.hasBackgroundImage()) {
1614 m_graphicsLayer->setContentsToImage(0);
1618 IntRect destRect = pixelSnappedIntRect(LayoutRect(backgroundBoxForPainting()));
1622 RefPtr<Image> image = style.backgroundLayers()->image()->cachedImage()->image();
1623 toRenderBox(renderer()).getGeometryForBackgroundImage(&m_owningLayer.renderer(), destRect, phase, tileSize);
1624 m_graphicsLayer->setContentsTileSize(tileSize);
1625 m_graphicsLayer->setContentsTilePhase(phase);
1626 m_graphicsLayer->setContentsRect(destRect);
1627 m_graphicsLayer->setContentsClippingRect(destRect);
1628 m_graphicsLayer->setContentsToImage(image.get());
1629 didUpdateContentsRect = true;
1632 void RenderLayerBacking::updateRootLayerConfiguration()
1634 if (!m_usingTiledCacheLayer)
1637 Color backgroundColor;
1638 bool viewIsTransparent = compositor().viewHasTransparentBackground(&backgroundColor);
1640 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
1641 m_backgroundLayer->setBackgroundColor(backgroundColor);
1642 m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
1644 m_graphicsLayer->setBackgroundColor(Color());
1645 m_graphicsLayer->setContentsOpaque(false);
1647 m_graphicsLayer->setBackgroundColor(backgroundColor);
1648 m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
1652 static bool supportsDirectBoxDecorationsComposition(const RenderLayerModelObject& renderer)
1654 if (!GraphicsLayer::supportsBackgroundColorContent())
1657 if (renderer.hasClip())
1660 if (hasBoxDecorationsOrBackgroundImage(&renderer.style()))
1663 // FIXME: We can't create a directly composited background if this
1664 // layer will have children that intersect with the background layer.
1665 // A better solution might be to introduce a flattening layer if
1666 // we do direct box decoration composition.
1667 // https://bugs.webkit.org/show_bug.cgi?id=119461
1668 if (hasPerspectiveOrPreserves3D(&renderer.style()))
1671 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
1672 if (renderer.style().backgroundComposite() != CompositeSourceOver)
1675 if (renderer.style().backgroundClip() == TextFillBox)
1681 bool RenderLayerBacking::paintsBoxDecorations() const
1683 if (!m_owningLayer.hasVisibleBoxDecorations())
1686 if (!supportsDirectBoxDecorationsComposition(renderer()))
1692 bool RenderLayerBacking::paintsChildren() const
1694 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers())
1697 if (hasVisibleNonCompositingDescendantLayers())
1703 static bool isRestartedPlugin(RenderObject* renderer)
1705 if (!renderer->isEmbeddedObject())
1708 Element* element = toElement(renderer->node());
1709 if (!element || !element->isPluginElement())
1712 return toHTMLPlugInElement(element)->isRestartedPlugin();
1715 static bool isCompositedPlugin(RenderObject* renderer)
1717 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
1720 // A "simple container layer" is a RenderLayer which has no visible content to render.
1721 // It may have no children, or all its children may be themselves composited.
1722 // This is a useful optimization, because it allows us to avoid allocating backing store.
1723 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
1725 if (renderer().hasMask()) // masks require special treatment
1728 if (renderer().isReplaced() && (!isCompositedPlugin(&renderer()) || isRestartedPlugin(&renderer())))
1731 if (paintsBoxDecorations() || paintsChildren())
1734 if (renderer().isRenderNamedFlowFragmentContainer())
1737 if (renderer().isRenderView()) {
1738 // Look to see if the root object has a non-simple background
1739 RenderObject* rootObject = renderer().document().documentElement() ? renderer().document().documentElement()->renderer() : 0;
1743 RenderStyle* style = &rootObject->style();
1745 // Reject anything that has a border, a border-radius or outline,
1746 // or is not a simple background (no background, or solid color).
1747 if (hasBoxDecorationsOrBackgroundImage(style))
1750 // Now look at the body's renderer.
1751 HTMLElement* body = renderer().document().body();
1752 RenderObject* bodyObject = (body && body->hasTagName(bodyTag)) ? body->renderer() : 0;
1756 style = &bodyObject->style();
1758 if (hasBoxDecorationsOrBackgroundImage(style))
1765 static bool hasVisibleNonCompositingDescendant(RenderLayer& parent)
1767 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1768 parent.updateLayerListsIfNeeded();
1770 #if !ASSERT_DISABLED
1771 LayerListMutationDetector mutationChecker(&parent);
1774 if (Vector<RenderLayer*>* normalFlowList = parent.normalFlowList()) {
1775 size_t listSize = normalFlowList->size();
1776 for (size_t i = 0; i < listSize; ++i) {
1777 RenderLayer* curLayer = normalFlowList->at(i);
1778 if (!curLayer->isComposited()
1779 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer)))
1784 if (parent.isStackingContainer()) {
1785 if (!parent.hasVisibleDescendant())
1788 // Use the m_hasCompositingDescendant bit to optimize?
1789 if (Vector<RenderLayer*>* negZOrderList = parent.negZOrderList()) {
1790 size_t listSize = negZOrderList->size();
1791 for (size_t i = 0; i < listSize; ++i) {
1792 RenderLayer* curLayer = negZOrderList->at(i);
1793 if (!curLayer->isComposited()
1794 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer)))
1799 if (Vector<RenderLayer*>* posZOrderList = parent.posZOrderList()) {
1800 size_t listSize = posZOrderList->size();
1801 for (size_t i = 0; i < listSize; ++i) {
1802 RenderLayer* curLayer = posZOrderList->at(i);
1803 if (!curLayer->isComposited()
1804 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer)))
1813 // Conservative test for having no rendered children.
1814 bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
1816 return hasVisibleNonCompositingDescendant(m_owningLayer);
1819 bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const
1821 if (isSimpleContainer || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer.isReflection())
1824 if (isDirectlyCompositedImage())
1827 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1828 // and set background color on the layer in that case, instead of allocating backing store and painting.
1830 if (renderer().isVideo() && toRenderVideo(renderer()).shouldDisplayVideo())
1831 return m_owningLayer.hasBoxDecorationsOrBackground();
1834 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
1835 if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents)
1836 return m_owningLayer.hasBoxDecorationsOrBackground();
1842 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1843 // that require painting. Direct compositing saves backing store.
1844 bool RenderLayerBacking::isDirectlyCompositedImage() const
1846 if (!renderer().isRenderImage() || renderer().isMedia() || m_owningLayer.hasBoxDecorationsOrBackground() || renderer().hasClip())
1849 RenderImage& imageRenderer = toRenderImage(renderer());
1850 if (CachedImage* cachedImage = imageRenderer.cachedImage()) {
1851 if (!cachedImage->hasImage())
1854 Image* image = cachedImage->imageForRenderer(&imageRenderer);
1855 if (!image->isBitmapImage())
1858 if (image->orientationForCurrentFrame() != DefaultImageOrientation)
1861 return m_graphicsLayer->shouldDirectlyCompositeImage(image);
1867 void RenderLayerBacking::contentChanged(ContentChangeType changeType)
1869 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1870 updateImageContents();
1874 if ((changeType == BackgroundImageChanged) && canCreateTiledImage(&renderer().style()))
1875 updateGraphicsLayerGeometry();
1877 if ((changeType == MaskImageChanged) && m_maskLayer) {
1878 // The composited layer bounds relies on box->maskClipRect(), which changes
1879 // when the mask image becomes available.
1880 updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot);
1883 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
1884 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
1885 m_graphicsLayer->setContentsNeedsDisplay();
1891 void RenderLayerBacking::updateImageContents()
1893 ASSERT(renderer().isRenderImage());
1894 RenderImage& imageRenderer = toRenderImage(renderer());
1896 CachedImage* cachedImage = imageRenderer.cachedImage();
1900 Image* image = cachedImage->imageForRenderer(&imageRenderer);
1904 // We have to wait until the image is fully loaded before setting it on the layer.
1905 if (!cachedImage->isLoaded())
1908 // This is a no-op if the layer doesn't have an inner layer for the image.
1909 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
1911 LayoutRect contentsClippingRect = imageRenderer.contentBoxRect();
1912 contentsClippingRect.move(contentOffsetInCompostingLayer());
1913 m_graphicsLayer->setContentsClippingRect(pixelSnappedIntRect(contentsClippingRect));
1915 m_graphicsLayer->setContentsToImage(image);
1916 bool isSimpleContainer = false;
1917 updateDrawsContent(isSimpleContainer);
1919 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1920 // the image. So we have to kick the animation each time; this has the downside that the
1921 // image will keep animating, even if its layer is not visible.
1922 image->startAnimation();
1925 FloatPoint3D RenderLayerBacking::computeTransformOriginForPainting(const LayoutRect& borderBox) const
1927 const RenderStyle& style = renderer().style();
1928 float deviceScaleFactor = renderer().document().deviceScaleFactor();
1930 FloatPoint3D origin;
1931 origin.setX(roundToDevicePixel(floatValueForLength(style.transformOriginX(), borderBox.width()), deviceScaleFactor));
1932 origin.setY(roundToDevicePixel(floatValueForLength(style.transformOriginY(), borderBox.height()), deviceScaleFactor));
1933 origin.setZ(style.transformOriginZ());
1938 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
1939 LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const
1941 return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y()) + m_devicePixelFractionFromRenderer;
1944 LayoutRect RenderLayerBacking::contentsBox() const
1946 if (!renderer().isBox())
1947 return LayoutRect();
1949 RenderBox& renderBox = toRenderBox(renderer());
1950 LayoutRect contentsRect;
1952 if (renderBox.isVideo())
1953 contentsRect = toRenderVideo(renderBox).videoBox();
1956 if (renderBox.isRenderReplaced()) {
1957 RenderReplaced& renderReplaced = *toRenderReplaced(&renderBox);
1958 contentsRect = renderReplaced.replacedContentRect(renderBox.intrinsicSize());
1960 contentsRect = renderBox.contentBoxRect();
1962 contentsRect.move(contentOffsetInCompostingLayer());
1963 return contentsRect;
1966 static LayoutRect backgroundRectForBox(const RenderBox& box)
1968 switch (box.style().backgroundClip()) {
1970 return box.borderBoxRect();
1971 case PaddingFillBox:
1972 return box.paddingBoxRect();
1973 case ContentFillBox:
1974 return box.contentBoxRect();
1979 ASSERT_NOT_REACHED();
1980 return LayoutRect();
1983 FloatRect RenderLayerBacking::backgroundBoxForPainting() const
1985 if (!renderer().isBox())
1988 LayoutRect backgroundBox = backgroundRectForBox(toRenderBox(renderer()));
1989 backgroundBox.move(contentOffsetInCompostingLayer());
1990 return pixelSnappedForPainting(backgroundBox, deviceScaleFactor());
1993 GraphicsLayer* RenderLayerBacking::parentForSublayers() const
1995 if (m_scrollingContentsLayer)
1996 return m_scrollingContentsLayer.get();
1999 // FIXME: Can we remove this iOS-specific code path?
2000 if (GraphicsLayer* clippingLayer = this->clippingLayer())
2001 return clippingLayer;
2002 return m_graphicsLayer.get();
2004 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
2008 GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
2010 if (m_ancestorClippingLayer)
2011 return m_ancestorClippingLayer.get();
2013 if (m_contentsContainmentLayer)
2014 return m_contentsContainmentLayer.get();
2016 return m_graphicsLayer.get();
2019 bool RenderLayerBacking::paintsIntoWindow() const
2021 if (m_usingTiledCacheLayer)
2024 if (m_owningLayer.isRootLayer()) {
2025 #if PLATFORM(IOS) || USE(COORDINATED_GRAPHICS)
2026 if (compositor().inForcedCompositingMode())
2030 return compositor().rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
2036 void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
2038 if (requiresOwnBacking == m_requiresOwnBackingStore)
2041 m_requiresOwnBackingStore = requiresOwnBacking;
2043 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
2044 // cached clip rects, so when it changes we have to clear clip rects on descendants.
2045 m_owningLayer.clearClipRectsIncludingDescendants(PaintingClipRects);
2046 m_owningLayer.computeRepaintRectsIncludingDescendants();
2048 compositor().repaintInCompositedAncestor(m_owningLayer, compositedBounds());
2051 void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer shouldClip)
2053 ASSERT(!paintsIntoCompositedAncestor());
2055 FrameView& frameView = owningLayer().renderer().view().frameView();
2056 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2057 frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBoxForPainting());
2059 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2060 // By default, setNeedsDisplay will clip to the size of the GraphicsLayer, which does not include margin tiles.
2061 // So if the TiledBacking has a margin that needs to be invalidated, we need to send in a rect to setNeedsDisplayInRect
2062 // that is large enough to include the margin. TiledBacking::bounds() includes the margin.
2063 TiledBacking* tiledBacking = this->tiledBacking();
2064 FloatRect rectToRepaint = tiledBacking ? tiledBacking->bounds() : FloatRect(FloatPoint(0, 0), m_graphicsLayer->size());
2065 m_graphicsLayer->setNeedsDisplayInRect(rectToRepaint, shouldClip);
2068 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
2069 m_foregroundLayer->setNeedsDisplay();
2071 if (m_backgroundLayer && m_backgroundLayer->drawsContent())
2072 m_backgroundLayer->setNeedsDisplay();
2074 if (m_maskLayer && m_maskLayer->drawsContent())
2075 m_maskLayer->setNeedsDisplay();
2077 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
2078 m_scrollingContentsLayer->setNeedsDisplay();
2081 // r is in the coordinate space of the layer's render object
2082 void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, GraphicsLayer::ShouldClipToLayer shouldClip)
2084 ASSERT(!paintsIntoCompositedAncestor());
2086 FloatRect pixelSnappedRectForPainting = pixelSnappedForPainting(r, deviceScaleFactor());
2087 FrameView& frameView = owningLayer().renderer().view().frameView();
2088 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2089 frameView.addTrackedRepaintRect(pixelSnappedRectForPainting);
2091 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2092 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2093 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
2094 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2097 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
2098 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2099 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
2100 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2103 // FIXME: need to split out repaints for the background.
2104 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
2105 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2106 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
2107 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2110 if (m_maskLayer && m_maskLayer->drawsContent()) {
2111 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2112 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
2113 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2116 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
2117 FloatRect layerDirtyRect = pixelSnappedRectForPainting;
2118 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
2120 // Account for the fact that RenderLayerBacking::updateGraphicsLayerGeometry() bakes scrollOffset into offsetFromRenderer on iOS.
2121 layerDirtyRect.move(-m_owningLayer.scrollOffset() + m_devicePixelFractionFromRenderer);
2123 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2127 void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context,
2128 const IntRect& paintDirtyRect, // In the coords of rootLayer.
2129 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
2131 if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
2133 // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy
2134 // when pages are restored from the PageCache.
2135 // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache
2136 ASSERT_NOT_REACHED();
2141 FontCachePurgePreventer fontCachePurgePreventer;
2143 RenderLayer::PaintLayerFlags paintFlags = 0;
2144 if (paintingPhase & GraphicsLayerPaintBackground)
2145 paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase;
2146 if (paintingPhase & GraphicsLayerPaintForeground)
2147 paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
2148 if (paintingPhase & GraphicsLayerPaintMask)
2149 paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
2150 if (paintingPhase & GraphicsLayerPaintOverflowContents)
2151 paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
2152 if (paintingPhase & GraphicsLayerPaintCompositedScroll)
2153 paintFlags |= RenderLayer::PaintLayerPaintingCompositingScrollingPhase;
2155 if (graphicsLayer == m_backgroundLayer.get())
2156 paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
2157 else if (compositor().fixedRootBackgroundLayer())
2158 paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground;
2161 RenderElement::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(&m_owningLayer.renderer());
2164 FrameView::PaintingState paintingState;
2165 if (m_owningLayer.isRootLayer())
2166 m_owningLayer.renderer().view().frameView().willPaintContents(context, paintDirtyRect, paintingState);
2168 // FIXME: GraphicsLayers need a way to split for RenderRegions.
2169 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, m_devicePixelFractionFromRenderer);
2170 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags);
2172 if (m_owningLayer.containsDirtyOverlayScrollbars())
2173 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
2175 if (m_owningLayer.isRootLayer())
2176 m_owningLayer.renderer().view().frameView().didPaintContents(context, paintDirtyRect, paintingState);
2178 compositor().didPaintBacking(this);
2180 ASSERT(!m_owningLayer.m_usedTransparency);
2183 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
2189 const IntRect& scrollbarRect = scrollbar->frameRect();
2190 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
2191 IntRect transformedClip = clip;
2192 transformedClip.moveBy(scrollbarRect.location());
2193 scrollbar->paint(&context, transformedClip);
2197 // Up-call from compositing layer drawing callback.
2198 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const FloatRect& clip)
2201 if (Page* page = renderer().frame().page())
2202 page->setIsPainting(true);
2205 // The dirtyRect is in the coords of the painting root.
2206 IntRect dirtyRect = enclosingIntRect(clip);
2208 if (graphicsLayer == m_graphicsLayer.get()
2209 || graphicsLayer == m_foregroundLayer.get()
2210 || graphicsLayer == m_backgroundLayer.get()
2211 || graphicsLayer == m_maskLayer.get()
2212 || graphicsLayer == m_scrollingContentsLayer.get()) {
2213 InspectorInstrumentation::willPaint(&renderer());
2215 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
2216 dirtyRect.intersect(enclosingIntRect(compositedBoundsIncludingMargin()));
2218 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2219 paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
2221 InspectorInstrumentation::didPaint(&renderer(), &context, dirtyRect);
2222 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2223 paintScrollbar(m_owningLayer.horizontalScrollbar(), context, dirtyRect);
2224 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2225 paintScrollbar(m_owningLayer.verticalScrollbar(), context, dirtyRect);
2226 } else if (graphicsLayer == layerForScrollCorner()) {
2227 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
2229 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
2230 LayoutRect transformedClip = LayoutRect(clip);
2231 transformedClip.moveBy(scrollCornerAndResizer.location());
2232 m_owningLayer.paintScrollCorner(&context, IntPoint(), pixelSnappedIntRect(transformedClip));
2233 m_owningLayer.paintResizer(&context, IntPoint(), transformedClip);
2237 if (Page* page = renderer().frame().page())
2238 page->setIsPainting(false);
2242 float RenderLayerBacking::pageScaleFactor() const
2244 return compositor().pageScaleFactor();
2247 float RenderLayerBacking::deviceScaleFactor() const
2249 return compositor().deviceScaleFactor();
2252 float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer* layer) const
2254 return compositor().contentsScaleMultiplierForNewTiles(layer);
2257 bool RenderLayerBacking::paintsOpaquelyAtNonIntegralScales(const GraphicsLayer*) const
2259 return m_isMainFrameRenderViewLayer;
2262 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
2264 compositor().didFlushChangesForLayer(m_owningLayer, layer);
2267 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
2269 GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
2270 if (graphicsLayer != transformedLayer)
2273 if (m_owningLayer.hasTransform()) {
2274 transform = m_owningLayer.currentTransform(RenderStyle::ExcludeTransformOrigin);
2280 bool RenderLayerBacking::isTrackingRepaints() const
2282 return static_cast<GraphicsLayerClient&>(compositor()).isTrackingRepaints();
2285 bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer) const
2287 // Skip the root tile cache's flattening layer.
2288 return m_isMainFrameRenderViewLayer && layer && layer == m_childContainmentLayer.get();
2291 bool RenderLayerBacking::shouldDumpPropertyForLayer(const GraphicsLayer* layer, const char* propertyName) const
2293 // For backwards compatibility with WebKit1 and other platforms,
2294 // skip some properties on the root tile cache.
2295 if (m_isMainFrameRenderViewLayer && layer == m_graphicsLayer.get()) {
2296 if (!strcmp(propertyName, "drawsContent"))
2299 // Background color could be of interest to tests or other dumpers if it's non-white.
2300 if (!strcmp(propertyName, "backgroundColor") && layer->backgroundColor() == Color::white)
2303 // The root tile cache's repaints will show up at the top with FrameView's,
2304 // so don't dump them twice.
2305 if (!strcmp(propertyName, "repaintRects"))
2312 bool RenderLayerBacking::shouldAggressivelyRetainTiles(const GraphicsLayer*) const
2314 // Only the main frame TileController has enough information about in-window state to
2315 // correctly implement aggressive tile retention.
2316 if (!m_isMainFrameRenderViewLayer)
2319 if (Page* page = renderer().frame().page())
2320 return page->settings().aggressiveTileRetentionEnabled();
2324 bool RenderLayerBacking::shouldTemporarilyRetainTileCohorts(const GraphicsLayer*) const
2326 if (Page* page = renderer().frame().page())
2327 return page->settings().temporaryTileCohortRetentionEnabled();
2332 void RenderLayerBacking::verifyNotPainting()
2334 ASSERT(!renderer().frame().page() || !renderer().frame().page()->isPainting());
2338 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
2340 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
2341 bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
2342 #if ENABLE(CSS_FILTERS)
2343 bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
2345 bool hasFilter = false;
2348 if (!hasOpacity && !hasTransform && !hasFilter)
2351 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
2352 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2353 #if ENABLE(CSS_FILTERS)
2354 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
2357 size_t numKeyframes = keyframes.size();
2358 for (size_t i = 0; i < numKeyframes; ++i) {
2359 const KeyframeValue& currentKeyframe = keyframes[i];
2360 const RenderStyle* keyframeStyle = currentKeyframe.style();
2361 double key = currentKeyframe.key();
2366 // Get timing function.
2367 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0).timingFunction() : 0;
2369 bool isFirstOrLastKeyframe = key == 0 || key == 1;
2370 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
2371 transformVector.insert(TransformAnimationValue::create(key, keyframeStyle->transform(), tf));
2373 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
2374 opacityVector.insert(FloatAnimationValue::create(key, keyframeStyle->opacity(), tf));
2376 #if ENABLE(CSS_FILTERS)
2377 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
2378 filterVector.insert(FilterAnimationValue::create(key, keyframeStyle->filter(), tf));
2382 if (renderer().frame().page() && !renderer().frame().page()->settings().acceleratedCompositedAnimationsEnabled())
2385 bool didAnimate = false;
2387 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
2390 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2393 #if ENABLE(CSS_FILTERS)
2394 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2401 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
2403 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
2406 void RenderLayerBacking::animationFinished(const String& animationName)
2408 m_graphicsLayer->removeAnimation(animationName);
2411 bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
2413 bool didAnimate = false;
2415 ASSERT(property != CSSPropertyInvalid);
2417 if (property == CSSPropertyOpacity) {
2418 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
2419 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
2420 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2421 opacityVector.insert(FloatAnimationValue::create(0, compositingOpacity(fromStyle->opacity())));
2422 opacityVector.insert(FloatAnimationValue::create(1, compositingOpacity(toStyle->opacity())));
2423 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
2424 if (m_graphicsLayer->addAnimation(opacityVector, FloatSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
2425 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
2426 updateOpacity(toStyle);
2432 if (property == CSSPropertyWebkitTransform && m_owningLayer.hasTransform()) {
2433 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
2434 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
2435 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
2436 transformVector.insert(TransformAnimationValue::create(0, fromStyle->transform()));
2437 transformVector.insert(TransformAnimationValue::create(1, toStyle->transform()));
2438 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
2439 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
2440 updateTransform(toStyle);
2446 #if ENABLE(CSS_FILTERS)
2447 if (property == CSSPropertyWebkitFilter && m_owningLayer.hasFilter()) {
2448 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
2449 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
2450 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
2451 filterVector.insert(FilterAnimationValue::create(0, fromStyle->filter()));
2452 filterVector.insert(FilterAnimationValue::create(1, toStyle->filter()));
2453 if (m_graphicsLayer->addAnimation(filterVector, FloatSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) {
2454 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
2455 updateFilters(toStyle);
2465 void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
2467 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2468 if (animatedProperty != AnimatedPropertyInvalid)
2469 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
2472 void RenderLayerBacking::transitionFinished(CSSPropertyID property)
2474 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2475 if (animatedProperty != AnimatedPropertyInvalid)
2476 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
2479 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
2481 renderer().animation().notifyAnimationStarted(&renderer(), time);
2484 void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer)
2486 if (renderer().documentBeingDestroyed())
2488 compositor().scheduleLayerFlush(layer->canThrottleLayerFlush());
2491 void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
2493 compositor().notifyFlushBeforeDisplayRefresh(layer);
2496 // This is used for the 'freeze' API, for testing only.
2497 void RenderLayerBacking::suspendAnimations(double time)
2499 m_graphicsLayer->suspendAnimations(time);
2502 void RenderLayerBacking::resumeAnimations()
2504 m_graphicsLayer->resumeAnimations();
2507 LayoutRect RenderLayerBacking::compositedBounds() const
2509 return m_compositedBounds;
2512 void RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds)
2514 m_compositedBounds = bounds;
2517 LayoutRect RenderLayerBacking::compositedBoundsIncludingMargin() const
2519 TiledBacking* tiledBacking = this->tiledBacking();
2520 if (!tiledBacking || !tiledBacking->hasMargins())
2521 return compositedBounds();
2523 LayoutRect boundsIncludingMargin = compositedBounds();
2524 LayoutUnit leftMarginWidth = tiledBacking->leftMarginWidth();
2525 LayoutUnit topMarginHeight = tiledBacking->topMarginHeight();
2527 boundsIncludingMargin.moveBy(LayoutPoint(-leftMarginWidth, -topMarginHeight));
2528 boundsIncludingMargin.expand(leftMarginWidth + tiledBacking->rightMarginWidth(), topMarginHeight + tiledBacking->bottomMarginHeight());
2530 return boundsIncludingMargin;
2533 CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
2535 CSSPropertyID cssProperty = CSSPropertyInvalid;
2537 case AnimatedPropertyWebkitTransform:
2538 cssProperty = CSSPropertyWebkitTransform;
2540 case AnimatedPropertyOpacity:
2541 cssProperty = CSSPropertyOpacity;
2543 case AnimatedPropertyBackgroundColor:
2544 cssProperty = CSSPropertyBackgroundColor;
2546 case AnimatedPropertyWebkitFilter:
2547 #if ENABLE(CSS_FILTERS)
2548 cssProperty = CSSPropertyWebkitFilter;
2550 ASSERT_NOT_REACHED();
2553 case AnimatedPropertyInvalid:
2554 ASSERT_NOT_REACHED();
2559 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
2561 switch (cssProperty) {
2562 case CSSPropertyWebkitTransform:
2563 return AnimatedPropertyWebkitTransform;
2564 case CSSPropertyOpacity:
2565 return AnimatedPropertyOpacity;
2566 case CSSPropertyBackgroundColor:
2567 return AnimatedPropertyBackgroundColor;
2568 #if ENABLE(CSS_FILTERS)
2569 case CSSPropertyWebkitFilter:
2570 return AnimatedPropertyWebkitFilter;
2573 // It's fine if we see other css properties here; they are just not accelerated.
2576 return AnimatedPropertyInvalid;
2579 CompositingLayerType RenderLayerBacking::compositingLayerType() const
2581 if (m_graphicsLayer->hasContentsLayer())
2582 return MediaCompositingLayer;
2584 if (m_graphicsLayer->drawsContent())
2585 return m_graphicsLayer->usingTiledBacking() ? TiledCompositingLayer : NormalCompositingLayer;
2587 return ContainerCompositingLayer;
2590 double RenderLayerBacking::backingStoreMemoryEstimate() const
2592 double backingMemory;
2594 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
2595 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
2596 if (m_foregroundLayer)
2597 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
2598 if (m_backgroundLayer)
2599 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
2601 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
2603 if (m_scrollingContentsLayer)
2604 backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
2606 if (m_layerForHorizontalScrollbar)
2607 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
2609 if (m_layerForVerticalScrollbar)
2610 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
2612 if (m_layerForScrollCorner)
2613 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
2615 return backingMemory;
2618 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2619 bool RenderLayerBacking::mediaLayerMustBeUpdatedOnMainThread() const
2621 return renderer().frame().page() && renderer().frame().page()->settings().isVideoPluginProxyEnabled();
2625 } // namespace WebCore