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 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 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 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 111 static bool hasBoxDecorations(const RenderStyle* style) 112 { 113 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter(); 114 } 115 116 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style) 117 { 118 return hasBoxDecorations(style) || style->hasBackgroundImage(); 119 } 120 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 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 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. 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 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 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 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 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 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 259 void CompositedLayerMapping::updateOpacity(const RenderStyle* style) 260 { 261 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity())); 262 } 263 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 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 296 void CompositedLayerMapping::updateLayerBlendMode(const RenderStyle* style) 297 { 298 setBlendMode(style->blendMode()); 299 } 300 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1023 void CompositedLayerMapping::updateContentsRect() 1024 { 1025 m_graphicsLayer->setContentsRect(pixelSnappedIntRect(contentsBox())); 1026 } 1027 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 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 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. 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 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 1169 void CompositedLayerMapping::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground) 1170 { 1171 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground; 1172 } 1173 1174 // Only a member function so it can call createGraphicsLayer. 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 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 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 1232 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> 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 { 1305 void operator() (GraphicsLayer* layer) const { layer->setRenderingContext(renderingContext); } 1306 int renderingContext; 1307 }; 1308 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 { 1334 void operator() (GraphicsLayer* layer) const { layer->setShouldFlattenTransform(shouldFlatten); } 1335 bool shouldFlatten; 1336 }; 1337 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 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 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 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 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 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 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 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 1493 void CompositedLayerMapping::updateClipParent(RenderLayer* clipParent) 1494 { 1495 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) 1496 scrollingCoordinator->updateClipParentForGraphicsLayer(m_graphicsLayer.get(), clipParent); 1497 } 1498 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 1544 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 1562 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 1590 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 1599 void CompositedLayerMapping::updateBackgroundColor() 1600 { 1601 m_graphicsLayer->setBackgroundColor(rendererBackgroundColor()); 1602 } 1603 1604 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 1615 static bool isCompositedPlugin(RenderObject* renderer) 1616 { 1617 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->requiresAcceleratedCompositing(); 1618 } 1619 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 1644 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. 1691 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 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 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 1750 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. 1763 LayoutSize CompositedLayerMapping::contentOffsetInCompositingLayer() const 1764 { 1765 return LayoutSize(-m_compositedBounds.x(), -m_compositedBounds.y()); 1766 } 1767 1768 LayoutRect CompositedLayerMapping::contentsBox() const 1769 { 1770 LayoutRect contentsBox = contentsRect(renderer()); 1771 contentsBox.move(contentOffsetInCompositingLayer()); 1772 return contentsBox; 1773 } 1774 1775 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 1792 GraphicsLayer* CompositedLayerMapping::localRootForOwningLayer() const 1793 { 1794 if (m_ancestorClippingLayer) 1795 return m_ancestorClippingLayer.get(); 1796 1797 return m_graphicsLayer.get(); 1798 } 1799 1800 GraphicsLayer* CompositedLayerMapping::childForSuperlayers() const 1801 { 1802 if (m_squashingContainmentLayer) 1803 return m_squashingContainmentLayer.get(); 1804 1805 return localRootForOwningLayer(); 1806 } 1807 1808 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 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 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 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 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 1870 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 { 1878 void operator() (GraphicsLayer* layer) const 1879 { 1880 if (layer->drawsContent()) 1881 layer->setNeedsDisplay(); 1882 } 1883 }; 1884 1885 void CompositedLayerMapping::setSquashingContentsNeedDisplay() 1886 { 1887 ApplyToGraphicsLayers(this, SetContentsNeedsDisplayFunctor(), ApplyToSquashingLayer); 1888 } 1889 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 { 1898 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 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 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 1930 const GraphicsLayerPaintInfo* CompositedLayerMapping::containingSquashedLayer(const RenderObject* renderObject) 1931 { 1932 return CompositedLayerMapping::containingSquashedLayer(renderObject, m_squashedLayers); 1933 } 1934 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 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 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. 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 2112 bool CompositedLayerMapping::isTrackingRepaints() const 2113 { 2114 GraphicsLayerClient* client = compositor(); 2115 return client ? client->isTrackingRepaints() : false; 2116 } 2117 2118 struct CollectTrackedRepaintRectsFunctor { 2119 void operator() (GraphicsLayer* layer) const { layer->collectTrackedRepaintRects(*rects); } 2120 Vector<FloatRect>* rects; 2121 }; 2122 2123 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 2132 void CompositedLayerMapping::verifyNotPainting() 2133 { 2134 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting()); 2135 } 2136 #endif 2137 2138 void CompositedLayerMapping::notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) 2139 { 2140 renderer()->node()->document().compositorPendingAnimations().notifyCompositorAnimationStarted(monotonicTime); 2141 } 2142 2143 IntRect CompositedLayerMapping::pixelSnappedCompositedBounds() const 2144 { 2145 LayoutRect bounds = m_compositedBounds; 2146 bounds.move(m_owningLayer.subpixelAccumulation()); 2147 return pixelSnappedIntRect(bounds); 2148 } 2149 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 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 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 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