1 /*
2 * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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.
24 */
25
26 #include "config.h"
27
28 #include "core/rendering/compositing/CompositedLayerMapping.h"
29
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/geometry/TransformState.h"
54 #include "platform/graphics/GraphicsContext.h"
55 #include "wtf/CurrentTime.h"
56 #include "wtf/text/StringBuilder.h"
57
58 using namespace std;
59
60 namespace WebCore {
61
62 using namespace HTMLNames;
63
64 static IntRect clipBox(RenderBox* renderer);
65
contentsRect(const RenderObject * renderer)66 static IntRect contentsRect(const RenderObject* renderer)
67 {
68 if (!renderer->isBox())
69 return IntRect();
70
71 return renderer->isVideo() ?
72 toRenderVideo(renderer)->videoBox() :
73 pixelSnappedIntRect(toRenderBox(renderer)->contentBoxRect());
74 }
75
backgroundRect(const RenderObject * renderer)76 static IntRect backgroundRect(const RenderObject* renderer)
77 {
78 if (!renderer->isBox())
79 return IntRect();
80
81 LayoutRect rect;
82 const RenderBox* box = toRenderBox(renderer);
83 EFillBox clip = box->style()->backgroundClip();
84 switch (clip) {
85 case BorderFillBox:
86 rect = box->borderBoxRect();
87 break;
88 case PaddingFillBox:
89 rect = box->paddingBoxRect();
90 break;
91 case ContentFillBox:
92 rect = box->contentBoxRect();
93 break;
94 case TextFillBox:
95 break;
96 }
97
98 return pixelSnappedIntRect(rect);
99 }
100
isAcceleratedCanvas(const RenderObject * renderer)101 static inline bool isAcceleratedCanvas(const RenderObject* renderer)
102 {
103 if (renderer->isCanvas()) {
104 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
105 if (CanvasRenderingContext* context = canvas->renderingContext())
106 return context->isAccelerated();
107 }
108 return false;
109 }
110
hasBoxDecorations(const RenderStyle * style)111 static bool hasBoxDecorations(const RenderStyle* style)
112 {
113 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
114 }
115
hasBoxDecorationsOrBackgroundImage(const RenderStyle * style)116 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
117 {
118 return hasBoxDecorations(style) || style->hasBackgroundImage();
119 }
120
contentLayerSupportsDirectBackgroundComposition(const RenderObject * renderer)121 static bool contentLayerSupportsDirectBackgroundComposition(const RenderObject* renderer)
122 {
123 // No support for decorations - border, border-radius or outline.
124 // Only simple background - solid color or transparent.
125 if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
126 return false;
127
128 // If there is no background, there is nothing to support.
129 if (!renderer->style()->hasBackground())
130 return true;
131
132 // Simple background that is contained within the contents rect.
133 return contentsRect(renderer).contains(backgroundRect(renderer));
134 }
135
platformLayerForPlugin(RenderObject * renderer)136 static blink::WebLayer* platformLayerForPlugin(RenderObject* renderer)
137 {
138 if (!renderer->isEmbeddedObject())
139 return 0;
140 Widget* widget = toRenderEmbeddedObject(renderer)->widget();
141 if (!widget || !widget->isPluginView())
142 return 0;
143 return toPluginView(widget)->platformLayer();
144
145 }
146
isAcceleratedContents(RenderObject * renderer)147 static inline bool isAcceleratedContents(RenderObject* renderer)
148 {
149 return isAcceleratedCanvas(renderer)
150 || (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing())
151 || renderer->isVideo();
152 }
153
154 // Get the scrolling coordinator in a way that works inside CompositedLayerMapping's destructor.
scrollingCoordinatorFromLayer(RenderLayer & layer)155 static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer& layer)
156 {
157 Page* page = layer.renderer()->frame()->page();
158 if (!page)
159 return 0;
160
161 return page->scrollingCoordinator();
162 }
163
CompositedLayerMapping(RenderLayer & layer)164 CompositedLayerMapping::CompositedLayerMapping(RenderLayer& layer)
165 : m_owningLayer(layer)
166 , m_pendingUpdateScope(GraphicsLayerUpdateNone)
167 , m_isMainFrameRenderViewLayer(false)
168 , m_requiresOwnBackingStoreForIntrinsicReasons(true)
169 , m_requiresOwnBackingStoreForAncestorReasons(true)
170 , m_canCompositeFilters(false)
171 , m_backgroundLayerPaintsFixedRootBackground(false)
172 , m_scrollingContentsAreEmpty(false)
173 {
174 if (layer.isRootLayer() && renderer()->frame()->isMainFrame())
175 m_isMainFrameRenderViewLayer = true;
176
177 createPrimaryGraphicsLayer();
178 }
179
~CompositedLayerMapping()180 CompositedLayerMapping::~CompositedLayerMapping()
181 {
182 // Hits in compositing/squashing/squash-onto-nephew.html.
183 DisableCompositingQueryAsserts disabler;
184
185 // Do not leave the destroyed pointer dangling on any RenderLayers that painted to this mapping's squashing layer.
186 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
187 RenderLayer* oldSquashedLayer = m_squashedLayers[i].renderLayer;
188 if (oldSquashedLayer->groupedMapping() == this) {
189 oldSquashedLayer->setGroupedMapping(0, true);
190 oldSquashedLayer->setLostGroupedMapping(true);
191 }
192 }
193
194 updateClippingLayers(false, false);
195 updateOverflowControlsLayers(false, false, false);
196 updateChildTransformLayer(false);
197 updateForegroundLayer(false);
198 updateBackgroundLayer(false);
199 updateMaskLayer(false);
200 updateClippingMaskLayers(false);
201 updateScrollingLayers(false);
202 updateSquashingLayers(false);
203 destroyGraphicsLayers();
204 }
205
createGraphicsLayer(CompositingReasons reasons)206 PassOwnPtr<GraphicsLayer> CompositedLayerMapping::createGraphicsLayer(CompositingReasons reasons)
207 {
208 GraphicsLayerFactory* graphicsLayerFactory = 0;
209 if (Page* page = renderer()->frame()->page())
210 graphicsLayerFactory = page->chrome().client().graphicsLayerFactory();
211
212 OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
213
214 graphicsLayer->setCompositingReasons(reasons);
215 if (Node* owningNode = m_owningLayer.renderer()->generatingNode())
216 graphicsLayer->setOwnerNodeId(InspectorNodeIds::idForNode(owningNode));
217
218 return graphicsLayer.release();
219 }
220
createPrimaryGraphicsLayer()221 void CompositedLayerMapping::createPrimaryGraphicsLayer()
222 {
223 m_graphicsLayer = createGraphicsLayer(m_owningLayer.compositingReasons());
224
225 #if !OS(ANDROID)
226 if (m_isMainFrameRenderViewLayer)
227 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
228 #endif
229
230 updateOpacity(renderer()->style());
231 updateTransform(renderer()->style());
232 updateFilters(renderer()->style());
233
234 if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
235 updateLayerBlendMode(renderer()->style());
236 updateIsRootForIsolatedGroup();
237 }
238 }
239
destroyGraphicsLayers()240 void CompositedLayerMapping::destroyGraphicsLayers()
241 {
242 if (m_graphicsLayer)
243 m_graphicsLayer->removeFromParent();
244
245 m_ancestorClippingLayer = nullptr;
246 m_graphicsLayer = nullptr;
247 m_foregroundLayer = nullptr;
248 m_backgroundLayer = nullptr;
249 m_childContainmentLayer = nullptr;
250 m_childTransformLayer = nullptr;
251 m_maskLayer = nullptr;
252 m_childClippingMaskLayer = nullptr;
253
254 m_scrollingLayer = nullptr;
255 m_scrollingContentsLayer = nullptr;
256 m_scrollingBlockSelectionLayer = nullptr;
257 }
258
updateOpacity(const RenderStyle * style)259 void CompositedLayerMapping::updateOpacity(const RenderStyle* style)
260 {
261 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
262 }
263
updateTransform(const RenderStyle * style)264 void CompositedLayerMapping::updateTransform(const RenderStyle* style)
265 {
266 // FIXME: This could use m_owningLayer.transform(), but that currently has transform-origin
267 // baked into it, and we don't want that.
268 TransformationMatrix t;
269 if (m_owningLayer.hasTransform()) {
270 style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
271 makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing());
272 }
273
274 m_graphicsLayer->setTransform(t);
275 }
276
updateFilters(const RenderStyle * style)277 void CompositedLayerMapping::updateFilters(const RenderStyle* style)
278 {
279 unsigned didCompositeFilters = m_canCompositeFilters;
280 m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer().computeFilterOperations(style));
281 if (didCompositeFilters != m_canCompositeFilters) {
282 //
283 // If filters used to be painted in software and are now painted in the compositor, we need to:
284 // (1) Remove the FilterEffectRenderer, which was used for painting filters in software.
285 // (2) Repaint the layer contents to remove the software-applied filter because the compositor will apply it.
286 //
287 // Similarly, if filters used to be painted in the compositor and are now painted in software, we need to:
288 // (1) Create a FilterEffectRenderer.
289 // (2) Repaint the layer contents to apply a software filter because the compositor won't apply it.
290 //
291 m_owningLayer.updateOrRemoveFilterEffectRenderer();
292 setContentsNeedDisplay();
293 }
294 }
295
updateLayerBlendMode(const RenderStyle * style)296 void CompositedLayerMapping::updateLayerBlendMode(const RenderStyle* style)
297 {
298 setBlendMode(style->blendMode());
299 }
300
updateIsRootForIsolatedGroup()301 void CompositedLayerMapping::updateIsRootForIsolatedGroup()
302 {
303 bool isolate = m_owningLayer.shouldIsolateCompositedDescendants();
304
305 // non stacking context layers should never isolate
306 ASSERT(m_owningLayer.stackingNode()->isStackingContext() || !isolate);
307
308 m_graphicsLayer->setIsRootForIsolatedGroup(isolate);
309 }
310
updateContentsOpaque()311 void CompositedLayerMapping::updateContentsOpaque()
312 {
313 // For non-root layers, background is always painted by the primary graphics layer.
314 ASSERT(m_isMainFrameRenderViewLayer || !m_backgroundLayer);
315 if (m_backgroundLayer) {
316 m_graphicsLayer->setContentsOpaque(false);
317 m_backgroundLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
318 } else {
319 m_graphicsLayer->setContentsOpaque(m_owningLayer.backgroundIsKnownToBeOpaqueInRect(compositedBounds()));
320 }
321 }
322
updateCompositedBounds(GraphicsLayerUpdater::UpdateType updateType)323 void CompositedLayerMapping::updateCompositedBounds(GraphicsLayerUpdater::UpdateType updateType)
324 {
325 if (!shouldUpdateGraphicsLayer(updateType))
326 return;
327
328 // FIXME: if this is really needed for performance, it would be better to store it on RenderLayer.
329 m_compositedBounds = m_owningLayer.boundingBoxForCompositing();
330 }
331
updateAfterWidgetResize()332 void CompositedLayerMapping::updateAfterWidgetResize()
333 {
334 if (renderer()->isRenderPart()) {
335 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
336 innerCompositor->frameViewDidChangeSize();
337 // We can floor this point because our frameviews are always aligned to pixel boundaries.
338 ASSERT(contentsBox().location() == flooredIntPoint(contentsBox().location()));
339 innerCompositor->frameViewDidChangeLocation(flooredIntPoint(contentsBox().location()));
340 }
341 }
342 }
343
updateCompositingReasons()344 void CompositedLayerMapping::updateCompositingReasons()
345 {
346 // All other layers owned by this mapping will have the same compositing reason
347 // for their lifetime, so they are initialized only when created.
348 m_graphicsLayer->setCompositingReasons(m_owningLayer.compositingReasons());
349 }
350
updateGraphicsLayerConfiguration(GraphicsLayerUpdater::UpdateType updateType)351 bool CompositedLayerMapping::updateGraphicsLayerConfiguration(GraphicsLayerUpdater::UpdateType updateType)
352 {
353 if (!shouldUpdateGraphicsLayer(updateType))
354 return false;
355
356 RenderLayerCompositor* compositor = this->compositor();
357 RenderObject* renderer = this->renderer();
358
359 m_owningLayer.updateDescendantDependentFlags();
360 m_owningLayer.stackingNode()->updateZOrderLists();
361
362 bool layerConfigChanged = false;
363 setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(&m_owningLayer));
364
365 // The background layer is currently only used for fixed root backgrounds.
366 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
367 layerConfigChanged = true;
368
369 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(&m_owningLayer)))
370 layerConfigChanged = true;
371
372 bool needsDescendantsClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer);
373
374 // Our scrolling layer will clip.
375 if (m_owningLayer.needsCompositedScrolling())
376 needsDescendantsClippingLayer = false;
377
378 RenderLayer* scrollParent = compositor->acceleratedCompositingForOverflowScrollEnabled() ? m_owningLayer.scrollParent() : 0;
379 bool needsAncestorClip = compositor->clippedByNonAncestorInStackingTree(&m_owningLayer);
380 if (scrollParent) {
381 // If our containing block is our ancestor scrolling layer, then we'll already be clipped
382 // to it via our scroll parent and we don't need an ancestor clipping layer.
383 if (m_owningLayer.renderer()->containingBlock()->enclosingLayer() == m_owningLayer.ancestorScrollingLayer())
384 needsAncestorClip = false;
385 }
386
387 if (updateClippingLayers(needsAncestorClip, needsDescendantsClippingLayer))
388 layerConfigChanged = true;
389
390 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
391 layerConfigChanged = true;
392
393 bool scrollingConfigChanged = false;
394 if (updateScrollingLayers(m_owningLayer.needsCompositedScrolling())) {
395 layerConfigChanged = true;
396 scrollingConfigChanged = true;
397 }
398
399 bool hasPerspective = false;
400 if (RenderStyle* style = renderer->style())
401 hasPerspective = style->hasPerspective();
402 bool needsChildTransformLayer = hasPerspective && (layerForChildrenTransform() == m_childTransformLayer.get()) && renderer->isBox();
403 if (updateChildTransformLayer(needsChildTransformLayer))
404 layerConfigChanged = true;
405
406 updateScrollParent(scrollParent);
407 updateClipParent(m_owningLayer.clipParent());
408
409 if (updateSquashingLayers(!m_squashedLayers.isEmpty()))
410 layerConfigChanged = true;
411
412 if (layerConfigChanged)
413 updateInternalHierarchy();
414
415 if (scrollingConfigChanged) {
416 if (renderer->view())
417 compositor->scrollingLayerDidChange(&m_owningLayer);
418 }
419
420 // A mask layer is not part of the hierarchy proper, it's an auxiliary layer
421 // that's plugged into another GraphicsLayer that is part of the hierarchy.
422 // It has no parent or child GraphicsLayer. For that reason, we process it
423 // here, after the hierarchy has been updated.
424 bool maskLayerChanged = false;
425 if (updateMaskLayer(renderer->hasMask())) {
426 maskLayerChanged = true;
427 m_graphicsLayer->setMaskLayer(m_maskLayer.get());
428 }
429
430 bool hasChildClippingLayer = compositor->clipsCompositingDescendants(&m_owningLayer) && (hasClippingLayer() || hasScrollingLayer());
431 // If we have a border radius or clip path on a scrolling layer, we need a clipping mask to properly
432 // clip the scrolled contents, even if there are no composited descendants.
433 bool hasClipPath = renderer->style()->clipPath();
434 bool needsChildClippingMask = (hasClipPath || renderer->style()->hasBorderRadius()) && (hasChildClippingLayer || isAcceleratedContents(renderer) || hasScrollingLayer());
435 if (updateClippingMaskLayers(needsChildClippingMask)) {
436 // Clip path clips the entire subtree, including scrollbars. It must be attached directly onto
437 // the main m_graphicsLayer.
438 if (hasClipPath)
439 m_graphicsLayer->setMaskLayer(m_childClippingMaskLayer.get());
440 else if (hasClippingLayer())
441 clippingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
442 else if (hasScrollingLayer())
443 scrollingLayer()->setMaskLayer(m_childClippingMaskLayer.get());
444 else if (isAcceleratedContents(renderer))
445 m_graphicsLayer->setContentsClippingMaskLayer(m_childClippingMaskLayer.get());
446 }
447
448 if (m_owningLayer.reflectionInfo()) {
449 if (m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping()) {
450 GraphicsLayer* reflectionLayer = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping()->mainGraphicsLayer();
451 m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
452 }
453 } else {
454 m_graphicsLayer->setReplicatedByLayer(0);
455 }
456
457 updateBackgroundColor();
458
459 if (isDirectlyCompositedImage())
460 updateImageContents();
461
462 if (blink::WebLayer* layer = platformLayerForPlugin(renderer)) {
463 m_graphicsLayer->setContentsToPlatformLayer(layer);
464 } else if (renderer->node() && renderer->node()->isFrameOwnerElement() && toHTMLFrameOwnerElement(renderer->node())->contentFrame()) {
465 blink::WebLayer* layer = toHTMLFrameOwnerElement(renderer->node())->contentFrame()->remotePlatformLayer();
466 if (layer)
467 m_graphicsLayer->setContentsToPlatformLayer(layer);
468 } else if (renderer->isVideo()) {
469 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer->node());
470 m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer());
471 } else if (isAcceleratedCanvas(renderer)) {
472 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer->node());
473 if (CanvasRenderingContext* context = canvas->renderingContext())
474 m_graphicsLayer->setContentsToPlatformLayer(context->platformLayer());
475 layerConfigChanged = true;
476 }
477 if (renderer->isRenderPart())
478 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
479
480 // Changes to either the internal hierarchy or the mask layer have an impact
481 // on painting phases, so we need to update when either are updated.
482 if (layerConfigChanged || maskLayerChanged)
483 updatePaintingPhases();
484
485 return layerConfigChanged;
486 }
487
clipBox(RenderBox * renderer)488 static IntRect clipBox(RenderBox* renderer)
489 {
490 LayoutRect result = PaintInfo::infiniteRect();
491 if (renderer->hasOverflowClip())
492 result = renderer->overflowClipRect(LayoutPoint());
493
494 if (renderer->hasClip())
495 result.intersect(renderer->clipRect(LayoutPoint()));
496
497 return pixelSnappedIntRect(result);
498 }
499
computeOffsetFromCompositedAncestor(const RenderLayer * layer,const RenderLayer * compositedAncestor)500 static LayoutPoint computeOffsetFromCompositedAncestor(const RenderLayer* layer, const RenderLayer* compositedAncestor)
501 {
502 LayoutPoint offset;
503 layer->convertToLayerCoords(compositedAncestor, offset);
504 if (compositedAncestor)
505 offset.move(compositedAncestor->compositedLayerMapping()->owningLayer().subpixelAccumulation());
506 return offset;
507 }
508
computeBoundsOfOwningLayer(const RenderLayer * compositedAncestor,IntRect & localBounds,IntRect & compositingBoundsRelativeToCompositedAncestor,LayoutPoint & offsetFromCompositedAncestor,IntPoint & snappedOffsetFromCompositedAncestor)509 void CompositedLayerMapping::computeBoundsOfOwningLayer(const RenderLayer* compositedAncestor, IntRect& localBounds, IntRect& compositingBoundsRelativeToCompositedAncestor, LayoutPoint& offsetFromCompositedAncestor,
510 IntPoint& snappedOffsetFromCompositedAncestor)
511 {
512 LayoutRect localRawCompositingBounds = compositedBounds();
513 offsetFromCompositedAncestor = computeOffsetFromCompositedAncestor(&m_owningLayer, compositedAncestor);
514 snappedOffsetFromCompositedAncestor = IntPoint(offsetFromCompositedAncestor.x().round(), offsetFromCompositedAncestor.y().round());
515
516 LayoutSize subpixelAccumulation = offsetFromCompositedAncestor - snappedOffsetFromCompositedAncestor;
517 m_owningLayer.setSubpixelAccumulation(subpixelAccumulation);
518
519 // Move the bounds by the subpixel accumulation so that it pixel-snaps relative to absolute pixels instead of local coordinates.
520 localRawCompositingBounds.move(subpixelAccumulation);
521 localBounds = pixelSnappedIntRect(localRawCompositingBounds);
522
523 compositingBoundsRelativeToCompositedAncestor = localBounds;
524 compositingBoundsRelativeToCompositedAncestor.moveBy(snappedOffsetFromCompositedAncestor);
525 }
526
updateSquashingLayerGeometry(const LayoutPoint & offsetFromCompositedAncestor,const IntPoint & graphicsLayerParentLocation,const RenderLayer & referenceLayer,Vector<GraphicsLayerPaintInfo> & layers,GraphicsLayer * squashingLayer,LayoutPoint * offsetFromTransformedAncestor,Vector<RenderLayer * > & layersNeedingPaintInvalidation)527 void CompositedLayerMapping::updateSquashingLayerGeometry(const LayoutPoint& offsetFromCompositedAncestor, const IntPoint& graphicsLayerParentLocation, const RenderLayer& referenceLayer,
528 Vector<GraphicsLayerPaintInfo>& layers, GraphicsLayer* squashingLayer, LayoutPoint* offsetFromTransformedAncestor, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
529 {
530 if (!squashingLayer)
531 return;
532 ASSERT(compositor()->layerSquashingEnabled());
533
534 LayoutPoint offsetFromReferenceLayerToParentGraphicsLayer(offsetFromCompositedAncestor);
535 offsetFromReferenceLayerToParentGraphicsLayer.moveBy(-graphicsLayerParentLocation);
536
537 // FIXME: Cache these offsets.
538 LayoutPoint referenceOffsetFromTransformedAncestor = referenceLayer.computeOffsetFromTransformedAncestor();
539
540 LayoutRect totalSquashBounds;
541 for (size_t i = 0; i < layers.size(); ++i) {
542 LayoutRect squashedBounds = layers[i].renderLayer->boundingBoxForCompositing();
543
544 // Store the local bounds of the RenderLayer subtree before applying the offset.
545 layers[i].compositedBounds = squashedBounds;
546
547 LayoutPoint offsetFromTransformedAncestorForSquashedLayer = layers[i].renderLayer->computeOffsetFromTransformedAncestor();
548 LayoutSize offsetFromSquashingLayer = offsetFromTransformedAncestorForSquashedLayer - referenceOffsetFromTransformedAncestor;
549
550 squashedBounds.move(offsetFromSquashingLayer);
551 totalSquashBounds.unite(squashedBounds);
552 }
553
554 // The totalSquashBounds is positioned with respect to referenceLayer of this CompositedLayerMapping.
555 // But the squashingLayer needs to be positioned with respect to the ancestor CompositedLayerMapping.
556 // The conversion between referenceLayer and the ancestor CLM is already computed as
557 // offsetFromReferenceLayerToParentGraphicsLayer.
558 totalSquashBounds.moveBy(offsetFromReferenceLayerToParentGraphicsLayer);
559 IntRect squashLayerBounds = enclosingIntRect(totalSquashBounds);
560 IntPoint squashLayerOrigin = squashLayerBounds.location();
561 LayoutSize squashLayerOriginInOwningLayerSpace = squashLayerOrigin - offsetFromReferenceLayerToParentGraphicsLayer;
562
563 // Now that the squashing bounds are known, we can convert the RenderLayer painting offsets
564 // from CLM owning layer space to the squashing layer space.
565 //
566 // The painting offset we want to compute for each squashed RenderLayer is essentially the position of
567 // the squashed RenderLayer described w.r.t. referenceLayer's origin. For this purpose we already cached
568 // offsetFromSquashingCLM before, which describes where the squashed RenderLayer is located w.r.t.
569 // referenceLayer. So we just need to convert that point from referenceLayer space to referenceLayer
570 // space. This is simply done by subtracing squashLayerOriginInOwningLayerSpace, but then the offset
571 // overall needs to be negated because that's the direction that the painting code expects the
572 // offset to be.
573 for (size_t i = 0; i < layers.size(); ++i) {
574 LayoutPoint offsetFromTransformedAncestorForSquashedLayer = layers[i].renderLayer->computeOffsetFromTransformedAncestor();
575 LayoutSize offsetFromSquashLayerOrigin = (offsetFromTransformedAncestorForSquashedLayer - referenceOffsetFromTransformedAncestor) - squashLayerOriginInOwningLayerSpace;
576
577 // It is ok to repaint here, because all of the geometry needed to correctly repaint is computed by this point.
578 IntSize newOffsetFromRenderer = -IntSize(offsetFromSquashLayerOrigin.width().round(), offsetFromSquashLayerOrigin.height().round());
579 LayoutSize subpixelAccumulation = offsetFromSquashLayerOrigin + newOffsetFromRenderer;
580 if (layers[i].offsetFromRendererSet && layers[i].offsetFromRenderer != newOffsetFromRenderer) {
581 layers[i].renderLayer->repainter().repaintIncludingNonCompositingDescendants();
582 layersNeedingPaintInvalidation.append(layers[i].renderLayer);
583 }
584 layers[i].offsetFromRenderer = newOffsetFromRenderer;
585 layers[i].offsetFromRendererSet = true;
586
587 layers[i].renderLayer->setSubpixelAccumulation(subpixelAccumulation);
588
589 // FIXME: find a better design to avoid this redundant value - most likely it will make
590 // sense to move the paint task info into RenderLayer's m_compositingProperties.
591 layers[i].renderLayer->setOffsetFromSquashingLayerOrigin(layers[i].offsetFromRenderer);
592 }
593
594 squashingLayer->setPosition(squashLayerBounds.location());
595 squashingLayer->setSize(squashLayerBounds.size());
596
597 *offsetFromTransformedAncestor = referenceOffsetFromTransformedAncestor;
598 offsetFromTransformedAncestor->move(squashLayerOriginInOwningLayerSpace);
599
600 for (size_t i = 0; i < layers.size(); ++i)
601 layers[i].localClipRectForSquashedLayer = localClipRectForSquashedLayer(referenceLayer, layers[i], layers);
602 }
603
updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType updateType,const RenderLayer * compositingContainer,Vector<RenderLayer * > & layersNeedingPaintInvalidation)604 void CompositedLayerMapping::updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType updateType, const RenderLayer* compositingContainer, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
605 {
606 if (!shouldUpdateGraphicsLayer(updateType))
607 return;
608
609 // Set transform property, if it is not animating. We have to do this here because the transform
610 // is affected by the layer dimensions.
611 if (!renderer()->style()->isRunningTransformAnimationOnCompositor())
612 updateTransform(renderer()->style());
613
614 // Set opacity, if it is not animating.
615 if (!renderer()->style()->isRunningOpacityAnimationOnCompositor())
616 updateOpacity(renderer()->style());
617
618 m_owningLayer.updateDescendantDependentFlags();
619
620 // We compute everything relative to the enclosing compositing layer.
621 IntRect ancestorCompositingBounds;
622 if (compositingContainer) {
623 ASSERT(compositingContainer->hasCompositedLayerMapping());
624 ancestorCompositingBounds = compositingContainer->compositedLayerMapping()->pixelSnappedCompositedBounds();
625 }
626
627 IntRect localCompositingBounds;
628 IntRect relativeCompositingBounds;
629 LayoutPoint offsetFromCompositedAncestor;
630 IntPoint snappedOffsetFromCompositedAncestor;
631 computeBoundsOfOwningLayer(compositingContainer, localCompositingBounds, relativeCompositingBounds, offsetFromCompositedAncestor, snappedOffsetFromCompositedAncestor);
632
633 IntPoint graphicsLayerParentLocation;
634 computeGraphicsLayerParentLocation(compositingContainer, ancestorCompositingBounds, graphicsLayerParentLocation);
635
636 // Might update graphicsLayerParentLocation.
637 updateAncestorClippingLayerGeometry(compositingContainer, snappedOffsetFromCompositedAncestor, graphicsLayerParentLocation);
638
639 FloatSize contentsSize = relativeCompositingBounds.size();
640
641 updateMainGraphicsLayerGeometry(relativeCompositingBounds, localCompositingBounds, graphicsLayerParentLocation);
642 updateSquashingLayerGeometry(offsetFromCompositedAncestor, graphicsLayerParentLocation, m_owningLayer, m_squashedLayers, m_squashingLayer.get(), &m_squashingLayerOffsetFromTransformedAncestor, layersNeedingPaintInvalidation);
643
644 // If we have a layer that clips children, position it.
645 IntRect clippingBox;
646 if (m_childContainmentLayer)
647 clippingBox = clipBox(toRenderBox(renderer()));
648
649 updateChildContainmentLayerGeometry(clippingBox, localCompositingBounds);
650 updateChildTransformLayerGeometry();
651
652 updateMaskLayerGeometry();
653 updateTransformGeometry(snappedOffsetFromCompositedAncestor, relativeCompositingBounds);
654 updateForegroundLayerGeometry(contentsSize, clippingBox);
655 updateBackgroundLayerGeometry(contentsSize);
656 updateReflectionLayerGeometry(layersNeedingPaintInvalidation);
657 updateScrollingLayerGeometry(localCompositingBounds);
658 updateChildClippingMaskLayerGeometry();
659
660 if (m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->scrollsOverflow())
661 m_owningLayer.scrollableArea()->positionOverflowControls(IntSize());
662
663 if (RuntimeEnabledFeatures::cssCompositingEnabled()) {
664 updateLayerBlendMode(renderer()->style());
665 updateIsRootForIsolatedGroup();
666 }
667
668 updateContentsRect();
669 updateBackgroundColor();
670 updateDrawsContent();
671 updateContentsOpaque();
672 updateAfterWidgetResize();
673 updateRenderingContext();
674 updateShouldFlattenTransform();
675 updateChildrenTransform();
676 updateScrollParent(compositor()->acceleratedCompositingForOverflowScrollEnabled() ? m_owningLayer.scrollParent() : 0);
677 registerScrollingLayers();
678
679 updateCompositingReasons();
680 }
681
updateMainGraphicsLayerGeometry(const IntRect & relativeCompositingBounds,const IntRect & localCompositingBounds,IntPoint & graphicsLayerParentLocation)682 void CompositedLayerMapping::updateMainGraphicsLayerGeometry(const IntRect& relativeCompositingBounds, const IntRect& localCompositingBounds, IntPoint& graphicsLayerParentLocation)
683 {
684 m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
685 m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
686
687 FloatSize oldSize = m_graphicsLayer->size();
688 const IntSize& contentsSize = relativeCompositingBounds.size();
689 if (oldSize != contentsSize)
690 m_graphicsLayer->setSize(contentsSize);
691
692 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
693 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
694 // non-compositing visible layers.
695 bool contentsVisible = m_owningLayer.hasVisibleContent() || hasVisibleNonCompositingDescendant(&m_owningLayer);
696 if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled() && renderer()->isVideo()) {
697 HTMLMediaElement* mediaElement = toHTMLMediaElement(renderer()->node());
698 if (mediaElement->isFullscreen())
699 contentsVisible = false;
700 }
701 m_graphicsLayer->setContentsVisible(contentsVisible);
702
703 m_graphicsLayer->setBackfaceVisibility(renderer()->style()->backfaceVisibility() == BackfaceVisibilityVisible);
704 }
705
computeGraphicsLayerParentLocation(const RenderLayer * compositingContainer,const IntRect & ancestorCompositingBounds,IntPoint & graphicsLayerParentLocation)706 void CompositedLayerMapping::computeGraphicsLayerParentLocation(const RenderLayer* compositingContainer, const IntRect& ancestorCompositingBounds, IntPoint& graphicsLayerParentLocation)
707 {
708 if (compositingContainer && compositingContainer->compositedLayerMapping()->hasClippingLayer()) {
709 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
710 // position relative to it.
711 IntRect clippingBox = clipBox(toRenderBox(compositingContainer->renderer()));
712 graphicsLayerParentLocation = clippingBox.location() + roundedIntSize(compositingContainer->subpixelAccumulation());
713 } else if (compositingContainer && compositingContainer->compositedLayerMapping()->childTransformLayer()) {
714 // Similarly, if the compositing ancestor has a child transform layer, we parent in that, and therefore
715 // position relative to it. It's already taken into account the contents offset, so we do not need to here.
716 graphicsLayerParentLocation = roundedIntPoint(compositingContainer->subpixelAccumulation());
717 } else if (compositingContainer) {
718 graphicsLayerParentLocation = ancestorCompositingBounds.location();
719 } else {
720 graphicsLayerParentLocation = renderer()->view()->documentRect().location();
721 }
722
723 if (compositingContainer && compositingContainer->needsCompositedScrolling()) {
724 RenderBox* renderBox = toRenderBox(compositingContainer->renderer());
725 IntSize scrollOffset = renderBox->scrolledContentOffset();
726 IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
727 graphicsLayerParentLocation = scrollOrigin - scrollOffset;
728 }
729 }
730
updateAncestorClippingLayerGeometry(const RenderLayer * compositingContainer,const IntPoint & snappedOffsetFromCompositedAncestor,IntPoint & graphicsLayerParentLocation)731 void CompositedLayerMapping::updateAncestorClippingLayerGeometry(const RenderLayer* compositingContainer, const IntPoint& snappedOffsetFromCompositedAncestor, IntPoint& graphicsLayerParentLocation)
732 {
733 if (!compositingContainer || !m_ancestorClippingLayer)
734 return;
735
736 // FIXME: this should use cached clip rects, but this sometimes give
737 // inaccurate results (and trips the ASSERTS in RenderLayerClipper).
738 ClipRectsContext clipRectsContext(compositingContainer, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
739 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer.clipper().backgroundClipRect(clipRectsContext).rect());
740 ASSERT(parentClipRect != PaintInfo::infiniteRect());
741 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
742 m_ancestorClippingLayer->setSize(parentClipRect.size());
743
744 // backgroundRect is relative to compositingContainer, so subtract snappedOffsetFromCompositedAncestor.X/snappedOffsetFromCompositedAncestor.Y to get back to local coords.
745 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - snappedOffsetFromCompositedAncestor);
746
747 // The primary layer is then parented in, and positioned relative to this clipping layer.
748 graphicsLayerParentLocation = parentClipRect.location();
749 }
750
updateChildContainmentLayerGeometry(const IntRect & clippingBox,const IntRect & localCompositingBounds)751 void CompositedLayerMapping::updateChildContainmentLayerGeometry(const IntRect& clippingBox, const IntRect& localCompositingBounds)
752 {
753 if (!m_childContainmentLayer)
754 return;
755
756 m_childContainmentLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location() + roundedIntSize(m_owningLayer.subpixelAccumulation())));
757 m_childContainmentLayer->setSize(clippingBox.size());
758 m_childContainmentLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
759 if (m_childClippingMaskLayer && !m_scrollingLayer && !renderer()->style()->clipPath()) {
760 m_childClippingMaskLayer->setPosition(m_childContainmentLayer->position());
761 m_childClippingMaskLayer->setSize(m_childContainmentLayer->size());
762 m_childClippingMaskLayer->setOffsetFromRenderer(m_childContainmentLayer->offsetFromRenderer());
763 }
764 }
765
updateChildTransformLayerGeometry()766 void CompositedLayerMapping::updateChildTransformLayerGeometry()
767 {
768 if (!m_childTransformLayer)
769 return;
770 const IntRect borderBox = toRenderBox(m_owningLayer.renderer())->pixelSnappedBorderBoxRect();
771 m_childTransformLayer->setSize(borderBox.size());
772 m_childTransformLayer->setPosition(FloatPoint(contentOffsetInCompositingLayer()));
773 }
774
updateMaskLayerGeometry()775 void CompositedLayerMapping::updateMaskLayerGeometry()
776 {
777 if (!m_maskLayer)
778 return;
779
780 if (m_maskLayer->size() != m_graphicsLayer->size()) {
781 m_maskLayer->setSize(m_graphicsLayer->size());
782 m_maskLayer->setNeedsDisplay();
783 }
784 m_maskLayer->setPosition(FloatPoint());
785 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
786 }
787
updateTransformGeometry(const IntPoint & snappedOffsetFromCompositedAncestor,const IntRect & relativeCompositingBounds)788 void CompositedLayerMapping::updateTransformGeometry(const IntPoint& snappedOffsetFromCompositedAncestor, const IntRect& relativeCompositingBounds)
789 {
790 if (m_owningLayer.hasTransform()) {
791 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
792
793 // Get layout bounds in the coords of compositingContainer to match relativeCompositingBounds.
794 IntRect layerBounds = pixelSnappedIntRect(toLayoutPoint(m_owningLayer.subpixelAccumulation()), borderBox.size());
795 layerBounds.moveBy(snappedOffsetFromCompositedAncestor);
796
797 // Update properties that depend on layer dimensions
798 FloatPoint3D transformOrigin = computeTransformOrigin(IntRect(IntPoint(), layerBounds.size()));
799
800 // |transformOrigin| is in the local space of this layer. layerBounds - relativeCompositingBounds converts to the space of the
801 // compositing bounds relative to the composited ancestor. This does not apply to the z direction, since the page is 2D.
802 FloatPoint3D compositedTransformOrigin(
803 layerBounds.x() - relativeCompositingBounds.x() + transformOrigin.x(),
804 layerBounds.y() - relativeCompositingBounds.y() + transformOrigin.y(),
805 transformOrigin.z());
806 m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
807 } else {
808 FloatPoint3D compositedTransformOrigin(
809 relativeCompositingBounds.width() * 0.5f,
810 relativeCompositingBounds.height() * 0.5f,
811 0.f);
812 m_graphicsLayer->setTransformOrigin(compositedTransformOrigin);
813 }
814 }
815
updateReflectionLayerGeometry(Vector<RenderLayer * > & layersNeedingPaintInvalidation)816 void CompositedLayerMapping::updateReflectionLayerGeometry(Vector<RenderLayer*>& layersNeedingPaintInvalidation)
817 {
818 if (!m_owningLayer.reflectionInfo() || !m_owningLayer.reflectionInfo()->reflectionLayer()->hasCompositedLayerMapping())
819 return;
820
821 CompositedLayerMappingPtr reflectionCompositedLayerMapping = m_owningLayer.reflectionInfo()->reflectionLayer()->compositedLayerMapping();
822 reflectionCompositedLayerMapping->updateGraphicsLayerGeometry(GraphicsLayerUpdater::ForceUpdate, &m_owningLayer, layersNeedingPaintInvalidation);
823 }
824
updateScrollingLayerGeometry(const IntRect & localCompositingBounds)825 void CompositedLayerMapping::updateScrollingLayerGeometry(const IntRect& localCompositingBounds)
826 {
827 if (!m_scrollingLayer)
828 return;
829
830 ASSERT(m_scrollingContentsLayer);
831 RenderBox* renderBox = toRenderBox(renderer());
832 IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
833
834 IntSize adjustedScrollOffset = m_owningLayer.scrollableArea()->adjustedScrollOffset();
835 m_scrollingLayer->setPosition(FloatPoint(clientBox.location() - localCompositingBounds.location() + roundedIntSize(m_owningLayer.subpixelAccumulation())));
836 m_scrollingLayer->setSize(clientBox.size());
837
838 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
839 m_scrollingLayer->setOffsetFromRenderer(-toIntSize(clientBox.location()));
840
841 if (m_childClippingMaskLayer && !renderer()->style()->clipPath()) {
842 m_childClippingMaskLayer->setPosition(m_scrollingLayer->position());
843 m_childClippingMaskLayer->setSize(m_scrollingLayer->size());
844 m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
845 }
846
847 bool clientBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
848
849 IntSize scrollSize(renderBox->scrollWidth(), renderBox->scrollHeight());
850 if (scrollSize != m_scrollingContentsLayer->size() || clientBoxOffsetChanged)
851 m_scrollingContentsLayer->setNeedsDisplay();
852
853 IntSize scrollingContentsOffset = toIntSize(clientBox.location() - adjustedScrollOffset);
854 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) {
855 bool coordinatorHandlesOffset = compositor()->scrollingLayerDidChange(&m_owningLayer);
856 m_scrollingContentsLayer->setPosition(coordinatorHandlesOffset ? FloatPoint() : FloatPoint(-adjustedScrollOffset));
857 }
858
859 m_scrollingContentsLayer->setSize(scrollSize);
860 // FIXME: The paint offset and the scroll offset should really be separate concepts.
861 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
862
863 if (m_foregroundLayer) {
864 if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
865 m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
866 m_foregroundLayer->setNeedsDisplay();
867 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
868 }
869
870 updateScrollingBlockSelection();
871 }
872
updateChildClippingMaskLayerGeometry()873 void CompositedLayerMapping::updateChildClippingMaskLayerGeometry()
874 {
875 if (!m_childClippingMaskLayer || !renderer()->style()->clipPath())
876 return;
877 RenderBox* renderBox = toRenderBox(renderer());
878 IntRect clientBox = enclosingIntRect(renderBox->clientBoxRect());
879
880 m_childClippingMaskLayer->setPosition(m_graphicsLayer->position());
881 m_childClippingMaskLayer->setSize(m_graphicsLayer->size());
882 m_childClippingMaskLayer->setOffsetFromRenderer(toIntSize(clientBox.location()));
883
884 // NOTE: also some stuff happening in updateChildContainmentLayerGeometry().
885 }
886
updateForegroundLayerGeometry(const FloatSize & relativeCompositingBoundsSize,const IntRect & clippingBox)887 void CompositedLayerMapping::updateForegroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize, const IntRect& clippingBox)
888 {
889 if (!m_foregroundLayer)
890 return;
891
892 FloatSize foregroundSize = relativeCompositingBoundsSize;
893 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
894 m_foregroundLayer->setPosition(FloatPoint());
895
896 if (hasClippingLayer()) {
897 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
898 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
899 foregroundSize = FloatSize(clippingBox.size());
900 foregroundOffset = toIntSize(clippingBox.location());
901 } else if (m_childTransformLayer) {
902 // Things are different if we have a child transform layer rather
903 // than a clipping layer. In this case, we want to actually change
904 // the position of the layer (to compensate for our ancestor
905 // compositing layer's position) rather than leave the position the
906 // same and use offset-from-renderer + size to describe a clipped
907 // "window" onto the clipped layer.
908
909 m_foregroundLayer->setPosition(-m_childTransformLayer->position());
910 }
911
912 if (foregroundSize != m_foregroundLayer->size()) {
913 m_foregroundLayer->setSize(foregroundSize);
914 m_foregroundLayer->setNeedsDisplay();
915 }
916 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
917
918 // NOTE: there is some more configuring going on in updateScrollingLayerGeometry().
919 }
920
updateBackgroundLayerGeometry(const FloatSize & relativeCompositingBoundsSize)921 void CompositedLayerMapping::updateBackgroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize)
922 {
923 if (!m_backgroundLayer)
924 return;
925
926 FloatSize backgroundSize = relativeCompositingBoundsSize;
927 if (backgroundLayerPaintsFixedRootBackground()) {
928 FrameView* frameView = toRenderView(renderer())->frameView();
929 backgroundSize = frameView->visibleContentRect().size();
930 }
931 m_backgroundLayer->setPosition(FloatPoint());
932 if (backgroundSize != m_backgroundLayer->size()) {
933 m_backgroundLayer->setSize(backgroundSize);
934 m_backgroundLayer->setNeedsDisplay();
935 }
936 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
937 }
938
registerScrollingLayers()939 void CompositedLayerMapping::registerScrollingLayers()
940 {
941 // Register fixed position layers and their containers with the scrolling coordinator.
942 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
943 if (!scrollingCoordinator)
944 return;
945
946 scrollingCoordinator->updateLayerPositionConstraint(&m_owningLayer);
947
948 // Page scale is applied as a transform on the root render view layer. Because the scroll
949 // layer is further up in the hierarchy, we need to avoid marking the root render view
950 // layer as a container.
951 bool isContainer = m_owningLayer.hasTransform() && !m_owningLayer.isRootLayer();
952 // FIXME: we should make certain that childForSuperLayers will never be the m_squashingContainmentLayer here
953 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(localRootForOwningLayer(), isContainer);
954 }
955
updateInternalHierarchy()956 void CompositedLayerMapping::updateInternalHierarchy()
957 {
958 // m_foregroundLayer has to be inserted in the correct order with child layers,
959 // so it's not inserted here.
960 if (m_ancestorClippingLayer)
961 m_ancestorClippingLayer->removeAllChildren();
962
963 m_graphicsLayer->removeFromParent();
964
965 if (m_ancestorClippingLayer)
966 m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
967
968 if (m_childContainmentLayer)
969 m_graphicsLayer->addChild(m_childContainmentLayer.get());
970 else if (m_childTransformLayer)
971 m_graphicsLayer->addChild(m_childTransformLayer.get());
972
973 if (m_scrollingLayer) {
974 GraphicsLayer* superLayer = m_graphicsLayer.get();
975
976 if (m_childContainmentLayer)
977 superLayer = m_childContainmentLayer.get();
978
979 if (m_childTransformLayer)
980 superLayer = m_childTransformLayer.get();
981
982 superLayer->addChild(m_scrollingLayer.get());
983 }
984
985 // The clip for child layers does not include space for overflow controls, so they exist as
986 // siblings of the clipping layer if we have one. Normal children of this layer are set as
987 // children of the clipping layer.
988 if (m_layerForHorizontalScrollbar)
989 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
990 if (m_layerForVerticalScrollbar)
991 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
992 if (m_layerForScrollCorner)
993 m_graphicsLayer->addChild(m_layerForScrollCorner.get());
994
995 // The squashing containment layer, if it exists, becomes a no-op parent.
996 if (m_squashingLayer) {
997 ASSERT(compositor()->layerSquashingEnabled());
998 ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) || (!m_ancestorClippingLayer && m_squashingContainmentLayer));
999
1000 if (m_squashingContainmentLayer) {
1001 m_squashingContainmentLayer->removeAllChildren();
1002 m_squashingContainmentLayer->addChild(m_graphicsLayer.get());
1003 m_squashingContainmentLayer->addChild(m_squashingLayer.get());
1004 } else {
1005 // The ancestor clipping layer is already set up and has m_graphicsLayer under it.
1006 m_ancestorClippingLayer->addChild(m_squashingLayer.get());
1007 }
1008 }
1009 }
1010
updatePaintingPhases()1011 void CompositedLayerMapping::updatePaintingPhases()
1012 {
1013 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
1014 if (m_scrollingContentsLayer) {
1015 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
1016 if (!m_foregroundLayer)
1017 paintPhase |= GraphicsLayerPaintForeground;
1018 m_scrollingContentsLayer->setPaintingPhase(paintPhase);
1019 m_scrollingBlockSelectionLayer->setPaintingPhase(paintPhase);
1020 }
1021 }
1022
updateContentsRect()1023 void CompositedLayerMapping::updateContentsRect()
1024 {
1025 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox()));
1026 }
1027
updateScrollingBlockSelection()1028 void CompositedLayerMapping::updateScrollingBlockSelection()
1029 {
1030 if (!m_scrollingBlockSelectionLayer)
1031 return;
1032
1033 if (!m_scrollingContentsAreEmpty) {
1034 // In this case, the selection will be painted directly into m_scrollingContentsLayer.
1035 m_scrollingBlockSelectionLayer->setDrawsContent(false);
1036 return;
1037 }
1038
1039 const IntRect blockSelectionGapsBounds = m_owningLayer.blockSelectionGapsBounds();
1040 const bool shouldDrawContent = !blockSelectionGapsBounds.isEmpty();
1041 m_scrollingBlockSelectionLayer->setDrawsContent(shouldDrawContent);
1042 if (!shouldDrawContent)
1043 return;
1044
1045 const IntPoint position = blockSelectionGapsBounds.location() + m_owningLayer.scrollableArea()->adjustedScrollOffset();
1046 if (m_scrollingBlockSelectionLayer->size() == blockSelectionGapsBounds.size() && m_scrollingBlockSelectionLayer->position() == position)
1047 return;
1048
1049 m_scrollingBlockSelectionLayer->setPosition(position);
1050 m_scrollingBlockSelectionLayer->setSize(blockSelectionGapsBounds.size());
1051 m_scrollingBlockSelectionLayer->setOffsetFromRenderer(toIntSize(blockSelectionGapsBounds.location()), GraphicsLayer::SetNeedsDisplay);
1052 }
1053
updateDrawsContent()1054 void CompositedLayerMapping::updateDrawsContent()
1055 {
1056 if (m_scrollingLayer) {
1057 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
1058 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
1059 // m_scrollingLayer never has backing store.
1060 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
1061 bool hasNonScrollingPaintedContent = m_owningLayer.hasVisibleContent() && m_owningLayer.hasBoxDecorationsOrBackground();
1062 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
1063
1064 m_scrollingContentsAreEmpty = !m_owningLayer.hasVisibleContent() || !(renderer()->hasBackground() || paintsChildren());
1065 m_scrollingContentsLayer->setDrawsContent(!m_scrollingContentsAreEmpty);
1066
1067 updateScrollingBlockSelection();
1068 return;
1069 }
1070
1071 bool hasPaintedContent = containsPaintedContent();
1072 if (hasPaintedContent && isAcceleratedCanvas(renderer())) {
1073 CanvasRenderingContext* context = toHTMLCanvasElement(renderer()->node())->renderingContext();
1074 // Content layer may be null if context is lost.
1075 if (blink::WebLayer* contentLayer = context->platformLayer()) {
1076 Color bgColor(Color::transparent);
1077 if (contentLayerSupportsDirectBackgroundComposition(renderer())) {
1078 bgColor = rendererBackgroundColor();
1079 hasPaintedContent = false;
1080 }
1081 contentLayer->setBackgroundColor(bgColor.rgb());
1082 }
1083 }
1084
1085 // FIXME: we could refine this to only allocate backings for one of these layers if possible.
1086 m_graphicsLayer->setDrawsContent(hasPaintedContent);
1087 if (m_foregroundLayer)
1088 m_foregroundLayer->setDrawsContent(hasPaintedContent);
1089
1090 if (m_backgroundLayer)
1091 m_backgroundLayer->setDrawsContent(hasPaintedContent);
1092 }
1093
updateChildrenTransform()1094 void CompositedLayerMapping::updateChildrenTransform()
1095 {
1096 if (GraphicsLayer* childTransformLayer = layerForChildrenTransform()) {
1097 childTransformLayer->setTransform(owningLayer().perspectiveTransform());
1098 childTransformLayer->setTransformOrigin(FloatPoint3D(childTransformLayer->size().width() * 0.5f, childTransformLayer->size().height() * 0.5f, 0.f));
1099 bool hasPerspective = false;
1100 if (RenderStyle* style = m_owningLayer.renderer()->style())
1101 hasPerspective = style->hasPerspective();
1102 if (hasPerspective)
1103 childTransformLayer->setShouldFlattenTransform(false);
1104
1105 // Note, if the target is the scrolling layer, we need to ensure that the
1106 // scrolling content layer doesn't flatten the transform. (It would be nice
1107 // if we could apply transform to the scrolling content layer, but that's
1108 // too late, we need the children transform to be applied _before_ the
1109 // scrolling offset.)
1110 if (childTransformLayer == m_scrollingLayer.get())
1111 m_scrollingContentsLayer->setShouldFlattenTransform(false);
1112 }
1113 }
1114
1115 // Return true if the layers changed.
updateClippingLayers(bool needsAncestorClip,bool needsDescendantClip)1116 bool CompositedLayerMapping::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
1117 {
1118 bool layersChanged = false;
1119
1120 if (needsAncestorClip) {
1121 if (!m_ancestorClippingLayer) {
1122 m_ancestorClippingLayer = createGraphicsLayer(CompositingReasonLayerForAncestorClip);
1123 m_ancestorClippingLayer->setMasksToBounds(true);
1124 layersChanged = true;
1125 }
1126 } else if (m_ancestorClippingLayer) {
1127 m_ancestorClippingLayer->removeFromParent();
1128 m_ancestorClippingLayer = nullptr;
1129 layersChanged = true;
1130 }
1131
1132 if (needsDescendantClip) {
1133 // We don't need a child containment layer if we're the main frame render view
1134 // layer. It's redundant as the frame clip above us will handle this clipping.
1135 if (!m_childContainmentLayer && !m_isMainFrameRenderViewLayer) {
1136 m_childContainmentLayer = createGraphicsLayer(CompositingReasonLayerForDescendantClip);
1137 m_childContainmentLayer->setMasksToBounds(true);
1138 layersChanged = true;
1139 }
1140 } else if (hasClippingLayer()) {
1141 m_childContainmentLayer->removeFromParent();
1142 m_childContainmentLayer = nullptr;
1143 layersChanged = true;
1144 }
1145
1146 return layersChanged;
1147 }
1148
updateChildTransformLayer(bool needsChildTransformLayer)1149 bool CompositedLayerMapping::updateChildTransformLayer(bool needsChildTransformLayer)
1150 {
1151 bool layersChanged = false;
1152
1153 if (needsChildTransformLayer) {
1154 if (!m_childTransformLayer) {
1155 m_childTransformLayer = createGraphicsLayer(CompositingReasonLayerForPerspective);
1156 m_childTransformLayer->setDrawsContent(false);
1157 m_childTransformLayer->setShouldFlattenTransform(false);
1158 layersChanged = true;
1159 }
1160 } else if (m_childTransformLayer) {
1161 m_childTransformLayer->removeFromParent();
1162 m_childTransformLayer = nullptr;
1163 layersChanged = true;
1164 }
1165
1166 return layersChanged;
1167 }
1168
setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)1169 void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
1170 {
1171 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
1172 }
1173
1174 // Only a member function so it can call createGraphicsLayer.
toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer> & layer,bool needsLayer,CompositingReasons reason)1175 bool CompositedLayerMapping::toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer>& layer, bool needsLayer, CompositingReasons reason)
1176 {
1177 if (needsLayer == !!layer)
1178 return false;
1179 layer = needsLayer ? createGraphicsLayer(reason) : nullptr;
1180 return true;
1181 }
1182
updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer,bool needsVerticalScrollbarLayer,bool needsScrollCornerLayer)1183 bool CompositedLayerMapping::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
1184 {
1185 bool horizontalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForHorizontalScrollbar, needsHorizontalScrollbarLayer, CompositingReasonLayerForHorizontalScrollbar);
1186 bool verticalScrollbarLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForVerticalScrollbar, needsVerticalScrollbarLayer, CompositingReasonLayerForVerticalScrollbar);
1187 bool scrollCornerLayerChanged = toggleScrollbarLayerIfNeeded(m_layerForScrollCorner, needsScrollCornerLayer, CompositingReasonLayerForScrollCorner);
1188
1189 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1190 if (horizontalScrollbarLayerChanged)
1191 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), HorizontalScrollbar);
1192 if (verticalScrollbarLayerChanged)
1193 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer.scrollableArea(), VerticalScrollbar);
1194 }
1195
1196 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
1197 }
1198
positionOverflowControlsLayers(const IntSize & offsetFromRoot)1199 void CompositedLayerMapping::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
1200 {
1201 IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer() - roundedIntSize(m_owningLayer.subpixelAccumulation());
1202 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1203 Scrollbar* hBar = m_owningLayer.scrollableArea()->horizontalScrollbar();
1204 if (hBar) {
1205 layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1206 layer->setSize(hBar->frameRect().size());
1207 if (layer->hasContentsLayer())
1208 layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
1209 }
1210 layer->setDrawsContent(hBar && !layer->hasContentsLayer());
1211 }
1212
1213 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1214 Scrollbar* vBar = m_owningLayer.scrollableArea()->verticalScrollbar();
1215 if (vBar) {
1216 layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
1217 layer->setSize(vBar->frameRect().size());
1218 if (layer->hasContentsLayer())
1219 layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
1220 }
1221 layer->setDrawsContent(vBar && !layer->hasContentsLayer());
1222 }
1223
1224 if (GraphicsLayer* layer = layerForScrollCorner()) {
1225 const LayoutRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
1226 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
1227 layer->setSize(scrollCornerAndResizer.size());
1228 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
1229 }
1230 }
1231
hasUnpositionedOverflowControlsLayers() const1232 bool CompositedLayerMapping::hasUnpositionedOverflowControlsLayers() const
1233 {
1234 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1235 if (!layer->drawsContent())
1236 return true;
1237 }
1238
1239 if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1240 if (!layer->drawsContent())
1241 return true;
1242 }
1243
1244 if (GraphicsLayer* layer = layerForScrollCorner()) {
1245 if (!layer->drawsContent())
1246 return true;
1247 }
1248
1249 return false;
1250 }
1251
1252 enum ApplyToGraphicsLayersModeFlags {
1253 ApplyToCoreLayers = (1 << 0),
1254 ApplyToSquashingLayer = (1 << 1),
1255 ApplyToScrollbarLayers = (1 << 2),
1256 ApplyToBackgroundLayer = (1 << 3),
1257 ApplyToMaskLayers = (1 << 4),
1258 ApplyToContentLayers = (1 << 5),
1259 ApplyToAllGraphicsLayers = (ApplyToSquashingLayer | ApplyToScrollbarLayers | ApplyToBackgroundLayer | ApplyToMaskLayers | ApplyToCoreLayers | ApplyToContentLayers)
1260 };
1261 typedef unsigned ApplyToGraphicsLayersMode;
1262
1263 template <typename Func>
ApplyToGraphicsLayers(const CompositedLayerMapping * mapping,const Func & f,ApplyToGraphicsLayersMode mode)1264 static void ApplyToGraphicsLayers(const CompositedLayerMapping* mapping, const Func& f, ApplyToGraphicsLayersMode mode)
1265 {
1266 ASSERT(mode);
1267
1268 if ((mode & ApplyToCoreLayers) && mapping->squashingContainmentLayer())
1269 f(mapping->squashingContainmentLayer());
1270 if ((mode & ApplyToCoreLayers) && mapping->childTransformLayer())
1271 f(mapping->childTransformLayer());
1272 if ((mode & ApplyToCoreLayers) && mapping->ancestorClippingLayer())
1273 f(mapping->ancestorClippingLayer());
1274 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->mainGraphicsLayer())
1275 f(mapping->mainGraphicsLayer());
1276 if ((mode & ApplyToCoreLayers) && mapping->clippingLayer())
1277 f(mapping->clippingLayer());
1278 if ((mode & ApplyToCoreLayers) && mapping->scrollingLayer())
1279 f(mapping->scrollingLayer());
1280 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->scrollingContentsLayer())
1281 f(mapping->scrollingContentsLayer());
1282 if (((mode & ApplyToCoreLayers) || (mode & ApplyToContentLayers)) && mapping->foregroundLayer())
1283 f(mapping->foregroundLayer());
1284
1285 if ((mode & ApplyToSquashingLayer) && mapping->squashingLayer())
1286 f(mapping->squashingLayer());
1287
1288 if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->maskLayer())
1289 f(mapping->maskLayer());
1290 if (((mode & ApplyToMaskLayers) || (mode & ApplyToContentLayers)) && mapping->childClippingMaskLayer())
1291 f(mapping->childClippingMaskLayer());
1292
1293 if (((mode & ApplyToBackgroundLayer) || (mode & ApplyToContentLayers)) && mapping->backgroundLayer())
1294 f(mapping->backgroundLayer());
1295
1296 if ((mode & ApplyToScrollbarLayers) && mapping->layerForHorizontalScrollbar())
1297 f(mapping->layerForHorizontalScrollbar());
1298 if ((mode & ApplyToScrollbarLayers) && mapping->layerForVerticalScrollbar())
1299 f(mapping->layerForVerticalScrollbar());
1300 if ((mode & ApplyToScrollbarLayers) && mapping->layerForScrollCorner())
1301 f(mapping->layerForScrollCorner());
1302 }
1303
1304 struct UpdateRenderingContextFunctor {
operator ()WebCore::UpdateRenderingContextFunctor1305 void operator() (GraphicsLayer* layer) const { layer->setRenderingContext(renderingContext); }
1306 int renderingContext;
1307 };
1308
updateRenderingContext()1309 void CompositedLayerMapping::updateRenderingContext()
1310 {
1311 // All layers but the squashing layer (which contains 'alien' content) should be included in this
1312 // rendering context.
1313 int id = 0;
1314
1315 // NB, it is illegal at this point to query an ancestor's compositing state. Some compositing
1316 // reasons depend on the compositing state of ancestors. So if we want a rendering context id
1317 // for the context root, we cannot ask for the id of its associated WebLayer now; it may not have
1318 // one yet. We could do a second past after doing the compositing updates to get these ids,
1319 // but this would actually be harmful. We do not want to attach any semantic meaning to
1320 // the context id other than the fact that they group a number of layers together for the
1321 // sake of 3d sorting. So instead we will ask the compositor to vend us an arbitrary, but
1322 // consistent id.
1323 if (RenderLayer* root = m_owningLayer.renderingContextRoot()) {
1324 if (Node* node = root->renderer()->node())
1325 id = static_cast<int>(WTF::PtrHash<Node*>::hash(node));
1326 }
1327
1328 UpdateRenderingContextFunctor functor = { id };
1329 ApplyToGraphicsLayersMode mode = ApplyToAllGraphicsLayers & ~ApplyToSquashingLayer;
1330 ApplyToGraphicsLayers<UpdateRenderingContextFunctor>(this, functor, mode);
1331 }
1332
1333 struct UpdateShouldFlattenTransformFunctor {
operator ()WebCore::UpdateShouldFlattenTransformFunctor1334 void operator() (GraphicsLayer* layer) const { layer->setShouldFlattenTransform(shouldFlatten); }
1335 bool shouldFlatten;
1336 };
1337
updateShouldFlattenTransform()1338 void CompositedLayerMapping::updateShouldFlattenTransform()
1339 {
1340 // All CLM-managed layers that could affect a descendant layer should update their
1341 // should-flatten-transform value (the other layers' transforms don't matter here).
1342 UpdateShouldFlattenTransformFunctor functor = { !m_owningLayer.shouldPreserve3D() };
1343 ApplyToGraphicsLayersMode mode = ApplyToCoreLayers;
1344 ApplyToGraphicsLayers(this, functor, mode);
1345 }
1346
updateForegroundLayer(bool needsForegroundLayer)1347 bool CompositedLayerMapping::updateForegroundLayer(bool needsForegroundLayer)
1348 {
1349 bool layerChanged = false;
1350 if (needsForegroundLayer) {
1351 if (!m_foregroundLayer) {
1352 m_foregroundLayer = createGraphicsLayer(CompositingReasonLayerForForeground);
1353 m_foregroundLayer->setDrawsContent(true);
1354 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
1355 layerChanged = true;
1356 }
1357 } else if (m_foregroundLayer) {
1358 FloatRect repaintRect(FloatPoint(), m_foregroundLayer->size());
1359 m_foregroundLayer->removeFromParent();
1360 m_foregroundLayer = nullptr;
1361 layerChanged = true;
1362 }
1363
1364 return layerChanged;
1365 }
1366
updateBackgroundLayer(bool needsBackgroundLayer)1367 bool CompositedLayerMapping::updateBackgroundLayer(bool needsBackgroundLayer)
1368 {
1369 bool layerChanged = false;
1370 if (needsBackgroundLayer) {
1371 if (!m_backgroundLayer) {
1372 m_backgroundLayer = createGraphicsLayer(CompositingReasonLayerForBackground);
1373 m_backgroundLayer->setDrawsContent(true);
1374 m_backgroundLayer->setTransformOrigin(FloatPoint3D());
1375 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
1376 #if !OS(ANDROID)
1377 m_backgroundLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
1378 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(false);
1379 #endif
1380 layerChanged = true;
1381 }
1382 } else {
1383 if (m_backgroundLayer) {
1384 m_backgroundLayer->removeFromParent();
1385 m_backgroundLayer = nullptr;
1386 #if !OS(ANDROID)
1387 m_graphicsLayer->contentLayer()->setDrawCheckerboardForMissingTiles(true);
1388 #endif
1389 layerChanged = true;
1390 }
1391 }
1392
1393 if (layerChanged && !m_owningLayer.renderer()->documentBeingDestroyed())
1394 compositor()->rootFixedBackgroundsChanged();
1395
1396 return layerChanged;
1397 }
1398
updateMaskLayer(bool needsMaskLayer)1399 bool CompositedLayerMapping::updateMaskLayer(bool needsMaskLayer)
1400 {
1401 bool layerChanged = false;
1402 if (needsMaskLayer) {
1403 if (!m_maskLayer) {
1404 m_maskLayer = createGraphicsLayer(CompositingReasonLayerForMask);
1405 m_maskLayer->setDrawsContent(true);
1406 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
1407 layerChanged = true;
1408 }
1409 } else if (m_maskLayer) {
1410 m_maskLayer = nullptr;
1411 layerChanged = true;
1412 }
1413
1414 return layerChanged;
1415 }
1416
updateClippingMaskLayers(bool needsChildClippingMaskLayer)1417 bool CompositedLayerMapping::updateClippingMaskLayers(bool needsChildClippingMaskLayer)
1418 {
1419 bool layerChanged = false;
1420 if (needsChildClippingMaskLayer) {
1421 if (!m_childClippingMaskLayer) {
1422 m_childClippingMaskLayer = createGraphicsLayer(CompositingReasonLayerForClippingMask);
1423 m_childClippingMaskLayer->setDrawsContent(true);
1424 m_childClippingMaskLayer->setPaintingPhase(GraphicsLayerPaintChildClippingMask);
1425 layerChanged = true;
1426 }
1427 } else if (m_childClippingMaskLayer) {
1428 m_childClippingMaskLayer = nullptr;
1429 layerChanged = true;
1430 }
1431 return layerChanged;
1432 }
1433
updateScrollingLayers(bool needsScrollingLayers)1434 bool CompositedLayerMapping::updateScrollingLayers(bool needsScrollingLayers)
1435 {
1436 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
1437
1438 bool layerChanged = false;
1439 if (needsScrollingLayers) {
1440 if (!m_scrollingLayer) {
1441 // Outer layer which corresponds with the scroll view.
1442 m_scrollingLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContainer);
1443 m_scrollingLayer->setDrawsContent(false);
1444 m_scrollingLayer->setMasksToBounds(true);
1445
1446 // Inner layer which renders the content that scrolls.
1447 m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContents);
1448 m_scrollingContentsLayer->setDrawsContent(true);
1449 m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
1450
1451 m_scrollingBlockSelectionLayer = createGraphicsLayer(CompositingReasonLayerForScrollingBlockSelection);
1452 m_scrollingBlockSelectionLayer->setDrawsContent(true);
1453 m_scrollingContentsLayer->addChild(m_scrollingBlockSelectionLayer.get());
1454
1455 layerChanged = true;
1456 if (scrollingCoordinator)
1457 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
1458 }
1459 } else if (m_scrollingLayer) {
1460 m_scrollingLayer = nullptr;
1461 m_scrollingContentsLayer = nullptr;
1462 m_scrollingBlockSelectionLayer = nullptr;
1463 layerChanged = true;
1464 if (scrollingCoordinator)
1465 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer.scrollableArea());
1466 }
1467
1468 return layerChanged;
1469 }
1470
updateScrollParentForGraphicsLayer(GraphicsLayer * layer,GraphicsLayer * topmostLayer,RenderLayer * scrollParent,ScrollingCoordinator * scrollingCoordinator)1471 static void updateScrollParentForGraphicsLayer(GraphicsLayer* layer, GraphicsLayer* topmostLayer, RenderLayer* scrollParent, ScrollingCoordinator* scrollingCoordinator)
1472 {
1473 if (!layer)
1474 return;
1475
1476 // Only the topmost layer has a scroll parent. All other layers have a null scroll parent.
1477 if (layer != topmostLayer)
1478 scrollParent = 0;
1479
1480 scrollingCoordinator->updateScrollParentForGraphicsLayer(layer, scrollParent);
1481 }
1482
updateScrollParent(RenderLayer * scrollParent)1483 void CompositedLayerMapping::updateScrollParent(RenderLayer* scrollParent)
1484 {
1485 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
1486 GraphicsLayer* topmostLayer = childForSuperlayers();
1487 updateScrollParentForGraphicsLayer(m_squashingContainmentLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1488 updateScrollParentForGraphicsLayer(m_ancestorClippingLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1489 updateScrollParentForGraphicsLayer(m_graphicsLayer.get(), topmostLayer, scrollParent, scrollingCoordinator);
1490 }
1491 }
1492
updateClipParent(RenderLayer * clipParent)1493 void CompositedLayerMapping::updateClipParent(RenderLayer* clipParent)
1494 {
1495 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer))
1496 scrollingCoordinator->updateClipParentForGraphicsLayer(m_graphicsLayer.get(), clipParent);
1497 }
1498
updateSquashingLayers(bool needsSquashingLayers)1499 bool CompositedLayerMapping::updateSquashingLayers(bool needsSquashingLayers)
1500 {
1501 bool layersChanged = false;
1502
1503 if (needsSquashingLayers) {
1504 ASSERT(compositor()->layerSquashingEnabled());
1505
1506 if (!m_squashingLayer) {
1507 m_squashingLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContents);
1508 m_squashingLayer->setDrawsContent(true);
1509 layersChanged = true;
1510 }
1511
1512 if (m_ancestorClippingLayer) {
1513 if (m_squashingContainmentLayer) {
1514 m_squashingContainmentLayer->removeFromParent();
1515 m_squashingContainmentLayer = nullptr;
1516 layersChanged = true;
1517 }
1518 } else {
1519 if (!m_squashingContainmentLayer) {
1520 m_squashingContainmentLayer = createGraphicsLayer(CompositingReasonLayerForSquashingContainer);
1521 layersChanged = true;
1522 }
1523 }
1524
1525 ASSERT((m_ancestorClippingLayer && !m_squashingContainmentLayer) || (!m_ancestorClippingLayer && m_squashingContainmentLayer));
1526 ASSERT(m_squashingLayer);
1527 } else {
1528 if (m_squashingLayer) {
1529 m_squashingLayer->removeFromParent();
1530 m_squashingLayer = nullptr;
1531 layersChanged = true;
1532 }
1533 if (m_squashingContainmentLayer) {
1534 m_squashingContainmentLayer->removeFromParent();
1535 m_squashingContainmentLayer = nullptr;
1536 layersChanged = true;
1537 }
1538 ASSERT(!m_squashingLayer && !m_squashingContainmentLayer);
1539 }
1540
1541 return layersChanged;
1542 }
1543
paintingPhaseForPrimaryLayer() const1544 GraphicsLayerPaintingPhase CompositedLayerMapping::paintingPhaseForPrimaryLayer() const
1545 {
1546 unsigned phase = 0;
1547 if (!m_backgroundLayer)
1548 phase |= GraphicsLayerPaintBackground;
1549 if (!m_foregroundLayer)
1550 phase |= GraphicsLayerPaintForeground;
1551 if (!m_maskLayer)
1552 phase |= GraphicsLayerPaintMask;
1553
1554 if (m_scrollingContentsLayer) {
1555 phase &= ~GraphicsLayerPaintForeground;
1556 phase |= GraphicsLayerPaintCompositedScroll;
1557 }
1558
1559 return static_cast<GraphicsLayerPaintingPhase>(phase);
1560 }
1561
compositingOpacity(float rendererOpacity) const1562 float CompositedLayerMapping::compositingOpacity(float rendererOpacity) const
1563 {
1564 float finalOpacity = rendererOpacity;
1565
1566 for (RenderLayer* curr = m_owningLayer.parent(); curr; curr = curr->parent()) {
1567 // We only care about parents that are stacking contexts.
1568 // Recall that opacity creates stacking context.
1569 if (!curr->stackingNode()->isStackingContext())
1570 continue;
1571
1572 // If we found a composited layer, regardless of whether it actually
1573 // paints into it, we want to compute opacity relative to it. So we can
1574 // break here.
1575 //
1576 // FIXME: with grouped backings, a composited descendant will have to
1577 // continue past the grouped (squashed) layers that its parents may
1578 // contribute to. This whole confusion can be avoided by specifying
1579 // explicitly the composited ancestor where we would stop accumulating
1580 // opacity.
1581 if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == HasOwnBackingButPaintsIntoAncestor)
1582 break;
1583
1584 finalOpacity *= curr->renderer()->opacity();
1585 }
1586
1587 return finalOpacity;
1588 }
1589
rendererBackgroundColor() const1590 Color CompositedLayerMapping::rendererBackgroundColor() const
1591 {
1592 RenderObject* backgroundRenderer = renderer();
1593 if (backgroundRenderer->isDocumentElement())
1594 backgroundRenderer = backgroundRenderer->rendererForRootBackground();
1595
1596 return backgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
1597 }
1598
updateBackgroundColor()1599 void CompositedLayerMapping::updateBackgroundColor()
1600 {
1601 m_graphicsLayer->setBackgroundColor(rendererBackgroundColor());
1602 }
1603
paintsChildren() const1604 bool CompositedLayerMapping::paintsChildren() const
1605 {
1606 if (m_owningLayer.hasVisibleContent() && m_owningLayer.hasNonEmptyChildRenderers())
1607 return true;
1608
1609 if (hasVisibleNonCompositingDescendant(&m_owningLayer))
1610 return true;
1611
1612 return false;
1613 }
1614
isCompositedPlugin(RenderObject * renderer)1615 static bool isCompositedPlugin(RenderObject* renderer)
1616 {
1617 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing();
1618 }
1619
hasVisibleNonCompositingDescendant(RenderLayer * parent)1620 bool CompositedLayerMapping::hasVisibleNonCompositingDescendant(RenderLayer* parent)
1621 {
1622 if (!parent->hasVisibleDescendant())
1623 return false;
1624
1625 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
1626 parent->stackingNode()->updateLayerListsIfNeeded();
1627
1628 #if ASSERT_ENABLED
1629 LayerListMutationDetector mutationChecker(parent->stackingNode());
1630 #endif
1631
1632 RenderLayerStackingNodeIterator normalFlowIterator(*parent->stackingNode(), AllChildren);
1633 while (RenderLayerStackingNode* curNode = normalFlowIterator.next()) {
1634 RenderLayer* curLayer = curNode->layer();
1635 if (curLayer->hasCompositedLayerMapping())
1636 continue;
1637 if (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))
1638 return true;
1639 }
1640
1641 return false;
1642 }
1643
containsPaintedContent() const1644 bool CompositedLayerMapping::containsPaintedContent() const
1645 {
1646 if (paintsIntoCompositedAncestor() || m_owningLayer.isReflection())
1647 return false;
1648
1649 if (isDirectlyCompositedImage())
1650 return false;
1651
1652 RenderObject* renderObject = renderer();
1653 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
1654 // and set background color on the layer in that case, instead of allocating backing store and painting.
1655 if (renderObject->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
1656 return m_owningLayer.hasBoxDecorationsOrBackground();
1657
1658 if (m_owningLayer.hasVisibleBoxDecorations())
1659 return true;
1660
1661 if (renderObject->hasMask()) // masks require special treatment
1662 return true;
1663
1664 if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
1665 return true;
1666
1667 if (renderObject->isRenderRegion())
1668 return true;
1669
1670 if (renderObject->node() && renderObject->node()->isDocumentNode()) {
1671 // Look to see if the root object has a non-simple background
1672 RenderObject* rootObject = renderObject->document().documentElement() ? renderObject->document().documentElement()->renderer() : 0;
1673 // Reject anything that has a border, a border-radius or outline,
1674 // or is not a simple background (no background, or solid color).
1675 if (rootObject && hasBoxDecorationsOrBackgroundImage(rootObject->style()))
1676 return true;
1677
1678 // Now look at the body's renderer.
1679 HTMLElement* body = renderObject->document().body();
1680 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
1681 if (bodyObject && hasBoxDecorationsOrBackgroundImage(bodyObject->style()))
1682 return true;
1683 }
1684
1685 // FIXME: it's O(n^2). A better solution is needed.
1686 return paintsChildren();
1687 }
1688
1689 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
1690 // that require painting. Direct compositing saves backing store.
isDirectlyCompositedImage() const1691 bool CompositedLayerMapping::isDirectlyCompositedImage() const
1692 {
1693 RenderObject* renderObject = renderer();
1694
1695 if (!renderObject->isImage() || m_owningLayer.hasBoxDecorationsOrBackground() || renderObject->hasClip())
1696 return false;
1697
1698 RenderImage* imageRenderer = toRenderImage(renderObject);
1699 if (ImageResource* cachedImage = imageRenderer->cachedImage()) {
1700 if (!cachedImage->hasImage())
1701 return false;
1702
1703 Image* image = cachedImage->imageForRenderer(imageRenderer);
1704 return image->isBitmapImage();
1705 }
1706
1707 return false;
1708 }
1709
contentChanged(ContentChangeType changeType)1710 void CompositedLayerMapping::contentChanged(ContentChangeType changeType)
1711 {
1712 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
1713 updateImageContents();
1714 return;
1715 }
1716
1717 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
1718 m_graphicsLayer->setContentsNeedsDisplay();
1719 return;
1720 }
1721 }
1722
updateImageContents()1723 void CompositedLayerMapping::updateImageContents()
1724 {
1725 ASSERT(renderer()->isImage());
1726 RenderImage* imageRenderer = toRenderImage(renderer());
1727
1728 ImageResource* cachedImage = imageRenderer->cachedImage();
1729 if (!cachedImage)
1730 return;
1731
1732 Image* image = cachedImage->imageForRenderer(imageRenderer);
1733 if (!image)
1734 return;
1735
1736 // We have to wait until the image is fully loaded before setting it on the layer.
1737 if (!cachedImage->isLoaded())
1738 return;
1739
1740 // This is a no-op if the layer doesn't have an inner layer for the image.
1741 m_graphicsLayer->setContentsToImage(image);
1742 updateDrawsContent();
1743
1744 // Image animation is "lazy", in that it automatically stops unless someone is drawing
1745 // the image. So we have to kick the animation each time; this has the downside that the
1746 // image will keep animating, even if its layer is not visible.
1747 image->startAnimation();
1748 }
1749
computeTransformOrigin(const IntRect & borderBox) const1750 FloatPoint3D CompositedLayerMapping::computeTransformOrigin(const IntRect& borderBox) const
1751 {
1752 RenderStyle* style = renderer()->style();
1753
1754 FloatPoint3D origin;
1755 origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
1756 origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
1757 origin.setZ(style->transformOriginZ());
1758
1759 return origin;
1760 }
1761
1762 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
contentOffsetInCompositingLayer() const1763 LayoutSize CompositedLayerMapping::contentOffsetInCompositingLayer() const
1764 {
1765 return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1766 }
1767
contentsBox() const1768 LayoutRect CompositedLayerMapping::contentsBox() const
1769 {
1770 LayoutRect contentsBox = contentsRect(renderer());
1771 contentsBox.move(contentOffsetInCompositingLayer());
1772 return contentsBox;
1773 }
1774
parentForSublayers() const1775 GraphicsLayer* CompositedLayerMapping::parentForSublayers() const
1776 {
1777 if (m_scrollingBlockSelectionLayer)
1778 return m_scrollingBlockSelectionLayer.get();
1779
1780 if (m_scrollingContentsLayer)
1781 return m_scrollingContentsLayer.get();
1782
1783 if (m_childContainmentLayer)
1784 return m_childContainmentLayer.get();
1785
1786 if (m_childTransformLayer)
1787 return m_childTransformLayer.get();
1788
1789 return m_graphicsLayer.get();
1790 }
1791
localRootForOwningLayer() const1792 GraphicsLayer* CompositedLayerMapping::localRootForOwningLayer() const
1793 {
1794 if (m_ancestorClippingLayer)
1795 return m_ancestorClippingLayer.get();
1796
1797 return m_graphicsLayer.get();
1798 }
1799
childForSuperlayers() const1800 GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const
1801 {
1802 if (m_squashingContainmentLayer)
1803 return m_squashingContainmentLayer.get();
1804
1805 return localRootForOwningLayer();
1806 }
1807
layerForChildrenTransform() const1808 GraphicsLayer* CompositedLayerMapping::layerForChildrenTransform() const
1809 {
1810 if (GraphicsLayer* clipLayer = clippingLayer())
1811 return clipLayer;
1812 if (m_scrollingLayer)
1813 return m_scrollingLayer.get();
1814 return m_childTransformLayer.get();
1815 }
1816
updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer * compositingAncestorLayer)1817 bool CompositedLayerMapping::updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer* compositingAncestorLayer)
1818 {
1819 unsigned previousRequiresOwnBackingStoreForAncestorReasons = m_requiresOwnBackingStoreForAncestorReasons;
1820 bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
1821 bool canPaintIntoAncestor = compositingAncestorLayer
1822 && (compositingAncestorLayer->compositedLayerMapping()->mainGraphicsLayer()->drawsContent()
1823 || compositingAncestorLayer->compositedLayerMapping()->paintsIntoCompositedAncestor());
1824 m_requiresOwnBackingStoreForAncestorReasons = !canPaintIntoAncestor;
1825
1826 if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
1827 paintsIntoCompositedAncestorChanged();
1828 return m_requiresOwnBackingStoreForAncestorReasons != previousRequiresOwnBackingStoreForAncestorReasons;
1829 }
1830
updateRequiresOwnBackingStoreForIntrinsicReasons()1831 bool CompositedLayerMapping::updateRequiresOwnBackingStoreForIntrinsicReasons()
1832 {
1833 unsigned previousRequiresOwnBackingStoreForIntrinsicReasons = m_requiresOwnBackingStoreForIntrinsicReasons;
1834 bool previousPaintsIntoCompositedAncestor = paintsIntoCompositedAncestor();
1835 RenderObject* renderer = m_owningLayer.renderer();
1836 m_requiresOwnBackingStoreForIntrinsicReasons = m_owningLayer.isRootLayer()
1837 || (m_owningLayer.compositingReasons() & CompositingReasonComboReasonsThatRequireOwnBacking)
1838 || m_owningLayer.transform()
1839 || m_owningLayer.clipsCompositingDescendantsWithBorderRadius() // FIXME: Revisit this if the paintsIntoCompositedAncestor state is removed.
1840 || renderer->isTransparent()
1841 || renderer->hasMask()
1842 || renderer->hasReflection()
1843 || renderer->hasFilter();
1844
1845 if (paintsIntoCompositedAncestor() != previousPaintsIntoCompositedAncestor)
1846 paintsIntoCompositedAncestorChanged();
1847 return m_requiresOwnBackingStoreForIntrinsicReasons != previousRequiresOwnBackingStoreForIntrinsicReasons;
1848 }
1849
paintsIntoCompositedAncestorChanged()1850 void CompositedLayerMapping::paintsIntoCompositedAncestorChanged()
1851 {
1852 // The answer to paintsIntoCompositedAncestor() affects cached clip rects, so when
1853 // it changes we have to clear clip rects on descendants.
1854 m_owningLayer.clipper().clearClipRectsIncludingDescendants(PaintingClipRects);
1855 m_owningLayer.repainter().computeRepaintRectsIncludingNonCompositingDescendants();
1856
1857 compositor()->repaintInCompositedAncestor(&m_owningLayer, compositedBounds());
1858 }
1859
setBlendMode(blink::WebBlendMode blendMode)1860 void CompositedLayerMapping::setBlendMode(blink::WebBlendMode blendMode)
1861 {
1862 if (m_ancestorClippingLayer) {
1863 m_ancestorClippingLayer->setBlendMode(blendMode);
1864 m_graphicsLayer->setBlendMode(blink::WebBlendModeNormal);
1865 } else {
1866 m_graphicsLayer->setBlendMode(blendMode);
1867 }
1868 }
1869
updateTypeForChildren(GraphicsLayerUpdater::UpdateType updateType) const1870 GraphicsLayerUpdater::UpdateType CompositedLayerMapping::updateTypeForChildren(GraphicsLayerUpdater::UpdateType updateType) const
1871 {
1872 if (m_pendingUpdateScope >= GraphicsLayerUpdateSubtree)
1873 return GraphicsLayerUpdater::ForceUpdate;
1874 return updateType;
1875 }
1876
1877 struct SetContentsNeedsDisplayFunctor {
operator ()WebCore::SetContentsNeedsDisplayFunctor1878 void operator() (GraphicsLayer* layer) const
1879 {
1880 if (layer->drawsContent())
1881 layer->setNeedsDisplay();
1882 }
1883 };
1884
setSquashingContentsNeedDisplay()1885 void CompositedLayerMapping::setSquashingContentsNeedDisplay()
1886 {
1887 ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToSquashingLayer);
1888 }
1889
setContentsNeedDisplay()1890 void CompositedLayerMapping::setContentsNeedDisplay()
1891 {
1892 // FIXME: need to split out repaints for the background.
1893 ASSERT(!paintsIntoCompositedAncestor());
1894 ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToContentLayers);
1895 }
1896
1897 struct SetContentsNeedsDisplayInRectFunctor {
operator ()WebCore::SetContentsNeedsDisplayInRectFunctor1898 void operator() (GraphicsLayer* layer) const
1899 {
1900 if (layer->drawsContent()) {
1901 IntRect layerDirtyRect = r;
1902 layerDirtyRect.move(-layer->offsetFromRenderer());
1903 layer->setNeedsDisplayInRect(layerDirtyRect);
1904 }
1905 }
1906
1907 IntRect r;
1908 };
1909
1910 // r is in the coordinate space of the layer's render object
setContentsNeedDisplayInRect(const IntRect & r)1911 void CompositedLayerMapping::setContentsNeedDisplayInRect(const IntRect& r)
1912 {
1913 // FIXME: need to split out repaints for the background.
1914 ASSERT(!paintsIntoCompositedAncestor());
1915 SetContentsNeedsDisplayInRectFunctor functor = { r };
1916 ApplyToGraphicsLayers(this, functor, ApplyToContentLayers);
1917 }
1918
containingSquashedLayer(const RenderObject * renderObject,const Vector<GraphicsLayerPaintInfo> & layers)1919 const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject, const Vector<GraphicsLayerPaintInfo>& layers)
1920 {
1921 for (size_t i = 0; i < layers.size(); ++i) {
1922 if (renderObject->isDescendantOf(layers[i].renderLayer->renderer())) {
1923 return &layers[i];
1924 break;
1925 }
1926 }
1927 return 0;
1928 }
1929
containingSquashedLayer(const RenderObject * renderObject)1930 const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject)
1931 {
1932 return CompositedLayerMapping::containingSquashedLayer(renderObject, m_squashedLayers);
1933 }
1934
localClipRectForSquashedLayer(const RenderLayer & referenceLayer,const GraphicsLayerPaintInfo & paintInfo,const Vector<GraphicsLayerPaintInfo> & layers)1935 IntRect CompositedLayerMapping::localClipRectForSquashedLayer(const RenderLayer& referenceLayer, const GraphicsLayerPaintInfo& paintInfo, const Vector<GraphicsLayerPaintInfo>& layers)
1936 {
1937 const RenderObject* clippingContainer = paintInfo.renderLayer->renderer()->clippingContainer();
1938 if (clippingContainer == referenceLayer.renderer()->clippingContainer())
1939 return PaintInfo::infiniteRect();
1940
1941 ASSERT(clippingContainer);
1942
1943 const GraphicsLayerPaintInfo* ancestorPaintInfo = containingSquashedLayer(clippingContainer, layers);
1944 // Must be there, otherwise CompositingLayerAssigner::canSquashIntoCurrentSquashingOwner would have disallowed squashing.
1945 ASSERT(ancestorPaintInfo);
1946
1947 // FIXME: this is a potential performance issue. We shoudl consider caching these clip rects or otherwise optimizing.
1948 ClipRectsContext clipRectsContext(ancestorPaintInfo->renderLayer, TemporaryClipRects);
1949 IntRect parentClipRect = pixelSnappedIntRect(paintInfo.renderLayer->clipper().backgroundClipRect(clipRectsContext).rect());
1950 ASSERT(parentClipRect != PaintInfo::infiniteRect());
1951
1952 // Convert from ancestor to local coordinates.
1953 IntSize ancestorToLocalOffset = paintInfo.offsetFromRenderer - ancestorPaintInfo->offsetFromRenderer;
1954 parentClipRect.move(ancestorToLocalOffset);
1955 return parentClipRect;
1956 }
1957
doPaintTask(GraphicsLayerPaintInfo & paintInfo,GraphicsContext * context,const IntRect & clip)1958 void CompositedLayerMapping::doPaintTask(GraphicsLayerPaintInfo& paintInfo, GraphicsContext* context,
1959 const IntRect& clip) // In the coords of rootLayer.
1960 {
1961 if (paintsIntoCompositedAncestor()) {
1962 ASSERT_NOT_REACHED();
1963 return;
1964 }
1965
1966 FontCachePurgePreventer fontCachePurgePreventer;
1967
1968 PaintLayerFlags paintFlags = 0;
1969 if (paintInfo.paintingPhase & GraphicsLayerPaintBackground)
1970 paintFlags |= PaintLayerPaintingCompositingBackgroundPhase;
1971 if (paintInfo.paintingPhase & GraphicsLayerPaintForeground)
1972 paintFlags |= PaintLayerPaintingCompositingForegroundPhase;
1973 if (paintInfo.paintingPhase & GraphicsLayerPaintMask)
1974 paintFlags |= PaintLayerPaintingCompositingMaskPhase;
1975 if (paintInfo.paintingPhase & GraphicsLayerPaintChildClippingMask)
1976 paintFlags |= PaintLayerPaintingChildClippingMaskPhase;
1977 if (paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)
1978 paintFlags |= PaintLayerPaintingOverflowContents;
1979 if (paintInfo.paintingPhase & GraphicsLayerPaintCompositedScroll)
1980 paintFlags |= PaintLayerPaintingCompositingScrollingPhase;
1981
1982 if (paintInfo.isBackgroundLayer)
1983 paintFlags |= (PaintLayerPaintingRootBackgroundOnly | PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
1984 else if (compositor()->fixedRootBackgroundLayer())
1985 paintFlags |= PaintLayerPaintingSkipRootBackground;
1986
1987 // Note carefully: in theory it is appropriate to invoke context->save() here
1988 // and restore the context after painting. For efficiency, we are assuming that
1989 // it is equivalent to manually undo this offset translation, which means we are
1990 // assuming that the context's space was not affected by the RenderLayer
1991 // painting code.
1992
1993 IntSize offset = paintInfo.offsetFromRenderer;
1994 context->translate(-offset.width(), -offset.height());
1995
1996 // The dirtyRect is in the coords of the painting root.
1997 IntRect dirtyRect(clip);
1998 dirtyRect.move(offset);
1999
2000 if (!(paintInfo.paintingPhase & GraphicsLayerPaintOverflowContents)) {
2001 LayoutRect bounds = paintInfo.compositedBounds;
2002 bounds.move(paintInfo.renderLayer->subpixelAccumulation());
2003 dirtyRect.intersect(pixelSnappedIntRect(bounds));
2004 } else {
2005 dirtyRect.move(roundedIntSize(paintInfo.renderLayer->subpixelAccumulation()));
2006 }
2007
2008 #ifndef NDEBUG
2009 paintInfo.renderLayer->renderer()->assertSubtreeIsLaidOut();
2010 #endif
2011
2012 if (paintInfo.renderLayer->compositingState() != PaintsIntoGroupedBacking) {
2013 // FIXME: GraphicsLayers need a way to split for RenderRegions.
2014 LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.renderLayer->subpixelAccumulation());
2015 paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags);
2016
2017 ASSERT(!paintInfo.isBackgroundLayer || paintFlags & PaintLayerPaintingRootBackgroundOnly);
2018
2019 if (paintInfo.renderLayer->containsDirtyOverlayScrollbars())
2020 paintInfo.renderLayer->paintLayerContents(context, paintingInfo, paintFlags | PaintLayerPaintingOverlayScrollbars);
2021 } else {
2022 ASSERT(compositor()->layerSquashingEnabled());
2023 LayerPaintingInfo paintingInfo(paintInfo.renderLayer, dirtyRect, PaintBehaviorNormal, paintInfo.renderLayer->subpixelAccumulation());
2024
2025 // RenderLayer::paintLayer assumes that the caller clips to the passed rect. Squashed layers need to do this clipping in software,
2026 // since there is no graphics layer to clip them precisely. Furthermore, in some cases we squash layers that need clipping in software
2027 // from clipping ancestors (see CompositedLayerMapping::localClipRectForSquashedLayer()).
2028 context->save();
2029 dirtyRect.intersect(paintInfo.localClipRectForSquashedLayer);
2030 context->clip(dirtyRect);
2031 paintInfo.renderLayer->paintLayer(context, paintingInfo, paintFlags);
2032 context->restore();
2033 }
2034
2035 ASSERT(!paintInfo.renderLayer->usedTransparency());
2036
2037 // Manually restore the context to its original state by applying the opposite translation.
2038 context->translate(offset.width(), offset.height());
2039 }
2040
paintScrollbar(Scrollbar * scrollbar,GraphicsContext & context,const IntRect & clip)2041 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
2042 {
2043 if (!scrollbar)
2044 return;
2045
2046 context.save();
2047 const IntRect& scrollbarRect = scrollbar->frameRect();
2048 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
2049 IntRect transformedClip = clip;
2050 transformedClip.moveBy(scrollbarRect.location());
2051 scrollbar->paint(&context, transformedClip);
2052 context.restore();
2053 }
2054
2055 // Up-call from compositing layer drawing callback.
paintContents(const GraphicsLayer * graphicsLayer,GraphicsContext & context,GraphicsLayerPaintingPhase paintingPhase,const IntRect & clip)2056 void CompositedLayerMapping::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
2057 {
2058 // https://code.google.com/p/chromium/issues/detail?id=343772
2059 DisableCompositingQueryAsserts disabler;
2060 #ifndef NDEBUG
2061 // FIXME: once the state machine is ready, this can be removed and we can refer to that instead.
2062 if (Page* page = renderer()->frame()->page())
2063 page->setIsPainting(true);
2064 #endif
2065 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(m_owningLayer.renderer(), clip, graphicsLayer));
2066 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
2067 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
2068 InspectorInstrumentation::willPaint(m_owningLayer.renderer(), graphicsLayer);
2069
2070 if (graphicsLayer == m_graphicsLayer.get()
2071 || graphicsLayer == m_foregroundLayer.get()
2072 || graphicsLayer == m_backgroundLayer.get()
2073 || graphicsLayer == m_maskLayer.get()
2074 || graphicsLayer == m_childClippingMaskLayer.get()
2075 || graphicsLayer == m_scrollingContentsLayer.get()
2076 || graphicsLayer == m_scrollingBlockSelectionLayer.get()) {
2077
2078 GraphicsLayerPaintInfo paintInfo;
2079 paintInfo.renderLayer = &m_owningLayer;
2080 paintInfo.compositedBounds = compositedBounds();
2081 paintInfo.offsetFromRenderer = graphicsLayer->offsetFromRenderer();
2082 paintInfo.paintingPhase = paintingPhase;
2083 paintInfo.isBackgroundLayer = (graphicsLayer == m_backgroundLayer);
2084
2085 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
2086 doPaintTask(paintInfo, &context, clip);
2087 } else if (graphicsLayer == m_squashingLayer.get()) {
2088 ASSERT(compositor()->layerSquashingEnabled());
2089 for (size_t i = 0; i < m_squashedLayers.size(); ++i)
2090 doPaintTask(m_squashedLayers[i], &context, clip);
2091 } else if (graphicsLayer == layerForHorizontalScrollbar()) {
2092 paintScrollbar(m_owningLayer.scrollableArea()->horizontalScrollbar(), context, clip);
2093 } else if (graphicsLayer == layerForVerticalScrollbar()) {
2094 paintScrollbar(m_owningLayer.scrollableArea()->verticalScrollbar(), context, clip);
2095 } else if (graphicsLayer == layerForScrollCorner()) {
2096 const IntRect& scrollCornerAndResizer = m_owningLayer.scrollableArea()->scrollCornerAndResizerRect();
2097 context.save();
2098 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
2099 IntRect transformedClip = clip;
2100 transformedClip.moveBy(scrollCornerAndResizer.location());
2101 m_owningLayer.scrollableArea()->paintScrollCorner(&context, IntPoint(), transformedClip);
2102 m_owningLayer.scrollableArea()->paintResizer(&context, IntPoint(), transformedClip);
2103 context.restore();
2104 }
2105 InspectorInstrumentation::didPaint(m_owningLayer.renderer(), graphicsLayer, &context, clip);
2106 #ifndef NDEBUG
2107 if (Page* page = renderer()->frame()->page())
2108 page->setIsPainting(false);
2109 #endif
2110 }
2111
isTrackingRepaints() const2112 bool CompositedLayerMapping::isTrackingRepaints() const
2113 {
2114 GraphicsLayerClient* client = compositor();
2115 return client ? client->isTrackingRepaints() : false;
2116 }
2117
2118 struct CollectTrackedRepaintRectsFunctor {
operator ()WebCore::CollectTrackedRepaintRectsFunctor2119 void operator() (GraphicsLayer* layer) const { layer->collectTrackedRepaintRects(*rects); }
2120 Vector<FloatRect>* rects;
2121 };
2122
collectTrackedRepaintRects() const2123 PassOwnPtr<Vector<FloatRect> > CompositedLayerMapping::collectTrackedRepaintRects() const
2124 {
2125 OwnPtr<Vector<FloatRect> > rects = adoptPtr(new Vector<FloatRect>);
2126 CollectTrackedRepaintRectsFunctor functor = { rects.get() };
2127 ApplyToGraphicsLayers(this, functor, ApplyToAllGraphicsLayers);
2128 return rects.release();
2129 }
2130
2131 #ifndef NDEBUG
verifyNotPainting()2132 void CompositedLayerMapping::verifyNotPainting()
2133 {
2134 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
2135 }
2136 #endif
2137
notifyAnimationStarted(const GraphicsLayer *,double monotonicTime)2138 void CompositedLayerMapping::notifyAnimationStarted(const GraphicsLayer*, double monotonicTime)
2139 {
2140 renderer()->node()->document().compositorPendingAnimations().notifyCompositorAnimationStarted(monotonicTime);
2141 }
2142
pixelSnappedCompositedBounds() const2143 IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const
2144 {
2145 LayoutRect bounds = m_compositedBounds;
2146 bounds.move(m_owningLayer.subpixelAccumulation());
2147 return pixelSnappedIntRect(bounds);
2148 }
2149
updateSquashingLayerAssignment(RenderLayer * squashedLayer,const RenderLayer & owningLayer,size_t nextSquashedLayerIndex)2150 bool CompositedLayerMapping::updateSquashingLayerAssignment(RenderLayer* squashedLayer, const RenderLayer& owningLayer, size_t nextSquashedLayerIndex)
2151 {
2152 ASSERT(compositor()->layerSquashingEnabled());
2153
2154 GraphicsLayerPaintInfo paintInfo;
2155 paintInfo.renderLayer = squashedLayer;
2156 // NOTE: composited bounds are updated elsewhere
2157 // NOTE: offsetFromRenderer is updated elsewhere
2158 paintInfo.paintingPhase = GraphicsLayerPaintAllWithOverflowClip;
2159 paintInfo.isBackgroundLayer = false;
2160
2161 // Change tracking on squashing layers: at the first sign of something changed, just invalidate the layer.
2162 // FIXME: Perhaps we can find a tighter more clever mechanism later.
2163 bool updatedAssignment = false;
2164 if (nextSquashedLayerIndex < m_squashedLayers.size()) {
2165 if (!paintInfo.isEquivalentForSquashing(m_squashedLayers[nextSquashedLayerIndex])) {
2166 compositor()->repaintOnCompositingChange(squashedLayer);
2167 updatedAssignment = true;
2168 m_squashedLayers[nextSquashedLayerIndex] = paintInfo;
2169 }
2170 } else {
2171 compositor()->repaintOnCompositingChange(squashedLayer);
2172 m_squashedLayers.append(paintInfo);
2173 updatedAssignment = true;
2174 }
2175 squashedLayer->setGroupedMapping(this);
2176 return updatedAssignment;
2177 }
2178
removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer * layer)2179 void CompositedLayerMapping::removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer* layer)
2180 {
2181 size_t layerIndex = kNotFound;
2182
2183 for (size_t i = 0; i < m_squashedLayers.size(); ++i) {
2184 if (m_squashedLayers[i].renderLayer == layer) {
2185 layerIndex = i;
2186 break;
2187 }
2188 }
2189
2190 if (layerIndex == kNotFound)
2191 return;
2192
2193 m_squashedLayers.remove(layerIndex);
2194 }
2195
finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex)2196 void CompositedLayerMapping::finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex)
2197 {
2198 ASSERT(compositor()->layerSquashingEnabled());
2199
2200 // Any additional squashed RenderLayers in the array no longer exist, and removing invalidates the squashingLayer contents.
2201 if (nextSquashedLayerIndex < m_squashedLayers.size())
2202 m_squashedLayers.remove(nextSquashedLayerIndex, m_squashedLayers.size() - nextSquashedLayerIndex);
2203 }
2204
debugName(const GraphicsLayer * graphicsLayer)2205 String CompositedLayerMapping::debugName(const GraphicsLayer* graphicsLayer)
2206 {
2207 String name;
2208 if (graphicsLayer == m_graphicsLayer.get()) {
2209 name = m_owningLayer.debugName();
2210 } else if (graphicsLayer == m_squashingContainmentLayer.get()) {
2211 name = "Squashing Containment Layer";
2212 } else if (graphicsLayer == m_squashingLayer.get()) {
2213 name = "Squashing Layer";
2214 } else if (graphicsLayer == m_ancestorClippingLayer.get()) {
2215 name = "Ancestor Clipping Layer";
2216 } else if (graphicsLayer == m_foregroundLayer.get()) {
2217 name = m_owningLayer.debugName() + " (foreground) Layer";
2218 } else if (graphicsLayer == m_backgroundLayer.get()) {
2219 name = m_owningLayer.debugName() + " (background) Layer";
2220 } else if (graphicsLayer == m_childContainmentLayer.get()) {
2221 name = "Child Containment Layer";
2222 } else if (graphicsLayer == m_childTransformLayer.get()) {
2223 name = "Child Transform Layer";
2224 } else if (graphicsLayer == m_maskLayer.get()) {
2225 name = "Mask Layer";
2226 } else if (graphicsLayer == m_childClippingMaskLayer.get()) {
2227 name = "Child Clipping Mask Layer";
2228 } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) {
2229 name = "Horizontal Scrollbar Layer";
2230 } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) {
2231 name = "Vertical Scrollbar Layer";
2232 } else if (graphicsLayer == m_layerForScrollCorner.get()) {
2233 name = "Scroll Corner Layer";
2234 } else if (graphicsLayer == m_scrollingLayer.get()) {
2235 name = "Scrolling Layer";
2236 } else if (graphicsLayer == m_scrollingContentsLayer.get()) {
2237 name = "Scrolling Contents Layer";
2238 } else if (graphicsLayer == m_scrollingBlockSelectionLayer.get()) {
2239 name = "Scrolling Block Selection Layer";
2240 } else {
2241 ASSERT_NOT_REACHED();
2242 }
2243
2244 return name;
2245 }
2246
2247 } // namespace WebCore
2248