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 "core/HTMLNames.h"
31 #include "core/fetch/ImageResource.h"
32 #include "core/html/HTMLCanvasElement.h"
33 #include "core/html/HTMLIFrameElement.h"
34 #include "core/html/HTMLMediaElement.h"
35 #include "core/html/canvas/CanvasRenderingContext.h"
36 #include "core/inspector/InspectorInstrumentation.h"
37 #include "core/inspector/InspectorNodeIds.h"
38 #include "core/inspector/InspectorTraceEvents.h"
39 #include "core/page/Chrome.h"
40 #include "core/frame/FrameView.h"
41 #include "core/page/scrolling/ScrollingCoordinator.h"
42 #include "core/plugins/PluginView.h"
43 #include "core/rendering/FilterEffectRenderer.h"
44 #include "core/rendering/RenderImage.h"
45 #include "core/rendering/RenderLayerStackingNodeIterator.h"
46 #include "core/rendering/RenderVideo.h"
47 #include "core/rendering/RenderView.h"
48 #include "core/rendering/compositing/RenderLayerCompositor.h"
49 #include "core/rendering/style/KeyframeList.h"
50 #include "platform/LengthFunctions.h"
51 #include "platform/RuntimeEnabledFeatures.h"
52 #include "platform/fonts/FontCache.h"
53 #include "platform/graphics/GraphicsContext.h"
54 #include "wtf/CurrentTime.h"
55 #include "wtf/text/StringBuilder.h"
61 using namespace HTMLNames;
63 static IntRect clipBox(RenderBox* renderer);
65 static IntRect contentsRect(const RenderObject* renderer)
67 if (!renderer->isBox())
70 return renderer->isVideo() ?
71 toRenderVideo(renderer)->videoBox() :
72 pixelSnappedIntRect(toRenderBox(renderer)->contentBoxRect());
75 static IntRect backgroundRect(const RenderObject* renderer)
77 if (!renderer->isBox())
81 const RenderBox* box = toRenderBox(renderer);
82 EFillBox clip = box->style()->backgroundClip();
85 rect = box->borderBoxRect();
88 rect = box->paddingBoxRect();
91 rect = box->contentBoxRect();
97 return pixelSnappedIntRect(rect);
100 static inline bool isAcceleratedCanvas(const RenderObject* renderer)
102 if (renderer->isCanvas()) {
103 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
104 if (CanvasRenderingContext* context = canvas->renderingContext())
105 return context->isAccelerated();
110 static bool hasBoxDecorations(const RenderStyle* style)
112 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
115 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
117 return hasBoxDecorations(style) || style->hasBackgroundImage();
120 static bool contentLayerSupportsDirectBackgroundComposition(const RenderObject* renderer)
122 // No support for decorations - border, border-radius or outline.
123 // Only simple background - solid color or transparent.
124 if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
127 // If there is no background, there is nothing to support.
128 if (!renderer->style()->hasBackground())
131 // Simple background that is contained within the contents rect.
132 return contentsRect(renderer).contains(backgroundRect(renderer));
135 static blink::WebLayer* platformLayerForPlugin(RenderObject* renderer)
137 if (!renderer->isEmbeddedObject())
139 Widget* widget = toRenderEmbeddedObject(renderer)->widget();
140 if (!widget || !widget->isPluginView())
142 return toPluginView(widget)->platformLayer();
146 static inline bool isAcceleratedContents(RenderObject* renderer)
148 return isAcceleratedCanvas(renderer)
149 || (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing())
150 || renderer->isVideo();
153 // Get the scrolling coordinator in a way that works inside CompositedLayerMapping's destructor.
154 static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer)
156 Page* page = layer.renderer()->frame()->page();
160 return page->scrollingCoordinator();
163 CompositedLayerMapping::CompositedLayerMapping(RenderLayer& layer)
164 : m_owningLayer(layer)
165 , m_pendingUpdateScope(GraphicsLayerUpdateNone)
166 , m_isMainFrameRenderViewLayer(false)
167 , m_requiresOwnBackingStoreForIntrinsicReasons(true)
168 , m_requiresOwnBackingStoreForAncestorReasons(true)
169 , m_canCompositeFilters(false)
170 , m_backgroundLayerPaintsFixedRootBackground(false)
171 , m_scrollingContentsAreEmpty(false)
173 if (layer.isRootLayer() && renderer()->frame()->isMainFrame())
174 m_isMainFrameRenderViewLayer = true;
176 createPrimaryGraphicsLayer();
179 CompositedLayerMapping::~CompositedLayerMapping()
181 // Hits in compositing/squashing/squash-onto-nephew.html.
182 DisableCompositingQueryAsserts disabler;
184 // Do not leave the destroyed pointer dangling on any RenderLayers that painted to this mapping's squashing layer.
185 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
186 RenderLayer* oldSquashedLayer = m_squashedLayers[i].renderLayer;
187 if (oldSquashedLayer->groupedMapping() == this) {
188 oldSquashedLayer->setGroupedMapping(0, true);
189 oldSquashedLayer->setLostGroupedMapping(true);
193 updateClippingLayers(false, false);
194 updateOverflowControlsLayers(false, false, false);
195 updateChildTransformLayer(false);
196 updateForegroundLayer(false);
197 updateBackgroundLayer(false);
198 updateMaskLayer(false);
199 updateClippingMaskLayers(false);
200 updateScrollingLayers(false);
201 updateSquashingLayers(false);
202 destroyGraphicsLayers();
205 PassOwnPtr<GraphicsLayer> CompositedLayerMapping::createGraphicsLayer(CompositingReasons reasons)
207 GraphicsLayerFactory* graphicsLayerFactory = 0;
208 if (Page* page = renderer()->frame()->page())
209 graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
211 OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
213 graphicsLayer->setCompositingReasons(reasons);
214 if (Node* owningNode = m_owningLayer.renderer()->generatingNode())
215 graphicsLayer->setOwnerNodeId(InspectorNodeIds::idForNode(owningNode));
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());
233 if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
234 updateLayerBlendMode(renderer()->style());
235 updateIsRootForIsolatedGroup();
239 void CompositedLayerMapping::destroyGraphicsLayers()
242 m_graphicsLayer->removeFromParent();
244 m_ancestorClippingLayer = nullptr;
245 m_graphicsLayer = nullptr;
246 m_foregroundLayer = nullptr;
247 m_backgroundLayer = nullptr;
248 m_childContainmentLayer = nullptr;
249 m_childTransformLayer = nullptr;
250 m_maskLayer = nullptr;
251 m_childClippingMaskLayer = nullptr;
253 m_scrollingLayer = nullptr;
254 m_scrollingContentsLayer = nullptr;
255 m_scrollingBlockSelectionLayer = 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()->hasAcceleratedCompositing());
273 m_graphicsLayer->setTransform(t);
276 void CompositedLayerMapping::updateFilters(const RenderStyle* style)
278 unsigned 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::updateContentsOpaque()
312 // For non-root layers, background is always painted by the primary graphics layer.
313 ASSERT(m_isMainFrameRenderViewLayer || !m_backgroundLayer);
314 if (m_backgroundLayer) {
315 m_graphicsLayer->setContentsOpaque(false);
316 m_backgroundLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
318 m_graphicsLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
322 void CompositedLayerMapping::updateCompositedBounds(GraphicsLayerUpdater::UpdateType updateType)
324 if (!shouldUpdateGraphicsLayer(updateType))
327 // FIXME: if this is really needed for performance, it would be better to store it on RenderLayer.
328 m_compositedBounds = m_owningLayer.boundingBoxForCompositing();
331 void CompositedLayerMapping::updateAfterWidgetResize()
333 if (renderer()->isRenderPart()) {
334 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
335 innerCompositor->frameViewDidChangeSize();
336 // We can floor this point because our frameviews are always aligned to pixel boundaries.
337 ASSERT(contentsBox().location() == flooredIntPoint(contentsBox().location()));
338 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
343 void CompositedLayerMapping::updateCompositingReasons()
345 // All other layers owned by this mapping will have the same compositing reason
346 // for their lifetime, so they are initialized only when created.
347 m_graphicsLayer->setCompositingReasons(m_owningLayer.compositingReasons());
350 bool CompositedLayerMapping::updateGraphicsLayerConfiguration(GraphicsLayerUpdater::UpdateType updateType)
352 if (!shouldUpdateGraphicsLayer(updateType))
355 RenderLayerCompositor* compositor = this->compositor();
356 RenderObject* renderer = this->renderer();
358 m_owningLayer.updateDescendantDependentFlags();
359 m_owningLayer.stackingNode()->updateZOrderLists();
361 bool layerConfigChanged = false;
362 setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(&m_owningLayer));
364 // The background layer is currently only used for fixed root backgrounds.
365 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
366 layerConfigChanged = true;
368 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(&m_owningLayer)))
369 layerConfigChanged = true;
371 bool needsDescendantsClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer);
373 // Our scrolling layer will clip.
374 if (m_owningLayer.needsCompositedScrolling())
375 needsDescendantsClippingLayer = false;
377 RenderLayer* scrollParent = compositor->acceleratedCompositingForOverflowScrollEnabled() ? m_owningLayer.scrollParent() : 0;
378 bool needsAncestorClip = compositor->clippedByNonAncestorInStackingTree(&m_owningLayer);
380 // If our containing block is our ancestor scrolling layer, then we'll already be clipped
381 // to it via our scroll parent and we don't need an ancestor clipping layer.
382 if (m_owningLayer.renderer()->containingBlock()->enclosingLayer() == m_owningLayer.ancestorScrollingLayer())
383 needsAncestorClip = false;
386 if (updateClippingLayers(needsAncestorClip, needsDescendantsClippingLayer))
387 layerConfigChanged = true;
389 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
390 layerConfigChanged = true;
392 bool scrollingConfigChanged = false;
393 if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling())) {
394 layerConfigChanged = true;
395 scrollingConfigChanged = true;
398 bool hasPerspective = false;
399 if (RenderStyle* style = renderer->style())
400 hasPerspective = style->hasPerspective();
401 bool needsChildTransformLayer = hasPerspective && (layerForChildrenTransform() == m_childTransformLayer.get()) && renderer->isBox();
402 if (updateChildTransformLayer(needsChildTransformLayer))
403 layerConfigChanged = true;
405 updateScrollParent(scrollParent);
406 updateClipParent(m_owningLayer.clipParent());
408 if (updateSquashingLayers(!m_squashedLayers.isEmpty()))
409 layerConfigChanged = true;
411 if (layerConfigChanged)
412 updateInternalHierarchy();
414 if (scrollingConfigChanged) {
415 if (renderer->view())
416 compositor->scrollingLayerDidChange(&m_owningLayer);
419 // A mask layer is not part of the hierarchy proper, it's an auxiliary layer
420 // that's plugged into another GraphicsLayer that is part of the hierarchy.
421 // It has no parent or child GraphicsLayer. For that reason, we process it
422 // here, after the hierarchy has been updated.
423 bool maskLayerChanged = false;
424 if (updateMaskLayer(renderer->hasMask())) {
425 maskLayerChanged = true;
426 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
429 bool hasChildClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer) && (hasClippingLayer() || hasScrollingLayer());
430 // If we have a border radius or clip path on a scrolling layer, we need a clipping mask to properly
431 // clip the scrolled contents, even if there are no composited descendants.
432 bool hasClipPath = renderer->style()->clipPath();
433 bool needsChildClippingMask = (hasClipPath || renderer->style()->hasBorderRadius()) && (hasChildClippingLayer || isAcceleratedContents(renderer) || hasScrollingLayer());
434 if (updateClippingMaskLayers(needsChildClippingMask)) {
435 // Clip path clips the entire subtree, including scrollbars. It must be attached directly onto
436 // the main m_graphicsLayer.
438 m_graphicsLayer->setMaskLayer(m_childClippingMaskLayer.get());
439 else if (hasClippingLayer())
440 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
441 else if (hasScrollingLayer())
442 scrollingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
443 else if (isAcceleratedContents(renderer))
444 m_graphicsLayer->setContentsClippingMaskLayer(m_childClippingMaskLayer.get());
447 if (m_owningLayer.reflectionInfo()) {
448 if (m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
449 GraphicsLayer* reflectionLayer = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping()->mainGraphicsLayer();
450 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
453 m_graphicsLayer->setReplicatedByLayer(0);
456 updateBackgroundColor();
458 if (isDirectlyCompositedImage())
459 updateImageContents();
461 if (blink::WebLayer* layer = platformLayerForPlugin(renderer)) {
462 m_graphicsLayer->setContentsToPlatformLayer(layer);
463 } else if (renderer->node() && renderer->node()->isFrameOwnerElement() && toHTMLFrameOwnerElement(renderer->node())->contentFrame()) {
464 blink::WebLayer* layer = toHTMLFrameOwnerElement(renderer->node())->contentFrame()->remotePlatformLayer();
466 m_graphicsLayer->setContentsToPlatformLayer(layer);
467 } else if (renderer->isVideo()) {
468 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer->node());
469 m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer());
470 } else if (isAcceleratedCanvas(renderer)) {
471 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
472 if (CanvasRenderingContext* context = canvas->renderingContext())
473 m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer());
474 layerConfigChanged = true;
476 if (renderer->isRenderPart())
477 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
479 // Changes to either the internal hierarchy or the mask layer have an impact
480 // on painting phases, so we need to update when either are updated.
481 if (layerConfigChanged || maskLayerChanged)
482 updatePaintingPhases();
484 return layerConfigChanged;
487 static IntRect clipBox(RenderBox* renderer)
489 LayoutRect result = PaintInfo::infiniteRect();
490 if (renderer->hasOverflowClip())
491 result = renderer->overflowClipRect(LayoutPoint());
493 if (renderer->hasClip())
494 result.intersect(renderer->clipRect(LayoutPoint()));
496 return pixelSnappedIntRect(result);
499 static LayoutPoint computeOffsetFromCompositedAncestor(const RenderLayer* layer, const RenderLayer* compositedAncestor)
502 layer->convertToLayerCoords(compositedAncestor, offset);
503 if (compositedAncestor)
504 offset.move(compositedAncestor->compositedLayerMapping()->owningLayer().subpixelAccumulation());
508 void CompositedLayerMapping::computeBoundsOfOwningLayer(const RenderLayer* compositedAncestor, IntRect& localBounds, IntRect& compositingBoundsRelativeToCompositedAncestor, LayoutPoint& offsetFromCompositedAncestor,
509 IntPoint& snappedOffsetFromCompositedAncestor)
511 LayoutRect localRawCompositingBounds = compositedBounds();
512 offsetFromCompositedAncestor = computeOffsetFromCompositedAncestor(&m_owningLayer, compositedAncestor);
513 snappedOffsetFromCompositedAncestor = IntPoint(offsetFromCompositedAncestor.x().round(), offsetFromCompositedAncestor.y().round());
515 LayoutSize subpixelAccumulation = offsetFromCompositedAncestor - snappedOffsetFromCompositedAncestor;
516 m_owningLayer.setSubpixelAccumulation(subpixelAccumulation);
518 // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates.
519 localRawCompositingBounds.move(subpixelAccumulation);
520 localBounds = pixelSnappedIntRect(localRawCompositingBounds);
522 compositingBoundsRelativeToCompositedAncestor = localBounds;
523 compositingBoundsRelativeToCompositedAncestor.moveBy(snappedOffsetFromCompositedAncestor);
526 void CompositedLayerMapping::updateSquashingLayerGeometry(const LayoutPoint& offsetFromCompositedAncestor, const IntPoint& graphicsLayerParentLocation, const RenderLayer& referenceLayer,
527 Vector<GraphicsLayerPaintInfo>& layers, GraphicsLayer* squashingLayer, LayoutPoint* offsetFromTransformedAncestor, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
531 ASSERT(compositor()->layerSquashingEnabled());
533 LayoutPoint offsetFromReferenceLayerToParentGraphicsLayer(offsetFromCompositedAncestor);
534 offsetFromReferenceLayerToParentGraphicsLayer.moveBy(-graphicsLayerParentLocation);
536 // FIXME: Cache these offsets.
537 LayoutPoint referenceOffsetFromTransformedAncestor = referenceLayer.computeOffsetFromTransformedAncestor();
539 LayoutRect totalSquashBounds;
540 for (size_t i = 0; i < layers.size(); ++i) {
541 LayoutRect squashedBounds = layers[i].renderLayer->boundingBoxForCompositing();
543 // Store the local bounds of the RenderLayer subtree before applying the offset.
544 layers[i].compositedBounds = squashedBounds;
546 LayoutPoint offsetFromTransformedAncestorForSquashedLayer = layers[i].renderLayer->computeOffsetFromTransformedAncestor();
547 LayoutSize offsetFromSquashingLayer = offsetFromTransformedAncestorForSquashedLayer - referenceOffsetFromTransformedAncestor;
549 squashedBounds.move(offsetFromSquashingLayer);
550 totalSquashBounds.unite(squashedBounds);
553 // The totalSquashBounds is positioned with respect to referenceLayer of this CompositedLayerMapping.
554 // But the squashingLayer needs to be positioned with respect to the ancestor CompositedLayerMapping.
555 // The conversion between referenceLayer and the ancestor CLM is already computed as
556 // offsetFromReferenceLayerToParentGraphicsLayer.
557 totalSquashBounds.moveBy(offsetFromReferenceLayerToParentGraphicsLayer);
558 IntRect squashLayerBounds = enclosingIntRect(totalSquashBounds);
559 IntPoint squashLayerOrigin = squashLayerBounds.location();
560 LayoutSize squashLayerOriginInOwningLayerSpace = squashLayerOrigin - offsetFromReferenceLayerToParentGraphicsLayer;
562 // Now that the squashing bounds are known, we can convert the RenderLayer painting offsets
563 // from CLM owning layer space to the squashing layer space.
565 // The painting offset we want to compute for each squashed RenderLayer is essentially the position of
566 // the squashed RenderLayer described w.r.t. referenceLayer's origin. For this purpose we already cached
567 // offsetFromSquashingCLM before, which describes where the squashed RenderLayer is located w.r.t.
568 // referenceLayer. So we just need to convert that point from referenceLayer space to referenceLayer
569 // space. This is simply done by subtracing squashLayerOriginInOwningLayerSpace, but then the offset
570 // overall needs to be negated because that's the direction that the painting code expects the
572 for (size_t i = 0; i < layers.size(); ++i) {
573 LayoutPoint offsetFromTransformedAncestorForSquashedLayer = layers[i].renderLayer->computeOffsetFromTransformedAncestor();
574 LayoutSize offsetFromSquashLayerOrigin = (offsetFromTransformedAncestorForSquashedLayer - referenceOffsetFromTransformedAncestor) - squashLayerOriginInOwningLayerSpace;
576 // It is ok to repaint here, because all of the geometry needed to correctly repaint is computed by this point.
577 IntSize newOffsetFromRenderer = -IntSize(offsetFromSquashLayerOrigin.width().round(), offsetFromSquashLayerOrigin.height().round());
578 LayoutSize subpixelAccumulation = offsetFromSquashLayerOrigin + newOffsetFromRenderer;
579 if (layers[i].offsetFromRendererSet && layers[i].offsetFromRenderer != newOffsetFromRenderer) {
580 layers[i].renderLayer->repainter().repaintIncludingNonCompositingDescendants();
581 layersNeedingPaintInvalidation.append(layers[i].renderLayer);
583 layers[i].offsetFromRenderer = newOffsetFromRenderer;
584 layers[i].offsetFromRendererSet = true;
586 layers[i].renderLayer->setSubpixelAccumulation(subpixelAccumulation);
588 // FIXME: find a better design to avoid this redundant value - most likely it will make
589 // sense to move the paint task info into RenderLayer's m_compositingProperties.
590 layers[i].renderLayer->setOffsetFromSquashingLayerOrigin(layers[i].offsetFromRenderer);
593 squashingLayer->setPosition(squashLayerBounds.location());
594 squashingLayer->setSize(squashLayerBounds.size());
596 *offsetFromTransformedAncestor = referenceOffsetFromTransformedAncestor;
597 offsetFromTransformedAncestor->move(squashLayerOriginInOwningLayerSpace);
599 for (size_t i = 0; i < layers.size(); ++i)
600 layers[i].localClipRectForSquashedLayer = localClipRectForSquashedLayer(referenceLayer, layers[i], layers);
603 void CompositedLayerMapping::updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType updateType, const RenderLayer* compositingContainer, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
605 if (!shouldUpdateGraphicsLayer(updateType))
608 // Set transform property, if it is not animating. We have to do this here because the transform
609 // is affected by the layer dimensions.
610 if (!renderer()->style()->isRunningTransformAnimationOnCompositor())
611 updateTransform(renderer()->style());
613 // Set opacity, if it is not animating.
614 if (!renderer()->style()->isRunningOpacityAnimationOnCompositor())
615 updateOpacity(renderer()->style());
617 m_owningLayer.updateDescendantDependentFlags();
619 // We compute everything relative to the enclosing compositing layer.
620 IntRect ancestorCompositingBounds;
621 if (compositingContainer) {
622 ASSERT(compositingContainer->hasCompositedLayerMapping());
623 ancestorCompositingBounds = compositingContainer->compositedLayerMapping()->pixelSnappedCompositedBounds();
626 IntRect localCompositingBounds;
627 IntRect relativeCompositingBounds;
628 LayoutPoint offsetFromCompositedAncestor;
629 IntPoint snappedOffsetFromCompositedAncestor;
630 computeBoundsOfOwningLayer(compositingContainer, localCompositingBounds, relativeCompositingBounds, offsetFromCompositedAncestor, snappedOffsetFromCompositedAncestor);
632 IntPoint graphicsLayerParentLocation;
633 computeGraphicsLayerParentLocation(compositingContainer, ancestorCompositingBounds, graphicsLayerParentLocation);
635 // Might update graphicsLayerParentLocation.
636 updateAncestorClippingLayerGeometry(compositingContainer, snappedOffsetFromCompositedAncestor, graphicsLayerParentLocation);
638 FloatSize contentsSize = relativeCompositingBounds.size();
640 updateMainGraphicsLayerGeometry(relativeCompositingBounds, localCompositingBounds, graphicsLayerParentLocation);
641 updateSquashingLayerGeometry(offsetFromCompositedAncestor, graphicsLayerParentLocation, m_owningLayer, m_squashedLayers, m_squashingLayer.get(), &m_squashingLayerOffsetFromTransformedAncestor, layersNeedingPaintInvalidation);
643 // If we have a layer that clips children, position it.
645 if (m_childContainmentLayer)
646 clippingBox = clipBox(toRenderBox(renderer()));
648 updateChildContainmentLayerGeometry(clippingBox, localCompositingBounds);
649 updateChildTransformLayerGeometry();
651 updateMaskLayerGeometry();
652 updateTransformGeometry(snappedOffsetFromCompositedAncestor, relativeCompositingBounds);
653 updateForegroundLayerGeometry(contentsSize, clippingBox);
654 updateBackgroundLayerGeometry(contentsSize);
655 updateReflectionLayerGeometry(layersNeedingPaintInvalidation);
656 updateScrollingLayerGeometry(localCompositingBounds);
657 updateChildClippingMaskLayerGeometry();
659 if (m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->scrollsOverflow())
660 m_owningLayer.scrollableArea()->positionOverflowControls(IntSize());
662 if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
663 updateLayerBlendMode(renderer()->style());
664 updateIsRootForIsolatedGroup();
667 updateContentsRect();
668 updateBackgroundColor();
669 updateDrawsContent();
670 updateContentsOpaque();
671 updateAfterWidgetResize();
672 updateRenderingContext();
673 updateShouldFlattenTransform();
674 updateChildrenTransform();
675 updateScrollParent(compositor()->acceleratedCompositingForOverflowScrollEnabled() ? m_owningLayer.scrollParent() : 0);
676 registerScrollingLayers();
678 updateCompositingReasons();
681 void CompositedLayerMapping::updateMainGraphicsLayerGeometry(const IntRect& relativeCompositingBounds, const IntRect& localCompositingBounds, IntPoint& graphicsLayerParentLocation)
683 m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
684 m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
686 FloatSize oldSize = m_graphicsLayer->size();
687 const IntSize& contentsSize = relativeCompositingBounds.size();
688 if (oldSize != contentsSize)
689 m_graphicsLayer->setSize(contentsSize);
691 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
692 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
693 // non-compositing visible layers.
694 bool contentsVisible = m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendant(&m_owningLayer);
695 if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && renderer()->isVideo()) {
696 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer()->node());
697 if (mediaElement->isFullscreen())
698 contentsVisible = false;
700 m_graphicsLayer->setContentsVisible(contentsVisible);
702 m_graphicsLayer->setBackfaceVisibility(renderer()->style()->backfaceVisibility() == BackfaceVisibilityVisible);
705 void CompositedLayerMapping::computeGraphicsLayerParentLocation(const RenderLayer* compositingContainer, const IntRect& ancestorCompositingBounds, IntPoint& graphicsLayerParentLocation)
707 if (compositingContainer && compositingContainer->compositedLayerMapping()->hasClippingLayer()) {
708 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
709 // position relative to it.
710 IntRect clippingBox = clipBox(toRenderBox(compositingContainer->renderer()));
711 graphicsLayerParentLocation = clippingBox.location() + roundedIntSize(compositingContainer->subpixelAccumulation());
712 } else if (compositingContainer && compositingContainer->compositedLayerMapping()->childTransformLayer()) {
713 // Similarly, if the compositing ancestor has a child transform layer, we parent in that, and therefore
714 // position relative to it. It's already taken into account the contents offset, so we do not need to here.
715 graphicsLayerParentLocation = roundedIntPoint(compositingContainer->subpixelAccumulation());
716 } else if (compositingContainer) {
717 graphicsLayerParentLocation = ancestorCompositingBounds.location();
719 graphicsLayerParentLocation = renderer()->view()->documentRect().location();
722 if (compositingContainer && compositingContainer->needsCompositedScrolling()) {
723 RenderBox* renderBox = toRenderBox(compositingContainer->renderer());
724 IntSize scrollOffset = renderBox->scrolledContentOffset();
725 IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
726 graphicsLayerParentLocation = scrollOrigin - scrollOffset;
730 void CompositedLayerMapping::updateAncestorClippingLayerGeometry(const RenderLayer* compositingContainer, const IntPoint& snappedOffsetFromCompositedAncestor, IntPoint& graphicsLayerParentLocation)
732 if (!compositingContainer || !m_ancestorClippingLayer)
735 // FIXME: this should use cached clip rects, but this sometimes give
736 // inaccurate results (and trips the ASSERTS in RenderLayerClipper).
737 ClipRectsContext clipRectsContext(compositingContainer, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
738 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
739 ASSERT(parentClipRect != PaintInfo::infiniteRect());
740 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
741 m_ancestorClippingLayer->setSize(parentClipRect.size());
743 // backgroundRect is relative to compositingContainer, so subtract snappedOffsetFromCompositedAncestor.X/snappedOffsetFromCompositedAncestor.Y to get back to local coords.
744 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - snappedOffsetFromCompositedAncestor);
746 // The primary layer is then parented in, and positioned relative to this clipping layer.
747 graphicsLayerParentLocation = parentClipRect.location();
750 void CompositedLayerMapping::updateChildContainmentLayerGeometry(const IntRect& clippingBox, const IntRect& localCompositingBounds)
752 if (!m_childContainmentLayer)
755 m_childContainmentLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location() + roundedIntSize(m_owningLayer.subpixelAccumulation())));
756 m_childContainmentLayer->setSize(clippingBox.size());
757 m_childContainmentLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
758 if (m_childClippingMaskLayer && !m_scrollingLayer && !renderer()->style()->clipPath()) {
759 m_childClippingMaskLayer->setPosition(m_childContainmentLayer->position());
760 m_childClippingMaskLayer->setSize(m_childContainmentLayer->size());
761 m_childClippingMaskLayer->setOffsetFromRenderer(m_childContainmentLayer->offsetFromRenderer());
765 void CompositedLayerMapping::updateChildTransformLayerGeometry()
767 if (!m_childTransformLayer)
769 const IntRect borderBox = toRenderBox(m_owningLayer.renderer())->pixelSnappedBorderBoxRect();
770 m_childTransformLayer->setSize(borderBox.size());
771 m_childTransformLayer->setPosition(FloatPoint(contentOffsetInCompositingLayer()));
774 void CompositedLayerMapping::updateMaskLayerGeometry()
779 if (m_maskLayer->size() != m_graphicsLayer->size()) {
780 m_maskLayer->setSize(m_graphicsLayer->size());
781 m_maskLayer->setNeedsDisplay();
783 m_maskLayer->setPosition(FloatPoint());
784 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
787 void CompositedLayerMapping::updateTransformGeometry(const IntPoint& snappedOffsetFromCompositedAncestor, const IntRect& relativeCompositingBounds)
789 if (m_owningLayer.hasTransform()) {
790 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
792 // Get layout bounds in the coords of compositingContainer to match relativeCompositingBounds.
793 IntRect layerBounds = pixelSnappedIntRect(toLayoutPoint(m_owningLayer.subpixelAccumulation()), borderBox.size());
794 layerBounds.moveBy(snappedOffsetFromCompositedAncestor);
796 // Update properties that depend on layer dimensions
797 FloatPoint3D transformOrigin = computeTransformOrigin(IntRect(IntPoint(), layerBounds.size()));
799 // |transformOrigin| is in the local space of this layer. layerBounds - relativeCompositingBounds converts to the space of the
800 // compositing bounds relative to the composited ancestor. This does not apply to the z direction, since the page is 2D.
801 FloatPoint3D compositedTransformOrigin(
802 layerBounds.x() - relativeCompositingBounds.x() + transformOrigin.x(),
803 layerBounds.y() - relativeCompositingBounds.y() + transformOrigin.y(),
804 transformOrigin.z());
805 m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
807 FloatPoint3D compositedTransformOrigin(
808 relativeCompositingBounds.width() * 0.5f,
809 relativeCompositingBounds.height() * 0.5f,
811 m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
815 void CompositedLayerMapping::updateReflectionLayerGeometry(Vector<RenderLayer*>& layersNeedingPaintInvalidation)
817 if (!m_owningLayer.reflectionInfo() || !m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping())
820 CompositedLayerMappingPtr reflectionCompositedLayerMapping = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping();
821 reflectionCompositedLayerMapping->updateGraphicsLayerGeometry(GraphicsLayerUpdater::ForceUpdate, &m_owningLayer, layersNeedingPaintInvalidation);
824 void CompositedLayerMapping::updateScrollingLayerGeometry(const IntRect& localCompositingBounds)
826 if (!m_scrollingLayer)
829 ASSERT(m_scrollingContentsLayer);
830 RenderBox* renderBox = toRenderBox(renderer());
831 IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
833 IntSize adjustedScrollOffset = m_owningLayer.scrollableArea()->adjustedScrollOffset();
834 m_scrollingLayer->setPosition(FloatPoint(clientBox.location() - localCompositingBounds.location() + roundedIntSize(m_owningLayer.subpixelAccumulation())));
835 m_scrollingLayer->setSize(clientBox.size());
837 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
838 m_scrollingLayer->setOffsetFromRenderer(-toIntSize(clientBox.location()));
840 if (m_childClippingMaskLayer && !renderer()->style()->clipPath()) {
841 m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
842 m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
843 m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
846 bool clientBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
848 IntSize scrollSize(renderBox->scrollWidth(), renderBox->scrollHeight());
849 if (scrollSize != m_scrollingContentsLayer->size() || clientBoxOffsetChanged)
850 m_scrollingContentsLayer->setNeedsDisplay();
852 IntSize scrollingContentsOffset = toIntSize(clientBox.location() - adjustedScrollOffset);
853 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) {
854 bool coordinatorHandlesOffset = compositor()->scrollingLayerDidChange(&m_owningLayer);
855 m_scrollingContentsLayer->setPosition(coordinatorHandlesOffset ? FloatPoint() : FloatPoint(-adjustedScrollOffset));
858 m_scrollingContentsLayer->setSize(scrollSize);
859 // FIXME: The paint offset and the scroll offset should really be separate concepts.
860 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
862 if (m_foregroundLayer) {
863 if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
864 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
865 m_foregroundLayer->setNeedsDisplay();
866 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
869 updateScrollingBlockSelection();
872 void CompositedLayerMapping::updateChildClippingMaskLayerGeometry()
874 if (!m_childClippingMaskLayer || !renderer()->style()->clipPath())
876 RenderBox* renderBox = toRenderBox(renderer());
877 IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
879 m_childClippingMaskLayer->setPosition(m_graphicsLayer->position());
880 m_childClippingMaskLayer->setSize(m_graphicsLayer->size());
881 m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
883 // NOTE: also some stuff happening in updateChildContainmentLayerGeometry().
886 void CompositedLayerMapping::updateForegroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize, const IntRect& clippingBox)
888 if (!m_foregroundLayer)
891 FloatSize foregroundSize = relativeCompositingBoundsSize;
892 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
893 m_foregroundLayer->setPosition(FloatPoint());
895 if (hasClippingLayer()) {
896 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
897 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
898 foregroundSize = FloatSize(clippingBox.size());
899 foregroundOffset = toIntSize(clippingBox.location());
900 } else if (m_childTransformLayer) {
901 // Things are different if we have a child transform layer rather
902 // than a clipping layer. In this case, we want to actually change
903 // the position of the layer (to compensate for our ancestor
904 // compositing layer's position) rather than leave the position the
905 // same and use offset-from-renderer + size to describe a clipped
906 // "window" onto the clipped layer.
908 m_foregroundLayer->setPosition(-m_childTransformLayer->position());
911 if (foregroundSize != m_foregroundLayer->size()) {
912 m_foregroundLayer->setSize(foregroundSize);
913 m_foregroundLayer->setNeedsDisplay();
915 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
917 // NOTE: there is some more configuring going on in updateScrollingLayerGeometry().
920 void CompositedLayerMapping::updateBackgroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize)
922 if (!m_backgroundLayer)
925 FloatSize backgroundSize = relativeCompositingBoundsSize;
926 if (backgroundLayerPaintsFixedRootBackground()) {
927 FrameView* frameView = toRenderView(renderer())->frameView();
928 backgroundSize = frameView->visibleContentRect().size();
930 m_backgroundLayer->setPosition(FloatPoint());
931 if (backgroundSize != m_backgroundLayer->size()) {
932 m_backgroundLayer->setSize(backgroundSize);
933 m_backgroundLayer->setNeedsDisplay();
935 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
938 void CompositedLayerMapping::registerScrollingLayers()
940 // Register fixed position layers and their containers with the scrolling coordinator.
941 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
942 if (!scrollingCoordinator)
945 scrollingCoordinator->updateLayerPositionConstraint(&m_owningLayer);
947 // Page scale is applied as a transform on the root render view layer. Because the scroll
948 // layer is further up in the hierarchy, we need to avoid marking the root render view
949 // layer as a container.
950 bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer();
951 // FIXME: we should make certain that childForSuperLayers will never be the m_squashingContainmentLayer here
952 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(localRootForOwningLayer(), isContainer);
955 void CompositedLayerMapping::updateInternalHierarchy()
957 // m_foregroundLayer has to be inserted in the correct order with child layers,
958 // so it's not inserted here.
959 if (m_ancestorClippingLayer)
960 m_ancestorClippingLayer->removeAllChildren();
962 m_graphicsLayer->removeFromParent();
964 if (m_ancestorClippingLayer)
965 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
967 if (m_childContainmentLayer)
968 m_graphicsLayer->addChild(m_childContainmentLayer.get());
969 else if (m_childTransformLayer)
970 m_graphicsLayer->addChild(m_childTransformLayer.get());
972 if (m_scrollingLayer) {
973 GraphicsLayer* superLayer = m_graphicsLayer.get();
975 if (m_childContainmentLayer)
976 superLayer = m_childContainmentLayer.get();
978 if (m_childTransformLayer)
979 superLayer = m_childTransformLayer.get();
981 superLayer->addChild(m_scrollingLayer.get());
984 // The clip for child layers does not include space for overflow controls, so they exist as
985 // siblings of the clipping layer if we have one. Normal children of this layer are set as
986 // children of the clipping layer.
987 if (m_layerForHorizontalScrollbar)
988 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
989 if (m_layerForVerticalScrollbar)
990 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
991 if (m_layerForScrollCorner)
992 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
994 // The squashing containment layer, if it exists, becomes a no-op parent.
995 if (m_squashingLayer) {
996 ASSERT(compositor()->layerSquashingEnabled());
997 ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) || (!m_ancestorClippingLayer && m_squashingContainmentLayer));
999 if (m_squashingContainmentLayer) {
1000 m_squashingContainmentLayer->removeAllChildren();
1001 m_squashingContainmentLayer->addChild(m_graphicsLayer.get());
1002 m_squashingContainmentLayer->addChild(m_squashingLayer.get());
1004 // The ancestor clipping layer is already set up and has m_graphicsLayer under it.
1005 m_ancestorClippingLayer->addChild(m_squashingLayer.get());
1010 void CompositedLayerMapping::updatePaintingPhases()
1012 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1013 if (m_scrollingContentsLayer) {
1014 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1015 if (!m_foregroundLayer)
1016 paintPhase |= GraphicsLayerPaintForeground;
1017 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1018 m_scrollingBlockSelectionLayer->setPaintingPhase(paintPhase);
1022 void CompositedLayerMapping::updateContentsRect()
1024 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
1027 void CompositedLayerMapping::updateScrollingBlockSelection()
1029 if (!m_scrollingBlockSelectionLayer)
1032 if (!m_scrollingContentsAreEmpty) {
1033 // In this case, the selection will be painted directly into m_scrollingContentsLayer.
1034 m_scrollingBlockSelectionLayer->setDrawsContent(false);
1038 const IntRect blockSelectionGapsBounds = m_owningLayer.blockSelectionGapsBounds();
1039 const bool shouldDrawContent = !blockSelectionGapsBounds.isEmpty();
1040 m_scrollingBlockSelectionLayer->setDrawsContent(shouldDrawContent);
1041 if (!shouldDrawContent)
1044 const IntPoint position = blockSelectionGapsBounds.location() + m_owningLayer.scrollableArea()->adjustedScrollOffset();
1045 if (m_scrollingBlockSelectionLayer->size() == blockSelectionGapsBounds.size() && m_scrollingBlockSelectionLayer->position() == position)
1048 m_scrollingBlockSelectionLayer->setPosition(position);
1049 m_scrollingBlockSelectionLayer->setSize(blockSelectionGapsBounds.size());
1050 m_scrollingBlockSelectionLayer->setOffsetFromRenderer(toIntSize(blockSelectionGapsBounds.location()), GraphicsLayer::SetNeedsDisplay);
1053 void CompositedLayerMapping::updateDrawsContent()
1055 if (m_scrollingLayer) {
1056 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1057 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1058 // m_scrollingLayer never has backing store.
1059 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1060 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground();
1061 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1063 m_scrollingContentsAreEmpty = !m_owningLayer.hasVisibleContent() || !(renderer()->hasBackground() || paintsChildren());
1064 m_scrollingContentsLayer->setDrawsContent(!m_scrollingContentsAreEmpty);
1066 updateScrollingBlockSelection();
1070 bool hasPaintedContent = containsPaintedContent();
1071 if (hasPaintedContent && isAcceleratedCanvas(renderer())) {
1072 CanvasRenderingContext* context = toHTMLCanvasElement(renderer()->node())->renderingContext();
1073 // Content layer may be null if context is lost.
1074 if (blink::WebLayer* contentLayer = context->platformLayer()) {
1075 Color bgColor(Color::transparent);
1076 if (contentLayerSupportsDirectBackgroundComposition(renderer())) {
1077 bgColor = rendererBackgroundColor();
1078 hasPaintedContent = false;
1080 contentLayer->setBackgroundColor(bgColor.rgb());
1084 // FIXME: we could refine this to only allocate backings for one of these layers if possible.
1085 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1086 if (m_foregroundLayer)
1087 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1089 if (m_backgroundLayer)
1090 m_backgroundLayer->setDrawsContent(hasPaintedContent);
1093 void CompositedLayerMapping::updateChildrenTransform()
1095 if (GraphicsLayer* childTransformLayer = layerForChildrenTransform()) {
1096 childTransformLayer->setTransform(owningLayer().perspectiveTransform());
1097 childTransformLayer->setTransformOrigin(FloatPoint3D(childTransformLayer->size().width() * 0.5f, childTransformLayer->size().height() * 0.5f, 0.f));
1098 bool hasPerspective = false;
1099 if (RenderStyle* style = m_owningLayer.renderer()->style())
1100 hasPerspective = style->hasPerspective();
1102 childTransformLayer->setShouldFlattenTransform(false);
1104 // Note, if the target is the scrolling layer, we need to ensure that the
1105 // scrolling content layer doesn't flatten the transform. (It would be nice
1106 // if we could apply transform to the scrolling content layer, but that's
1107 // too late, we need the children transform to be applied _before_ the
1108 // scrolling offset.)
1109 if (childTransformLayer == m_scrollingLayer.get())
1110 m_scrollingContentsLayer->setShouldFlattenTransform(false);
1114 // Return true if the layers changed.
1115 bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
1117 bool layersChanged = false;
1119 if (needsAncestorClip) {
1120 if (!m_ancestorClippingLayer) {
1121 m_ancestorClippingLayer = createGraphicsLayer(CompositingReasonLayerForAncestorClip);
1122 m_ancestorClippingLayer->setMasksToBounds(true);
1123 layersChanged = true;
1125 } else if (m_ancestorClippingLayer) {
1126 m_ancestorClippingLayer->removeFromParent();
1127 m_ancestorClippingLayer = nullptr;
1128 layersChanged = true;
1131 if (needsDescendantClip) {
1132 // We don't need a child containment layer if we're the main frame render view
1133 // layer. It's redundant as the frame clip above us will handle this clipping.
1134 if (!m_childContainmentLayer && !m_isMainFrameRenderViewLayer) {
1135 m_childContainmentLayer = createGraphicsLayer(CompositingReasonLayerForDescendantClip);
1136 m_childContainmentLayer->setMasksToBounds(true);
1137 layersChanged = true;
1139 } else if (hasClippingLayer()) {
1140 m_childContainmentLayer->removeFromParent();
1141 m_childContainmentLayer = nullptr;
1142 layersChanged = true;
1145 return layersChanged;
1148 bool CompositedLayerMapping::updateChildTransformLayer(bool needsChildTransformLayer)
1150 bool layersChanged = false;
1152 if (needsChildTransformLayer) {
1153 if (!m_childTransformLayer) {
1154 m_childTransformLayer = createGraphicsLayer(CompositingReasonLayerForPerspective);
1155 m_childTransformLayer->setDrawsContent(false);
1156 m_childTransformLayer->setShouldFlattenTransform(false);
1157 layersChanged = true;
1159 } else if (m_childTransformLayer) {
1160 m_childTransformLayer->removeFromParent();
1161 m_childTransformLayer = nullptr;
1162 layersChanged = true;
1165 return layersChanged;
1168 void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1170 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1173 // Only a member function so it can call createGraphicsLayer.
1174 bool CompositedLayerMapping::toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer>& layer, bool needsLayer, CompositingReasons reason)
1176 if (needsLayer == !!layer)
1178 layer = needsLayer ? createGraphicsLayer(reason) : nullptr;
1182 bool CompositedLayerMapping::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1184 bool horizontalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForHorizontalScrollbar, needsHorizontalScrollbarLayer, CompositingReasonLayerForHorizontalScrollbar);
1185 bool verticalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForVerticalScrollbar, needsVerticalScrollbarLayer, CompositingReasonLayerForVerticalScrollbar);
1186 bool scrollCornerLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForScrollCorner, needsScrollCornerLayer, CompositingReasonLayerForScrollCorner);
1188 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1189 if (horizontalScrollbarLayerChanged)
1190 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), HorizontalScrollbar);
1191 if (verticalScrollbarLayerChanged)
1192 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), VerticalScrollbar);
1195 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1198 void CompositedLayerMapping::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
1200 IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer() - roundedIntSize(m_owningLayer.subpixelAccumulation());
1201 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1202 Scrollbar* hBar = m_owningLayer.scrollableArea()->horizontalScrollbar();
1204 layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1205 layer->setSize(hBar->frameRect().size());
1206 if (layer->hasContentsLayer())
1207 layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
1209 layer->setDrawsContent(hBar && !layer->hasContentsLayer());
1212 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1213 Scrollbar* vBar = m_owningLayer.scrollableArea()->verticalScrollbar();
1215 layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1216 layer->setSize(vBar->frameRect().size());
1217 if (layer->hasContentsLayer())
1218 layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
1220 layer->setDrawsContent(vBar && !layer->hasContentsLayer());
1223 if (GraphicsLayer* layer = layerForScrollCorner()) {
1224 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
1225 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1226 layer->setSize(scrollCornerAndResizer.size());
1227 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1231 bool CompositedLayerMapping::hasUnpositionedOverflowControlsLayers() const
1233 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1234 if (!layer->drawsContent())
1238 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1239 if (!layer->drawsContent())
1243 if (GraphicsLayer* layer = layerForScrollCorner()) {
1244 if (!layer->drawsContent())
1251 enum ApplyToGraphicsLayersModeFlags {
1252 ApplyToCoreLayers = (1 << 0),
1253 ApplyToSquashingLayer = (1 << 1),
1254 ApplyToScrollbarLayers = (1 << 2),
1255 ApplyToBackgroundLayer = (1 << 3),
1256 ApplyToMaskLayers = (1 << 4),
1257 ApplyToContentLayers = (1 << 5),
1258 ApplyToAllGraphicsLayers = (ApplyToSquashingLayer | ApplyToScrollbarLayers | ApplyToBackgroundLayer | ApplyToMaskLayers | ApplyToCoreLayers | ApplyToContentLayers)
1260 typedef unsigned ApplyToGraphicsLayersMode;
1262 template <typename Func>
1263 static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping, const Func& f, ApplyToGraphicsLayersMode mode)
1267 if ((mode & ApplyToCoreLayers) && mapping->squashingContainmentLayer())
1268 f(mapping->squashingContainmentLayer());
1269 if ((mode & ApplyToCoreLayers) && mapping->childTransformLayer())
1270 f(mapping->childTransformLayer());
1271 if ((mode & ApplyToCoreLayers) && mapping->ancestorClippingLayer())
1272 f(mapping->ancestorClippingLayer());
1273 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->mainGraphicsLayer())
1274 f(mapping->mainGraphicsLayer());
1275 if ((mode & ApplyToCoreLayers) && mapping->clippingLayer())
1276 f(mapping->clippingLayer());
1277 if ((mode & ApplyToCoreLayers) && mapping->scrollingLayer())
1278 f(mapping->scrollingLayer());
1279 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->scrollingContentsLayer())
1280 f(mapping->scrollingContentsLayer());
1281 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->foregroundLayer())
1282 f(mapping->foregroundLayer());
1284 if ((mode & ApplyToSquashingLayer) && mapping->squashingLayer())
1285 f(mapping->squashingLayer());
1287 if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->maskLayer())
1288 f(mapping->maskLayer());
1289 if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->childClippingMaskLayer())
1290 f(mapping->childClippingMaskLayer());
1292 if (((mode & ApplyToBackgroundLayer) || (mode & ApplyToContentLayers)) && mapping->backgroundLayer())
1293 f(mapping->backgroundLayer());
1295 if ((mode & ApplyToScrollbarLayers) && mapping->layerForHorizontalScrollbar())
1296 f(mapping->layerForHorizontalScrollbar());
1297 if ((mode & ApplyToScrollbarLayers) && mapping->layerForVerticalScrollbar())
1298 f(mapping->layerForVerticalScrollbar());
1299 if ((mode & ApplyToScrollbarLayers) && mapping->layerForScrollCorner())
1300 f(mapping->layerForScrollCorner());
1303 struct UpdateRenderingContextFunctor {
1304 void operator() (GraphicsLayer* layer) const { layer->setRenderingContext(renderingContext); }
1305 int renderingContext;
1308 void CompositedLayerMapping::updateRenderingContext()
1310 // All layers but the squashing layer (which contains 'alien' content) should be included in this
1311 // rendering context.
1314 // NB, it is illegal at this point to query an ancestor's compositing state. Some compositing
1315 // reasons depend on the compositing state of ancestors. So if we want a rendering context id
1316 // for the context root, we cannot ask for the id of its associated WebLayer now; it may not have
1317 // one yet. We could do a second past after doing the compositing updates to get these ids,
1318 // but this would actually be harmful. We do not want to attach any semantic meaning to
1319 // the context id other than the fact that they group a number of layers together for the
1320 // sake of 3d sorting. So instead we will ask the compositor to vend us an arbitrary, but
1322 if (RenderLayer* root = m_owningLayer.renderingContextRoot()) {
1323 if (Node* node = root->renderer()->node())
1324 id = static_cast<int>(WTF::PtrHash<Node*>::hash(node));
1327 UpdateRenderingContextFunctor functor = { id };
1328 ApplyToGraphicsLayersMode mode = ApplyToAllGraphicsLayers & ~ApplyToSquashingLayer;
1329 ApplyToGraphicsLayers<UpdateRenderingContextFunctor>(this, functor, mode);
1332 struct UpdateShouldFlattenTransformFunctor {
1333 void operator() (GraphicsLayer* layer) const { layer->setShouldFlattenTransform(shouldFlatten); }
1337 void CompositedLayerMapping::updateShouldFlattenTransform()
1339 // All CLM-managed layers that could affect a descendant layer should update their
1340 // should-flatten-transform value (the other layers' transforms don't matter here).
1341 UpdateShouldFlattenTransformFunctor functor = { !m_owningLayer.shouldPreserve3D() };
1342 ApplyToGraphicsLayersMode mode = ApplyToCoreLayers;
1343 ApplyToGraphicsLayers(this, functor, mode);
1346 bool CompositedLayerMapping::updateForegroundLayer(bool needsForegroundLayer)
1348 bool layerChanged = false;
1349 if (needsForegroundLayer) {
1350 if (!m_foregroundLayer) {
1351 m_foregroundLayer = createGraphicsLayer(CompositingReasonLayerForForeground);
1352 m_foregroundLayer->setDrawsContent(true);
1353 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1354 layerChanged = true;
1356 } else if (m_foregroundLayer) {
1357 FloatRect repaintRect(FloatPoint(), m_foregroundLayer->size());
1358 m_foregroundLayer->removeFromParent();
1359 m_foregroundLayer = nullptr;
1360 layerChanged = true;
1363 return layerChanged;
1366 bool CompositedLayerMapping::updateBackgroundLayer(bool needsBackgroundLayer)
1368 bool layerChanged = false;
1369 if (needsBackgroundLayer) {
1370 if (!m_backgroundLayer) {
1371 m_backgroundLayer = createGraphicsLayer(CompositingReasonLayerForBackground);
1372 m_backgroundLayer->setDrawsContent(true);
1373 m_backgroundLayer->setTransformOrigin(FloatPoint3D());
1374 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1376 m_backgroundLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
1377 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(false);
1379 layerChanged = true;
1382 if (m_backgroundLayer) {
1383 m_backgroundLayer->removeFromParent();
1384 m_backgroundLayer = nullptr;
1386 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
1388 layerChanged = true;
1392 if (layerChanged && !m_owningLayer.renderer()->documentBeingDestroyed())
1393 compositor()->rootFixedBackgroundsChanged();
1395 return layerChanged;
1398 bool CompositedLayerMapping::updateMaskLayer(bool needsMaskLayer)
1400 bool layerChanged = false;
1401 if (needsMaskLayer) {
1403 m_maskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
1404 m_maskLayer->setDrawsContent(true);
1405 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
1406 layerChanged = true;
1408 } else if (m_maskLayer) {
1409 m_maskLayer = nullptr;
1410 layerChanged = true;
1413 return layerChanged;
1416 bool CompositedLayerMapping::updateClippingMaskLayers(bool needsChildClippingMaskLayer)
1418 bool layerChanged = false;
1419 if (needsChildClippingMaskLayer) {
1420 if (!m_childClippingMaskLayer) {
1421 m_childClippingMaskLayer = createGraphicsLayer(CompositingReasonLayerForClippingMask);
1422 m_childClippingMaskLayer->setDrawsContent(true);
1423 m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
1424 layerChanged = true;
1426 } else if (m_childClippingMaskLayer) {
1427 m_childClippingMaskLayer = nullptr;
1428 layerChanged = true;
1430 return layerChanged;
1433 bool CompositedLayerMapping::updateScrollingLayers(bool needsScrollingLayers)
1435 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1437 bool layerChanged = false;
1438 if (needsScrollingLayers) {
1439 if (!m_scrollingLayer) {
1440 // Outer layer which corresponds with the scroll view.
1441 m_scrollingLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContainer);
1442 m_scrollingLayer->setDrawsContent(false);
1443 m_scrollingLayer->setMasksToBounds(true);
1445 // Inner layer which renders the content that scrolls.
1446 m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContents);
1447 m_scrollingContentsLayer->setDrawsContent(true);
1448 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
1450 m_scrollingBlockSelectionLayer = createGraphicsLayer(CompositingReasonLayerForScrollingBlockSelection);
1451 m_scrollingBlockSelectionLayer->setDrawsContent(true);
1452 m_scrollingContentsLayer->addChild(m_scrollingBlockSelectionLayer.get());
1454 layerChanged = true;
1455 if (scrollingCoordinator)
1456 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
1458 } else if (m_scrollingLayer) {
1459 m_scrollingLayer = nullptr;
1460 m_scrollingContentsLayer = nullptr;
1461 m_scrollingBlockSelectionLayer = nullptr;
1462 layerChanged = true;
1463 if (scrollingCoordinator)
1464 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
1467 return layerChanged;
1470 static void updateScrollParentForGraphicsLayer(GraphicsLayer* layer, GraphicsLayer* topmostLayer, RenderLayer* scrollParent, ScrollingCoordinator* scrollingCoordinator)
1475 // Only the topmost layer has a scroll parent. All other layers have a null scroll parent.
1476 if (layer != topmostLayer)
1479 scrollingCoordinator->updateScrollParentForGraphicsLayer(layer, scrollParent);
1482 void CompositedLayerMapping::updateScrollParent(RenderLayer* scrollParent)
1484 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1485 GraphicsLayer* topmostLayer = childForSuperlayers();
1486 updateScrollParentForGraphicsLayer(m_squashingContainmentLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1487 updateScrollParentForGraphicsLayer(m_ancestorClippingLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1488 updateScrollParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1492 void CompositedLayerMapping::updateClipParent(RenderLayer* clipParent)
1494 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer))
1495 scrollingCoordinator->updateClipParentForGraphicsLayer(m_graphicsLayer.get(), clipParent);
1498 bool CompositedLayerMapping::updateSquashingLayers(bool needsSquashingLayers)
1500 bool layersChanged = false;
1502 if (needsSquashingLayers) {
1503 ASSERT(compositor()->layerSquashingEnabled());
1505 if (!m_squashingLayer) {
1506 m_squashingLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContents);
1507 m_squashingLayer->setDrawsContent(true);
1508 layersChanged = true;
1511 if (m_ancestorClippingLayer) {
1512 if (m_squashingContainmentLayer) {
1513 m_squashingContainmentLayer->removeFromParent();
1514 m_squashingContainmentLayer = nullptr;
1515 layersChanged = true;
1518 if (!m_squashingContainmentLayer) {
1519 m_squashingContainmentLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContainer);
1520 layersChanged = true;
1524 ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) || (!m_ancestorClippingLayer && m_squashingContainmentLayer));
1525 ASSERT(m_squashingLayer);
1527 if (m_squashingLayer) {
1528 m_squashingLayer->removeFromParent();
1529 m_squashingLayer = nullptr;
1530 layersChanged = true;
1532 if (m_squashingContainmentLayer) {
1533 m_squashingContainmentLayer->removeFromParent();
1534 m_squashingContainmentLayer = nullptr;
1535 layersChanged = true;
1537 ASSERT(!m_squashingLayer && !m_squashingContainmentLayer);
1540 return layersChanged;
1543 GraphicsLayerPaintingPhase CompositedLayerMapping::paintingPhaseForPrimaryLayer() const
1546 if (!m_backgroundLayer)
1547 phase |= GraphicsLayerPaintBackground;
1548 if (!m_foregroundLayer)
1549 phase |= GraphicsLayerPaintForeground;
1551 phase |= GraphicsLayerPaintMask;
1553 if (m_scrollingContentsLayer) {
1554 phase &= ~GraphicsLayerPaintForeground;
1555 phase |= GraphicsLayerPaintCompositedScroll;
1558 return static_cast<GraphicsLayerPaintingPhase>(phase);
1561 float CompositedLayerMapping::compositingOpacity(float rendererOpacity) const
1563 float finalOpacity = rendererOpacity;
1565 for (RenderLayer* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1566 // We only care about parents that are stacking contexts.
1567 // Recall that opacity creates stacking context.
1568 if (!curr->stackingNode()->isStackingContext())
1571 // If we found a composited layer, regardless of whether it actually
1572 // paints into it, we want to compute opacity relative to it. So we can
1575 // FIXME: with grouped backings, a composited descendant will have to
1576 // continue past the grouped (squashed) layers that its parents may
1577 // contribute to. This whole confusion can be avoided by specifying
1578 // explicitly the composited ancestor where we would stop accumulating
1580 if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == HasOwnBackingButPaintsIntoAncestor)
1583 finalOpacity *= curr->renderer()->opacity();
1586 return finalOpacity;
1589 Color CompositedLayerMapping::rendererBackgroundColor() const
1591 RenderObject* backgroundRenderer = renderer();
1592 if (backgroundRenderer->isDocumentElement())
1593 backgroundRenderer = backgroundRenderer->rendererForRootBackground();
1595 return backgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
1598 void CompositedLayerMapping::updateBackgroundColor()
1600 m_graphicsLayer->setBackgroundColor(rendererBackgroundColor());
1603 bool CompositedLayerMapping::paintsChildren() const
1605 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers())
1608 if (hasVisibleNonCompositingDescendant(&m_owningLayer))
1614 static bool isCompositedPlugin(RenderObject* renderer)
1616 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing();
1619 bool CompositedLayerMapping::hasVisibleNonCompositingDescendant(RenderLayer* parent)
1621 if (!parent->hasVisibleDescendant())
1624 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1625 parent->stackingNode()->updateLayerListsIfNeeded();
1628 LayerListMutationDetector mutationChecker(parent->stackingNode());
1631 RenderLayerStackingNodeIterator normalFlowIterator(*parent->stackingNode(), AllChildren);
1632 while (RenderLayerStackingNode* curNode = normalFlowIterator.next()) {
1633 RenderLayer* curLayer = curNode->layer();
1634 if (curLayer->hasCompositedLayerMapping())
1636 if (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))
1643 bool CompositedLayerMapping::containsPaintedContent() const
1645 if (paintsIntoCompositedAncestor() || m_owningLayer.isReflection())
1648 if (isDirectlyCompositedImage())
1651 RenderObject* renderObject = renderer();
1652 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1653 // and set background color on the layer in that case, instead of allocating backing store and painting.
1654 if (renderObject->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
1655 return m_owningLayer.hasBoxDecorationsOrBackground();
1657 if (m_owningLayer.hasVisibleBoxDecorations())
1660 if (renderObject->hasMask()) // masks require special treatment
1663 if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
1666 if (renderObject->isRenderRegion())
1669 if (renderObject->node() && renderObject->node()->isDocumentNode()) {
1670 // Look to see if the root object has a non-simple background
1671 RenderObject* rootObject = renderObject->document().documentElement() ? renderObject->document().documentElement()->renderer() : 0;
1672 // Reject anything that has a border, a border-radius or outline,
1673 // or is not a simple background (no background, or solid color).
1674 if (rootObject && hasBoxDecorationsOrBackgroundImage(rootObject->style()))
1677 // Now look at the body's renderer.
1678 HTMLElement* body = renderObject->document().body();
1679 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
1680 if (bodyObject && hasBoxDecorationsOrBackgroundImage(bodyObject->style()))
1684 // FIXME: it's O(n^2). A better solution is needed.
1685 return paintsChildren();
1688 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1689 // that require painting. Direct compositing saves backing store.
1690 bool CompositedLayerMapping::isDirectlyCompositedImage() const
1692 RenderObject* renderObject = renderer();
1694 if (!renderObject->isImage() || m_owningLayer.hasBoxDecorationsOrBackground() || renderObject->hasClip())
1697 RenderImage* imageRenderer = toRenderImage(renderObject);
1698 if (ImageResource* cachedImage = imageRenderer->cachedImage()) {
1699 if (!cachedImage->hasImage())
1702 Image* image = cachedImage->imageForRenderer(imageRenderer);
1703 return image->isBitmapImage();
1709 void CompositedLayerMapping::contentChanged(ContentChangeType changeType)
1711 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1712 updateImageContents();
1716 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
1717 m_graphicsLayer->setContentsNeedsDisplay();
1722 void CompositedLayerMapping::updateImageContents()
1724 ASSERT(renderer()->isImage());
1725 RenderImage* imageRenderer = toRenderImage(renderer());
1727 ImageResource* cachedImage = imageRenderer->cachedImage();
1731 Image* image = cachedImage->imageForRenderer(imageRenderer);
1735 // We have to wait until the image is fully loaded before setting it on the layer.
1736 if (!cachedImage->isLoaded())
1739 // This is a no-op if the layer doesn't have an inner layer for the image.
1740 m_graphicsLayer->setContentsToImage(image);
1741 updateDrawsContent();
1743 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1744 // the image. So we have to kick the animation each time; this has the downside that the
1745 // image will keep animating, even if its layer is not visible.
1746 image->startAnimation();
1749 FloatPoint3D CompositedLayerMapping::computeTransformOrigin(const IntRect& borderBox) const
1751 RenderStyle* style = renderer()->style();
1753 FloatPoint3D origin;
1754 origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
1755 origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
1756 origin.setZ(style->transformOriginZ());
1761 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
1762 LayoutSize CompositedLayerMapping::contentOffsetInCompositingLayer() const
1764 return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1767 LayoutRect CompositedLayerMapping::contentsBox() const
1769 LayoutRect contentsBox = contentsRect(renderer());
1770 contentsBox.move(contentOffsetInCompositingLayer());
1774 GraphicsLayer* CompositedLayerMapping::parentForSublayers() const
1776 if (m_scrollingBlockSelectionLayer)
1777 return m_scrollingBlockSelectionLayer.get();
1779 if (m_scrollingContentsLayer)
1780 return m_scrollingContentsLayer.get();
1782 if (m_childContainmentLayer)
1783 return m_childContainmentLayer.get();
1785 if (m_childTransformLayer)
1786 return m_childTransformLayer.get();
1788 return m_graphicsLayer.get();
1791 GraphicsLayer* CompositedLayerMapping::localRootForOwningLayer() const
1793 if (m_ancestorClippingLayer)
1794 return m_ancestorClippingLayer.get();
1796 return m_graphicsLayer.get();
1799 GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const
1801 if (m_squashingContainmentLayer)
1802 return m_squashingContainmentLayer.get();
1804 return localRootForOwningLayer();
1807 GraphicsLayer* CompositedLayerMapping::layerForChildrenTransform() const
1809 if (GraphicsLayer* clipLayer = clippingLayer())
1811 if (m_scrollingLayer)
1812 return m_scrollingLayer.get();
1813 return m_childTransformLayer.get();
1816 bool CompositedLayerMapping::updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer* compositingAncestorLayer)
1818 unsigned previousRequiresOwnBackingStoreForAncestorReasons = m_requiresOwnBackingStoreForAncestorReasons;
1819 bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
1820 bool canPaintIntoAncestor = compositingAncestorLayer
1821 && (compositingAncestorLayer->compositedLayerMapping()->mainGraphicsLayer()->drawsContent()
1822 || compositingAncestorLayer->compositedLayerMapping()->paintsIntoCompositedAncestor());
1823 m_requiresOwnBackingStoreForAncestorReasons = !canPaintIntoAncestor;
1825 if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
1826 paintsIntoCompositedAncestorChanged();
1827 return m_requiresOwnBackingStoreForAncestorReasons != previousRequiresOwnBackingStoreForAncestorReasons;
1830 bool CompositedLayerMapping::updateRequiresOwnBackingStoreForIntrinsicReasons()
1832 unsigned previousRequiresOwnBackingStoreForIntrinsicReasons = m_requiresOwnBackingStoreForIntrinsicReasons;
1833 bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
1834 RenderObject* renderer = m_owningLayer.renderer();
1835 m_requiresOwnBackingStoreForIntrinsicReasons = m_owningLayer.isRootLayer()
1836 || (m_owningLayer.compositingReasons() & CompositingReasonComboReasonsThatRequireOwnBacking)
1837 || m_owningLayer.transform()
1838 || m_owningLayer.clipsCompositingDescendantsWithBorderRadius() // FIXME: Revisit this if the paintsIntoCompositedAncestor state is removed.
1839 || renderer->isTransparent()
1840 || renderer->hasMask()
1841 || renderer->hasReflection()
1842 || renderer->hasFilter();
1844 if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
1845 paintsIntoCompositedAncestorChanged();
1846 return m_requiresOwnBackingStoreForIntrinsicReasons != previousRequiresOwnBackingStoreForIntrinsicReasons;
1849 void CompositedLayerMapping::paintsIntoCompositedAncestorChanged()
1851 // The answer to paintsIntoCompositedAncestor() affects cached clip rects, so when
1852 // it changes we have to clear clip rects on descendants.
1853 m_owningLayer.clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
1854 m_owningLayer.repainter().computeRepaintRectsIncludingNonCompositingDescendants();
1856 compositor()->repaintInCompositedAncestor(&m_owningLayer, compositedBounds());
1859 void CompositedLayerMapping::setBlendMode(blink::WebBlendMode blendMode)
1861 if (m_ancestorClippingLayer) {
1862 m_ancestorClippingLayer->setBlendMode(blendMode);
1863 m_graphicsLayer->setBlendMode(blink::WebBlendModeNormal);
1865 m_graphicsLayer->setBlendMode(blendMode);
1869 GraphicsLayerUpdater::UpdateType CompositedLayerMapping::updateTypeForChildren(GraphicsLayerUpdater::UpdateType updateType) const
1871 if (m_pendingUpdateScope >= GraphicsLayerUpdateSubtree)
1872 return GraphicsLayerUpdater::ForceUpdate;
1876 struct SetContentsNeedsDisplayFunctor {
1877 void operator() (GraphicsLayer* layer) const
1879 if (layer->drawsContent())
1880 layer->setNeedsDisplay();
1884 void CompositedLayerMapping::setSquashingContentsNeedDisplay()
1886 ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToSquashingLayer);
1889 void CompositedLayerMapping::setContentsNeedDisplay()
1891 // FIXME: need to split out repaints for the background.
1892 ASSERT(!paintsIntoCompositedAncestor());
1893 ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToContentLayers);
1896 struct SetContentsNeedsDisplayInRectFunctor {
1897 void operator() (GraphicsLayer* layer) const
1899 if (layer->drawsContent()) {
1900 IntRect layerDirtyRect = r;
1901 layerDirtyRect.move(-layer->offsetFromRenderer());
1902 layer->setNeedsDisplayInRect(layerDirtyRect);
1909 // r is in the coordinate space of the layer's render object
1910 void CompositedLayerMapping::setContentsNeedDisplayInRect(const IntRect& r)
1912 // FIXME: need to split out repaints for the background.
1913 ASSERT(!paintsIntoCompositedAncestor());
1914 SetContentsNeedsDisplayInRectFunctor functor = { r };
1915 ApplyToGraphicsLayers(this, functor, ApplyToContentLayers);
1918 const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject, const Vector<GraphicsLayerPaintInfo>& layers)
1920 for (size_t i = 0; i < layers.size(); ++i) {
1921 if (renderObject->isDescendantOf(layers[i].renderLayer->renderer())) {
1929 const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject)
1931 return CompositedLayerMapping::containingSquashedLayer(renderObject, m_squashedLayers);
1934 IntRect CompositedLayerMapping::localClipRectForSquashedLayer(const RenderLayer& referenceLayer, const GraphicsLayerPaintInfo& paintInfo, const Vector<GraphicsLayerPaintInfo>& layers)
1936 const RenderObject* clippingContainer = paintInfo.renderLayer->renderer()->clippingContainer();
1937 if (clippingContainer == referenceLayer.renderer()->clippingContainer())
1938 return PaintInfo::infiniteRect();
1940 ASSERT(clippingContainer);
1942 const GraphicsLayerPaintInfo* ancestorPaintInfo = containingSquashedLayer(clippingContainer, layers);
1943 // Must be there, otherwise CompositingLayerAssigner::canSquashIntoCurrentSquashingOwner would have disallowed squashing.
1944 ASSERT(ancestorPaintInfo);
1946 // FIXME: this is a potential performance issue. We shoudl consider caching these clip rects or otherwise optimizing.
1947 ClipRectsContext clipRectsContext(ancestorPaintInfo->renderLayer, TemporaryClipRects);
1948 IntRect parentClipRect = pixelSnappedIntRect(paintInfo.renderLayer->clipper().backgroundClipRect(clipRectsContext).rect());
1949 ASSERT(parentClipRect != PaintInfo::infiniteRect());
1951 // Convert from ancestor to local coordinates.
1952 IntSize ancestorToLocalOffset = paintInfo.offsetFromRenderer - ancestorPaintInfo->offsetFromRenderer;
1953 parentClipRect.move(ancestorToLocalOffset);
1954 return parentClipRect;
1957 void CompositedLayerMapping::doPaintTask(GraphicsLayerPaintInfo& paintInfo, GraphicsContext* context,
1958 const IntRect& clip) // In the coords of rootLayer.
1960 if (paintsIntoCompositedAncestor()) {
1961 ASSERT_NOT_REACHED();
1965 FontCachePurgePreventer fontCachePurgePreventer;
1967 PaintLayerFlags paintFlags = 0;
1968 if (paintInfo.paintingPhase & GraphicsLayerPaintBackground)
1969 paintFlags |= PaintLayerPaintingCompositingBackgroundPhase;
1970 if (paintInfo.paintingPhase & GraphicsLayerPaintForeground)
1971 paintFlags |= PaintLayerPaintingCompositingForegroundPhase;
1972 if (paintInfo.paintingPhase & GraphicsLayerPaintMask)
1973 paintFlags |= PaintLayerPaintingCompositingMaskPhase;
1974 if (paintInfo.paintingPhase & GraphicsLayerPaintChildClippingMask)
1975 paintFlags |= PaintLayerPaintingChildClippingMaskPhase;
1976 if (paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)
1977 paintFlags |= PaintLayerPaintingOverflowContents;
1978 if (paintInfo.paintingPhase & GraphicsLayerPaintCompositedScroll)
1979 paintFlags |= PaintLayerPaintingCompositingScrollingPhase;
1981 if (paintInfo.isBackgroundLayer)
1982 paintFlags |= (PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
1983 else if (compositor()->fixedRootBackgroundLayer())
1984 paintFlags |= PaintLayerPaintingSkipRootBackground;
1986 // Note carefully: in theory it is appropriate to invoke context->save() here
1987 // and restore the context after painting. For efficiency, we are assuming that
1988 // it is equivalent to manually undo this offset translation, which means we are
1989 // assuming that the context's space was not affected by the RenderLayer
1992 IntSize offset = paintInfo.offsetFromRenderer;
1993 context->translate(-offset.width(), -offset.height());
1995 // The dirtyRect is in the coords of the painting root.
1996 IntRect dirtyRect(clip);
1997 dirtyRect.move(offset);
1999 if (!(paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)) {
2000 LayoutRect bounds = paintInfo.compositedBounds;
2001 bounds.move(paintInfo.renderLayer->subpixelAccumulation());
2002 dirtyRect.intersect(pixelSnappedIntRect(bounds));
2004 dirtyRect.move(roundedIntSize(paintInfo.renderLayer->subpixelAccumulation()));
2008 paintInfo.renderLayer->renderer()->assertSubtreeIsLaidOut();
2011 if (paintInfo.renderLayer->compositingState() != PaintsIntoGroupedBacking) {
2012 // FIXME: GraphicsLayers need a way to split for RenderRegions.
2013 LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.renderLayer->subpixelAccumulation());
2014 paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags);
2016 ASSERT(!paintInfo.isBackgroundLayer || paintFlags & PaintLayerPaintingRootBackgroundOnly);
2018 if (paintInfo.renderLayer->containsDirtyOverlayScrollbars())
2019 paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags | PaintLayerPaintingOverlayScrollbars);
2021 ASSERT(compositor()->layerSquashingEnabled());
2022 LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.renderLayer->subpixelAccumulation());
2024 // RenderLayer::paintLayer assumes that the caller clips to the passed rect. Squashed layers need to do this clipping in software,
2025 // since there is no graphics layer to clip them precisely. Furthermore, in some cases we squash layers that need clipping in software
2026 // from clipping ancestors (see CompositedLayerMapping::localClipRectForSquashedLayer()).
2028 dirtyRect.intersect(paintInfo.localClipRectForSquashedLayer);
2029 context->clip(dirtyRect);
2030 paintInfo.renderLayer->paintLayer(context, paintingInfo, paintFlags);
2034 ASSERT(!paintInfo.renderLayer->usedTransparency());
2036 // Manually restore the context to its original state by applying the opposite translation.
2037 context->translate(offset.width(), offset.height());
2040 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
2046 const IntRect& scrollbarRect = scrollbar->frameRect();
2047 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
2048 IntRect transformedClip = clip;
2049 transformedClip.moveBy(scrollbarRect.location());
2050 scrollbar->paint(&context, transformedClip);
2054 // Up-call from compositing layer drawing callback.
2055 void CompositedLayerMapping::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
2057 // https://code.google.com/p/chromium/issues/detail?id=343772
2058 DisableCompositingQueryAsserts disabler;
2060 // FIXME: once the state machine is ready, this can be removed and we can refer to that instead.
2061 if (Page* page = renderer()->frame()->page())
2062 page->setIsPainting(true);
2064 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(m_owningLayer.renderer(), clip, graphicsLayer));
2065 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
2066 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
2067 InspectorInstrumentation::willPaint(m_owningLayer.renderer(), graphicsLayer);
2069 if (graphicsLayer == m_graphicsLayer.get()
2070 || graphicsLayer == m_foregroundLayer.get()
2071 || graphicsLayer == m_backgroundLayer.get()
2072 || graphicsLayer == m_maskLayer.get()
2073 || graphicsLayer == m_childClippingMaskLayer.get()
2074 || graphicsLayer == m_scrollingContentsLayer.get()
2075 || graphicsLayer == m_scrollingBlockSelectionLayer.get()) {
2077 GraphicsLayerPaintInfo paintInfo;
2078 paintInfo.renderLayer = &m_owningLayer;
2079 paintInfo.compositedBounds = compositedBounds();
2080 paintInfo.offsetFromRenderer = graphicsLayer->offsetFromRenderer();
2081 paintInfo.paintingPhase = paintingPhase;
2082 paintInfo.isBackgroundLayer = (graphicsLayer == m_backgroundLayer);
2084 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2085 doPaintTask(paintInfo, &context, clip);
2086 } else if (graphicsLayer == m_squashingLayer.get()) {
2087 ASSERT(compositor()->layerSquashingEnabled());
2088 for (size_t i = 0; i < m_squashedLayers.size(); ++i)
2089 doPaintTask(m_squashedLayers[i], &context, clip);
2090 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2091 paintScrollbar(m_owningLayer.scrollableArea()->horizontalScrollbar(), context, clip);
2092 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2093 paintScrollbar(m_owningLayer.scrollableArea()->verticalScrollbar(), context, clip);
2094 } else if (graphicsLayer == layerForScrollCorner()) {
2095 const IntRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
2097 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
2098 IntRect transformedClip = clip;
2099 transformedClip.moveBy(scrollCornerAndResizer.location());
2100 m_owningLayer.scrollableArea()->paintScrollCorner(&context, IntPoint(), transformedClip);
2101 m_owningLayer.scrollableArea()->paintResizer(&context, IntPoint(), transformedClip);
2104 InspectorInstrumentation::didPaint(m_owningLayer.renderer(), graphicsLayer, &context, clip);
2106 if (Page* page = renderer()->frame()->page())
2107 page->setIsPainting(false);
2111 bool CompositedLayerMapping::isTrackingRepaints() const
2113 GraphicsLayerClient* client = compositor();
2114 return client ? client->isTrackingRepaints() : false;
2117 struct CollectTrackedRepaintRectsFunctor {
2118 void operator() (GraphicsLayer* layer) const { layer->collectTrackedRepaintRects(*rects); }
2119 Vector<FloatRect>* rects;
2122 PassOwnPtr<Vector<FloatRect> > CompositedLayerMapping::collectTrackedRepaintRects() const
2124 OwnPtr<Vector<FloatRect> > rects = adoptPtr(new Vector<FloatRect>);
2125 CollectTrackedRepaintRectsFunctor functor = { rects.get() };
2126 ApplyToGraphicsLayers(this, functor, ApplyToAllGraphicsLayers);
2127 return rects.release();
2131 void CompositedLayerMapping::verifyNotPainting()
2133 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
2137 void CompositedLayerMapping::notifyAnimationStarted(const GraphicsLayer*, double monotonicTime)
2139 renderer()->node()->document().compositorPendingAnimations().notifyCompositorAnimationStarted(monotonicTime);
2142 IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const
2144 LayoutRect bounds = m_compositedBounds;
2145 bounds.move(m_owningLayer.subpixelAccumulation());
2146 return pixelSnappedIntRect(bounds);
2149 bool CompositedLayerMapping::updateSquashingLayerAssignment(RenderLayer* squashedLayer, const RenderLayer& owningLayer, size_t nextSquashedLayerIndex)
2151 ASSERT(compositor()->layerSquashingEnabled());
2153 GraphicsLayerPaintInfo paintInfo;
2154 paintInfo.renderLayer = squashedLayer;
2155 // NOTE: composited bounds are updated elsewhere
2156 // NOTE: offsetFromRenderer is updated elsewhere
2157 paintInfo.paintingPhase = GraphicsLayerPaintAllWithOverflowClip;
2158 paintInfo.isBackgroundLayer = false;
2160 // Change tracking on squashing layers: at the first sign of something changed, just invalidate the layer.
2161 // FIXME: Perhaps we can find a tighter more clever mechanism later.
2162 bool updatedAssignment = false;
2163 if (nextSquashedLayerIndex < m_squashedLayers.size()) {
2164 if (!paintInfo.isEquivalentForSquashing(m_squashedLayers[nextSquashedLayerIndex])) {
2165 compositor()->repaintOnCompositingChange(squashedLayer);
2166 updatedAssignment = true;
2167 m_squashedLayers[nextSquashedLayerIndex] = paintInfo;
2170 compositor()->repaintOnCompositingChange(squashedLayer);
2171 m_squashedLayers.append(paintInfo);
2172 updatedAssignment = true;
2174 squashedLayer->setGroupedMapping(this);
2175 return updatedAssignment;
2178 void CompositedLayerMapping::removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer* layer)
2180 size_t layerIndex = kNotFound;
2182 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
2183 if (m_squashedLayers[i].renderLayer == layer) {
2189 if (layerIndex == kNotFound)
2192 m_squashedLayers.remove(layerIndex);
2195 void CompositedLayerMapping::finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex)
2197 ASSERT(compositor()->layerSquashingEnabled());
2199 // Any additional squashed RenderLayers in the array no longer exist, and removing invalidates the squashingLayer contents.
2200 if (nextSquashedLayerIndex < m_squashedLayers.size())
2201 m_squashedLayers.remove(nextSquashedLayerIndex, m_squashedLayers.size() - nextSquashedLayerIndex);
2204 String CompositedLayerMapping::debugName(const GraphicsLayer* graphicsLayer)
2207 if (graphicsLayer == m_graphicsLayer.get()) {
2208 name = m_owningLayer.debugName();
2209 } else if (graphicsLayer == m_squashingContainmentLayer.get()) {
2210 name = "Squashing Containment Layer";
2211 } else if (graphicsLayer == m_squashingLayer.get()) {
2212 name = "Squashing Layer";
2213 } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
2214 name = "Ancestor Clipping Layer";
2215 } else if (graphicsLayer == m_foregroundLayer.get()) {
2216 name = m_owningLayer.debugName() + " (foreground) Layer";
2217 } else if (graphicsLayer == m_backgroundLayer.get()) {
2218 name = m_owningLayer.debugName() + " (background) Layer";
2219 } else if (graphicsLayer == m_childContainmentLayer.get()) {
2220 name = "Child Containment Layer";
2221 } else if (graphicsLayer == m_childTransformLayer.get()) {
2222 name = "Child Transform Layer";
2223 } else if (graphicsLayer == m_maskLayer.get()) {
2224 name = "Mask Layer";
2225 } else if (graphicsLayer == m_childClippingMaskLayer.get()) {
2226 name = "Child Clipping Mask Layer";
2227 } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
2228 name = "Horizontal Scrollbar Layer";
2229 } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
2230 name = "Vertical Scrollbar Layer";
2231 } else if (graphicsLayer == m_layerForScrollCorner.get()) {
2232 name = "Scroll Corner Layer";
2233 } else if (graphicsLayer == m_scrollingLayer.get()) {
2234 name = "Scrolling Layer";
2235 } else if (graphicsLayer == m_scrollingContentsLayer.get()) {
2236 name = "Scrolling Contents Layer";
2237 } else if (graphicsLayer == m_scrollingBlockSelectionLayer.get()) {
2238 name = "Scrolling Block Selection Layer";
2240 ASSERT_NOT_REACHED();
2246 } // namespace WebCore