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 #include "core/rendering/compositing/CompositedLayerMapping.h"
30 #include "CSSPropertyNames.h"
31 #include "HTMLNames.h"
32 #include "RuntimeEnabledFeatures.h"
33 #include "core/animation/ActiveAnimations.h"
34 #include "core/fetch/ImageResource.h"
35 #include "core/html/HTMLIFrameElement.h"
36 #include "core/html/HTMLMediaElement.h"
37 #include "core/html/canvas/CanvasRenderingContext.h"
38 #include "core/inspector/InspectorInstrumentation.h"
39 #include "core/page/Chrome.h"
40 #include "core/frame/FrameView.h"
41 #include "core/frame/Settings.h"
42 #include "core/page/scrolling/ScrollingCoordinator.h"
43 #include "core/plugins/PluginView.h"
44 #include "core/rendering/FilterEffectRenderer.h"
45 #include "core/rendering/RenderApplet.h"
46 #include "core/rendering/RenderEmbeddedObject.h"
47 #include "core/rendering/RenderIFrame.h"
48 #include "core/rendering/RenderImage.h"
49 #include "core/rendering/RenderLayerStackingNodeIterator.h"
50 #include "core/rendering/RenderVideo.h"
51 #include "core/rendering/RenderView.h"
52 #include "core/rendering/compositing/GraphicsLayerUpdater.h"
53 #include "core/rendering/compositing/RenderLayerCompositor.h"
54 #include "core/rendering/style/KeyframeList.h"
55 #include "platform/LengthFunctions.h"
56 #include "platform/fonts/FontCache.h"
57 #include "platform/graphics/GraphicsContext.h"
58 #include "wtf/CurrentTime.h"
59 #include "wtf/text/StringBuilder.h"
65 using namespace HTMLNames;
67 static IntRect clipBox(RenderBox* renderer);
69 static IntRect contentsRect(const RenderObject* renderer)
71 if (!renderer->isBox())
74 return renderer->isVideo() ?
75 toRenderVideo(renderer)->videoBox() :
76 pixelSnappedIntRect(toRenderBox(renderer)->contentBoxRect());
79 static IntRect backgroundRect(const RenderObject* renderer)
81 if (!renderer->isBox())
85 const RenderBox* box = toRenderBox(renderer);
86 EFillBox clip = box->style()->backgroundClip();
89 rect = box->borderBoxRect();
92 rect = box->paddingBoxRect();
95 rect = box->contentBoxRect();
101 return pixelSnappedIntRect(rect);
104 static inline bool isAcceleratedCanvas(const RenderObject* renderer)
106 if (renderer->isCanvas()) {
107 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
108 if (CanvasRenderingContext* context = canvas->renderingContext())
109 return context->isAccelerated();
114 static bool hasBoxDecorations(const RenderStyle* style)
116 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
119 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
121 return hasBoxDecorations(style) || style->hasBackgroundImage();
124 static bool contentLayerSupportsDirectBackgroundComposition(const RenderObject* renderer)
126 // No support for decorations - border, border-radius or outline.
127 // Only simple background - solid color or transparent.
128 if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
131 // If there is no background, there is nothing to support.
132 if (!renderer->style()->hasBackground())
135 // Simple background that is contained within the contents rect.
136 return contentsRect(renderer).contains(backgroundRect(renderer));
139 static blink::WebLayer* platformLayerForPlugin(RenderObject* renderer)
141 if (!renderer->isEmbeddedObject())
143 Widget* widget = toRenderEmbeddedObject(renderer)->widget();
144 if (!widget || !widget->isPluginView())
146 return toPluginView(widget)->platformLayer();
150 static inline bool isAcceleratedContents(RenderObject* renderer)
152 return isAcceleratedCanvas(renderer)
153 || (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing())
154 || renderer->isVideo();
157 // Get the scrolling coordinator in a way that works inside CompositedLayerMapping's destructor.
158 static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer)
160 Page* page = layer.renderer()->frame()->page();
164 return page->scrollingCoordinator();
167 CompositedLayerMapping::CompositedLayerMapping(RenderLayer& layer)
168 : m_owningLayer(layer)
169 , m_artificiallyInflatedBounds(false)
170 , m_isMainFrameRenderViewLayer(false)
171 , m_requiresOwnBackingStoreForIntrinsicReasons(true)
172 , m_requiresOwnBackingStoreForAncestorReasons(true)
173 , m_canCompositeFilters(false)
174 , m_backgroundLayerPaintsFixedRootBackground(false)
175 , m_needToUpdateGeometry(false)
176 , m_needToUpdateGeometryOfAllDecendants(false)
178 if (layer.isRootLayer() && renderer()->frame()->isMainFrame())
179 m_isMainFrameRenderViewLayer = true;
181 createPrimaryGraphicsLayer();
184 CompositedLayerMapping::~CompositedLayerMapping()
186 // Do not leave the destroyed pointer dangling on any RenderLayers that painted to this mapping's squashing layer.
187 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
188 RenderLayer* oldSquashedLayer = m_squashedLayers[i].renderLayer;
189 if (oldSquashedLayer->groupedMapping() == this) {
190 oldSquashedLayer->setGroupedMapping(0, true);
191 oldSquashedLayer->setLostGroupedMapping(true);
195 updateClippingLayers(false, false);
196 updateOverflowControlsLayers(false, false, false);
197 updateChildTransformLayer(false);
198 updateForegroundLayer(false);
199 updateBackgroundLayer(false);
200 updateMaskLayer(false);
201 updateClippingMaskLayers(false);
202 updateScrollingLayers(false);
203 updateSquashingLayers(false);
204 destroyGraphicsLayers();
207 PassOwnPtr<GraphicsLayer> CompositedLayerMapping::createGraphicsLayer(CompositingReasons reasons)
209 GraphicsLayerFactory* graphicsLayerFactory = 0;
210 if (Page* page = renderer()->frame()->page())
211 graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
213 OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
215 graphicsLayer->setCompositingReasons(reasons);
217 return graphicsLayer.release();
220 void CompositedLayerMapping::createPrimaryGraphicsLayer()
222 m_graphicsLayer = createGraphicsLayer(m_owningLayer.compositingReasons());
225 if (m_isMainFrameRenderViewLayer)
226 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
229 updateOpacity(renderer()->style());
230 updateTransform(renderer()->style());
231 updateFilters(renderer()->style());
232 updateHasGpuRasterizationHint(renderer()->style());
234 if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
235 updateLayerBlendMode(renderer()->style());
236 updateIsRootForIsolatedGroup();
240 void CompositedLayerMapping::destroyGraphicsLayers()
243 m_graphicsLayer->removeFromParent();
245 m_ancestorClippingLayer = nullptr;
246 m_graphicsLayer = nullptr;
247 m_foregroundLayer = nullptr;
248 m_backgroundLayer = nullptr;
249 m_childContainmentLayer = nullptr;
250 m_childTransformLayer = nullptr;
251 m_maskLayer = nullptr;
252 m_childClippingMaskLayer = nullptr;
254 m_scrollingLayer = nullptr;
255 m_scrollingContentsLayer = nullptr;
258 void CompositedLayerMapping::updateOpacity(const RenderStyle* style)
260 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
263 void CompositedLayerMapping::updateTransform(const RenderStyle* style)
265 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
266 // baked into it, and we don't want that.
267 TransformationMatrix t;
268 if (m_owningLayer.hasTransform()) {
269 style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
270 makeMatrixRenderable(t, compositor()->canRender3DTransforms());
273 m_graphicsLayer->setTransform(t);
276 void CompositedLayerMapping::updateFilters(const RenderStyle* style)
278 bool didCompositeFilters = m_canCompositeFilters;
279 m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer().computeFilterOperations(style));
280 if (didCompositeFilters != m_canCompositeFilters) {
282 // If filters used to be painted in software and are now painted in the compositor, we need to:
283 // (1) Remove the FilterEffectRenderer, which was used for painting filters in software.
284 // (2) Repaint the layer contents to remove the software-applied filter because the compositor will apply it.
286 // Similarly, if filters used to be painted in the compositor and are now painted in software, we need to:
287 // (1) Create a FilterEffectRenderer.
288 // (2) Repaint the layer contents to apply a software filter because the compositor won't apply it.
290 m_owningLayer.updateOrRemoveFilterEffectRenderer();
291 setContentsNeedDisplay();
295 void CompositedLayerMapping::updateLayerBlendMode(const RenderStyle* style)
297 setBlendMode(style->blendMode());
300 void CompositedLayerMapping::updateIsRootForIsolatedGroup()
302 bool isolate = m_owningLayer.shouldIsolateCompositedDescendants();
304 // non stacking context layers should never isolate
305 ASSERT(m_owningLayer.stackingNode()->isStackingContext() || !isolate);
307 m_graphicsLayer->setIsRootForIsolatedGroup(isolate);
310 void CompositedLayerMapping::updateHasGpuRasterizationHint(const RenderStyle* style)
312 m_graphicsLayer->setHasGpuRasterizationHint(style->hasWillChangeGpuRasterizationHint());
315 void CompositedLayerMapping::updateContentsOpaque()
317 // For non-root layers, background is always painted by the primary graphics layer.
318 ASSERT(m_isMainFrameRenderViewLayer || !m_backgroundLayer);
319 if (m_backgroundLayer) {
320 m_graphicsLayer->setContentsOpaque(false);
321 m_backgroundLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
323 m_graphicsLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
327 static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
329 RenderStyle* style = renderer->style();
330 return (style->transformOriginX().type() == Fixed && style->transformOriginX().value())
331 || (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
334 static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
336 for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
337 if (curr->hasTransform() || curr->needsCompositedScrolling())
344 bool CompositedLayerMapping::shouldClipCompositedBounds() const
346 // Scrollbar layers use this layer for relative positioning, so don't clip.
347 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
350 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(&m_owningLayer))
353 // Scrolled composited layers are clipped by their ancestor clipping layer,
354 // so don't clip these, either.
355 if (!compositor()->clippedByAncestor(&m_owningLayer))
358 if (m_owningLayer.renderer()->containingBlock()->enclosingLayer() != m_owningLayer.ancestorScrollingLayer())
364 void CompositedLayerMapping::updateCompositedBounds(GraphicsLayerUpdater::UpdateType updateType)
366 if (!m_needToUpdateGeometry && updateType != GraphicsLayerUpdater::ForceUpdate)
369 // We need to know if we draw content in order to update our bounds (this has an effect
370 // on whether or not descendands will paint into our backing). Update this value now.
371 updateDrawsContent();
373 LayoutRect layerBounds = compositor()->calculateCompositedBounds(&m_owningLayer, &m_owningLayer);
375 // Clip to the size of the document or enclosing overflow-scroll layer.
376 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
377 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
378 if (shouldClipCompositedBounds()) {
379 RenderView* view = m_owningLayer.renderer()->view();
380 RenderLayer* rootLayer = view->layer();
382 LayoutRect clippingBounds;
383 if (renderer()->style()->position() == FixedPosition && renderer()->container() == view)
384 clippingBounds = view->frameView()->viewportConstrainedVisibleContentRect();
386 clippingBounds = view->unscaledDocumentRect();
388 if (&m_owningLayer != rootLayer)
389 clippingBounds.intersect(m_owningLayer.clipper().backgroundClipRect(ClipRectsContext(rootLayer, AbsoluteClipRects)).rect());
392 m_owningLayer.convertToLayerCoords(rootLayer, delta);
393 clippingBounds.move(-delta.x(), -delta.y());
395 layerBounds.intersect(clippingBounds);
398 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
399 // then we need to ensure that the compositing layer has non-zero size so that we can apply
400 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
401 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
402 layerBounds.setWidth(1);
403 layerBounds.setHeight(1);
404 m_artificiallyInflatedBounds = true;
406 m_artificiallyInflatedBounds = false;
409 setCompositedBounds(layerBounds);
412 void CompositedLayerMapping::updateAfterWidgetResize()
414 if (renderer()->isRenderPart()) {
415 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
416 innerCompositor->frameViewDidChangeSize();
417 // We can floor this point because our frameviews are always aligned to pixel boundaries.
418 ASSERT(contentsBox().location() == flooredIntPoint(contentsBox().location()));
419 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
424 void CompositedLayerMapping::updateCompositingReasons()
426 // All other layers owned by this mapping will have the same compositing reason
427 // for their lifetime, so they are initialized only when created.
428 m_graphicsLayer->setCompositingReasons(m_owningLayer.compositingReasons());
431 void CompositedLayerMapping::updateAfterLayout(UpdateAfterLayoutFlags flags)
433 RenderLayerCompositor* layerCompositor = compositor();
434 if (!layerCompositor->compositingLayersNeedRebuild()) {
435 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
436 // position of this layer's GraphicsLayer depends on the position of our compositing
437 // ancestor's GraphicsLayer. That cannot be determined until all the descendant
438 // RenderLayers of that ancestor have been processed via updateLayerPositions().
440 // The solution is to update compositing children of this layer here,
441 // via updateCompositingChildrenGeometry().
442 updateCompositedBounds(GraphicsLayerUpdater::ForceUpdate);
443 layerCompositor->updateCompositingDescendantGeometry(m_owningLayer.stackingNode(), &m_owningLayer, flags & CompositingChildrenOnly);
445 if (flags & IsUpdateRoot) {
446 updateGraphicsLayerGeometry(GraphicsLayerUpdater::ForceUpdate);
447 layerCompositor->updateRootLayerPosition();
448 RenderLayerStackingNode* stackingContainer = m_owningLayer.stackingNode()->enclosingStackingContainerNode();
449 if (!layerCompositor->compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != m_owningLayer.stackingNode()))
450 layerCompositor->updateCompositingDescendantGeometry(stackingContainer, stackingContainer->layer(), flags & CompositingChildrenOnly);
454 if (flags & NeedsFullRepaint && !paintsIntoCompositedAncestor())
455 setContentsNeedDisplay();
458 bool CompositedLayerMapping::updateGraphicsLayerConfiguration()
460 RenderLayerCompositor* compositor = this->compositor();
461 RenderObject* renderer = this->renderer();
463 m_owningLayer.updateDescendantDependentFlags();
464 m_owningLayer.stackingNode()->updateZOrderLists();
466 bool layerConfigChanged = false;
467 setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(&m_owningLayer));
469 // The background layer is currently only used for fixed root backgrounds.
470 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
471 layerConfigChanged = true;
473 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(&m_owningLayer)))
474 layerConfigChanged = true;
476 bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer);
478 // Our scrolling layer will clip.
479 if (m_owningLayer.needsCompositedScrolling())
480 needsDescendentsClippingLayer = false;
482 RenderLayer* scrollParent = renderer->compositorDrivenAcceleratedScrollingEnabled() ? m_owningLayer.scrollParent() : 0;
483 bool needsAncestorClip = compositor->clippedByAncestor(&m_owningLayer);
485 // If our containing block is our ancestor scrolling layer, then we'll already be clipped
486 // to it via our scroll parent and we don't need an ancestor clipping layer.
487 if (m_owningLayer.renderer()->containingBlock()->enclosingLayer() == m_owningLayer.ancestorCompositedScrollingLayer())
488 needsAncestorClip = false;
491 if (updateClippingLayers(needsAncestorClip, needsDescendentsClippingLayer))
492 layerConfigChanged = true;
494 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
495 layerConfigChanged = true;
497 if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling()))
498 layerConfigChanged = true;
500 bool hasPerspective = false;
501 if (RenderStyle* style = renderer->style())
502 hasPerspective = style->hasPerspective();
503 bool needsChildTransformLayer = hasPerspective && (layerForChildrenTransform() == m_childTransformLayer.get());
504 if (updateChildTransformLayer(needsChildTransformLayer))
505 layerConfigChanged = true;
507 updateScrollParent(scrollParent);
508 updateClipParent(m_owningLayer.clipParent());
510 if (updateSquashingLayers(!m_squashedLayers.isEmpty()))
511 layerConfigChanged = true;
513 if (layerConfigChanged)
514 updateInternalHierarchy();
516 if (updateMaskLayer(renderer->hasMask()))
517 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
519 bool hasChildClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer) && (hasClippingLayer() || hasScrollingLayer());
520 bool needsChildClippingMask = (renderer->style()->clipPath() || renderer->style()->hasBorderRadius()) && (hasChildClippingLayer || isAcceleratedContents(renderer));
521 if (updateClippingMaskLayers(needsChildClippingMask)) {
522 if (hasClippingLayer())
523 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
524 else if (hasScrollingLayer())
525 scrollingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
526 else if (isAcceleratedContents(renderer))
527 m_graphicsLayer->setContentsClippingMaskLayer(m_childClippingMaskLayer.get());
530 if (m_owningLayer.reflectionInfo()) {
531 if (m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
532 GraphicsLayer* reflectionLayer = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping()->mainGraphicsLayer();
533 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
536 m_graphicsLayer->setReplicatedByLayer(0);
539 updateBackgroundColor();
541 if (isDirectlyCompositedImage())
542 updateImageContents();
544 if (blink::WebLayer* layer = platformLayerForPlugin(renderer)) {
545 m_graphicsLayer->setContentsToPlatformLayer(layer);
546 } else if (renderer->node() && renderer->node()->isFrameOwnerElement() && toHTMLFrameOwnerElement(renderer->node())->contentFrame()) {
547 blink::WebLayer* layer = toHTMLFrameOwnerElement(renderer->node())->contentFrame()->remotePlatformLayer();
549 m_graphicsLayer->setContentsToPlatformLayer(layer);
550 } else if (renderer->isVideo()) {
551 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer->node());
552 m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer());
553 } else if (isAcceleratedCanvas(renderer)) {
554 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
555 if (CanvasRenderingContext* context = canvas->renderingContext())
556 m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer());
557 layerConfigChanged = true;
559 if (renderer->isRenderPart())
560 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
562 return layerConfigChanged;
565 static IntRect clipBox(RenderBox* renderer)
567 LayoutRect result = PaintInfo::infiniteRect();
568 if (renderer->hasOverflowClip())
569 result = renderer->overflowClipRect(LayoutPoint());
571 if (renderer->hasClip())
572 result.intersect(renderer->clipRect(LayoutPoint()));
574 return pixelSnappedIntRect(result);
577 static LayoutPoint computeOffsetFromCompositedAncestor(const RenderLayer* layer, const RenderLayer* compositedAncestor)
580 layer->convertToLayerCoords(compositedAncestor, offset);
581 if (compositedAncestor)
582 offset.move(compositedAncestor->compositedLayerMapping()->subpixelAccumulation());
586 void CompositedLayerMapping::adjustBoundsForSubPixelAccumulation(const RenderLayer* compositedAncestor, IntRect& localBounds, IntRect& relativeBounds, IntPoint& delta)
588 LayoutRect localRawCompositingBounds = compositedBounds();
589 LayoutPoint rawDelta = computeOffsetFromCompositedAncestor(&m_owningLayer, compositedAncestor);
590 // We call toInt and not floor here because toInt truncates, but floor will floor negative numbers
591 // down e.g. floor(-1.1) would become -2.
592 delta = IntPoint(rawDelta.x().toInt(), rawDelta.y().toInt());
593 m_subpixelAccumulation = toLayoutSize(rawDelta).fraction();
594 RELEASE_ASSERT(m_subpixelAccumulation.width() < 1 && m_subpixelAccumulation.height() < 1);
596 // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates.
597 localRawCompositingBounds.move(m_subpixelAccumulation);
598 localBounds = pixelSnappedIntRect(localRawCompositingBounds);
600 relativeBounds = localBounds;
601 relativeBounds.moveBy(delta);
604 void CompositedLayerMapping::updateSquashingLayerGeometry(const IntPoint& delta)
606 if (!m_squashingLayer)
609 ASSERT(compositor()->layerSquashingEnabled());
611 LayoutRect totalSquashBounds;
612 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
613 LayoutRect squashedBounds = compositor()->calculateCompositedBounds(m_squashedLayers[i].renderLayer, m_squashedLayers[i].renderLayer);
615 // Store the local bounds of the RenderLayer subtree before applying the offset.
616 m_squashedLayers[i].compositedBounds = squashedBounds;
618 squashedBounds.move(m_squashedLayers[i].offsetFromSquashingCLM);
619 totalSquashBounds.unite(squashedBounds);
622 // The totalSquashBounds is positioned with respect to m_owningLayer of this CompositedLayerMapping.
623 // But the squashingLayer needs to be positioned with respect to the ancestor CompositedLayerMapping.
624 // The conversion between m_owningLayer and the ancestor CLM is already computed in the caller as
625 // |delta| + |m_subpixelAccumulation|.
626 LayoutPoint rawDelta = delta + m_subpixelAccumulation;
627 totalSquashBounds.moveBy(rawDelta);
628 IntRect squashLayerBounds = enclosingIntRect(totalSquashBounds);
629 IntPoint squashLayerOrigin = squashLayerBounds.location();
630 LayoutPoint squashLayerOriginInOwningLayerSpace = LayoutPoint(squashLayerOrigin - rawDelta);
632 m_squashingLayer->setPosition(squashLayerBounds.location());
633 m_squashingLayer->setSize(squashLayerBounds.size());
635 // Now that the squashing bounds are known, we can convert the RenderLayer painting offsets
636 // from CLM owning layer space to the squashing layer space.
638 // The painting offset we want to compute for each squashed RenderLayer is essentially the position of
639 // the squashed RenderLayer described w.r.t. m_squashingLayer's origin. For this purpose we already cached
640 // offsetFromSquashingCLM before, which describes where the squashed RenderLayer is located w.r.t.
641 // m_owningLayer. So we just need to convert that point from m_owningLayer space to m_squashingLayer
642 // space. This is simply done by subtracing squashLayerOriginInOwningLayerSpace, but then the offset
643 // overall needs to be negated because that's the direction that the painting code expects the
645 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
646 LayoutSize offsetFromSquashLayerOrigin = LayoutPoint(m_squashedLayers[i].offsetFromSquashingCLM) - squashLayerOriginInOwningLayerSpace;
647 m_squashedLayers[i].offsetFromRenderer = -flooredIntSize(offsetFromSquashLayerOrigin);
648 m_squashedLayers[i].subpixelAccumulation = offsetFromSquashLayerOrigin.fraction();
649 ASSERT(m_squashedLayers[i].subpixelAccumulation ==
650 toLayoutSize(computeOffsetFromCompositedAncestor(m_squashedLayers[i].renderLayer, m_squashedLayers[i].renderLayer->ancestorCompositingLayer())).fraction());
652 // FIXME: find a better design to avoid this redundant value - most likely it will make
653 // sense to move the paint task info into RenderLayer's m_compositingProperties.
654 m_squashedLayers[i].renderLayer->setOffsetFromSquashingLayerOrigin(m_squashedLayers[i].offsetFromRenderer);
658 GraphicsLayerUpdater::UpdateType CompositedLayerMapping::updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType updateType)
660 // If we haven't built z-order lists yet, wait until later.
661 if (m_owningLayer.stackingNode()->isStackingContainer() && m_owningLayer.stackingNode()->zOrderListsDirty())
664 if (!m_needToUpdateGeometry && updateType != GraphicsLayerUpdater::ForceUpdate)
666 m_needToUpdateGeometry = false;
667 if (m_needToUpdateGeometryOfAllDecendants)
668 updateType = GraphicsLayerUpdater::ForceUpdate;
670 // Set transform property, if it is not animating. We have to do this here because the transform
671 // is affected by the layer dimensions.
672 if (!hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitTransform))
673 updateTransform(renderer()->style());
675 // Set opacity, if it is not animating.
676 if (!hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyOpacity))
677 updateOpacity(renderer()->style());
679 m_owningLayer.updateDescendantDependentFlags();
681 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
682 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
683 // non-compositing visible layers.
684 bool contentsVisible = m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendantLayers();
685 if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && renderer()->isVideo()) {
686 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer()->node());
687 if (mediaElement->isFullscreen())
688 contentsVisible = false;
690 m_graphicsLayer->setContentsVisible(contentsVisible);
692 RenderStyle* style = renderer()->style();
693 m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
695 RenderLayer* compAncestor = m_owningLayer.ancestorCompositingLayer();
697 // We compute everything relative to the enclosing compositing layer.
698 IntRect ancestorCompositingBounds;
700 ASSERT(compAncestor->hasCompositedLayerMapping());
701 ancestorCompositingBounds = compAncestor->compositedLayerMapping()->pixelSnappedCompositedBounds();
704 IntRect localCompositingBounds;
705 IntRect relativeCompositingBounds;
707 adjustBoundsForSubPixelAccumulation(compAncestor, localCompositingBounds, relativeCompositingBounds, delta);
709 IntPoint graphicsLayerParentLocation;
710 if (compAncestor && compAncestor->compositedLayerMapping()->hasClippingLayer()) {
711 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
712 // position relative to it.
713 IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
714 graphicsLayerParentLocation = clippingBox.location() + roundedIntSize(compAncestor->compositedLayerMapping()->subpixelAccumulation());
715 } else if (compAncestor) {
716 graphicsLayerParentLocation = ancestorCompositingBounds.location();
718 graphicsLayerParentLocation = renderer()->view()->documentRect().location();
721 if (compAncestor && compAncestor->needsCompositedScrolling()) {
722 RenderBox* renderBox = toRenderBox(compAncestor->renderer());
723 IntSize scrollOffset = renderBox->scrolledContentOffset();
724 IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
725 graphicsLayerParentLocation = scrollOrigin - scrollOffset;
728 if (compAncestor && m_ancestorClippingLayer) {
729 // FIXME: this should use cached clip rects, but this sometimes give
730 // inaccurate results (and trips the ASSERTS in RenderLayerClipper).
731 ClipRectsContext clipRectsContext(compAncestor, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
732 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
733 ASSERT(parentClipRect != PaintInfo::infiniteRect());
734 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
735 m_ancestorClippingLayer->setSize(parentClipRect.size());
737 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
738 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta);
740 // The primary layer is then parented in, and positioned relative to this clipping layer.
741 graphicsLayerParentLocation = parentClipRect.location();
744 FloatSize contentsSize = relativeCompositingBounds.size();
746 m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
747 m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
749 FloatSize oldSize = m_graphicsLayer->size();
750 if (oldSize != contentsSize)
751 m_graphicsLayer->setSize(contentsSize);
753 // If we have a layer that clips children, position it.
755 if (GraphicsLayer* clipLayer = clippingLayer()) {
756 clippingBox = clipBox(toRenderBox(renderer()));
757 clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location() + roundedIntSize(m_subpixelAccumulation)));
758 clipLayer->setSize(clippingBox.size());
759 clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
760 if (m_childClippingMaskLayer && !m_scrollingLayer) {
761 m_childClippingMaskLayer->setPosition(clipLayer->position());
762 m_childClippingMaskLayer->setSize(clipLayer->size());
763 m_childClippingMaskLayer->setOffsetFromRenderer(clipLayer->offsetFromRenderer());
765 } else if (m_childTransformLayer) {
766 m_childTransformLayer->setSize(contentsSize);
770 if (m_maskLayer->size() != m_graphicsLayer->size()) {
771 m_maskLayer->setSize(m_graphicsLayer->size());
772 m_maskLayer->setNeedsDisplay();
774 m_maskLayer->setPosition(FloatPoint());
775 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
778 if (m_owningLayer.hasTransform()) {
779 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
781 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
782 IntRect layerBounds = pixelSnappedIntRect(toLayoutPoint(m_subpixelAccumulation), borderBox.size());
783 layerBounds.moveBy(delta);
785 // Update properties that depend on layer dimensions
786 FloatPoint3D transformOrigin = computeTransformOrigin(IntRect(IntPoint(), layerBounds.size()));
787 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
789 relativeCompositingBounds.width() ? (layerBounds.x() - relativeCompositingBounds.x() + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
790 relativeCompositingBounds.height() ? (layerBounds.y() - relativeCompositingBounds.y() + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
791 transformOrigin.z());
792 m_graphicsLayer->setAnchorPoint(anchor);
794 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
797 if (GraphicsLayer* childrenTransformLayer = layerForChildrenTransform())
798 childrenTransformLayer->setAnchorPoint(m_graphicsLayer->anchorPoint());
800 if (m_foregroundLayer) {
801 FloatSize foregroundSize = contentsSize;
802 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
803 if (hasClippingLayer()) {
804 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
805 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
806 foregroundSize = FloatSize(clippingBox.size());
807 foregroundOffset = toIntSize(clippingBox.location());
810 m_foregroundLayer->setPosition(FloatPoint());
811 if (foregroundSize != m_foregroundLayer->size()) {
812 m_foregroundLayer->setSize(foregroundSize);
813 m_foregroundLayer->setNeedsDisplay();
815 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
818 if (m_backgroundLayer) {
819 FloatSize backgroundSize = contentsSize;
820 if (backgroundLayerPaintsFixedRootBackground()) {
821 FrameView* frameView = toRenderView(renderer())->frameView();
822 backgroundSize = frameView->visibleContentRect().size();
824 m_backgroundLayer->setPosition(FloatPoint());
825 if (backgroundSize != m_backgroundLayer->size()) {
826 m_backgroundLayer->setSize(backgroundSize);
827 m_backgroundLayer->setNeedsDisplay();
829 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
832 if (m_owningLayer.reflectionInfo() && m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
833 CompositedLayerMappingPtr reflectionCompositedLayerMapping = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping();
834 reflectionCompositedLayerMapping->updateGraphicsLayerGeometry(GraphicsLayerUpdater::ForceUpdate);
836 // The reflection layer has the bounds of m_owningLayer.reflectionLayer(),
837 // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
838 FloatRect layerBounds = compositedBounds();
839 FloatRect reflectionLayerBounds = reflectionCompositedLayerMapping->compositedBounds();
840 reflectionCompositedLayerMapping->mainGraphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
843 if (m_scrollingLayer) {
844 ASSERT(m_scrollingContentsLayer);
845 RenderBox* renderBox = toRenderBox(renderer());
846 IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
848 IntSize adjustedScrollOffset = m_owningLayer.scrollableArea()->adjustedScrollOffset();
849 m_scrollingLayer->setPosition(FloatPoint(clientBox.location() - localCompositingBounds.location() + roundedIntSize(m_subpixelAccumulation)));
850 m_scrollingLayer->setSize(clientBox.size());
852 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
853 m_scrollingLayer->setOffsetFromRenderer(-toIntSize(clientBox.location()));
855 if (m_childClippingMaskLayer) {
856 m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
857 m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
858 m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
861 bool clientBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
863 IntSize scrollSize(renderBox->scrollWidth(), renderBox->scrollHeight());
864 if (scrollSize != m_scrollingContentsLayer->size() || clientBoxOffsetChanged)
865 m_scrollingContentsLayer->setNeedsDisplay();
867 IntSize scrollingContentsOffset = toIntSize(clientBox.location() - adjustedScrollOffset);
868 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) {
869 bool coordinatorHandlesOffset = compositor()->scrollingLayerDidChange(&m_owningLayer);
870 m_scrollingContentsLayer->setPosition(coordinatorHandlesOffset ? FloatPoint() : FloatPoint(-adjustedScrollOffset));
873 m_scrollingContentsLayer->setSize(scrollSize);
874 // FIXME: The paint offset and the scroll offset should really be separate concepts.
875 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
877 if (m_foregroundLayer) {
878 if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
879 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
880 m_foregroundLayer->setNeedsDisplay();
881 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
885 updateSquashingLayerGeometry(delta);
887 if (m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->scrollsOverflow())
888 m_owningLayer.scrollableArea()->positionOverflowControls();
890 // We can't make this call in RenderLayerCompositor::allocateOrClearCompositedLayerMapping
891 // since it depends on whether compAncestor draws content, which gets updated later.
892 updateRequiresOwnBackingStoreForAncestorReasons(compAncestor);
894 if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
895 updateLayerBlendMode(style);
896 updateIsRootForIsolatedGroup();
899 updateHasGpuRasterizationHint(renderer()->style());
900 updateContentsRect();
901 updateBackgroundColor();
902 updateDrawsContent();
903 updateContentsOpaque();
904 updateAfterWidgetResize();
905 updateRenderingContext();
906 updateShouldFlattenTransform();
907 updateChildrenTransform();
908 updateScrollParent(renderer()->compositorDrivenAcceleratedScrollingEnabled() ? m_owningLayer.scrollParent() : 0);
909 registerScrollingLayers();
911 updateCompositingReasons();
916 void CompositedLayerMapping::registerScrollingLayers()
918 // Register fixed position layers and their containers with the scrolling coordinator.
919 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
920 if (!scrollingCoordinator)
923 compositor()->updateViewportConstraintStatus(&m_owningLayer);
925 scrollingCoordinator->updateLayerPositionConstraint(&m_owningLayer);
927 // Page scale is applied as a transform on the root render view layer. Because the scroll
928 // layer is further up in the hierarchy, we need to avoid marking the root render view
929 // layer as a container.
930 bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer();
931 // FIXME: we should make certain that childForSuperLayers will never be the m_squashingContainmentLayer here
932 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(localRootForOwningLayer(), isContainer);
935 void CompositedLayerMapping::updateInternalHierarchy()
937 // m_foregroundLayer has to be inserted in the correct order with child layers,
938 // so it's not inserted here.
939 if (m_ancestorClippingLayer)
940 m_ancestorClippingLayer->removeAllChildren();
942 m_graphicsLayer->removeFromParent();
944 if (m_ancestorClippingLayer)
945 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
947 if (m_childContainmentLayer)
948 m_graphicsLayer->addChild(m_childContainmentLayer.get());
949 else if (m_childTransformLayer)
950 m_graphicsLayer->addChild(m_childTransformLayer.get());
952 if (m_scrollingLayer) {
953 GraphicsLayer* superLayer = m_graphicsLayer.get();
955 if (m_childContainmentLayer)
956 superLayer = m_childContainmentLayer.get();
958 if (m_childTransformLayer)
959 superLayer = m_childTransformLayer.get();
961 superLayer->addChild(m_scrollingLayer.get());
964 // The clip for child layers does not include space for overflow controls, so they exist as
965 // siblings of the clipping layer if we have one. Normal children of this layer are set as
966 // children of the clipping layer.
967 if (m_layerForHorizontalScrollbar)
968 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
969 if (m_layerForVerticalScrollbar)
970 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
971 if (m_layerForScrollCorner)
972 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
974 // The squashing containment layer, if it exists, becomes a no-op parent.
975 if (m_squashingLayer) {
976 ASSERT(compositor()->layerSquashingEnabled());
977 ASSERT(m_squashingContainmentLayer);
979 m_squashingContainmentLayer->removeAllChildren();
981 if (m_ancestorClippingLayer)
982 m_squashingContainmentLayer->addChild(m_ancestorClippingLayer.get());
984 m_squashingContainmentLayer->addChild(m_graphicsLayer.get());
986 m_squashingContainmentLayer->addChild(m_squashingLayer.get());
990 void CompositedLayerMapping::updateContentsRect()
992 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
995 void CompositedLayerMapping::updateDrawsContent()
997 if (m_scrollingLayer) {
998 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
999 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1000 // m_scrollingLayer never has backing store.
1001 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1002 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground();
1003 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1005 bool hasScrollingPaintedContent = m_owningLayer.hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
1006 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
1010 bool hasPaintedContent = containsPaintedContent();
1011 if (hasPaintedContent && isAcceleratedCanvas(renderer())) {
1012 CanvasRenderingContext* context = toHTMLCanvasElement(renderer()->node())->renderingContext();
1013 // Content layer may be null if context is lost.
1014 if (blink::WebLayer* contentLayer = context->platformLayer()) {
1015 Color bgColor(Color::transparent);
1016 if (contentLayerSupportsDirectBackgroundComposition(renderer())) {
1017 bgColor = rendererBackgroundColor();
1018 hasPaintedContent = false;
1020 contentLayer->setBackgroundColor(bgColor.rgb());
1024 // FIXME: we could refine this to only allocate backings for one of these layers if possible.
1025 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1026 if (m_foregroundLayer)
1027 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1029 if (m_backgroundLayer)
1030 m_backgroundLayer->setDrawsContent(hasPaintedContent);
1033 void CompositedLayerMapping::updateChildrenTransform()
1035 if (GraphicsLayer* childTransformLayer = layerForChildrenTransform()) {
1036 childTransformLayer->setTransform(owningLayer().perspectiveTransform());
1037 bool hasPerspective = false;
1038 if (RenderStyle* style = m_owningLayer.renderer()->style())
1039 hasPerspective = style->hasPerspective();
1041 childTransformLayer->setShouldFlattenTransform(false);
1043 // Note, if the target is the scrolling layer, we need to ensure that the
1044 // scrolling content layer doesn't flatten the transform. (It would be nice
1045 // if we could apply transform to the scrolling content layer, but that's
1046 // too late, we need the children transform to be applied _before_ the
1047 // scrolling offset.)
1048 if (childTransformLayer == m_scrollingLayer.get())
1049 m_scrollingContentsLayer->setShouldFlattenTransform(false);
1053 // Return true if the layers changed.
1054 bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
1056 bool layersChanged = false;
1058 if (needsAncestorClip) {
1059 if (!m_ancestorClippingLayer) {
1060 m_ancestorClippingLayer = createGraphicsLayer(CompositingReasonLayerForAncestorClip);
1061 m_ancestorClippingLayer->setMasksToBounds(true);
1062 layersChanged = true;
1064 } else if (m_ancestorClippingLayer) {
1065 m_ancestorClippingLayer->removeFromParent();
1066 m_ancestorClippingLayer = nullptr;
1067 layersChanged = true;
1070 if (needsDescendantClip) {
1071 // We don't need a child containment layer if we're the main frame render view
1072 // layer. It's redundant as the frame clip above us will handle this clipping.
1073 if (!m_childContainmentLayer && !m_isMainFrameRenderViewLayer) {
1074 m_childContainmentLayer = createGraphicsLayer(CompositingReasonLayerForDescendantClip);
1075 m_childContainmentLayer->setMasksToBounds(true);
1076 layersChanged = true;
1078 } else if (hasClippingLayer()) {
1079 m_childContainmentLayer->removeFromParent();
1080 m_childContainmentLayer = nullptr;
1081 layersChanged = true;
1084 return layersChanged;
1087 bool CompositedLayerMapping::updateChildTransformLayer(bool needsChildTransformLayer)
1089 bool layersChanged = false;
1091 if (needsChildTransformLayer) {
1092 if (!m_childTransformLayer) {
1093 m_childTransformLayer = createGraphicsLayer(CompositingReasonLayerForPerspective);
1094 m_childTransformLayer->setDrawsContent(false);
1095 m_childTransformLayer->setShouldFlattenTransform(false);
1096 layersChanged = true;
1098 } else if (m_childTransformLayer) {
1099 m_childTransformLayer->removeFromParent();
1100 m_childTransformLayer = nullptr;
1101 layersChanged = true;
1104 return layersChanged;
1107 void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1109 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1112 // Only a member function so it can call createGraphicsLayer.
1113 bool CompositedLayerMapping::toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer>& layer, bool needsLayer, CompositingReasons reason)
1115 if (needsLayer == !!layer)
1117 layer = needsLayer ? createGraphicsLayer(reason) : nullptr;
1121 bool CompositedLayerMapping::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1123 bool horizontalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForHorizontalScrollbar, needsHorizontalScrollbarLayer, CompositingReasonLayerForHorizontalScrollbar);
1124 bool verticalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForVerticalScrollbar, needsVerticalScrollbarLayer, CompositingReasonLayerForVerticalScrollbar);
1125 bool scrollCornerLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForScrollCorner, needsScrollCornerLayer, CompositingReasonLayerForScrollCorner);
1127 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1128 if (horizontalScrollbarLayerChanged)
1129 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), HorizontalScrollbar);
1130 if (verticalScrollbarLayerChanged)
1131 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), VerticalScrollbar);
1134 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1137 void CompositedLayerMapping::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
1139 IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer() - roundedIntSize(m_subpixelAccumulation);
1140 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1141 Scrollbar* hBar = m_owningLayer.scrollableArea()->horizontalScrollbar();
1143 layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1144 layer->setSize(hBar->frameRect().size());
1145 if (layer->hasContentsLayer())
1146 layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
1148 layer->setDrawsContent(hBar && !layer->hasContentsLayer());
1151 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1152 Scrollbar* vBar = m_owningLayer.scrollableArea()->verticalScrollbar();
1154 layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1155 layer->setSize(vBar->frameRect().size());
1156 if (layer->hasContentsLayer())
1157 layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
1159 layer->setDrawsContent(vBar && !layer->hasContentsLayer());
1162 if (GraphicsLayer* layer = layerForScrollCorner()) {
1163 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
1164 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1165 layer->setSize(scrollCornerAndResizer.size());
1166 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1170 bool CompositedLayerMapping::hasUnpositionedOverflowControlsLayers() const
1172 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1173 if (!layer->drawsContent())
1177 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1178 if (!layer->drawsContent())
1182 if (GraphicsLayer* layer = layerForScrollCorner()) {
1183 if (!layer->drawsContent())
1190 enum ApplyToGraphicsLayersModeFlags {
1191 ApplyToCoreLayers = (1 << 0),
1192 ApplyToSquashingLayer = (1 << 1),
1193 ApplyToScrollbarLayers = (1 << 2),
1194 ApplyToBackgroundLayer = (1 << 3),
1195 ApplyToMaskLayers = (1 << 4),
1196 ApplyToContentLayers = (1 << 5),
1197 ApplyToAllGraphicsLayers = (ApplyToSquashingLayer | ApplyToScrollbarLayers | ApplyToBackgroundLayer | ApplyToMaskLayers | ApplyToCoreLayers | ApplyToContentLayers)
1199 typedef unsigned ApplyToGraphicsLayersMode;
1201 template <typename Func>
1202 static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping, const Func& f, ApplyToGraphicsLayersMode mode)
1206 if ((mode & ApplyToCoreLayers) && mapping->squashingContainmentLayer())
1207 f(mapping->squashingContainmentLayer());
1208 if ((mode & ApplyToCoreLayers) && mapping->childTransformLayer())
1209 f(mapping->childTransformLayer());
1210 if ((mode & ApplyToCoreLayers) && mapping->ancestorClippingLayer())
1211 f(mapping->ancestorClippingLayer());
1212 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->mainGraphicsLayer())
1213 f(mapping->mainGraphicsLayer());
1214 if ((mode & ApplyToCoreLayers) && mapping->clippingLayer())
1215 f(mapping->clippingLayer());
1216 if ((mode & ApplyToCoreLayers) && mapping->scrollingLayer())
1217 f(mapping->scrollingLayer());
1218 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->scrollingContentsLayer())
1219 f(mapping->scrollingContentsLayer());
1220 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->foregroundLayer())
1221 f(mapping->foregroundLayer());
1223 if ((mode & ApplyToSquashingLayer) && mapping->squashingLayer())
1224 f(mapping->squashingLayer());
1226 if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->maskLayer())
1227 f(mapping->maskLayer());
1228 if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->childClippingMaskLayer())
1229 f(mapping->childClippingMaskLayer());
1231 if (((mode & ApplyToBackgroundLayer) || (mode & ApplyToContentLayers)) && mapping->backgroundLayer())
1232 f(mapping->backgroundLayer());
1234 if ((mode & ApplyToScrollbarLayers) && mapping->layerForHorizontalScrollbar())
1235 f(mapping->layerForHorizontalScrollbar());
1236 if ((mode & ApplyToScrollbarLayers) && mapping->layerForVerticalScrollbar())
1237 f(mapping->layerForVerticalScrollbar());
1238 if ((mode & ApplyToScrollbarLayers) && mapping->layerForScrollCorner())
1239 f(mapping->layerForScrollCorner());
1242 struct UpdateRenderingContextFunctor {
1243 void operator() (GraphicsLayer* layer) const { layer->setRenderingContext(renderingContext); }
1244 int renderingContext;
1247 void CompositedLayerMapping::updateRenderingContext()
1249 // All layers but the squashing layer (which contains 'alien' content) should be included in this
1250 // rendering context.
1253 // NB, it is illegal at this point to query an ancestor's compositing state. Some compositing
1254 // reasons depend on the compositing state of ancestors. So if we want a rendering context id
1255 // for the context root, we cannot ask for the id of its associated WebLayer now; it may not have
1256 // one yet. We could do a second past after doing the compositing updates to get these ids,
1257 // but this would actually be harmful. We do not want to attach any semantic meaning to
1258 // the context id other than the fact that they group a number of layers together for the
1259 // sake of 3d sorting. So instead we will ask the compositor to vend us an arbitrary, but
1261 if (RenderLayer* root = m_owningLayer.renderingContextRoot()) {
1262 if (Node* node = root->renderer()->node())
1263 id = static_cast<int>(WTF::PtrHash<Node*>::hash(node));
1266 UpdateRenderingContextFunctor functor = { id };
1267 ApplyToGraphicsLayersMode mode = ApplyToAllGraphicsLayers & ~ApplyToSquashingLayer;
1268 ApplyToGraphicsLayers<UpdateRenderingContextFunctor>(this, functor, mode);
1271 struct UpdateShouldFlattenTransformFunctor {
1272 void operator() (GraphicsLayer* layer) const { layer->setShouldFlattenTransform(shouldFlatten); }
1276 void CompositedLayerMapping::updateShouldFlattenTransform()
1278 // All CLM-managed layers that could affect a descendant layer should update their
1279 // should-flatten-transform value (the other layers' transforms don't matter here).
1280 UpdateShouldFlattenTransformFunctor functor = { !m_owningLayer.shouldPreserve3D() };
1281 ApplyToGraphicsLayersMode mode = ApplyToCoreLayers;
1282 ApplyToGraphicsLayers(this, functor, mode);
1285 bool CompositedLayerMapping::updateForegroundLayer(bool needsForegroundLayer)
1287 bool layerChanged = false;
1288 if (needsForegroundLayer) {
1289 if (!m_foregroundLayer) {
1290 m_foregroundLayer = createGraphicsLayer(CompositingReasonLayerForForeground);
1291 m_foregroundLayer->setDrawsContent(true);
1292 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1293 // If the foreground layer pops content out of the graphics
1294 // layer, then the graphics layer needs to be repainted.
1295 // FIXME: This is conservative, as m_foregroundLayer could
1296 // be smaller than m_graphicsLayer due to clipping.
1297 m_graphicsLayer->setNeedsDisplay();
1298 layerChanged = true;
1300 } else if (m_foregroundLayer) {
1301 FloatRect repaintRect(FloatPoint(), m_foregroundLayer->size());
1302 m_graphicsLayer->setNeedsDisplayInRect(repaintRect);
1303 m_foregroundLayer->removeFromParent();
1304 m_foregroundLayer = nullptr;
1305 layerChanged = true;
1309 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1311 return layerChanged;
1314 bool CompositedLayerMapping::updateBackgroundLayer(bool needsBackgroundLayer)
1316 bool layerChanged = false;
1317 if (needsBackgroundLayer) {
1318 if (!m_backgroundLayer) {
1319 m_backgroundLayer = createGraphicsLayer(CompositingReasonLayerForBackground);
1320 m_backgroundLayer->setDrawsContent(true);
1321 m_backgroundLayer->setAnchorPoint(FloatPoint3D());
1322 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1324 m_backgroundLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
1325 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(false);
1327 layerChanged = true;
1330 if (m_backgroundLayer) {
1331 m_backgroundLayer->removeFromParent();
1332 m_backgroundLayer = nullptr;
1334 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
1336 layerChanged = true;
1340 if (layerChanged && !m_owningLayer.renderer()->documentBeingDestroyed())
1341 compositor()->rootFixedBackgroundsChanged();
1343 return layerChanged;
1346 bool CompositedLayerMapping::updateMaskLayer(bool needsMaskLayer)
1348 bool layerChanged = false;
1349 if (needsMaskLayer) {
1351 m_maskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
1352 m_maskLayer->setDrawsContent(true);
1353 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
1354 layerChanged = true;
1356 } else if (m_maskLayer) {
1357 m_maskLayer = nullptr;
1358 layerChanged = true;
1362 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1364 return layerChanged;
1367 bool CompositedLayerMapping::updateClippingMaskLayers(bool needsChildClippingMaskLayer)
1369 bool layerChanged = false;
1370 if (needsChildClippingMaskLayer) {
1371 if (!m_childClippingMaskLayer) {
1372 m_childClippingMaskLayer = createGraphicsLayer(CompositingReasonLayerForClippingMask);
1373 m_childClippingMaskLayer->setDrawsContent(true);
1374 m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
1375 layerChanged = true;
1377 } else if (m_childClippingMaskLayer) {
1378 m_childClippingMaskLayer = nullptr;
1379 layerChanged = true;
1381 return layerChanged;
1384 bool CompositedLayerMapping::updateScrollingLayers(bool needsScrollingLayers)
1386 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1388 bool layerChanged = false;
1389 if (needsScrollingLayers) {
1390 if (!m_scrollingLayer) {
1391 // Outer layer which corresponds with the scroll view.
1392 m_scrollingLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContainer);
1393 m_scrollingLayer->setDrawsContent(false);
1394 m_scrollingLayer->setMasksToBounds(true);
1396 // Inner layer which renders the content that scrolls.
1397 m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContents);
1398 m_scrollingContentsLayer->setDrawsContent(true);
1399 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1400 if (!m_foregroundLayer)
1401 paintPhase |= GraphicsLayerPaintForeground;
1402 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1403 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
1405 layerChanged = true;
1406 if (scrollingCoordinator)
1407 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
1409 } else if (m_scrollingLayer) {
1410 m_scrollingLayer = nullptr;
1411 m_scrollingContentsLayer = nullptr;
1412 layerChanged = true;
1413 if (scrollingCoordinator)
1414 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
1418 updateInternalHierarchy();
1419 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1420 m_graphicsLayer->setNeedsDisplay();
1421 if (renderer()->view())
1422 compositor()->scrollingLayerDidChange(&m_owningLayer);
1425 return layerChanged;
1428 static void updateScrollParentForGraphicsLayer(GraphicsLayer* layer, GraphicsLayer* topmostLayer, RenderLayer* scrollParent, ScrollingCoordinator* scrollingCoordinator)
1433 // Only the topmost layer has a scroll parent. All other layers have a null scroll parent.
1434 if (layer != topmostLayer)
1437 scrollingCoordinator->updateScrollParentForGraphicsLayer(layer, scrollParent);
1440 void CompositedLayerMapping::updateScrollParent(RenderLayer* scrollParent)
1442 if (!scrollParent && m_squashedLayers.size() && renderer()->compositorDrivenAcceleratedScrollingEnabled())
1443 scrollParent = m_squashedLayers[0].renderLayer->scrollParent();
1445 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1446 GraphicsLayer* topmostLayer = childForSuperlayers();
1447 updateScrollParentForGraphicsLayer(m_squashingContainmentLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1448 updateScrollParentForGraphicsLayer(m_ancestorClippingLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1449 updateScrollParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1453 void CompositedLayerMapping::updateClipParent(RenderLayer* clipParent)
1455 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer))
1456 scrollingCoordinator->updateClipParentForGraphicsLayer(m_graphicsLayer.get(), clipParent);
1459 bool CompositedLayerMapping::updateSquashingLayers(bool needsSquashingLayers)
1461 bool layersChanged = false;
1463 if (needsSquashingLayers) {
1464 ASSERT(compositor()->layerSquashingEnabled());
1466 if (!m_squashingLayer) {
1467 ASSERT(!m_squashingContainmentLayer);
1469 m_squashingLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContents);
1470 m_squashingLayer->setDrawsContent(true);
1472 // FIXME: containment layer needs a new CompositingReason, CompositingReasonOverlap is not appropriate.
1473 m_squashingContainmentLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContainer);
1474 layersChanged = true;
1477 ASSERT(m_squashingLayer && m_squashingContainmentLayer);
1479 if (m_squashingLayer) {
1480 m_squashingLayer->removeFromParent();
1481 m_squashingLayer = nullptr;
1482 // FIXME: do we need to invalidate something here?
1484 ASSERT(m_squashingContainmentLayer);
1485 m_squashingContainmentLayer->removeFromParent();
1486 m_squashingContainmentLayer = nullptr;
1487 layersChanged = true;
1490 ASSERT(!m_squashingLayer && !m_squashingContainmentLayer);
1493 return layersChanged;
1496 GraphicsLayerPaintingPhase CompositedLayerMapping::paintingPhaseForPrimaryLayer() const
1499 if (!m_backgroundLayer)
1500 phase |= GraphicsLayerPaintBackground;
1501 if (!m_foregroundLayer)
1502 phase |= GraphicsLayerPaintForeground;
1504 phase |= GraphicsLayerPaintMask;
1506 if (m_scrollingContentsLayer) {
1507 phase &= ~GraphicsLayerPaintForeground;
1508 phase |= GraphicsLayerPaintCompositedScroll;
1511 if (m_owningLayer.compositingReasons() & CompositingReasonOverflowScrollingParent)
1512 phase |= GraphicsLayerPaintCompositedScroll;
1514 return static_cast<GraphicsLayerPaintingPhase>(phase);
1517 float CompositedLayerMapping::compositingOpacity(float rendererOpacity) const
1519 float finalOpacity = rendererOpacity;
1521 for (RenderLayer* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1522 // We only care about parents that are stacking contexts.
1523 // Recall that opacity creates stacking context.
1524 if (!curr->stackingNode()->isStackingContainer())
1527 // If we found a composited layer, regardless of whether it actually
1528 // paints into it, we want to compute opacity relative to it. So we can
1531 // FIXME: with grouped backings, a composited descendant will have to
1532 // continue past the grouped (squashed) layers that its parents may
1533 // contribute to. This whole confusion can be avoided by specifying
1534 // explicitly the composited ancestor where we would stop accumulating
1536 if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == HasOwnBackingButPaintsIntoAncestor)
1539 finalOpacity *= curr->renderer()->opacity();
1542 return finalOpacity;
1545 Color CompositedLayerMapping::rendererBackgroundColor() const
1547 RenderObject* backgroundRenderer = renderer();
1548 if (backgroundRenderer->isRoot())
1549 backgroundRenderer = backgroundRenderer->rendererForRootBackground();
1551 return backgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
1554 void CompositedLayerMapping::updateBackgroundColor()
1556 m_graphicsLayer->setBackgroundColor(rendererBackgroundColor());
1559 bool CompositedLayerMapping::paintsChildren() const
1561 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers())
1564 if (hasVisibleNonCompositingDescendantLayers())
1570 static bool isCompositedPlugin(RenderObject* renderer)
1572 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing();
1575 static bool hasVisibleNonCompositingDescendant(RenderLayer* parent)
1577 if (!parent->hasVisibleDescendant())
1580 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1581 parent->stackingNode()->updateLayerListsIfNeeded();
1583 #if !ASSERT_DISABLED
1584 LayerListMutationDetector mutationChecker(parent->stackingNode());
1587 RenderLayerStackingNodeIterator normalFlowIterator(*parent->stackingNode(), AllChildren);
1588 while (RenderLayerStackingNode* curNode = normalFlowIterator.next()) {
1589 RenderLayer* curLayer = curNode->layer();
1590 if (curLayer->hasCompositedLayerMapping())
1592 if (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))
1599 // FIXME: By name the implementation is correct. But the code that uses this function means something
1600 // very slightly different - the implementation needs to also include composited descendants that
1601 // don't paint into their own backing, and instead paint into this backing.
1602 bool CompositedLayerMapping::hasVisibleNonCompositingDescendantLayers() const
1604 return hasVisibleNonCompositingDescendant(&m_owningLayer);
1607 bool CompositedLayerMapping::containsPaintedContent() const
1609 if (paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer.isReflection())
1612 if (isDirectlyCompositedImage())
1615 RenderObject* renderObject = renderer();
1616 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1617 // and set background color on the layer in that case, instead of allocating backing store and painting.
1618 if (renderObject->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
1619 return m_owningLayer.hasBoxDecorationsOrBackground();
1621 if (m_owningLayer.hasVisibleBoxDecorations())
1624 if (renderObject->hasMask()) // masks require special treatment
1627 if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
1630 if (renderObject->isRenderRegion())
1633 if (renderObject->node() && renderObject->node()->isDocumentNode()) {
1634 // Look to see if the root object has a non-simple background
1635 RenderObject* rootObject = renderObject->document().documentElement() ? renderObject->document().documentElement()->renderer() : 0;
1636 // Reject anything that has a border, a border-radius or outline,
1637 // or is not a simple background (no background, or solid color).
1638 if (rootObject && hasBoxDecorationsOrBackgroundImage(rootObject->style()))
1641 // Now look at the body's renderer.
1642 HTMLElement* body = renderObject->document().body();
1643 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
1644 if (bodyObject && hasBoxDecorationsOrBackgroundImage(bodyObject->style()))
1648 // FIXME: it's O(n^2). A better solution is needed.
1649 return paintsChildren();
1652 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1653 // that require painting. Direct compositing saves backing store.
1654 bool CompositedLayerMapping::isDirectlyCompositedImage() const
1656 RenderObject* renderObject = renderer();
1658 if (!renderObject->isImage() || m_owningLayer.hasBoxDecorationsOrBackground() || renderObject->hasClip())
1661 RenderImage* imageRenderer = toRenderImage(renderObject);
1662 if (ImageResource* cachedImage = imageRenderer->cachedImage()) {
1663 if (!cachedImage->hasImage())
1666 Image* image = cachedImage->imageForRenderer(imageRenderer);
1667 return image->isBitmapImage();
1673 void CompositedLayerMapping::contentChanged(ContentChangeType changeType)
1675 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1676 updateImageContents();
1680 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
1681 m_graphicsLayer->setContentsNeedsDisplay();
1686 void CompositedLayerMapping::updateImageContents()
1688 ASSERT(renderer()->isImage());
1689 RenderImage* imageRenderer = toRenderImage(renderer());
1691 ImageResource* cachedImage = imageRenderer->cachedImage();
1695 Image* image = cachedImage->imageForRenderer(imageRenderer);
1699 // We have to wait until the image is fully loaded before setting it on the layer.
1700 if (!cachedImage->isLoaded())
1703 // This is a no-op if the layer doesn't have an inner layer for the image.
1704 m_graphicsLayer->setContentsToImage(image);
1705 updateDrawsContent();
1707 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1708 // the image. So we have to kick the animation each time; this has the downside that the
1709 // image will keep animating, even if its layer is not visible.
1710 image->startAnimation();
1713 FloatPoint3D CompositedLayerMapping::computeTransformOrigin(const IntRect& borderBox) const
1715 RenderStyle* style = renderer()->style();
1717 FloatPoint3D origin;
1718 origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
1719 origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
1720 origin.setZ(style->transformOriginZ());
1725 FloatPoint CompositedLayerMapping::computePerspectiveOrigin(const IntRect& borderBox) const
1727 RenderStyle* style = renderer()->style();
1729 float boxWidth = borderBox.width();
1730 float boxHeight = borderBox.height();
1733 origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth));
1734 origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight));
1739 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
1740 LayoutSize CompositedLayerMapping::contentOffsetInCompostingLayer() const
1742 return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1745 LayoutRect CompositedLayerMapping::contentsBox() const
1747 LayoutRect contentsBox = contentsRect(renderer());
1748 contentsBox.move(contentOffsetInCompostingLayer());
1752 GraphicsLayer* CompositedLayerMapping::parentForSublayers() const
1754 if (m_scrollingContentsLayer)
1755 return m_scrollingContentsLayer.get();
1757 if (m_childContainmentLayer)
1758 return m_childContainmentLayer.get();
1760 if (m_childTransformLayer)
1761 return m_childTransformLayer.get();
1763 return m_graphicsLayer.get();
1766 GraphicsLayer* CompositedLayerMapping::localRootForOwningLayer() const
1768 if (m_ancestorClippingLayer)
1769 return m_ancestorClippingLayer.get();
1771 return m_graphicsLayer.get();
1774 GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const
1776 if (m_squashingContainmentLayer)
1777 return m_squashingContainmentLayer.get();
1779 return localRootForOwningLayer();
1782 GraphicsLayer* CompositedLayerMapping::layerForChildrenTransform() const
1784 if (GraphicsLayer* clipLayer = clippingLayer())
1786 if (m_scrollingLayer)
1787 return m_scrollingLayer.get();
1788 return m_childTransformLayer.get();
1791 bool CompositedLayerMapping::updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer* compositingAncestorLayer)
1793 bool previousRequiresOwnBackingStoreForAncestorReasons = m_requiresOwnBackingStoreForAncestorReasons;
1794 bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
1795 bool canPaintIntoAncestor = compositingAncestorLayer
1796 && (compositingAncestorLayer->compositedLayerMapping()->mainGraphicsLayer()->drawsContent()
1797 || compositingAncestorLayer->compositedLayerMapping()->paintsIntoCompositedAncestor());
1798 m_requiresOwnBackingStoreForAncestorReasons = !canPaintIntoAncestor;
1800 if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
1801 paintsIntoCompositedAncestorChanged();
1802 return m_requiresOwnBackingStoreForAncestorReasons != previousRequiresOwnBackingStoreForAncestorReasons;
1805 bool CompositedLayerMapping::updateRequiresOwnBackingStoreForIntrinsicReasons()
1807 bool previousRequiresOwnBackingStoreForIntrinsicReasons = m_requiresOwnBackingStoreForIntrinsicReasons;
1808 bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
1809 RenderObject* renderer = m_owningLayer.renderer();
1810 m_requiresOwnBackingStoreForIntrinsicReasons = m_owningLayer.isRootLayer()
1811 || (m_owningLayer.compositingReasons() & CompositingReasonComboReasonsThatRequireOwnBacking)
1812 || m_owningLayer.transform()
1813 || m_owningLayer.clipsCompositingDescendantsWithBorderRadius() // FIXME: Revisit this if the paintsIntoCompositedAncestor state is removed.
1814 || renderer->isTransparent()
1815 || renderer->hasMask()
1816 || renderer->hasReflection()
1817 || renderer->hasFilter();
1819 if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
1820 paintsIntoCompositedAncestorChanged();
1821 return m_requiresOwnBackingStoreForIntrinsicReasons != previousRequiresOwnBackingStoreForIntrinsicReasons;
1824 void CompositedLayerMapping::paintsIntoCompositedAncestorChanged()
1826 // The answer to paintsIntoCompositedAncestor() affects cached clip rects, so when
1827 // it changes we have to clear clip rects on descendants.
1828 m_owningLayer.clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
1829 m_owningLayer.repainter().computeRepaintRectsIncludingDescendants();
1831 compositor()->repaintInCompositedAncestor(&m_owningLayer, compositedBounds());
1834 void CompositedLayerMapping::setBlendMode(blink::WebBlendMode blendMode)
1836 if (m_ancestorClippingLayer) {
1837 m_ancestorClippingLayer->setBlendMode(blendMode);
1838 m_graphicsLayer->setBlendMode(blink::WebBlendModeNormal);
1840 m_graphicsLayer->setBlendMode(blendMode);
1844 void CompositedLayerMapping::setNeedsGeometryUpdate()
1846 m_needToUpdateGeometryOfAllDecendants = true;
1848 for (RenderLayer* current = &m_owningLayer; current; current = current->ancestorCompositingLayer()) {
1849 // FIXME: We should be able to return early from this function once we
1850 // find a CompositedLayerMapping that has m_needToUpdateGeometry set.
1851 // However, we can't do that until we remove the incremental compositing
1852 // updates because they can clear m_needToUpdateGeometry without walking
1854 ASSERT(current->hasCompositedLayerMapping());
1855 CompositedLayerMappingPtr mapping = current->compositedLayerMapping();
1856 mapping->m_needToUpdateGeometry = true;
1860 void CompositedLayerMapping::clearNeedsGeometryUpdate()
1862 m_needToUpdateGeometry = false;
1863 m_needToUpdateGeometryOfAllDecendants = false;
1866 struct SetContentsNeedsDisplayFunctor {
1867 void operator() (GraphicsLayer* layer) const
1869 if (layer->drawsContent())
1870 layer->setNeedsDisplay();
1874 void CompositedLayerMapping::setContentsNeedDisplay()
1876 // FIXME: need to split out repaints for the background.
1877 ASSERT(!paintsIntoCompositedAncestor());
1878 ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToContentLayers);
1881 struct SetContentsNeedsDisplayInRectFunctor {
1882 void operator() (GraphicsLayer* layer) const
1884 if (layer->drawsContent()) {
1885 IntRect layerDirtyRect = r;
1886 layerDirtyRect.move(-layer->offsetFromRenderer());
1887 layer->setNeedsDisplayInRect(layerDirtyRect);
1894 // r is in the coordinate space of the layer's render object
1895 void CompositedLayerMapping::setContentsNeedDisplayInRect(const IntRect& r)
1897 // FIXME: need to split out repaints for the background.
1898 ASSERT(!paintsIntoCompositedAncestor());
1899 SetContentsNeedsDisplayInRectFunctor functor = { r };
1900 ApplyToGraphicsLayers(this, functor, ApplyToContentLayers);
1903 void CompositedLayerMapping::doPaintTask(GraphicsLayerPaintInfo& paintInfo, GraphicsContext* context,
1904 const IntRect& clip) // In the coords of rootLayer.
1906 if (paintsIntoCompositedAncestor()) {
1907 ASSERT_NOT_REACHED();
1911 FontCachePurgePreventer fontCachePurgePreventer;
1913 PaintLayerFlags paintFlags = 0;
1914 if (paintInfo.paintingPhase & GraphicsLayerPaintBackground)
1915 paintFlags |= PaintLayerPaintingCompositingBackgroundPhase;
1916 if (paintInfo.paintingPhase & GraphicsLayerPaintForeground)
1917 paintFlags |= PaintLayerPaintingCompositingForegroundPhase;
1918 if (paintInfo.paintingPhase & GraphicsLayerPaintMask)
1919 paintFlags |= PaintLayerPaintingCompositingMaskPhase;
1920 if (paintInfo.paintingPhase & GraphicsLayerPaintChildClippingMask)
1921 paintFlags |= PaintLayerPaintingChildClippingMaskPhase;
1922 if (paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)
1923 paintFlags |= PaintLayerPaintingOverflowContents;
1924 if (paintInfo.paintingPhase & GraphicsLayerPaintCompositedScroll)
1925 paintFlags |= PaintLayerPaintingCompositingScrollingPhase;
1927 if (paintInfo.isBackgroundLayer)
1928 paintFlags |= (PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
1929 else if (compositor()->fixedRootBackgroundLayer())
1930 paintFlags |= PaintLayerPaintingSkipRootBackground;
1932 // Note carefully: in theory it is appropriate to invoke context->save() here
1933 // and restore the context after painting. For efficiency, we are assuming that
1934 // it is equivalent to manually undo this offset translation, which means we are
1935 // assuming that the context's space was not affected by the RenderLayer
1938 IntSize offset = paintInfo.offsetFromRenderer;
1939 context->translate(-offset);
1941 // The dirtyRect is in the coords of the painting root.
1942 IntRect dirtyRect(clip);
1943 dirtyRect.move(offset);
1945 if (!(paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)) {
1946 LayoutRect bounds = paintInfo.compositedBounds;
1947 bounds.move(paintInfo.subpixelAccumulation);
1948 dirtyRect.intersect(pixelSnappedIntRect(bounds));
1950 dirtyRect.move(roundedIntSize(paintInfo.subpixelAccumulation));
1954 paintInfo.renderLayer->renderer()->assertSubtreeIsLaidOut();
1957 if (paintInfo.renderLayer->compositingState() != PaintsIntoGroupedBacking) {
1958 // FIXME: GraphicsLayers need a way to split for RenderRegions.
1959 LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.subpixelAccumulation);
1960 paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags);
1962 ASSERT(!paintInfo.isBackgroundLayer || paintFlags & PaintLayerPaintingRootBackgroundOnly);
1964 if (paintInfo.renderLayer->containsDirtyOverlayScrollbars())
1965 paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags | PaintLayerPaintingOverlayScrollbars);
1967 ASSERT(compositor()->layerSquashingEnabled());
1968 LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.subpixelAccumulation);
1969 paintInfo.renderLayer->paintLayer(context, paintingInfo, paintFlags);
1972 ASSERT(!paintInfo.renderLayer->m_usedTransparency);
1974 // Manually restore the context to its original state by applying the opposite translation.
1975 context->translate(offset);
1978 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
1984 const IntRect& scrollbarRect = scrollbar->frameRect();
1985 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
1986 IntRect transformedClip = clip;
1987 transformedClip.moveBy(scrollbarRect.location());
1988 scrollbar->paint(&context, transformedClip);
1992 // Up-call from compositing layer drawing callback.
1993 void CompositedLayerMapping::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
1995 // https://code.google.com/p/chromium/issues/detail?id=343772
1996 DisableCompositingQueryAsserts disabler;
1998 // FIXME: once the state machine is ready, this can be removed and we can refer to that instead.
1999 if (Page* page = renderer()->frame()->page())
2000 page->setIsPainting(true);
2002 InspectorInstrumentation::willPaint(m_owningLayer.renderer(), graphicsLayer);
2004 if (graphicsLayer == m_graphicsLayer.get()
2005 || graphicsLayer == m_foregroundLayer.get()
2006 || graphicsLayer == m_backgroundLayer.get()
2007 || graphicsLayer == m_maskLayer.get()
2008 || graphicsLayer == m_childClippingMaskLayer.get()
2009 || graphicsLayer == m_scrollingContentsLayer.get()) {
2011 GraphicsLayerPaintInfo paintInfo;
2012 paintInfo.renderLayer = &m_owningLayer;
2013 paintInfo.compositedBounds = compositedBounds();
2014 paintInfo.offsetFromRenderer = graphicsLayer->offsetFromRenderer();
2015 paintInfo.paintingPhase = paintingPhase;
2016 paintInfo.isBackgroundLayer = (graphicsLayer == m_backgroundLayer);
2017 paintInfo.subpixelAccumulation = m_subpixelAccumulation;
2019 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2020 doPaintTask(paintInfo, &context, clip);
2021 } else if (graphicsLayer == m_squashingLayer.get()) {
2022 ASSERT(compositor()->layerSquashingEnabled());
2023 for (size_t i = 0; i < m_squashedLayers.size(); ++i)
2024 doPaintTask(m_squashedLayers[i], &context, clip);
2025 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2026 paintScrollbar(m_owningLayer.scrollableArea()->horizontalScrollbar(), context, clip);
2027 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2028 paintScrollbar(m_owningLayer.scrollableArea()->verticalScrollbar(), context, clip);
2029 } else if (graphicsLayer == layerForScrollCorner()) {
2030 const IntRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
2032 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
2033 IntRect transformedClip = clip;
2034 transformedClip.moveBy(scrollCornerAndResizer.location());
2035 m_owningLayer.scrollableArea()->paintScrollCorner(&context, IntPoint(), transformedClip);
2036 m_owningLayer.scrollableArea()->paintResizer(&context, IntPoint(), transformedClip);
2039 InspectorInstrumentation::didPaint(m_owningLayer.renderer(), graphicsLayer, &context, clip);
2041 if (Page* page = renderer()->frame()->page())
2042 page->setIsPainting(false);
2046 bool CompositedLayerMapping::isTrackingRepaints() const
2048 GraphicsLayerClient* client = compositor();
2049 return client ? client->isTrackingRepaints() : false;
2052 struct CollectTrackedRepaintRectsFunctor {
2053 void operator() (GraphicsLayer* layer) const { layer->collectTrackedRepaintRects(*rects); }
2054 Vector<FloatRect>* rects;
2057 PassOwnPtr<Vector<FloatRect> > CompositedLayerMapping::collectTrackedRepaintRects() const
2059 OwnPtr<Vector<FloatRect> > rects = adoptPtr(new Vector<FloatRect>);
2060 CollectTrackedRepaintRectsFunctor functor = { rects.get() };
2061 ApplyToGraphicsLayers(this, functor, ApplyToAllGraphicsLayers);
2062 return rects.release();
2066 void CompositedLayerMapping::verifyNotPainting()
2068 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
2072 void CompositedLayerMapping::notifyAnimationStarted(const GraphicsLayer*, double monotonicTime)
2074 renderer()->node()->document().cssPendingAnimations().notifyCompositorAnimationStarted(monotonicTime);
2077 IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const
2079 LayoutRect bounds = m_compositedBounds;
2080 bounds.move(m_subpixelAccumulation);
2081 return pixelSnappedIntRect(bounds);
2084 void CompositedLayerMapping::setCompositedBounds(const LayoutRect& bounds)
2086 m_compositedBounds = bounds;
2089 bool CompositedLayerMapping::updateSquashingLayerAssignment(RenderLayer* layer, LayoutSize offsetFromSquashingCLM, size_t nextSquashedLayerIndex)
2091 ASSERT(compositor()->layerSquashingEnabled());
2093 GraphicsLayerPaintInfo paintInfo;
2094 paintInfo.renderLayer = layer;
2095 // NOTE: composited bounds are updated elsewhere
2096 // NOTE: offsetFromRenderer is updated elsewhere
2097 paintInfo.offsetFromSquashingCLM = offsetFromSquashingCLM;
2098 paintInfo.paintingPhase = GraphicsLayerPaintAllWithOverflowClip;
2099 paintInfo.isBackgroundLayer = false;
2101 // Change tracking on squashing layers: at the first sign of something changed, just invalidate the layer.
2102 // FIXME: Perhaps we can find a tighter more clever mechanism later.
2103 bool updatedAssignment = false;
2104 if (nextSquashedLayerIndex < m_squashedLayers.size()) {
2105 if (!paintInfo.isEquivalentForSquashing(m_squashedLayers[nextSquashedLayerIndex])) {
2106 updatedAssignment = true;
2108 m_squashedLayers[nextSquashedLayerIndex] = paintInfo;
2110 m_squashedLayers.append(paintInfo);
2111 updatedAssignment = true;
2113 layer->setGroupedMapping(this);
2114 return updatedAssignment;
2117 void CompositedLayerMapping::removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer* layer)
2119 size_t layerIndex = kNotFound;
2121 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
2122 if (m_squashedLayers[i].renderLayer == layer) {
2128 if (layerIndex == kNotFound)
2131 m_squashedLayers.remove(layerIndex);
2134 void CompositedLayerMapping::finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex)
2136 ASSERT(compositor()->layerSquashingEnabled());
2138 // Any additional squashed RenderLayers in the array no longer exist, and removing invalidates the squashingLayer contents.
2139 if (nextSquashedLayerIndex < m_squashedLayers.size())
2140 m_squashedLayers.remove(nextSquashedLayerIndex, m_squashedLayers.size() - nextSquashedLayerIndex);
2143 String CompositedLayerMapping::debugName(const GraphicsLayer* graphicsLayer)
2146 if (graphicsLayer == m_graphicsLayer.get()) {
2147 name = m_owningLayer.debugName();
2148 } else if (graphicsLayer == m_squashingContainmentLayer.get()) {
2149 name = "Squashing Containment Layer";
2150 } else if (graphicsLayer == m_squashingLayer.get()) {
2151 name = "Squashing Layer";
2152 } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
2153 name = "Ancestor Clipping Layer";
2154 } else if (graphicsLayer == m_foregroundLayer.get()) {
2155 name = m_owningLayer.debugName() + " (foreground) Layer";
2156 } else if (graphicsLayer == m_backgroundLayer.get()) {
2157 name = m_owningLayer.debugName() + " (background) Layer";
2158 } else if (graphicsLayer == m_childContainmentLayer.get()) {
2159 name = "Child Containment Layer";
2160 } else if (graphicsLayer == m_childTransformLayer.get()) {
2161 name = "Child Transform Layer";
2162 } else if (graphicsLayer == m_maskLayer.get()) {
2163 name = "Mask Layer";
2164 } else if (graphicsLayer == m_childClippingMaskLayer.get()) {
2165 name = "Child Clipping Mask Layer";
2166 } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
2167 name = "Horizontal Scrollbar Layer";
2168 } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
2169 name = "Vertical Scrollbar Layer";
2170 } else if (graphicsLayer == m_layerForScrollCorner.get()) {
2171 name = "Scroll Corner Layer";
2172 } else if (graphicsLayer == m_scrollingLayer.get()) {
2173 name = "Scrolling Layer";
2174 } else if (graphicsLayer == m_scrollingContentsLayer.get()) {
2175 name = "Scrolling Contents Layer";
2177 ASSERT_NOT_REACHED();
2183 } // namespace WebCore