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