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 COMPUTER, 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 #if USE(ACCELERATED_COMPOSITING)
30 #include "RenderLayerBacking.h"
32 #include "AnimationController.h"
33 #include "CanvasRenderingContext.h"
34 #include "CSSPropertyNames.h"
35 #include "CachedImage.h"
37 #include "FontCache.h"
38 #include "FrameView.h"
39 #include "GraphicsContext.h"
40 #include "GraphicsLayer.h"
41 #include "HTMLCanvasElement.h"
42 #include "HTMLIFrameElement.h"
43 #include "HTMLMediaElement.h"
44 #include "HTMLNames.h"
45 #include "HTMLPlugInElement.h"
46 #include "InspectorInstrumentation.h"
47 #include "KeyframeList.h"
48 #include "MainFrame.h"
49 #include "PluginViewBase.h"
50 #include "ProgressTracker.h"
51 #include "RenderFlowThread.h"
52 #include "RenderIFrame.h"
53 #include "RenderImage.h"
54 #include "RenderLayerCompositor.h"
55 #include "RenderEmbeddedObject.h"
56 #include "RenderNamedFlowFragment.h"
57 #include "RenderRegion.h"
58 #include "RenderVideo.h"
59 #include "RenderView.h"
60 #include "ScrollingCoordinator.h"
62 #include "StyleResolver.h"
63 #include "TiledBacking.h"
64 #include <wtf/text/StringBuilder.h>
66 #if ENABLE(CSS_FILTERS)
67 #include "FilterEffectRenderer.h"
68 #if ENABLE(CSS_SHADERS)
69 #include "CustomFilterOperation.h"
73 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
74 #include "GraphicsContext3D.h"
79 using namespace HTMLNames;
81 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
82 static IntRect clipBox(RenderBox& renderer);
84 CanvasCompositingStrategy canvasCompositingStrategy(const RenderObject& renderer)
86 ASSERT(renderer.isCanvas());
88 const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer.node());
89 CanvasRenderingContext* context = canvas->renderingContext();
90 if (!context || !context->isAccelerated())
91 return UnacceleratedCanvas;
94 return CanvasAsLayerContents;
96 #if ENABLE(ACCELERATED_2D_CANVAS)
97 return CanvasAsLayerContents;
99 return CanvasPaintedToLayer; // On Mac and iOS we paint accelerated canvases into their layers.
103 // Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor.
104 static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer)
106 Page* page = layer.renderer().frame().page();
110 return page->scrollingCoordinator();
113 bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false;
115 RenderLayerBacking::RenderLayerBacking(RenderLayer& layer)
116 : m_owningLayer(layer)
118 , m_artificiallyInflatedBounds(false)
119 , m_isMainFrameRenderViewLayer(false)
120 , m_usingTiledCacheLayer(false)
121 , m_requiresOwnBackingStore(true)
122 #if ENABLE(CSS_FILTERS)
123 , m_canCompositeFilters(false)
125 , m_backgroundLayerPaintsFixedRootBackground(false)
126 , m_didSwitchToFullTileCoverageDuringLoading(false)
128 Page* page = renderer().frame().page();
130 if (layer.isRootLayer() && page) {
131 if (renderer().frame().isMainFrame())
132 m_isMainFrameRenderViewLayer = true;
134 m_usingTiledCacheLayer = page->chrome().client().shouldUseTiledBackingForFrameView(renderer().frame().view());
137 createPrimaryGraphicsLayer();
139 if (m_usingTiledCacheLayer && page) {
140 TiledBacking* tiledBacking = this->tiledBacking();
142 tiledBacking->setIsInWindow(page->isInWindow());
144 if (m_isMainFrameRenderViewLayer) {
145 tiledBacking->setExposedRect(renderer().frame().view()->exposedRect());
146 tiledBacking->setUnparentsOffscreenTiles(true);
147 setTiledBackingHasMargins(page->settings().backgroundShouldExtendBeyondPage());
150 tiledBacking->setScrollingPerformanceLoggingEnabled(page->settings().scrollingPerformanceLoggingEnabled());
151 adjustTiledBackingCoverage();
155 RenderLayerBacking::~RenderLayerBacking()
157 updateAncestorClippingLayer(false);
158 updateDescendantClippingLayer(false);
159 updateOverflowControlsLayers(false, false, false);
160 updateForegroundLayer(false);
161 updateBackgroundLayer(false);
162 updateMaskLayer(false);
163 updateScrollingLayers(false);
164 detachFromScrollingCoordinator();
165 destroyGraphicsLayers();
168 void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer)
170 if (layer && layer->usingTiledBacking())
171 compositor().layerTiledBackingUsageChanged(layer, false);
174 std::unique_ptr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name)
176 GraphicsLayerFactory* graphicsLayerFactory = 0;
177 if (Page* page = renderer().frame().page())
178 graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
180 std::unique_ptr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
183 graphicsLayer->setName(name);
187 graphicsLayer->setMaintainsPixelAlignment(compositor().keepLayersPixelAligned());
189 #if PLATFORM(MAC) && USE(CA)
190 graphicsLayer->setAcceleratesDrawing(compositor().acceleratedDrawingEnabled());
193 return graphicsLayer;
196 bool RenderLayerBacking::shouldUseTiledBacking(const GraphicsLayer*) const
198 return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer;
201 bool RenderLayerBacking::tiledBackingHasMargin() const
203 return m_usingTiledCacheLayer && tiledBacking()->hasMargins();
206 void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking)
208 compositor().layerTiledBackingUsageChanged(layer, usingTiledBacking);
211 TiledBacking* RenderLayerBacking::tiledBacking() const
213 return m_graphicsLayer->tiledBacking();
216 static TiledBacking::TileCoverage computeTileCoverage(RenderLayerBacking* backing)
218 // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability.
219 FrameView& frameView = backing->owningLayer().renderer().view().frameView();
221 TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea;
222 bool useMinimalTilesDuringLiveResize = frameView.inLiveResize();
223 bool useMinimalTilesDuringLoading = false;
225 if (!backing->didSwitchToFullTileCoverageDuringLoading()) {
226 useMinimalTilesDuringLoading = !frameView.isVisuallyNonEmpty() || (frameView.frame().page()->progress().isMainLoadProgressing() && !frameView.wasScrolledByUser());
227 if (!useMinimalTilesDuringLoading)
228 backing->setDidSwitchToFullTileCoverageDuringLoading();
230 if (!(useMinimalTilesDuringLoading || useMinimalTilesDuringLiveResize)) {
231 bool clipsToExposedRect = !frameView.exposedRect().isInfinite();
232 if (frameView.horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
233 tileCoverage |= TiledBacking::CoverageForHorizontalScrolling;
235 if (frameView.verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect)
236 tileCoverage |= TiledBacking::CoverageForVerticalScrolling;
238 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(backing->owningLayer())) {
239 // Ask our TiledBacking for large tiles unless the only reason we're main-thread-scrolling
240 // is a page overlay (find-in-page, the Web Inspector highlight mechanism, etc.).
241 if (scrollingCoordinator->synchronousScrollingReasons() & ~ScrollingCoordinator::ForcedOnMainThread)
242 tileCoverage |= TiledBacking::CoverageForSlowScrolling;
247 void RenderLayerBacking::adjustTiledBackingCoverage()
249 if (!m_usingTiledCacheLayer)
252 TiledBacking::TileCoverage tileCoverage = computeTileCoverage(this);
253 tiledBacking()->setTileCoverage(tileCoverage);
256 void RenderLayerBacking::setTiledBackingHasMargins(bool extendBackground)
258 if (!m_usingTiledCacheLayer)
261 int marginSize = extendBackground ? 512 : 0;
262 tiledBacking()->setTileMargins(marginSize, marginSize, marginSize, marginSize);
265 void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter)
267 m_graphicsLayer->setShowDebugBorder(showBorder);
268 m_graphicsLayer->setShowRepaintCounter(showRepaintCounter);
270 if (m_ancestorClippingLayer)
271 m_ancestorClippingLayer->setShowDebugBorder(showBorder);
273 if (m_foregroundLayer) {
274 m_foregroundLayer->setShowDebugBorder(showBorder);
275 m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
278 if (m_contentsContainmentLayer)
279 m_contentsContainmentLayer->setShowDebugBorder(showBorder);
281 if (m_backgroundLayer) {
282 m_backgroundLayer->setShowDebugBorder(showBorder);
283 m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
287 m_maskLayer->setShowDebugBorder(showBorder);
288 m_maskLayer->setShowRepaintCounter(showRepaintCounter);
291 if (m_layerForHorizontalScrollbar)
292 m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
294 if (m_layerForVerticalScrollbar)
295 m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
297 if (m_layerForScrollCorner)
298 m_layerForScrollCorner->setShowDebugBorder(showBorder);
300 if (m_scrollingLayer)
301 m_scrollingLayer->setShowDebugBorder(showBorder);
303 if (m_scrollingContentsLayer) {
304 m_scrollingContentsLayer->setShowDebugBorder(showBorder);
305 m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter);
309 void RenderLayerBacking::createPrimaryGraphicsLayer()
313 layerName = m_owningLayer.name();
316 // The call to createGraphicsLayer ends calling back into here as
317 // a GraphicsLayerClient to ask if it shouldUseTiledBacking(). We only want
318 // the tile cache on our main layer. This is pretty ugly, but saves us from
319 // exposing the API to all clients.
321 m_creatingPrimaryGraphicsLayer = true;
322 m_graphicsLayer = createGraphicsLayer(layerName);
323 m_creatingPrimaryGraphicsLayer = false;
325 if (m_usingTiledCacheLayer)
326 m_childContainmentLayer = createGraphicsLayer("TiledBacking Flattening Layer");
328 if (m_isMainFrameRenderViewLayer) {
330 // Page scale is applied above the RenderView on iOS.
331 m_graphicsLayer->setContentsOpaque(true);
332 m_graphicsLayer->setAppliesPageScale();
336 #if PLATFORM(MAC) && USE(CA)
337 if (!compositor().acceleratedDrawingEnabled() && renderer().isCanvas()) {
338 const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer().element());
339 if (canvas->shouldAccelerate(canvas->size()))
340 m_graphicsLayer->setAcceleratesDrawing(true);
344 updateOpacity(&renderer().style());
345 updateTransform(&renderer().style());
346 #if ENABLE(CSS_FILTERS)
347 updateFilters(&renderer().style());
349 #if ENABLE(CSS_COMPOSITING)
350 updateBlendMode(&renderer().style());
355 void RenderLayerBacking::layerWillBeDestroyed()
357 RenderObject& renderer = this->renderer();
358 if (renderer.isEmbeddedObject() && toRenderEmbeddedObject(renderer).allowsAcceleratedCompositing()) {
359 PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(renderer).widget());
360 if (pluginViewBase && m_graphicsLayer->contentsLayerForMedia())
361 pluginViewBase->detachPluginLayer();
366 void RenderLayerBacking::destroyGraphicsLayers()
368 if (m_graphicsLayer) {
369 willDestroyLayer(m_graphicsLayer.get());
370 m_graphicsLayer->removeFromParent();
373 m_ancestorClippingLayer = nullptr;
374 m_contentsContainmentLayer = nullptr;
375 m_graphicsLayer = nullptr;
376 m_foregroundLayer = nullptr;
377 m_backgroundLayer = nullptr;
378 m_childContainmentLayer = nullptr;
379 m_maskLayer = nullptr;
381 m_scrollingLayer = nullptr;
382 m_scrollingContentsLayer = nullptr;
385 void RenderLayerBacking::updateOpacity(const RenderStyle* style)
387 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
390 void RenderLayerBacking::updateTransform(const RenderStyle* style)
392 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
393 // baked into it, and we don't want that.
394 TransformationMatrix t;
395 if (m_owningLayer.hasTransform()) {
396 style->applyTransform(t, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
397 makeMatrixRenderable(t, compositor().canRender3DTransforms());
400 if (m_contentsContainmentLayer) {
401 m_contentsContainmentLayer->setTransform(t);
402 m_graphicsLayer->setTransform(TransformationMatrix());
404 m_graphicsLayer->setTransform(t);
407 #if ENABLE(CSS_FILTERS)
408 void RenderLayerBacking::updateFilters(const RenderStyle* style)
410 m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer().computeFilterOperations(style));
414 #if ENABLE(CSS_COMPOSITING)
415 void RenderLayerBacking::updateBlendMode(const RenderStyle* style)
417 if (m_ancestorClippingLayer)
418 m_ancestorClippingLayer->setBlendMode(style->blendMode());
420 m_graphicsLayer->setBlendMode(style->blendMode());
424 static bool hasNonZeroTransformOrigin(const RenderObject& renderer)
426 const RenderStyle& style = renderer.style();
427 return (style.transformOriginX().type() == Fixed && style.transformOriginX().value())
428 || (style.transformOriginY().type() == Fixed && style.transformOriginY().value());
432 // FIXME: We should merge the concept of RenderLayer::{hasAcceleratedTouchScrolling, needsCompositedScrolling}()
433 // so that we can remove this iOS-specific variant.
434 static bool layerOrAncestorIsTransformedOrScrolling(RenderLayer& layer)
436 for (RenderLayer* curr = &layer; curr; curr = curr->parent()) {
437 if (curr->hasTransform() || curr->hasAcceleratedTouchScrolling())
444 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer& layer)
446 for (RenderLayer* curr = &layer; curr; curr = curr->parent()) {
447 if (curr->hasTransform() || curr->needsCompositedScrolling())
455 bool RenderLayerBacking::shouldClipCompositedBounds() const
458 // Scrollbar layers use this layer for relative positioning, so don't clip.
459 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
463 if (m_usingTiledCacheLayer)
467 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
470 if (layerOrAncestorIsTransformedOrScrolling(m_owningLayer))
474 if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions())
480 void RenderLayerBacking::updateCompositedBounds()
482 LayoutRect layerBounds = compositor().calculateCompositedBounds(m_owningLayer, m_owningLayer);
484 // Clip to the size of the document or enclosing overflow-scroll layer.
485 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
486 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
487 if (shouldClipCompositedBounds()) {
488 RenderView& view = m_owningLayer.renderer().view();
489 RenderLayer* rootLayer = view.layer();
491 LayoutRect clippingBounds;
492 if (renderer().style().position() == FixedPosition && renderer().container() == &view)
493 clippingBounds = view.frameView().viewportConstrainedVisibleContentRect();
495 clippingBounds = view.unscaledDocumentRect();
497 if (&m_owningLayer != rootLayer)
498 clippingBounds.intersect(m_owningLayer.backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
501 m_owningLayer.convertToLayerCoords(rootLayer, delta, RenderLayer::AdjustForColumns);
502 clippingBounds.move(-delta.x(), -delta.y());
504 layerBounds.intersect(clippingBounds);
507 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
508 // then we need to ensure that the compositing layer has non-zero size so that we can apply
509 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
510 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
511 layerBounds.setWidth(1);
512 layerBounds.setHeight(1);
513 m_artificiallyInflatedBounds = true;
515 m_artificiallyInflatedBounds = false;
517 setCompositedBounds(layerBounds);
520 void RenderLayerBacking::updateAfterWidgetResize()
522 if (!renderer().isWidget())
524 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderWidget(&renderer()))) {
525 innerCompositor->frameViewDidChangeSize();
526 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
530 void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags)
532 if (!compositor().compositingLayersNeedRebuild()) {
533 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
534 // position of this layer's GraphicsLayer depends on the position of our compositing
535 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
536 // RenderLayers of that ancestor have been processed via updateLayerPositions().
538 // The solution is to update compositing children of this layer here,
539 // via updateCompositingChildrenGeometry().
540 updateCompositedBounds();
541 compositor().updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly);
543 if (flags & IsUpdateRoot) {
544 updateGraphicsLayerGeometry();
545 compositor().updateRootLayerPosition();
546 RenderLayer* stackingContainer = m_owningLayer.enclosingStackingContainer();
547 if (!compositor().compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != &m_owningLayer))
548 compositor().updateCompositingDescendantGeometry(*stackingContainer, *stackingContainer, flags & CompositingChildrenOnly);
552 if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor())
553 setContentsNeedDisplay();
556 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
558 m_owningLayer.updateDescendantDependentFlags();
559 m_owningLayer.updateZOrderLists();
561 bool layerConfigChanged = false;
562 setBackgroundLayerPaintsFixedRootBackground(compositor().needsFixedRootBackgroundLayer(m_owningLayer));
564 // The background layer is currently only used for fixed root backgrounds.
565 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
566 layerConfigChanged = true;
568 if (updateForegroundLayer(compositor().needsContentsCompositingLayer(m_owningLayer)))
569 layerConfigChanged = true;
571 bool needsDescendentsClippingLayer = compositor().clipsCompositingDescendants(m_owningLayer);
574 // Our scrolling layer will clip.
575 if (m_owningLayer.hasAcceleratedTouchScrolling())
576 needsDescendentsClippingLayer = false;
578 // Our scrolling layer will clip.
579 if (m_owningLayer.needsCompositedScrolling())
580 needsDescendentsClippingLayer = false;
581 #endif // PLATFORM(IOS)
583 if (updateAncestorClippingLayer(compositor().clippedByAncestor(m_owningLayer)))
584 layerConfigChanged = true;
586 if (updateDescendantClippingLayer(needsDescendentsClippingLayer))
587 layerConfigChanged = true;
589 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
590 layerConfigChanged = true;
593 if (updateScrollingLayers(m_owningLayer.hasAcceleratedTouchScrolling()))
594 layerConfigChanged = true;
596 if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling()))
597 layerConfigChanged = true;
598 #endif // PLATFORM(IOS)
600 if (layerConfigChanged)
601 updateInternalHierarchy();
603 if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) {
604 if (layerConfigChanged || flatteningLayer->parent() != m_graphicsLayer.get())
605 m_graphicsLayer->addChild(flatteningLayer);
608 if (updateMaskLayer(renderer().hasMask()))
609 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
611 if (m_owningLayer.hasReflection()) {
612 if (m_owningLayer.reflectionLayer()->backing()) {
613 GraphicsLayer* reflectionLayer = m_owningLayer.reflectionLayer()->backing()->graphicsLayer();
614 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
617 m_graphicsLayer->setReplicatedByLayer(0);
619 bool isSimpleContainer = isSimpleContainerCompositingLayer();
620 bool didUpdateContentsRect = false;
621 updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect);
623 updateRootLayerConfiguration();
625 if (isDirectlyCompositedImage())
626 updateImageContents();
628 if (renderer().isEmbeddedObject() && toRenderEmbeddedObject(&renderer())->allowsAcceleratedCompositing()) {
629 PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(&renderer())->widget());
631 if (pluginViewBase && !m_graphicsLayer->contentsLayerForMedia()) {
632 pluginViewBase->detachPluginLayer();
633 pluginViewBase->attachPluginLayer();
636 if (!pluginViewBase->shouldNotAddLayer())
637 m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
641 else if (renderer().isVideo()) {
642 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer().element());
643 m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
646 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
647 else if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
648 const HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer().element());
649 if (CanvasRenderingContext* context = canvas->renderingContext())
650 m_graphicsLayer->setContentsToCanvas(context->platformLayer());
651 layerConfigChanged = true;
654 if (renderer().isWidget())
655 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderWidget(&renderer()));
657 return layerConfigChanged;
660 static IntRect clipBox(RenderBox& renderer)
662 LayoutRect result = LayoutRect::infiniteRect();
663 if (renderer.hasOverflowClip())
664 result = renderer.overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
666 if (renderer.hasClip())
667 result.intersect(renderer.clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
669 return pixelSnappedIntRect(result);
672 void RenderLayerBacking::updateGraphicsLayerGeometry()
674 // If we haven't built z-order lists yet, wait until later.
675 if (m_owningLayer.isStackingContainer() && m_owningLayer.m_zOrderListsDirty)
678 // Set transform property, if it is not animating. We have to do this here because the transform
679 // is affected by the layer dimensions.
680 if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(&renderer(), CSSPropertyWebkitTransform))
681 updateTransform(&renderer().style());
683 // Set opacity, if it is not animating.
684 if (!renderer().animation().isRunningAcceleratedAnimationOnRenderer(&renderer(), CSSPropertyOpacity))
685 updateOpacity(&renderer().style());
687 #if ENABLE(CSS_FILTERS)
688 updateFilters(&renderer().style());
691 #if ENABLE(CSS_COMPOSITING)
692 updateBlendMode(&renderer().style());
695 bool isSimpleContainer = isSimpleContainerCompositingLayer();
697 m_owningLayer.updateDescendantDependentFlags();
699 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
700 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
701 // non-compositing visible layers.
702 m_graphicsLayer->setContentsVisible(m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
704 const RenderStyle& style = renderer().style();
705 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
706 bool preserves3D = style.transformStyle3D() == TransformStyle3DPreserve3D && !renderer().hasReflection();
707 m_graphicsLayer->setPreserves3D(preserves3D);
708 m_graphicsLayer->setBackfaceVisibility(style.backfaceVisibility() == BackfaceVisibilityVisible);
710 RenderLayer* compAncestor = m_owningLayer.ancestorCompositingLayer();
712 // We compute everything relative to the enclosing compositing layer.
713 IntRect ancestorCompositingBounds;
715 ASSERT(compAncestor->backing());
716 ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds());
719 LayoutRect localRawCompositingBounds = compositedBounds();
720 LayoutPoint rawDelta;
721 m_owningLayer.convertToLayerCoords(compAncestor, rawDelta, RenderLayer::AdjustForColumns);
722 IntPoint delta = flooredIntPoint(rawDelta);
723 m_subpixelAccumulation = toLayoutSize(rawDelta.fraction());
724 // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates.
725 localRawCompositingBounds.move(m_subpixelAccumulation);
727 IntRect localCompositingBounds = pixelSnappedIntRect(localRawCompositingBounds);
728 IntRect relativeCompositingBounds(localCompositingBounds);
729 relativeCompositingBounds.moveBy(delta);
731 adjustAncestorCompositingBoundsForFlowThread(ancestorCompositingBounds, compAncestor);
733 IntPoint graphicsLayerParentLocation;
734 if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
735 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
736 // position relative to it.
737 IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
738 graphicsLayerParentLocation = clippingBox.location();
739 } else if (compAncestor)
740 graphicsLayerParentLocation = ancestorCompositingBounds.location();
742 graphicsLayerParentLocation = renderer().view().documentRect().location();
745 if (compAncestor && compAncestor->hasAcceleratedTouchScrolling()) {
746 RenderBox* renderBox = toRenderBox(&compAncestor->renderer());
747 IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(),
748 renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(),
749 renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
751 IntSize scrollOffset = compAncestor->scrolledContentOffset();
752 graphicsLayerParentLocation = paddingBox.location() - scrollOffset;
756 if (compAncestor && compAncestor->needsCompositedScrolling()) {
757 RenderBox& renderBox = toRenderBox(compAncestor->renderer());
758 IntSize scrollOffset = compAncestor->scrolledContentOffset();
759 IntPoint scrollOrigin(renderBox.borderLeft(), renderBox.borderTop());
760 graphicsLayerParentLocation = scrollOrigin - scrollOffset;
763 if (compAncestor && m_ancestorClippingLayer) {
764 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
765 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
766 // for a compositing layer, rootLayer is the layer itself.
767 RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
768 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer.backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions.
769 ASSERT(parentClipRect != IntRect::infiniteRect());
770 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
771 m_ancestorClippingLayer->setSize(parentClipRect.size());
773 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
774 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta);
776 // The primary layer is then parented in, and positioned relative to this clipping layer.
777 graphicsLayerParentLocation = parentClipRect.location();
780 FloatSize contentsSize = relativeCompositingBounds.size();
782 if (m_contentsContainmentLayer) {
783 m_contentsContainmentLayer->setPreserves3D(preserves3D);
784 m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
785 // Use the same size as m_graphicsLayer so transforms behave correctly.
786 m_contentsContainmentLayer->setSize(contentsSize);
787 graphicsLayerParentLocation = relativeCompositingBounds.location();
790 m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
791 m_graphicsLayer->setSize(contentsSize);
792 IntSize offsetFromRenderer = toIntSize(localCompositingBounds.location());
793 if (offsetFromRenderer != m_graphicsLayer->offsetFromRenderer()) {
794 m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
795 positionOverflowControlsLayers();
798 if (!m_isMainFrameRenderViewLayer) {
799 // For non-root layers, background is always painted by the primary graphics layer.
800 ASSERT(!m_backgroundLayer);
801 bool hadSubpixelRounding = LayoutSize(relativeCompositingBounds.size()) != localRawCompositingBounds.size();
802 m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer.backgroundIsKnownToBeOpaqueInRect(localCompositingBounds));
805 // If we have a layer that clips children, position it.
807 if (GraphicsLayer* clipLayer = clippingLayer()) {
808 clippingBox = clipBox(toRenderBox(renderer()));
809 clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
810 clipLayer->setSize(clippingBox.size());
811 clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
815 m_maskLayer->setSize(m_graphicsLayer->size());
816 m_maskLayer->setPosition(FloatPoint());
817 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
820 if (m_owningLayer.hasTransform()) {
821 const IntRect borderBox = toRenderBox(renderer()).pixelSnappedBorderBoxRect();
823 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
824 IntRect layerBounds(delta, borderBox.size());
826 // Update properties that depend on layer dimensions
827 FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
828 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
829 FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
830 relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
831 transformOrigin.z());
832 if (m_contentsContainmentLayer)
833 m_contentsContainmentLayer->setAnchorPoint(anchor);
835 m_graphicsLayer->setAnchorPoint(anchor);
837 const RenderStyle& style = renderer().style();
838 GraphicsLayer* clipLayer = clippingLayer();
839 if (style.hasPerspective()) {
840 TransformationMatrix t = owningLayer().perspectiveTransform();
843 clipLayer->setChildrenTransform(t);
844 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
847 m_graphicsLayer->setChildrenTransform(t);
850 clipLayer->setChildrenTransform(TransformationMatrix());
852 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
855 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
856 if (m_contentsContainmentLayer)
857 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
860 if (m_foregroundLayer) {
861 FloatPoint foregroundPosition;
862 FloatSize foregroundSize = contentsSize;
863 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
864 if (hasClippingLayer()) {
865 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
866 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
867 foregroundSize = FloatSize(clippingBox.size());
868 foregroundOffset = toIntSize(clippingBox.location());
871 m_foregroundLayer->setPosition(foregroundPosition);
872 m_foregroundLayer->setSize(foregroundSize);
873 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
876 if (m_backgroundLayer) {
877 FloatPoint backgroundPosition;
878 FloatSize backgroundSize = contentsSize;
879 if (backgroundLayerPaintsFixedRootBackground()) {
880 const FrameView& frameView = renderer().view().frameView();
881 backgroundPosition = IntPoint(frameView.scrollOffsetForFixedPosition());
882 backgroundSize = frameView.visibleContentRect().size();
884 m_backgroundLayer->setPosition(backgroundPosition);
885 m_backgroundLayer->setSize(backgroundSize);
886 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
889 if (m_owningLayer.reflectionLayer() && m_owningLayer.reflectionLayer()->isComposited()) {
890 RenderLayerBacking* reflectionBacking = m_owningLayer.reflectionLayer()->backing();
891 reflectionBacking->updateGraphicsLayerGeometry();
893 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
894 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
895 FloatRect layerBounds = compositedBounds();
896 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
897 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
900 if (m_scrollingLayer) {
901 ASSERT(m_scrollingContentsLayer);
902 RenderBox& renderBox = toRenderBox(renderer());
903 IntRect paddingBox(renderBox.borderLeft(), renderBox.borderTop(), renderBox.width() - renderBox.borderLeft() - renderBox.borderRight(), renderBox.height() - renderBox.borderTop() - renderBox.borderBottom());
904 IntSize scrollOffset = m_owningLayer.scrollOffset();
906 m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location()));
908 m_scrollingLayer->setSize(paddingBox.size());
910 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
911 m_scrollingLayer->setOffsetFromRenderer(IntPoint() - paddingBox.location());
912 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
914 if (m_owningLayer.isInUserScroll()) {
915 // If scrolling is happening externally, we don't want to touch the layer bounds origin here because that will cause
916 // jitter. Set a flag to ensure that we sync up later.
917 m_owningLayer.setRequiresScrollBoundsOriginUpdate(true);
919 // Note that we implement the contents offset via the bounds origin on this layer, rather than a position on the sublayer.
920 m_scrollingLayer->setBoundsOrigin(FloatPoint(scrollOffset.width(), scrollOffset.height()));
921 m_owningLayer.setRequiresScrollBoundsOriginUpdate(false);
924 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
926 m_scrollingContentsLayer->setPosition(FloatPoint());
928 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
929 m_scrollingContentsLayer->setNeedsDisplay();
931 m_scrollingContentsLayer->setSize(scrollSize);
932 // Scrolling the content layer does not need to trigger a repaint. The offset will be compensated away during painting.
933 // FIXME: The paint offset and the scroll offset should really be separate concepts.
934 m_scrollingContentsLayer->setOffsetFromRenderer(paddingBox.location() - IntPoint() - scrollOffset, GraphicsLayer::DontSetNeedsDisplay);
936 compositor().scrollingLayerAddedOrUpdated(&m_owningLayer);
938 m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
940 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
941 m_scrollingLayer->setOffsetFromRenderer(-toIntSize(paddingBox.location()));
943 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
945 IntSize scrollSize(m_owningLayer.scrollWidth(), m_owningLayer.scrollHeight());
946 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
947 m_scrollingContentsLayer->setNeedsDisplay();
949 IntSize scrollingContentsOffset = toIntSize(paddingBox.location() - scrollOffset);
950 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
951 compositor().scrollingLayerDidChange(m_owningLayer);
953 m_scrollingContentsLayer->setSize(scrollSize);
954 // FIXME: The paint offset and the scroll offset should really be separate concepts.
955 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
958 if (m_foregroundLayer) {
959 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
960 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
964 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
965 setRequiresOwnBackingStore(compositor().requiresOwnBackingStore(m_owningLayer, compAncestor, relativeCompositingBounds, ancestorCompositingBounds));
967 bool didUpdateContentsRect = false;
968 updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect);
969 if (!didUpdateContentsRect && m_graphicsLayer->hasContentsLayer())
972 updateDrawsContent(isSimpleContainer);
973 updateAfterWidgetResize();
974 registerScrollingLayers();
977 void RenderLayerBacking::adjustAncestorCompositingBoundsForFlowThread(IntRect& ancestorCompositingBounds, const RenderLayer* compositingAncestor) const
979 if (!m_owningLayer.isInsideFlowThread())
982 RenderLayer* flowThreadLayer = m_owningLayer.isInsideOutOfFlowThread() ? m_owningLayer.stackingContainer() : m_owningLayer.enclosingFlowThreadAncestor();
983 if (flowThreadLayer && flowThreadLayer->isRenderFlowThread()) {
984 RenderFlowThread& flowThread = toRenderFlowThread(flowThreadLayer->renderer());
985 if (m_owningLayer.isFlowThreadCollectingGraphicsLayersUnderRegions()) {
986 // The RenderNamedFlowThread is not composited, as we need it to paint the
987 // background layer of the regions. We need to compensate for that by manually
988 // subtracting the position of the flow-thread.
989 IntPoint flowPosition;
990 flowThreadLayer->convertToPixelSnappedLayerCoords(compositingAncestor, flowPosition);
991 ancestorCompositingBounds.moveBy(flowPosition);
994 // Move the ancestor position at the top of the region where the composited layer is going to display.
995 RenderNamedFlowFragment* parentRegion = flowThread.cachedRegionForCompositedLayer(m_owningLayer);
998 m_owningLayer.convertToPixelSnappedLayerCoords(flowThreadLayer, flowDelta);
999 parentRegion->adjustRegionBoundsFromFlowThreadPortionRect(flowDelta, ancestorCompositingBounds);
1000 RenderBoxModelObject* layerOwner = toRenderBoxModelObject(parentRegion->layerOwner());
1001 if (layerOwner->hasLayer() && layerOwner->layer()->backing()) {
1002 // Make sure that the region propagates its borders, paddings, outlines or box-shadows to layers inside it.
1003 // Note that the composited bounds of the RenderRegion are already calculated
1004 // because RenderLayerCompositor::rebuildCompositingLayerTree will only
1005 // iterate on the content of the region after the region itself is computed.
1006 ancestorCompositingBounds.moveBy(roundedIntPoint(layerOwner->layer()->backing()->compositedBounds().location()));
1007 ancestorCompositingBounds.move(-layerOwner->borderAndPaddingStart(), -layerOwner->borderAndPaddingBefore());
1013 void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer, bool& didUpdateContentsRect)
1015 if (!m_owningLayer.hasVisibleContent())
1018 // The order of operations here matters, since the last valid type of contents needs
1019 // to also update the contentsRect.
1020 updateDirectlyCompositedBackgroundColor(isSimpleContainer, didUpdateContentsRect);
1021 updateDirectlyCompositedBackgroundImage(isSimpleContainer, didUpdateContentsRect);
1024 void RenderLayerBacking::registerScrollingLayers()
1027 compositor().updateViewportConstraintStatus(m_owningLayer);
1029 // Register fixed position layers and their containers with the scrolling coordinator.
1030 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1031 if (!scrollingCoordinator)
1034 compositor().updateViewportConstraintStatus(m_owningLayer);
1036 if (!scrollingCoordinator->supportsFixedPositionLayers())
1039 // Page scale is applied as a transform on the root render view layer. Because the scroll
1040 // layer is further up in the hierarchy, we need to avoid marking the root render view
1041 // layer as a container.
1042 bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer();
1043 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
1047 void RenderLayerBacking::updateInternalHierarchy()
1049 // m_foregroundLayer has to be inserted in the correct order with child layers,
1050 // so it's not inserted here.
1051 if (m_ancestorClippingLayer)
1052 m_ancestorClippingLayer->removeAllChildren();
1054 if (m_contentsContainmentLayer) {
1055 m_contentsContainmentLayer->removeAllChildren();
1056 if (m_ancestorClippingLayer)
1057 m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get());
1060 if (m_backgroundLayer)
1061 m_contentsContainmentLayer->addChild(m_backgroundLayer.get());
1063 if (m_contentsContainmentLayer)
1064 m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
1065 else if (m_ancestorClippingLayer)
1066 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
1068 if (m_childContainmentLayer) {
1069 m_childContainmentLayer->removeFromParent();
1070 m_graphicsLayer->addChild(m_childContainmentLayer.get());
1073 if (m_scrollingLayer) {
1074 GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
1075 m_scrollingLayer->removeFromParent();
1076 superlayer->addChild(m_scrollingLayer.get());
1079 // The clip for child layers does not include space for overflow controls, so they exist as
1080 // siblings of the clipping layer if we have one. Normal children of this layer are set as
1081 // children of the clipping layer.
1082 if (m_layerForHorizontalScrollbar) {
1083 m_layerForHorizontalScrollbar->removeFromParent();
1084 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
1086 if (m_layerForVerticalScrollbar) {
1087 m_layerForVerticalScrollbar->removeFromParent();
1088 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
1090 if (m_layerForScrollCorner) {
1091 m_layerForScrollCorner->removeFromParent();
1092 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
1096 void RenderLayerBacking::resetContentsRect()
1098 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
1100 LayoutRect contentsClippingRect;
1101 if (renderer().isBox())
1102 contentsClippingRect = toRenderBox(renderer()).contentBoxRect();
1104 contentsClippingRect.move(contentOffsetInCompostingLayer());
1105 m_graphicsLayer->setContentsClippingRect(pixelSnappedIntRect(contentsClippingRect));
1107 m_graphicsLayer->setContentsTileSize(IntSize());
1108 m_graphicsLayer->setContentsTilePhase(IntPoint());
1111 void RenderLayerBacking::updateDrawsContent()
1113 updateDrawsContent(isSimpleContainerCompositingLayer());
1116 void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer)
1118 if (m_scrollingLayer) {
1119 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1120 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1121 // m_scrollingLayer never has backing store.
1122 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1123 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground();
1124 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1126 bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer().hasBackground() || paintsChildren());
1127 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
1131 bool hasPaintedContent = containsPaintedContent(isSimpleContainer);
1133 // FIXME: we could refine this to only allocate backing for one of these layers if possible.
1134 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1135 if (m_foregroundLayer)
1136 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1138 if (m_backgroundLayer)
1139 m_backgroundLayer->setDrawsContent(hasPaintedContent);
1142 // Return true if the layer changed.
1143 bool RenderLayerBacking::updateAncestorClippingLayer(bool needsAncestorClip)
1145 bool layersChanged = false;
1147 if (needsAncestorClip) {
1148 if (!m_ancestorClippingLayer) {
1149 m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer");
1150 m_ancestorClippingLayer->setMasksToBounds(true);
1151 layersChanged = true;
1153 } else if (hasAncestorClippingLayer()) {
1154 willDestroyLayer(m_ancestorClippingLayer.get());
1155 m_ancestorClippingLayer->removeFromParent();
1156 m_ancestorClippingLayer = nullptr;
1157 layersChanged = true;
1160 return layersChanged;
1163 // Return true if the layer changed.
1164 bool RenderLayerBacking::updateDescendantClippingLayer(bool needsDescendantClip)
1166 bool layersChanged = false;
1168 if (needsDescendantClip) {
1169 if (!m_childContainmentLayer && !m_usingTiledCacheLayer) {
1170 m_childContainmentLayer = createGraphicsLayer("Child clipping Layer");
1171 m_childContainmentLayer->setMasksToBounds(true);
1172 layersChanged = true;
1174 } else if (hasClippingLayer()) {
1175 willDestroyLayer(m_childContainmentLayer.get());
1176 m_childContainmentLayer->removeFromParent();
1177 m_childContainmentLayer = nullptr;
1178 layersChanged = true;
1181 return layersChanged;
1184 void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1186 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1189 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
1191 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1193 return m_owningLayer.horizontalScrollbar();
1196 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
1198 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1200 return m_owningLayer.verticalScrollbar();
1203 bool RenderLayerBacking::requiresScrollCornerLayer() const
1205 if (!m_owningLayer.hasOverlayScrollbars() && !m_owningLayer.needsCompositedScrolling())
1207 return !m_owningLayer.scrollCornerAndResizerRect().isEmpty();
1210 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1212 bool horizontalScrollbarLayerChanged = false;
1213 if (needsHorizontalScrollbarLayer) {
1214 if (!m_layerForHorizontalScrollbar) {
1215 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
1216 horizontalScrollbarLayerChanged = true;
1218 } else if (m_layerForHorizontalScrollbar) {
1219 willDestroyLayer(m_layerForHorizontalScrollbar.get());
1220 m_layerForHorizontalScrollbar = nullptr;
1221 horizontalScrollbarLayerChanged = true;
1224 bool verticalScrollbarLayerChanged = false;
1225 if (needsVerticalScrollbarLayer) {
1226 if (!m_layerForVerticalScrollbar) {
1227 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
1228 verticalScrollbarLayerChanged = true;
1230 } else if (m_layerForVerticalScrollbar) {
1231 willDestroyLayer(m_layerForVerticalScrollbar.get());
1232 m_layerForVerticalScrollbar = nullptr;
1233 verticalScrollbarLayerChanged = true;
1236 bool scrollCornerLayerChanged = false;
1237 if (needsScrollCornerLayer) {
1238 if (!m_layerForScrollCorner) {
1239 m_layerForScrollCorner = createGraphicsLayer("scroll corner");
1240 scrollCornerLayerChanged = true;
1242 } else if (m_layerForScrollCorner) {
1243 willDestroyLayer(m_layerForScrollCorner.get());
1244 m_layerForScrollCorner = nullptr;
1245 scrollCornerLayerChanged = true;
1248 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1249 if (horizontalScrollbarLayerChanged)
1250 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_owningLayer, HorizontalScrollbar);
1251 if (verticalScrollbarLayerChanged)
1252 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_owningLayer, VerticalScrollbar);
1255 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1258 void RenderLayerBacking::positionOverflowControlsLayers()
1260 if (!m_owningLayer.hasScrollbars())
1263 const IntRect borderBox = toRenderBox(renderer()).pixelSnappedBorderBoxRect();
1265 IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
1266 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1267 IntRect hBarRect = m_owningLayer.rectForHorizontalScrollbar(borderBox);
1268 layer->setPosition(hBarRect.location() - offsetFromRenderer);
1269 layer->setSize(hBarRect.size());
1270 if (layer->hasContentsLayer()) {
1271 IntRect barRect = IntRect(IntPoint(), hBarRect.size());
1272 layer->setContentsRect(barRect);
1273 layer->setContentsClippingRect(barRect);
1275 layer->setDrawsContent(m_owningLayer.horizontalScrollbar() && !layer->hasContentsLayer());
1278 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1279 IntRect vBarRect = m_owningLayer.rectForVerticalScrollbar(borderBox);
1280 layer->setPosition(vBarRect.location() - offsetFromRenderer);
1281 layer->setSize(vBarRect.size());
1282 if (layer->hasContentsLayer()) {
1283 IntRect barRect = IntRect(IntPoint(), vBarRect.size());
1284 layer->setContentsRect(barRect);
1285 layer->setContentsClippingRect(barRect);
1287 layer->setDrawsContent(m_owningLayer.verticalScrollbar() && !layer->hasContentsLayer());
1290 if (GraphicsLayer* layer = layerForScrollCorner()) {
1291 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
1292 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1293 layer->setSize(scrollCornerAndResizer.size());
1294 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1298 bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
1300 if (GraphicsLayer* layer = layerForHorizontalScrollbar())
1301 if (!layer->drawsContent())
1304 if (GraphicsLayer* layer = layerForVerticalScrollbar())
1305 if (!layer->drawsContent())
1308 if (GraphicsLayer* layer = layerForScrollCorner())
1309 if (!layer->drawsContent())
1315 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
1317 bool layerChanged = false;
1318 if (needsForegroundLayer) {
1319 if (!m_foregroundLayer) {
1322 layerName = m_owningLayer.name() + " (foreground)";
1324 m_foregroundLayer = createGraphicsLayer(layerName);
1325 m_foregroundLayer->setDrawsContent(true);
1326 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1327 layerChanged = true;
1329 } else if (m_foregroundLayer) {
1330 willDestroyLayer(m_foregroundLayer.get());
1331 m_foregroundLayer->removeFromParent();
1332 m_foregroundLayer = nullptr;
1333 layerChanged = true;
1337 m_graphicsLayer->setNeedsDisplay();
1338 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1341 return layerChanged;
1344 bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
1346 bool layerChanged = false;
1347 if (needsBackgroundLayer) {
1348 if (!m_backgroundLayer) {
1351 layerName = m_owningLayer.name() + " (background)";
1353 m_backgroundLayer = createGraphicsLayer(layerName);
1354 m_backgroundLayer->setDrawsContent(true);
1355 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1356 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1357 layerChanged = true;
1360 if (!m_contentsContainmentLayer) {
1363 layerName = m_owningLayer.name() + " (contents containment)";
1365 m_contentsContainmentLayer = createGraphicsLayer(layerName);
1366 m_contentsContainmentLayer->setAppliesPageScale(true);
1367 m_graphicsLayer->setAppliesPageScale(false);
1368 layerChanged = true;
1371 if (m_backgroundLayer) {
1372 willDestroyLayer(m_backgroundLayer.get());
1373 m_backgroundLayer->removeFromParent();
1374 m_backgroundLayer = nullptr;
1375 layerChanged = true;
1377 if (m_contentsContainmentLayer) {
1378 willDestroyLayer(m_contentsContainmentLayer.get());
1379 m_contentsContainmentLayer->removeFromParent();
1380 m_contentsContainmentLayer = nullptr;
1381 layerChanged = true;
1382 m_graphicsLayer->setAppliesPageScale(true);
1387 m_graphicsLayer->setNeedsDisplay();
1388 // This assumes that the background layer is only used for fixed backgrounds, which is currently a correct assumption.
1389 compositor().fixedRootBackgroundLayerChanged();
1392 return layerChanged;
1395 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
1397 bool layerChanged = false;
1398 if (needsMaskLayer) {
1400 m_maskLayer = createGraphicsLayer("Mask");
1401 m_maskLayer->setDrawsContent(true);
1402 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
1403 layerChanged = true;
1405 } else if (m_maskLayer) {
1406 willDestroyLayer(m_maskLayer.get());
1407 m_maskLayer = nullptr;
1408 layerChanged = true;
1412 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1414 return layerChanged;
1417 bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
1419 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1421 bool layerChanged = false;
1422 if (needsScrollingLayers) {
1423 if (!m_scrollingLayer) {
1424 // Outer layer which corresponds with the scroll view.
1425 m_scrollingLayer = createGraphicsLayer("Scrolling container");
1426 m_scrollingLayer->setDrawsContent(false);
1427 m_scrollingLayer->setMasksToBounds(true);
1429 // Inner layer which renders the content that scrolls.
1430 m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
1431 m_scrollingContentsLayer->setDrawsContent(true);
1432 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1433 if (!m_foregroundLayer)
1434 paintPhase |= GraphicsLayerPaintForeground;
1435 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1436 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
1438 layerChanged = true;
1439 if (scrollingCoordinator)
1440 scrollingCoordinator->scrollableAreaScrollLayerDidChange(&m_owningLayer);
1442 if (m_owningLayer.parent())
1443 compositor().scrollingLayerAddedOrUpdated(&m_owningLayer);
1446 } else if (m_scrollingLayer) {
1448 if (!renderer().documentBeingDestroyed())
1449 compositor().scrollingLayerRemoved(&m_owningLayer, m_scrollingLayer->platformLayer(), m_scrollingContentsLayer->platformLayer());
1451 willDestroyLayer(m_scrollingLayer.get());
1452 willDestroyLayer(m_scrollingContentsLayer.get());
1453 m_scrollingLayer = nullptr;
1454 m_scrollingContentsLayer = nullptr;
1455 layerChanged = true;
1456 if (scrollingCoordinator)
1457 scrollingCoordinator->scrollableAreaScrollLayerDidChange(&m_owningLayer);
1461 updateInternalHierarchy();
1462 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1464 m_graphicsLayer->setNeedsDisplay();
1465 compositor().scrollingLayerDidChange(m_owningLayer);
1469 return layerChanged;
1472 void RenderLayerBacking::attachToScrollingCoordinatorWithParent(RenderLayerBacking* parent)
1474 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1475 if (!scrollingCoordinator)
1478 // FIXME: When we support overflow areas, we will have to refine this for overflow areas that are also
1480 ScrollingNodeType nodeType;
1481 if (renderer().style().position() == FixedPosition)
1482 nodeType = FixedNode;
1483 else if (renderer().style().position() == StickyPosition)
1484 nodeType = StickyNode;
1486 nodeType = ScrollingNode;
1488 ScrollingNodeID parentID = parent ? parent->scrollLayerID() : 0;
1489 m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, m_scrollLayerID ? m_scrollLayerID : scrollingCoordinator->uniqueScrollLayerID(), parentID);
1492 void RenderLayerBacking::detachFromScrollingCoordinator()
1494 // If m_scrollLayerID is 0, then this backing is not attached to the ScrollingCoordinator.
1495 if (!m_scrollLayerID)
1498 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1499 if (!scrollingCoordinator)
1502 scrollingCoordinator->detachFromStateTree(m_scrollLayerID);
1503 m_scrollLayerID = 0;
1506 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
1509 if (!m_backgroundLayer)
1510 phase |= GraphicsLayerPaintBackground;
1511 if (!m_foregroundLayer)
1512 phase |= GraphicsLayerPaintForeground;
1514 phase |= GraphicsLayerPaintMask;
1516 if (m_scrollingContentsLayer) {
1517 phase &= ~GraphicsLayerPaintForeground;
1518 phase |= GraphicsLayerPaintCompositedScroll;
1521 return static_cast<GraphicsLayerPaintingPhase>(phase);
1524 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
1526 float finalOpacity = rendererOpacity;
1528 for (RenderLayer* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1529 // We only care about parents that are stacking contexts.
1530 // Recall that opacity creates stacking context.
1531 if (!curr->isStackingContainer())
1534 // If we found a compositing layer, we want to compute opacity
1535 // relative to it. So we can break here.
1536 if (curr->isComposited())
1539 finalOpacity *= curr->renderer().opacity();
1542 return finalOpacity;
1545 static bool hasBoxDecorations(const RenderStyle* style)
1547 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
1550 static bool canCreateTiledImage(const RenderStyle*);
1552 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
1554 if (hasBoxDecorations(style))
1557 if (!style->hasBackgroundImage())
1560 return !GraphicsLayer::supportsContentsTiling() || !canCreateTiledImage(style);
1563 static bool hasPerspectiveOrPreserves3D(const RenderStyle* style)
1565 return style->hasPerspective() || style->preserves3D();
1568 Color RenderLayerBacking::rendererBackgroundColor() const
1570 const auto& backgroundRenderer = renderer().isRoot() ? renderer().rendererForRootBackground() : renderer();
1571 return backgroundRenderer.style().visitedDependentColor(CSSPropertyBackgroundColor);
1574 void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(bool isSimpleContainer, bool& didUpdateContentsRect)
1576 if (!isSimpleContainer) {
1577 m_graphicsLayer->setContentsToSolidColor(Color());
1581 Color backgroundColor = rendererBackgroundColor();
1583 // An unset (invalid) color will remove the solid color.
1584 m_graphicsLayer->setContentsToSolidColor(backgroundColor);
1585 IntRect contentsRect = backgroundBox();
1586 m_graphicsLayer->setContentsRect(contentsRect);
1587 m_graphicsLayer->setContentsClippingRect(contentsRect);
1588 didUpdateContentsRect = true;
1591 bool canCreateTiledImage(const RenderStyle* style)
1593 const FillLayer* fillLayer = style->backgroundLayers();
1594 if (fillLayer->next())
1597 if (!fillLayer->imagesAreLoaded())
1600 if (fillLayer->attachment() != ScrollBackgroundAttachment)
1603 Color color = style->visitedDependentColor(CSSPropertyBackgroundColor);
1605 // FIXME: Allow color+image compositing when it makes sense.
1606 // For now bailing out.
1607 if (color.isValid() && color.alpha())
1610 StyleImage* styleImage = fillLayer->image();
1612 // FIXME: support gradients with isGeneratedImage.
1613 if (!styleImage->isCachedImage())
1616 Image* image = styleImage->cachedImage()->image();
1617 if (!image->isBitmapImage())
1623 void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(bool isSimpleContainer, bool& didUpdateContentsRect)
1625 if (!GraphicsLayer::supportsContentsTiling())
1628 if (isDirectlyCompositedImage())
1631 const RenderStyle& style = renderer().style();
1633 if (!isSimpleContainer || !style.hasBackgroundImage()) {
1634 m_graphicsLayer->setContentsToImage(0);
1638 IntRect destRect = backgroundBox();
1642 RefPtr<Image> image = style.backgroundLayers()->image()->cachedImage()->image();
1643 toRenderBox(renderer()).getGeometryForBackgroundImage(&m_owningLayer.renderer(), destRect, phase, tileSize);
1644 m_graphicsLayer->setContentsTileSize(tileSize);
1645 m_graphicsLayer->setContentsTilePhase(phase);
1646 m_graphicsLayer->setContentsRect(destRect);
1647 m_graphicsLayer->setContentsClippingRect(destRect);
1648 m_graphicsLayer->setContentsToImage(image.get());
1649 didUpdateContentsRect = true;
1652 void RenderLayerBacking::updateRootLayerConfiguration()
1654 if (!m_usingTiledCacheLayer)
1657 Color backgroundColor;
1658 bool viewIsTransparent = compositor().viewHasTransparentBackground(&backgroundColor);
1660 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) {
1661 m_backgroundLayer->setBackgroundColor(backgroundColor);
1662 m_backgroundLayer->setContentsOpaque(!viewIsTransparent);
1664 m_graphicsLayer->setBackgroundColor(Color());
1665 m_graphicsLayer->setContentsOpaque(false);
1667 m_graphicsLayer->setBackgroundColor(backgroundColor);
1668 m_graphicsLayer->setContentsOpaque(!viewIsTransparent);
1672 static bool supportsDirectBoxDecorationsComposition(const RenderLayerModelObject& renderer)
1674 if (!GraphicsLayer::supportsBackgroundColorContent())
1677 if (renderer.hasClip())
1680 if (hasBoxDecorationsOrBackgroundImage(&renderer.style()))
1683 // FIXME: We can't create a directly composited background if this
1684 // layer will have children that intersect with the background layer.
1685 // A better solution might be to introduce a flattening layer if
1686 // we do direct box decoration composition.
1687 // https://bugs.webkit.org/show_bug.cgi?id=119461
1688 if (hasPerspectiveOrPreserves3D(&renderer.style()))
1691 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
1692 if (renderer.style().backgroundComposite() != CompositeSourceOver)
1695 if (renderer.style().backgroundClip() == TextFillBox)
1701 bool RenderLayerBacking::paintsBoxDecorations() const
1703 if (!m_owningLayer.hasVisibleBoxDecorations())
1706 if (!supportsDirectBoxDecorationsComposition(renderer()))
1712 bool RenderLayerBacking::paintsChildren() const
1714 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers())
1717 if (hasVisibleNonCompositingDescendantLayers())
1723 static bool isRestartedPlugin(RenderObject* renderer)
1725 if (!renderer->isEmbeddedObject())
1728 Element* element = toElement(renderer->node());
1729 if (!element || !element->isPluginElement())
1732 return toHTMLPlugInElement(element)->isRestartedPlugin();
1735 static bool isCompositedPlugin(RenderObject* renderer)
1737 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
1740 // A "simple container layer" is a RenderLayer which has no visible content to render.
1741 // It may have no children, or all its children may be themselves composited.
1742 // This is a useful optimization, because it allows us to avoid allocating backing store.
1743 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
1745 if (renderer().hasMask()) // masks require special treatment
1748 if (renderer().isReplaced() && (!isCompositedPlugin(&renderer()) || isRestartedPlugin(&renderer())))
1751 if (paintsBoxDecorations() || paintsChildren())
1754 if (renderer().isRenderNamedFlowFragmentContainer())
1757 if (renderer().isRenderView()) {
1758 // Look to see if the root object has a non-simple background
1759 RenderObject* rootObject = renderer().document().documentElement() ? renderer().document().documentElement()->renderer() : 0;
1763 RenderStyle* style = &rootObject->style();
1765 // Reject anything that has a border, a border-radius or outline,
1766 // or is not a simple background (no background, or solid color).
1767 if (hasBoxDecorationsOrBackgroundImage(style))
1770 // Now look at the body's renderer.
1771 HTMLElement* body = renderer().document().body();
1772 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
1776 style = &bodyObject->style();
1778 if (hasBoxDecorationsOrBackgroundImage(style))
1785 static bool hasVisibleNonCompositingDescendant(RenderLayer& parent)
1787 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1788 parent.updateLayerListsIfNeeded();
1790 #if !ASSERT_DISABLED
1791 LayerListMutationDetector mutationChecker(&parent);
1794 if (Vector<RenderLayer*>* normalFlowList = parent.normalFlowList()) {
1795 size_t listSize = normalFlowList->size();
1796 for (size_t i = 0; i < listSize; ++i) {
1797 RenderLayer* curLayer = normalFlowList->at(i);
1798 if (!curLayer->isComposited()
1799 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer)))
1804 if (parent.isStackingContainer()) {
1805 if (!parent.hasVisibleDescendant())
1808 // Use the m_hasCompositingDescendant bit to optimize?
1809 if (Vector<RenderLayer*>* negZOrderList = parent.negZOrderList()) {
1810 size_t listSize = negZOrderList->size();
1811 for (size_t i = 0; i < listSize; ++i) {
1812 RenderLayer* curLayer = negZOrderList->at(i);
1813 if (!curLayer->isComposited()
1814 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer)))
1819 if (Vector<RenderLayer*>* posZOrderList = parent.posZOrderList()) {
1820 size_t listSize = posZOrderList->size();
1821 for (size_t i = 0; i < listSize; ++i) {
1822 RenderLayer* curLayer = posZOrderList->at(i);
1823 if (!curLayer->isComposited()
1824 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(*curLayer)))
1833 // Conservative test for having no rendered children.
1834 bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
1836 return hasVisibleNonCompositingDescendant(m_owningLayer);
1839 bool RenderLayerBacking::containsPaintedContent(bool isSimpleContainer) const
1841 if (isSimpleContainer || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer.isReflection())
1844 if (isDirectlyCompositedImage())
1847 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1848 // and set background color on the layer in that case, instead of allocating backing store and painting.
1850 if (renderer().isVideo() && toRenderVideo(renderer()).shouldDisplayVideo())
1851 return m_owningLayer.hasBoxDecorationsOrBackground();
1854 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
1855 if (renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents)
1856 return m_owningLayer.hasBoxDecorationsOrBackground();
1862 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1863 // that require painting. Direct compositing saves backing store.
1864 bool RenderLayerBacking::isDirectlyCompositedImage() const
1866 if (!renderer().isImage() || m_owningLayer.hasBoxDecorationsOrBackground() || renderer().hasClip())
1869 RenderImage& imageRenderer = toRenderImage(renderer());
1870 if (CachedImage* cachedImage = imageRenderer.cachedImage()) {
1871 if (!cachedImage->hasImage())
1874 Image* image = cachedImage->imageForRenderer(&imageRenderer);
1875 if (!image->isBitmapImage())
1878 if (image->orientationForCurrentFrame() != DefaultImageOrientation)
1881 return m_graphicsLayer->shouldDirectlyCompositeImage(image);
1887 void RenderLayerBacking::contentChanged(ContentChangeType changeType)
1889 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1890 updateImageContents();
1894 if ((changeType == BackgroundImageChanged) && canCreateTiledImage(&renderer().style()))
1895 updateGraphicsLayerGeometry();
1897 if ((changeType == MaskImageChanged) && m_maskLayer) {
1898 // The composited layer bounds relies on box->maskClipRect(), which changes
1899 // when the mask image becomes available.
1900 updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot);
1903 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
1904 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && renderer().isCanvas() && canvasCompositingStrategy(renderer()) == CanvasAsLayerContents) {
1905 m_graphicsLayer->setContentsNeedsDisplay();
1911 void RenderLayerBacking::updateImageContents()
1913 ASSERT(renderer().isImage());
1914 RenderImage& imageRenderer = toRenderImage(renderer());
1916 CachedImage* cachedImage = imageRenderer.cachedImage();
1920 Image* image = cachedImage->imageForRenderer(&imageRenderer);
1924 // We have to wait until the image is fully loaded before setting it on the layer.
1925 if (!cachedImage->isLoaded())
1928 // This is a no-op if the layer doesn't have an inner layer for the image.
1929 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
1931 LayoutRect contentsClippingRect = imageRenderer.contentBoxRect();
1932 contentsClippingRect.move(contentOffsetInCompostingLayer());
1933 m_graphicsLayer->setContentsClippingRect(pixelSnappedIntRect(contentsClippingRect));
1935 m_graphicsLayer->setContentsToImage(image);
1936 bool isSimpleContainer = false;
1937 updateDrawsContent(isSimpleContainer);
1939 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1940 // the image. So we have to kick the animation each time; this has the downside that the
1941 // image will keep animating, even if its layer is not visible.
1942 image->startAnimation();
1945 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
1947 const RenderStyle& style = renderer().style();
1949 FloatPoint3D origin;
1950 origin.setX(floatValueForLength(style.transformOriginX(), borderBox.width()));
1951 origin.setY(floatValueForLength(style.transformOriginY(), borderBox.height()));
1952 origin.setZ(style.transformOriginZ());
1957 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
1959 const RenderStyle& style = renderer().style();
1961 float boxWidth = borderBox.width();
1962 float boxHeight = borderBox.height();
1965 origin.setX(floatValueForLength(style.perspectiveOriginX(), boxWidth));
1966 origin.setY(floatValueForLength(style.perspectiveOriginY(), boxHeight));
1971 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
1972 LayoutSize RenderLayerBacking::contentOffsetInCompostingLayer() const
1974 return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1977 LayoutRect RenderLayerBacking::contentsBox() const
1979 if (!renderer().isBox())
1980 return LayoutRect();
1982 RenderBox& renderBox = toRenderBox(renderer());
1983 LayoutRect contentsRect;
1985 if (renderBox.isVideo())
1986 contentsRect = toRenderVideo(renderBox).videoBox();
1989 if (renderBox.isRenderReplaced()) {
1990 RenderReplaced& renderReplaced = *toRenderReplaced(&renderBox);
1991 contentsRect = renderReplaced.replacedContentRect(renderBox.intrinsicSize());
1993 contentsRect = renderBox.contentBoxRect();
1995 contentsRect.move(contentOffsetInCompostingLayer());
1996 return contentsRect;
1999 static LayoutRect backgroundRectForBox(const RenderBox& box)
2001 switch (box.style().backgroundClip()) {
2003 return box.borderBoxRect();
2004 case PaddingFillBox:
2005 return box.paddingBoxRect();
2006 case ContentFillBox:
2007 return box.contentBoxRect();
2012 ASSERT_NOT_REACHED();
2013 return LayoutRect();
2016 IntRect RenderLayerBacking::backgroundBox() const
2018 if (!renderer().isBox())
2021 LayoutRect backgroundBox = backgroundRectForBox(toRenderBox(renderer()));
2022 backgroundBox.move(contentOffsetInCompostingLayer());
2023 return pixelSnappedIntRect(backgroundBox);
2026 GraphicsLayer* RenderLayerBacking::parentForSublayers() const
2028 if (m_scrollingContentsLayer)
2029 return m_scrollingContentsLayer.get();
2032 // FIXME: Can we remove this iOS-specific code path?
2033 if (GraphicsLayer* clippingLayer = this->clippingLayer())
2034 return clippingLayer;
2035 return m_graphicsLayer.get();
2037 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
2041 GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
2043 if (m_ancestorClippingLayer)
2044 return m_ancestorClippingLayer.get();
2046 if (m_contentsContainmentLayer)
2047 return m_contentsContainmentLayer.get();
2049 return m_graphicsLayer.get();
2052 bool RenderLayerBacking::paintsIntoWindow() const
2054 if (m_usingTiledCacheLayer)
2057 if (m_owningLayer.isRootLayer()) {
2058 #if PLATFORM(IOS) || USE(COORDINATED_GRAPHICS)
2059 if (compositor().inForcedCompositingMode())
2063 return compositor().rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
2069 void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
2071 if (requiresOwnBacking == m_requiresOwnBackingStore)
2074 m_requiresOwnBackingStore = requiresOwnBacking;
2076 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
2077 // cached clip rects, so when it changes we have to clear clip rects on descendants.
2078 m_owningLayer.clearClipRectsIncludingDescendants(PaintingClipRects);
2079 m_owningLayer.computeRepaintRectsIncludingDescendants();
2081 compositor().repaintInCompositedAncestor(m_owningLayer, compositedBounds());
2084 #if ENABLE(CSS_COMPOSITING)
2085 void RenderLayerBacking::setBlendMode(BlendMode blendMode)
2087 m_graphicsLayer->setBlendMode(blendMode);
2091 void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer shouldClip)
2093 ASSERT(!paintsIntoCompositedAncestor());
2095 FrameView& frameView = owningLayer().renderer().view().frameView();
2096 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2097 frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBox());
2099 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2100 // By default, setNeedsDisplay will clip to the size of the GraphicsLayer, which does not include margin tiles.
2101 // So if the TiledBacking has a margin that needs to be invalidated, we need to send in a rect to setNeedsDisplayInRect
2102 // that is large enough to include the margin. TiledBacking::bounds() includes the margin.
2103 TiledBacking* tiledBacking = this->tiledBacking();
2104 FloatRect rectToRepaint = tiledBacking ? tiledBacking->bounds() : FloatRect(FloatPoint(0, 0), m_graphicsLayer->size());
2105 m_graphicsLayer->setNeedsDisplayInRect(rectToRepaint, shouldClip);
2108 if (m_foregroundLayer && m_foregroundLayer->drawsContent())
2109 m_foregroundLayer->setNeedsDisplay();
2111 if (m_backgroundLayer && m_backgroundLayer->drawsContent())
2112 m_backgroundLayer->setNeedsDisplay();
2114 if (m_maskLayer && m_maskLayer->drawsContent())
2115 m_maskLayer->setNeedsDisplay();
2117 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
2118 m_scrollingContentsLayer->setNeedsDisplay();
2121 // r is in the coordinate space of the layer's render object
2122 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r, GraphicsLayer::ShouldClipToLayer shouldClip)
2124 ASSERT(!paintsIntoCompositedAncestor());
2126 FrameView& frameView = owningLayer().renderer().view().frameView();
2127 if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
2128 frameView.addTrackedRepaintRect(pixelSnappedIntRect(r));
2130 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
2131 IntRect layerDirtyRect = r;
2132 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
2133 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2136 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
2137 IntRect layerDirtyRect = r;
2138 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
2139 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2142 // FIXME: need to split out repaints for the background.
2143 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
2144 IntRect layerDirtyRect = r;
2145 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer());
2146 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2149 if (m_maskLayer && m_maskLayer->drawsContent()) {
2150 IntRect layerDirtyRect = r;
2151 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
2152 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2155 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
2156 IntRect layerDirtyRect = r;
2157 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
2159 // Account for the fact that RenderLayerBacking::updateGraphicsLayerGeometry() bakes scrollOffset into offsetFromRenderer on iOS.
2160 layerDirtyRect.move(-m_owningLayer.scrollOffset());
2162 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
2166 void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context,
2167 const IntRect& paintDirtyRect, // In the coords of rootLayer.
2168 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
2170 if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
2172 // FIXME: Looks like the CALayer tree is out of sync with the GraphicsLayer heirarchy
2173 // when pages are restored from the PageCache.
2174 // <rdar://problem/8712587> ASSERT: When Going Back to Page with Plugins in PageCache
2175 ASSERT_NOT_REACHED();
2180 FontCachePurgePreventer fontCachePurgePreventer;
2182 RenderLayer::PaintLayerFlags paintFlags = 0;
2183 if (paintingPhase & GraphicsLayerPaintBackground)
2184 paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase;
2185 if (paintingPhase & GraphicsLayerPaintForeground)
2186 paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
2187 if (paintingPhase & GraphicsLayerPaintMask)
2188 paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
2189 if (paintingPhase & GraphicsLayerPaintOverflowContents)
2190 paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
2191 if (paintingPhase & GraphicsLayerPaintCompositedScroll)
2192 paintFlags |= RenderLayer::PaintLayerPaintingCompositingScrollingPhase;
2194 if (graphicsLayer == m_backgroundLayer.get())
2195 paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
2196 else if (compositor().fixedRootBackgroundLayer())
2197 paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground;
2199 // FIXME: GraphicsLayers need a way to split for RenderRegions.
2200 RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, paintDirtyRect, paintBehavior, m_subpixelAccumulation);
2201 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags);
2203 if (m_owningLayer.containsDirtyOverlayScrollbars())
2204 m_owningLayer.paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
2206 compositor().didPaintBacking(this);
2208 ASSERT(!m_owningLayer.m_usedTransparency);
2211 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
2217 const IntRect& scrollbarRect = scrollbar->frameRect();
2218 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
2219 IntRect transformedClip = clip;
2220 transformedClip.moveBy(scrollbarRect.location());
2221 scrollbar->paint(&context, transformedClip);
2225 // Up-call from compositing layer drawing callback.
2226 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
2229 if (Page* page = renderer().frame().page())
2230 page->setIsPainting(true);
2233 if (graphicsLayer == m_graphicsLayer.get()
2234 || graphicsLayer == m_foregroundLayer.get()
2235 || graphicsLayer == m_backgroundLayer.get()
2236 || graphicsLayer == m_maskLayer.get()
2237 || graphicsLayer == m_scrollingContentsLayer.get()) {
2238 InspectorInstrumentation::willPaint(&renderer());
2240 // The dirtyRect is in the coords of the painting root.
2241 IntRect dirtyRect = clip;
2242 if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
2243 dirtyRect.intersect(enclosingIntRect(compositedBoundsIncludingMargin()));
2245 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2246 paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
2248 InspectorInstrumentation::didPaint(&renderer(), &context, clip);
2249 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2250 paintScrollbar(m_owningLayer.horizontalScrollbar(), context, clip);
2251 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2252 paintScrollbar(m_owningLayer.verticalScrollbar(), context, clip);
2253 } else if (graphicsLayer == layerForScrollCorner()) {
2254 const IntRect& scrollCornerAndResizer = m_owningLayer.scrollCornerAndResizerRect();
2256 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
2257 IntRect transformedClip = clip;
2258 transformedClip.moveBy(scrollCornerAndResizer.location());
2259 m_owningLayer.paintScrollCorner(&context, IntPoint(), transformedClip);
2260 m_owningLayer.paintResizer(&context, IntPoint(), transformedClip);
2264 if (Page* page = renderer().frame().page())
2265 page->setIsPainting(false);
2269 float RenderLayerBacking::pageScaleFactor() const
2271 return compositor().pageScaleFactor();
2274 float RenderLayerBacking::deviceScaleFactor() const
2276 return compositor().deviceScaleFactor();
2279 float RenderLayerBacking::contentsScaleMultiplierForNewTiles(const GraphicsLayer* layer) const
2281 return compositor().contentsScaleMultiplierForNewTiles(layer);
2284 void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
2286 compositor().didFlushChangesForLayer(m_owningLayer, layer);
2289 bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
2291 GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
2292 if (graphicsLayer != transformedLayer)
2295 if (m_owningLayer.hasTransform()) {
2296 transform = m_owningLayer.currentTransform(RenderStyle::ExcludeTransformOrigin);
2302 bool RenderLayerBacking::isTrackingRepaints() const
2304 return static_cast<GraphicsLayerClient&>(compositor()).isTrackingRepaints();
2307 bool RenderLayerBacking::shouldSkipLayerInDump(const GraphicsLayer* layer) const
2309 // Skip the root tile cache's flattening layer.
2310 return m_isMainFrameRenderViewLayer && layer && layer == m_childContainmentLayer.get();
2313 bool RenderLayerBacking::shouldDumpPropertyForLayer(const GraphicsLayer* layer, const char* propertyName) const
2315 // For backwards compatibility with WebKit1 and other platforms,
2316 // skip some properties on the root tile cache.
2317 if (m_isMainFrameRenderViewLayer && layer == m_graphicsLayer.get()) {
2318 if (!strcmp(propertyName, "drawsContent"))
2321 // Background color could be of interest to tests or other dumpers if it's non-white.
2322 if (!strcmp(propertyName, "backgroundColor") && layer->backgroundColor() == Color::white)
2325 // The root tile cache's repaints will show up at the top with FrameView's,
2326 // so don't dump them twice.
2327 if (!strcmp(propertyName, "repaintRects"))
2335 void RenderLayerBacking::verifyNotPainting()
2337 ASSERT(!renderer().frame().page() || !renderer().frame().page()->isPainting());
2341 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
2343 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
2344 bool hasTransform = renderer().isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
2345 #if ENABLE(CSS_FILTERS)
2346 bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
2348 bool hasFilter = false;
2351 if (!hasOpacity && !hasTransform && !hasFilter)
2354 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
2355 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2356 #if ENABLE(CSS_FILTERS)
2357 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
2360 size_t numKeyframes = keyframes.size();
2361 for (size_t i = 0; i < numKeyframes; ++i) {
2362 const KeyframeValue& currentKeyframe = keyframes[i];
2363 const RenderStyle* keyframeStyle = currentKeyframe.style();
2364 double key = currentKeyframe.key();
2369 // Get timing function.
2370 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0).timingFunction() : 0;
2372 bool isFirstOrLastKeyframe = key == 0 || key == 1;
2373 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
2374 transformVector.insert(TransformAnimationValue::create(key, keyframeStyle->transform(), tf));
2376 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
2377 opacityVector.insert(FloatAnimationValue::create(key, keyframeStyle->opacity(), tf));
2379 #if ENABLE(CSS_FILTERS)
2380 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
2381 filterVector.insert(FilterAnimationValue::create(key, keyframeStyle->filter(), tf));
2385 if (renderer().frame().page() && !renderer().frame().page()->settings().acceleratedCompositedAnimationsEnabled())
2388 bool didAnimate = false;
2390 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
2393 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2396 #if ENABLE(CSS_FILTERS)
2397 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
2404 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
2406 m_graphicsLayer->pauseAnimation(animationName, timeOffset);
2409 void RenderLayerBacking::animationFinished(const String& animationName)
2411 m_graphicsLayer->removeAnimation(animationName);
2414 bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
2416 bool didAnimate = false;
2418 ASSERT(property != CSSPropertyInvalid);
2420 if (property == CSSPropertyOpacity) {
2421 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
2422 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
2423 KeyframeValueList opacityVector(AnimatedPropertyOpacity);
2424 opacityVector.insert(FloatAnimationValue::create(0, compositingOpacity(fromStyle->opacity())));
2425 opacityVector.insert(FloatAnimationValue::create(1, compositingOpacity(toStyle->opacity())));
2426 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
2427 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
2428 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
2429 updateOpacity(toStyle);
2435 if (property == CSSPropertyWebkitTransform && m_owningLayer.hasTransform()) {
2436 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
2437 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
2438 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
2439 transformVector.insert(TransformAnimationValue::create(0, fromStyle->transform()));
2440 transformVector.insert(TransformAnimationValue::create(1, toStyle->transform()));
2441 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer()).pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
2442 // To ensure that the correct transform is visible when the animation ends, also set the final transform.
2443 updateTransform(toStyle);
2449 #if ENABLE(CSS_FILTERS)
2450 if (property == CSSPropertyWebkitFilter && m_owningLayer.hasFilter()) {
2451 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
2452 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
2453 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
2454 filterVector.insert(FilterAnimationValue::create(0, fromStyle->filter()));
2455 filterVector.insert(FilterAnimationValue::create(1, toStyle->filter()));
2456 if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) {
2457 // To ensure that the correct filter is visible when the animation ends, also set the final filter.
2458 updateFilters(toStyle);
2468 void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
2470 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2471 if (animatedProperty != AnimatedPropertyInvalid)
2472 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
2475 void RenderLayerBacking::transitionFinished(CSSPropertyID property)
2477 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
2478 if (animatedProperty != AnimatedPropertyInvalid)
2479 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
2482 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
2484 renderer().animation().notifyAnimationStarted(&renderer(), time);
2487 void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer)
2489 if (renderer().documentBeingDestroyed())
2491 compositor().scheduleLayerFlush(layer->canThrottleLayerFlush());
2494 void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer)
2496 compositor().notifyFlushBeforeDisplayRefresh(layer);
2499 // This is used for the 'freeze' API, for testing only.
2500 void RenderLayerBacking::suspendAnimations(double time)
2502 m_graphicsLayer->suspendAnimations(time);
2505 void RenderLayerBacking::resumeAnimations()
2507 m_graphicsLayer->resumeAnimations();
2510 LayoutRect RenderLayerBacking::compositedBounds() const
2512 return m_compositedBounds;
2515 void RenderLayerBacking::setCompositedBounds(const LayoutRect& bounds)
2517 m_compositedBounds = bounds;
2520 LayoutRect RenderLayerBacking::compositedBoundsIncludingMargin() const
2522 TiledBacking* tiledBacking = this->tiledBacking();
2523 if (!tiledBacking || !tiledBacking->hasMargins())
2524 return compositedBounds();
2526 LayoutRect boundsIncludingMargin = compositedBounds();
2527 LayoutUnit leftMarginWidth = tiledBacking->leftMarginWidth();
2528 LayoutUnit topMarginHeight = tiledBacking->topMarginHeight();
2530 boundsIncludingMargin.moveBy(IntPoint(-leftMarginWidth, -topMarginHeight));
2531 boundsIncludingMargin.expand(leftMarginWidth + (LayoutUnit)tiledBacking->rightMarginWidth(), topMarginHeight + (LayoutUnit)tiledBacking->bottomMarginHeight());
2533 return boundsIncludingMargin;
2536 CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
2538 CSSPropertyID cssProperty = CSSPropertyInvalid;
2540 case AnimatedPropertyWebkitTransform:
2541 cssProperty = CSSPropertyWebkitTransform;
2543 case AnimatedPropertyOpacity:
2544 cssProperty = CSSPropertyOpacity;
2546 case AnimatedPropertyBackgroundColor:
2547 cssProperty = CSSPropertyBackgroundColor;
2549 case AnimatedPropertyWebkitFilter:
2550 #if ENABLE(CSS_FILTERS)
2551 cssProperty = CSSPropertyWebkitFilter;
2553 ASSERT_NOT_REACHED();
2556 case AnimatedPropertyInvalid:
2557 ASSERT_NOT_REACHED();
2562 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
2564 switch (cssProperty) {
2565 case CSSPropertyWebkitTransform:
2566 return AnimatedPropertyWebkitTransform;
2567 case CSSPropertyOpacity:
2568 return AnimatedPropertyOpacity;
2569 case CSSPropertyBackgroundColor:
2570 return AnimatedPropertyBackgroundColor;
2571 #if ENABLE(CSS_FILTERS)
2572 case CSSPropertyWebkitFilter:
2573 return AnimatedPropertyWebkitFilter;
2576 // It's fine if we see other css properties here; they are just not accelerated.
2579 return AnimatedPropertyInvalid;
2582 CompositingLayerType RenderLayerBacking::compositingLayerType() const
2584 if (m_graphicsLayer->hasContentsLayer())
2585 return MediaCompositingLayer;
2587 if (m_graphicsLayer->drawsContent())
2588 return m_graphicsLayer->usingTiledBacking() ? TiledCompositingLayer : NormalCompositingLayer;
2590 return ContainerCompositingLayer;
2593 double RenderLayerBacking::backingStoreMemoryEstimate() const
2595 double backingMemory;
2597 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
2598 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
2599 if (m_foregroundLayer)
2600 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
2601 if (m_backgroundLayer)
2602 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
2604 backingMemory += m_maskLayer->backingStoreMemoryEstimate();
2606 if (m_scrollingContentsLayer)
2607 backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
2609 if (m_layerForHorizontalScrollbar)
2610 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
2612 if (m_layerForVerticalScrollbar)
2613 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
2615 if (m_layerForScrollCorner)
2616 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
2618 return backingMemory;
2621 } // namespace WebCore
2623 #endif // USE(ACCELERATED_COMPOSITING)