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