1 /* 2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #include "core/rendering/compositing/RenderLayerCompositor.h" 29 30 #include "core/animation/DocumentAnimations.h" 31 #include "core/dom/FullscreenElementStack.h" 32 #include "core/dom/ScriptForbiddenScope.h" 33 #include "core/frame/FrameView.h" 34 #include "core/frame/LocalFrame.h" 35 #include "core/frame/Settings.h" 36 #include "core/html/HTMLIFrameElement.h" 37 #include "core/inspector/InspectorInstrumentation.h" 38 #include "core/inspector/InspectorNodeIds.h" 39 #include "core/page/Chrome.h" 40 #include "core/page/Page.h" 41 #include "core/page/scrolling/ScrollingCoordinator.h" 42 #include "core/rendering/RenderLayerStackingNode.h" 43 #include "core/rendering/RenderLayerStackingNodeIterator.h" 44 #include "core/rendering/RenderVideo.h" 45 #include "core/rendering/RenderView.h" 46 #include "core/rendering/compositing/CompositedLayerMapping.h" 47 #include "core/rendering/compositing/CompositingInputsUpdater.h" 48 #include "core/rendering/compositing/CompositingLayerAssigner.h" 49 #include "core/rendering/compositing/CompositingRequirementsUpdater.h" 50 #include "core/rendering/compositing/GraphicsLayerTreeBuilder.h" 51 #include "core/rendering/compositing/GraphicsLayerUpdater.h" 52 #include "platform/OverscrollTheme.h" 53 #include "platform/RuntimeEnabledFeatures.h" 54 #include "platform/TraceEvent.h" 55 #include "platform/graphics/GraphicsLayer.h" 56 #include "public/platform/Platform.h" 57 58 namespace WebCore { 59 60 RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView) 61 : m_renderView(renderView) 62 , m_compositingReasonFinder(renderView) 63 , m_pendingUpdateType(CompositingUpdateNone) 64 , m_hasAcceleratedCompositing(true) 65 , m_compositing(false) 66 , m_rootShouldAlwaysCompositeDirty(true) 67 , m_needsUpdateFixedBackground(false) 68 , m_isTrackingRepaints(false) 69 , m_rootLayerAttachment(RootLayerUnattached) 70 , m_inOverlayFullscreenVideo(false) 71 { 72 updateAcceleratedCompositingSettings(); 73 } 74 75 RenderLayerCompositor::~RenderLayerCompositor() 76 { 77 ASSERT(m_rootLayerAttachment == RootLayerUnattached); 78 } 79 80 bool RenderLayerCompositor::inCompositingMode() const 81 { 82 // FIXME: This should assert that lificycle is >= CompositingClean since 83 // the last step of updateIfNeeded can set this bit to false. 84 ASSERT(!m_rootShouldAlwaysCompositeDirty); 85 return m_compositing; 86 } 87 88 bool RenderLayerCompositor::staleInCompositingMode() const 89 { 90 return m_compositing; 91 } 92 93 void RenderLayerCompositor::setCompositingModeEnabled(bool enable) 94 { 95 if (enable == m_compositing) 96 return; 97 98 m_compositing = enable; 99 100 // RenderPart::requiresAcceleratedCompositing is used to determine self-paintingness 101 // and bases it's return value for frames on the m_compositing bit here. 102 if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) { 103 if (RenderPart* renderer = ownerElement->renderPart()) 104 renderer->layer()->updateSelfPaintingLayer(); 105 } 106 107 if (m_compositing) 108 ensureRootLayer(); 109 else 110 destroyRootLayer(); 111 112 // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so 113 // we need to schedule a style recalc in our parent document. 114 if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) 115 ownerElement->setNeedsCompositingUpdate(); 116 } 117 118 void RenderLayerCompositor::enableCompositingModeIfNeeded() 119 { 120 if (!m_rootShouldAlwaysCompositeDirty) 121 return; 122 123 m_rootShouldAlwaysCompositeDirty = false; 124 if (m_compositing) 125 return; 126 127 if (rootShouldAlwaysComposite()) { 128 // FIXME: Is this needed? It was added in https://bugs.webkit.org/show_bug.cgi?id=26651. 129 // No tests fail if it's deleted. 130 setNeedsCompositingUpdate(CompositingUpdateRebuildTree); 131 setCompositingModeEnabled(true); 132 } 133 } 134 135 bool RenderLayerCompositor::rootShouldAlwaysComposite() const 136 { 137 if (!m_hasAcceleratedCompositing) 138 return false; 139 return m_renderView.frame()->isMainFrame() || m_compositingReasonFinder.requiresCompositingForScrollableFrame(); 140 } 141 142 void RenderLayerCompositor::updateAcceleratedCompositingSettings() 143 { 144 m_compositingReasonFinder.updateTriggers(); 145 m_hasAcceleratedCompositing = m_renderView.document().settings()->acceleratedCompositingEnabled(); 146 m_rootShouldAlwaysCompositeDirty = true; 147 } 148 149 bool RenderLayerCompositor::layerSquashingEnabled() const 150 { 151 if (!RuntimeEnabledFeatures::layerSquashingEnabled()) 152 return false; 153 if (Settings* settings = m_renderView.document().settings()) 154 return settings->layerSquashingEnabled(); 155 return true; 156 } 157 158 bool RenderLayerCompositor::acceleratedCompositingForOverflowScrollEnabled() const 159 { 160 return m_compositingReasonFinder.hasOverflowScrollTrigger(); 161 } 162 163 static RenderVideo* findFullscreenVideoRenderer(Document& document) 164 { 165 // Recursively find the document that is in fullscreen. 166 Element* fullscreenElement = FullscreenElementStack::fullscreenElementFrom(document); 167 Document* contentDocument = &document; 168 while (fullscreenElement && fullscreenElement->isFrameOwnerElement()) { 169 contentDocument = toHTMLFrameOwnerElement(fullscreenElement)->contentDocument(); 170 if (!contentDocument) 171 return 0; 172 fullscreenElement = FullscreenElementStack::fullscreenElementFrom(*contentDocument); 173 } 174 // Get the current fullscreen element from the document. 175 fullscreenElement = FullscreenElementStack::currentFullScreenElementFrom(*contentDocument); 176 if (!isHTMLVideoElement(fullscreenElement)) 177 return 0; 178 RenderObject* renderer = fullscreenElement->renderer(); 179 if (!renderer) 180 return 0; 181 return toRenderVideo(renderer); 182 } 183 184 void RenderLayerCompositor::updateIfNeededRecursive() 185 { 186 for (Frame* child = m_renderView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) { 187 if (child->isLocalFrame()) 188 toLocalFrame(child)->contentRenderer()->compositor()->updateIfNeededRecursive(); 189 } 190 191 TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateIfNeededRecursive"); 192 193 ASSERT(!m_renderView.needsLayout()); 194 195 ScriptForbiddenScope forbidScript; 196 197 // FIXME: enableCompositingModeIfNeeded can trigger a CompositingUpdateRebuildTree, 198 // which asserts that it's not InCompositingUpdate. 199 enableCompositingModeIfNeeded(); 200 201 lifecycle().advanceTo(DocumentLifecycle::InCompositingUpdate); 202 updateIfNeeded(); 203 lifecycle().advanceTo(DocumentLifecycle::CompositingClean); 204 205 DocumentAnimations::startPendingAnimations(m_renderView.document()); 206 // TODO: Figure out why this fails on Chrome OS login page. crbug.com/365507 207 // ASSERT(lifecycle().state() == DocumentLifecycle::CompositingClean); 208 209 #if ASSERT_ENABLED 210 assertNoUnresolvedDirtyBits(); 211 for (Frame* child = m_renderView.frameView()->frame().tree().firstChild(); child; child = child->tree().nextSibling()) { 212 if (child->isLocalFrame()) 213 toLocalFrame(child)->contentRenderer()->compositor()->assertNoUnresolvedDirtyBits(); 214 } 215 #endif 216 } 217 218 void RenderLayerCompositor::setNeedsCompositingUpdate(CompositingUpdateType updateType) 219 { 220 ASSERT(updateType != CompositingUpdateNone); 221 222 // FIXME: This function should only set dirty bits. We shouldn't 223 // enable compositing mode here. 224 // We check needsLayout here because we don't know if we need to enable 225 // compositing mode until layout is up-to-date because we need to know 226 // if this frame scrolls. 227 // 228 // NOTE: CastStreamingApiTestWithPixelOutput.RtpStreamError triggers 229 // an ASSERT when this code is removed. 230 if (!m_renderView.needsLayout()) 231 enableCompositingModeIfNeeded(); 232 233 m_pendingUpdateType = std::max(m_pendingUpdateType, updateType); 234 page()->animator().scheduleVisualUpdate(); 235 lifecycle().ensureStateAtMost(DocumentLifecycle::LayoutClean); 236 } 237 238 void RenderLayerCompositor::didLayout() 239 { 240 // FIXME: Technically we only need to do this when the FrameView's 241 // isScrollable method would return a different value. 242 m_rootShouldAlwaysCompositeDirty = true; 243 enableCompositingModeIfNeeded(); 244 245 // FIXME: Rather than marking the entire RenderView as dirty, we should 246 // track which RenderLayers moved during layout and only dirty those 247 // specific RenderLayers. 248 rootRenderLayer()->setNeedsCompositingInputsUpdate(); 249 setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInputChange); 250 } 251 252 #if ASSERT_ENABLED 253 254 void RenderLayerCompositor::assertNoUnresolvedDirtyBits() 255 { 256 ASSERT(m_pendingUpdateType == CompositingUpdateNone); 257 ASSERT(!m_rootShouldAlwaysCompositeDirty); 258 } 259 260 #endif 261 262 void RenderLayerCompositor::applyOverlayFullscreenVideoAdjustment() 263 { 264 m_inOverlayFullscreenVideo = false; 265 if (!m_rootContentLayer) 266 return; 267 268 bool isMainFrame = m_renderView.frame()->isMainFrame(); 269 RenderVideo* video = findFullscreenVideoRenderer(m_renderView.document()); 270 if (!video || !video->hasCompositedLayerMapping()) { 271 if (isMainFrame) { 272 GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer(); 273 if (backgroundLayer && !backgroundLayer->parent()) 274 rootFixedBackgroundsChanged(); 275 } 276 return; 277 } 278 279 GraphicsLayer* videoLayer = video->compositedLayerMapping()->mainGraphicsLayer(); 280 281 // The fullscreen video has layer position equal to its enclosing frame's scroll position because fullscreen container is fixed-positioned. 282 // We should reset layer position here since we are going to reattach the layer at the very top level. 283 videoLayer->setPosition(IntPoint()); 284 285 // Only steal fullscreen video layer and clear all other layers if we are the main frame. 286 if (!isMainFrame) 287 return; 288 289 m_rootContentLayer->removeAllChildren(); 290 m_overflowControlsHostLayer->addChild(videoLayer); 291 if (GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer()) 292 backgroundLayer->removeFromParent(); 293 m_inOverlayFullscreenVideo = true; 294 } 295 296 void RenderLayerCompositor::updateIfNeeded() 297 { 298 CompositingUpdateType updateType = m_pendingUpdateType; 299 m_pendingUpdateType = CompositingUpdateNone; 300 301 if (!hasAcceleratedCompositing() || updateType == CompositingUpdateNone) 302 return; 303 304 RenderLayer* updateRoot = rootRenderLayer(); 305 306 Vector<RenderLayer*> layersNeedingRepaint; 307 308 if (updateType >= CompositingUpdateAfterCompositingInputChange) { 309 bool layersChanged = false; 310 { 311 TRACE_EVENT0("blink_rendering", "CompositingInputsUpdater::update"); 312 CompositingInputsUpdater(updateRoot).update(updateRoot); 313 #if ASSERT_ENABLED 314 CompositingInputsUpdater::assertNeedsCompositingInputsUpdateBitsCleared(updateRoot); 315 #endif 316 } 317 318 CompositingRequirementsUpdater(m_renderView, m_compositingReasonFinder).update(updateRoot); 319 320 { 321 TRACE_EVENT0("blink_rendering", "CompositingLayerAssigner::assign"); 322 CompositingLayerAssigner(this).assign(updateRoot, layersChanged, layersNeedingRepaint); 323 } 324 325 { 326 TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::updateAfterCompositingChange"); 327 if (const FrameView::ScrollableAreaSet* scrollableAreas = m_renderView.frameView()->scrollableAreas()) { 328 for (FrameView::ScrollableAreaSet::iterator it = scrollableAreas->begin(); it != scrollableAreas->end(); ++it) 329 (*it)->updateAfterCompositingChange(); 330 } 331 } 332 333 if (layersChanged) 334 updateType = std::max(updateType, CompositingUpdateRebuildTree); 335 } 336 337 if (updateType != CompositingUpdateNone) { 338 TRACE_EVENT0("blink_rendering", "GraphicsLayerUpdater::updateRecursive"); 339 GraphicsLayerUpdater updater; 340 updater.update(layersNeedingRepaint, *updateRoot); 341 342 if (updater.needsRebuildTree()) 343 updateType = std::max(updateType, CompositingUpdateRebuildTree); 344 345 #if ASSERT_ENABLED 346 // FIXME: Move this check to the end of the compositing update. 347 GraphicsLayerUpdater::assertNeedsToUpdateGraphicsLayerBitsCleared(*updateRoot); 348 #endif 349 } 350 351 if (updateType >= CompositingUpdateRebuildTree) { 352 GraphicsLayerVector childList; 353 { 354 TRACE_EVENT0("blink_rendering", "GraphicsLayerTreeBuilder::rebuild"); 355 GraphicsLayerTreeBuilder().rebuild(*updateRoot, childList); 356 } 357 358 if (childList.isEmpty()) 359 destroyRootLayer(); 360 else 361 m_rootContentLayer->setChildren(childList); 362 363 if (RuntimeEnabledFeatures::overlayFullscreenVideoEnabled()) 364 applyOverlayFullscreenVideoAdjustment(); 365 } 366 367 if (m_needsUpdateFixedBackground) { 368 rootFixedBackgroundsChanged(); 369 m_needsUpdateFixedBackground = false; 370 } 371 372 for (unsigned i = 0; i < layersNeedingRepaint.size(); i++) { 373 RenderLayer* layer = layersNeedingRepaint[i]; 374 layer->repainter().computeRepaintRectsIncludingNonCompositingDescendants(); 375 376 repaintOnCompositingChange(layer); 377 } 378 379 // Inform the inspector that the layer tree has changed. 380 if (m_renderView.frame()->isMainFrame()) 381 InspectorInstrumentation::layerTreeDidChange(m_renderView.frame()); 382 } 383 384 bool RenderLayerCompositor::allocateOrClearCompositedLayerMapping(RenderLayer* layer, const CompositingStateTransitionType compositedLayerUpdate) 385 { 386 bool compositedLayerMappingChanged = false; 387 bool nonCompositedReasonChanged = updateLayerIfViewportConstrained(layer); 388 389 // FIXME: It would be nice to directly use the layer's compositing reason, 390 // but allocateOrClearCompositedLayerMapping also gets called without having updated compositing 391 // requirements fully. 392 switch (compositedLayerUpdate) { 393 case AllocateOwnCompositedLayerMapping: 394 ASSERT(!layer->hasCompositedLayerMapping()); 395 setCompositingModeEnabled(true); 396 397 // If we need to repaint, do so before allocating the compositedLayerMapping and clearing out the groupedMapping. 398 repaintOnCompositingChange(layer); 399 400 // If this layer was previously squashed, we need to remove its reference to a groupedMapping right away, so 401 // that computing repaint rects will know the layer's correct compositingState. 402 // FIXME: do we need to also remove the layer from it's location in the squashing list of its groupedMapping? 403 // Need to create a test where a squashed layer pops into compositing. And also to cover all other 404 // sorts of compositingState transitions. 405 layer->setLostGroupedMapping(false); 406 layer->setGroupedMapping(0); 407 408 layer->ensureCompositedLayerMapping(); 409 compositedLayerMappingChanged = true; 410 411 // At this time, the ScrollingCooridnator only supports the top-level frame. 412 if (layer->isRootLayer() && m_renderView.frame()->isMainFrame()) { 413 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 414 scrollingCoordinator->frameViewRootLayerDidChange(m_renderView.frameView()); 415 } 416 break; 417 case RemoveOwnCompositedLayerMapping: 418 // PutInSquashingLayer means you might have to remove the composited layer mapping first. 419 case PutInSquashingLayer: 420 if (layer->hasCompositedLayerMapping()) { 421 // If we're removing the compositedLayerMapping from a reflection, clear the source GraphicsLayer's pointer to 422 // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection 423 // are both either composited, or not composited. 424 if (layer->isReflection()) { 425 RenderLayer* sourceLayer = toRenderLayerModelObject(layer->renderer()->parent())->layer(); 426 if (sourceLayer->hasCompositedLayerMapping()) { 427 ASSERT(sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->replicaLayer() == layer->compositedLayerMapping()->mainGraphicsLayer()); 428 sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->setReplicatedByLayer(0); 429 } 430 } 431 432 layer->clearCompositedLayerMapping(); 433 compositedLayerMappingChanged = true; 434 } 435 436 break; 437 case RemoveFromSquashingLayer: 438 case NoCompositingStateChange: 439 // Do nothing. 440 break; 441 } 442 443 if (layer->hasCompositedLayerMapping() && layer->compositedLayerMapping()->updateRequiresOwnBackingStoreForIntrinsicReasons()) 444 compositedLayerMappingChanged = true; 445 446 if (compositedLayerMappingChanged && layer->renderer()->isRenderPart()) { 447 RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer())); 448 if (innerCompositor && innerCompositor->staleInCompositingMode()) 449 innerCompositor->updateRootLayerAttachment(); 450 } 451 452 if (compositedLayerMappingChanged) 453 layer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects); 454 455 // If a fixed position layer gained/lost a compositedLayerMapping or the reason not compositing it changed, 456 // the scrolling coordinator needs to recalculate whether it can do fast scrolling. 457 if (compositedLayerMappingChanged || nonCompositedReasonChanged) { 458 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 459 scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView.frameView()); 460 } 461 462 return compositedLayerMappingChanged || nonCompositedReasonChanged; 463 } 464 465 bool RenderLayerCompositor::updateLayerIfViewportConstrained(RenderLayer* layer) 466 { 467 RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason; 468 m_compositingReasonFinder.requiresCompositingForPositionFixed(layer->renderer(), layer, &viewportConstrainedNotCompositedReason); 469 470 if (layer->viewportConstrainedNotCompositedReason() != viewportConstrainedNotCompositedReason) { 471 ASSERT(viewportConstrainedNotCompositedReason == RenderLayer::NoNotCompositedReason || layer->renderer()->style()->position() == FixedPosition); 472 layer->setViewportConstrainedNotCompositedReason(viewportConstrainedNotCompositedReason); 473 return true; 474 } 475 return false; 476 } 477 478 // These are temporary hacks to work around chicken-egg issues while we continue to refactor the compositing code. 479 // See crbug.com/383191 for a list of tests that fail if this method is removed. 480 void RenderLayerCompositor::applyUpdateLayerCompositingStateChickenEggHacks(RenderLayer* layer, CompositingStateTransitionType compositedLayerUpdate) 481 { 482 if (compositedLayerUpdate != NoCompositingStateChange) { 483 bool compositedLayerMappingChanged = allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate); 484 if (compositedLayerMappingChanged) { 485 // Repaint rects can only be computed for layers that have already been attached to the 486 // render tree, but a chicken-egg compositing update can happen before |layer| gets 487 // attached. Since newly-created renderers don't get parented until they are attached 488 // (see RenderTreeBuilder::createRendererForElementIfNeeded), we can check for attachment 489 // by checking for a parent. 490 if (layer->parent()) 491 layer->repainter().computeRepaintRectsIncludingNonCompositingDescendants(); 492 repaintOnCompositingChange(layer); 493 } 494 } 495 } 496 497 void RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, UpdateLayerCompositingStateOptions options) 498 { 499 layer->setCompositingReasons(layer->styleDeterminedCompositingReasons(), CompositingReasonComboAllStyleDeterminedReasons); 500 CompositingStateTransitionType compositedLayerUpdate = CompositingLayerAssigner(this).computeCompositedLayerUpdate(layer); 501 502 if (compositedLayerUpdate != NoCompositingStateChange) 503 setNeedsCompositingUpdate(CompositingUpdateRebuildTree); 504 505 if (options == UseChickenEggHacks) 506 applyUpdateLayerCompositingStateChickenEggHacks(layer, compositedLayerUpdate); 507 } 508 509 void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer) 510 { 511 // If the renderer is not attached yet, no need to repaint. 512 if (layer->renderer() != &m_renderView && !layer->renderer()->parent()) 513 return; 514 515 layer->repainter().repaintIncludingNonCompositingDescendants(); 516 } 517 518 // This method assumes that layout is up-to-date, unlike repaintOnCompositingChange(). 519 void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer* layer, const LayoutRect& rect) 520 { 521 RenderLayer* compositedAncestor = layer->enclosingCompositingLayerForRepaint(ExcludeSelf); 522 if (!compositedAncestor) 523 return; 524 ASSERT(compositedAncestor->compositingState() == PaintsIntoOwnBacking || compositedAncestor->compositingState() == PaintsIntoGroupedBacking); 525 526 LayoutPoint offset; 527 layer->convertToLayerCoords(compositedAncestor, offset); 528 LayoutRect repaintRect = rect; 529 repaintRect.moveBy(offset); 530 compositedAncestor->repainter().setBackingNeedsRepaintInRect(repaintRect); 531 } 532 533 void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset) 534 { 535 if (m_overflowControlsHostLayer) 536 m_overflowControlsHostLayer->setPosition(contentsOffset); 537 } 538 539 void RenderLayerCompositor::frameViewDidChangeSize() 540 { 541 if (m_containerLayer) { 542 FrameView* frameView = m_renderView.frameView(); 543 m_containerLayer->setSize(frameView->unscaledVisibleContentSize()); 544 545 frameViewDidScroll(); 546 updateOverflowControlsLayers(); 547 } 548 } 549 550 enum AcceleratedFixedRootBackgroundHistogramBuckets { 551 ScrolledMainFrameBucket = 0, 552 ScrolledMainFrameWithAcceleratedFixedRootBackground = 1, 553 ScrolledMainFrameWithUnacceleratedFixedRootBackground = 2, 554 AcceleratedFixedRootBackgroundHistogramMax = 3 555 }; 556 557 void RenderLayerCompositor::frameViewDidScroll() 558 { 559 FrameView* frameView = m_renderView.frameView(); 560 IntPoint scrollPosition = frameView->scrollPosition(); 561 562 if (!m_scrollLayer) 563 return; 564 565 bool scrollingCoordinatorHandlesOffset = false; 566 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) { 567 if (Settings* settings = m_renderView.document().settings()) { 568 if (m_renderView.frame()->isMainFrame() || settings->compositedScrollingForFramesEnabled()) 569 scrollingCoordinatorHandlesOffset = scrollingCoordinator->scrollableAreaScrollLayerDidChange(frameView); 570 } 571 } 572 573 // Scroll position = scroll minimum + scroll offset. Adjust the layer's 574 // position to handle whatever the scroll coordinator isn't handling. 575 // The minimum scroll position is non-zero for RTL pages with overflow. 576 if (scrollingCoordinatorHandlesOffset) 577 m_scrollLayer->setPosition(-frameView->minimumScrollPosition()); 578 else 579 m_scrollLayer->setPosition(-scrollPosition); 580 581 582 blink::Platform::current()->histogramEnumeration("Renderer.AcceleratedFixedRootBackground", 583 ScrolledMainFrameBucket, 584 AcceleratedFixedRootBackgroundHistogramMax); 585 } 586 587 void RenderLayerCompositor::frameViewScrollbarsExistenceDidChange() 588 { 589 if (m_containerLayer) 590 updateOverflowControlsLayers(); 591 } 592 593 void RenderLayerCompositor::rootFixedBackgroundsChanged() 594 { 595 if (!supportsFixedRootBackgroundCompositing()) 596 return; 597 598 // To avoid having to make the fixed root background layer fixed positioned to 599 // stay put, we position it in the layer tree as follows: 600 // 601 // + Overflow controls host 602 // + LocalFrame clip 603 // + (Fixed root background) <-- Here. 604 // + LocalFrame scroll 605 // + Root content layer 606 // + Scrollbars 607 // 608 // That is, it needs to be the first child of the frame clip, the sibling of 609 // the frame scroll layer. The compositor does not own the background layer, it 610 // just positions it (like the foreground layer). 611 if (GraphicsLayer* backgroundLayer = fixedRootBackgroundLayer()) 612 m_containerLayer->addChildBelow(backgroundLayer, m_scrollLayer.get()); 613 } 614 615 bool RenderLayerCompositor::scrollingLayerDidChange(RenderLayer* layer) 616 { 617 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 618 return scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer->scrollableArea()); 619 return false; 620 } 621 622 String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags) 623 { 624 ASSERT(lifecycle().state() >= DocumentLifecycle::CompositingClean); 625 626 if (!m_rootContentLayer) 627 return String(); 628 629 // We skip dumping the scroll and clip layers to keep layerTreeAsText output 630 // similar between platforms (unless we explicitly request dumping from the 631 // root. 632 GraphicsLayer* rootLayer = m_rootContentLayer.get(); 633 if (flags & LayerTreeIncludesRootLayer) 634 rootLayer = rootGraphicsLayer(); 635 636 String layerTreeText = rootLayer->layerTreeAsText(flags); 637 638 // The true root layer is not included in the dump, so if we want to report 639 // its repaint rects, they must be included here. 640 if (flags & LayerTreeIncludesRepaintRects) 641 return m_renderView.frameView()->trackedPaintInvalidationRectsAsText() + layerTreeText; 642 643 return layerTreeText; 644 } 645 646 RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer) 647 { 648 if (!renderer->node()->isFrameOwnerElement()) 649 return 0; 650 651 HTMLFrameOwnerElement* element = toHTMLFrameOwnerElement(renderer->node()); 652 if (Document* contentDocument = element->contentDocument()) { 653 if (RenderView* view = contentDocument->renderView()) 654 return view->compositor(); 655 } 656 return 0; 657 } 658 659 // FIXME: What does this function do? It needs a clearer name. 660 bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer) 661 { 662 RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer); 663 if (!innerCompositor || !innerCompositor->staleInCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame) 664 return false; 665 666 RenderLayer* layer = renderer->layer(); 667 if (!layer->hasCompositedLayerMapping()) 668 return false; 669 670 CompositedLayerMappingPtr compositedLayerMapping = layer->compositedLayerMapping(); 671 GraphicsLayer* hostingLayer = compositedLayerMapping->parentForSublayers(); 672 GraphicsLayer* rootLayer = innerCompositor->rootGraphicsLayer(); 673 if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) { 674 hostingLayer->removeAllChildren(); 675 hostingLayer->addChild(rootLayer); 676 } 677 return true; 678 } 679 680 void RenderLayerCompositor::repaintCompositedLayers() 681 { 682 recursiveRepaintLayer(rootRenderLayer()); 683 } 684 685 void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer* layer) 686 { 687 // FIXME: This method does not work correctly with transforms. 688 if (layer->compositingState() == PaintsIntoOwnBacking) { 689 layer->compositedLayerMapping()->setContentsNeedDisplay(); 690 // This function is called only when it is desired to repaint the entire compositing graphics layer tree. 691 // This includes squashing. 692 layer->compositedLayerMapping()->setSquashingContentsNeedDisplay(); 693 } 694 695 layer->stackingNode()->updateLayerListsIfNeeded(); 696 697 #if ASSERT_ENABLED 698 LayerListMutationDetector mutationChecker(layer->stackingNode()); 699 #endif 700 701 unsigned childrenToVisit = NormalFlowChildren; 702 if (layer->hasCompositingDescendant()) 703 childrenToVisit |= PositiveZOrderChildren | NegativeZOrderChildren; 704 RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), childrenToVisit); 705 while (RenderLayerStackingNode* curNode = iterator.next()) 706 recursiveRepaintLayer(curNode->layer()); 707 } 708 709 RenderLayer* RenderLayerCompositor::rootRenderLayer() const 710 { 711 return m_renderView.layer(); 712 } 713 714 GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const 715 { 716 if (m_overflowControlsHostLayer) 717 return m_overflowControlsHostLayer.get(); 718 return m_rootContentLayer.get(); 719 } 720 721 GraphicsLayer* RenderLayerCompositor::scrollLayer() const 722 { 723 return m_scrollLayer.get(); 724 } 725 726 GraphicsLayer* RenderLayerCompositor::containerLayer() const 727 { 728 return m_containerLayer.get(); 729 } 730 731 GraphicsLayer* RenderLayerCompositor::ensureRootTransformLayer() 732 { 733 ASSERT(rootGraphicsLayer()); 734 735 if (!m_rootTransformLayer.get()) { 736 m_rootTransformLayer = GraphicsLayer::create(graphicsLayerFactory(), this); 737 m_overflowControlsHostLayer->addChild(m_rootTransformLayer.get()); 738 m_rootTransformLayer->addChild(m_containerLayer.get()); 739 updateOverflowControlsLayers(); 740 } 741 742 return m_rootTransformLayer.get(); 743 } 744 745 void RenderLayerCompositor::setIsInWindow(bool isInWindow) 746 { 747 if (!staleInCompositingMode()) 748 return; 749 750 if (isInWindow) { 751 if (m_rootLayerAttachment != RootLayerUnattached) 752 return; 753 754 RootLayerAttachment attachment = m_renderView.frame()->isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame; 755 attachRootLayer(attachment); 756 } else { 757 if (m_rootLayerAttachment == RootLayerUnattached) 758 return; 759 760 detachRootLayer(); 761 } 762 } 763 764 void RenderLayerCompositor::updateRootLayerPosition() 765 { 766 if (m_rootContentLayer) { 767 const IntRect& documentRect = m_renderView.documentRect(); 768 m_rootContentLayer->setSize(documentRect.size()); 769 m_rootContentLayer->setPosition(documentRect.location()); 770 #if USE(RUBBER_BANDING) 771 if (m_layerForOverhangShadow) 772 OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get()); 773 #endif 774 } 775 if (m_containerLayer) { 776 FrameView* frameView = m_renderView.frameView(); 777 m_containerLayer->setSize(frameView->unscaledVisibleContentSize()); 778 } 779 } 780 781 void RenderLayerCompositor::updateStyleDeterminedCompositingReasons(RenderLayer* layer) 782 { 783 CompositingReasons reasons = m_compositingReasonFinder.styleDeterminedReasons(layer->renderer()); 784 layer->setStyleDeterminedCompositingReasons(reasons); 785 } 786 787 void RenderLayerCompositor::updateDirectCompositingReasons(RenderLayer* layer) 788 { 789 CompositingReasons reasons = m_compositingReasonFinder.directReasons(layer); 790 layer->setCompositingReasons(reasons, CompositingReasonComboAllDirectReasons); 791 } 792 793 void RenderLayerCompositor::setOverlayLayer(GraphicsLayer* layer) 794 { 795 ASSERT(rootGraphicsLayer()); 796 797 if (layer->parent() != m_overflowControlsHostLayer.get()) 798 m_overflowControlsHostLayer->addChild(layer); 799 } 800 801 bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const 802 { 803 // FIXME: We disable accelerated compositing for elements in a RenderFlowThread as it doesn't work properly. 804 // See http://webkit.org/b/84900 to re-enable it. 805 return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer() && !layer->subtreeIsInvisible() && layer->renderer()->flowThreadState() == RenderObject::NotInsideFlowThread; 806 } 807 808 // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, 809 // up to the enclosing compositing ancestor. This is required because compositing layers are parented 810 // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy. 811 // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy, 812 // but a sibling in the z-order hierarchy. 813 bool RenderLayerCompositor::clippedByNonAncestorInStackingTree(const RenderLayer* layer) const 814 { 815 if (!layer->hasCompositedLayerMapping() || !layer->parent()) 816 return false; 817 818 const RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); 819 if (!compositingAncestor) 820 return false; 821 822 RenderObject* clippingContainer = layer->renderer()->clippingContainer(); 823 if (!clippingContainer) 824 return false; 825 826 if (compositingAncestor->renderer()->isDescendantOf(clippingContainer)) 827 return false; 828 829 return true; 830 } 831 832 // Return true if the given layer is a stacking context and has compositing child 833 // layers that it needs to clip. In this case we insert a clipping GraphicsLayer 834 // into the hierarchy between this layer and its children in the z-order hierarchy. 835 bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const 836 { 837 return layer->hasCompositingDescendant() && layer->renderer()->hasClipOrOverflowClip(); 838 } 839 840 // If an element has negative z-index children, those children render in front of the 841 // layer background, so we need an extra 'contents' layer for the foreground of the layer 842 // object. 843 bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const 844 { 845 return layer->stackingNode()->hasNegativeZOrderList(); 846 } 847 848 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) 849 { 850 if (!scrollbar) 851 return; 852 853 context.save(); 854 const IntRect& scrollbarRect = scrollbar->frameRect(); 855 context.translate(-scrollbarRect.x(), -scrollbarRect.y()); 856 IntRect transformedClip = clip; 857 transformedClip.moveBy(scrollbarRect.location()); 858 scrollbar->paint(&context, transformedClip); 859 context.restore(); 860 } 861 862 void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip) 863 { 864 if (graphicsLayer == layerForHorizontalScrollbar()) 865 paintScrollbar(m_renderView.frameView()->horizontalScrollbar(), context, clip); 866 else if (graphicsLayer == layerForVerticalScrollbar()) 867 paintScrollbar(m_renderView.frameView()->verticalScrollbar(), context, clip); 868 else if (graphicsLayer == layerForScrollCorner()) { 869 const IntRect& scrollCorner = m_renderView.frameView()->scrollCornerRect(); 870 context.save(); 871 context.translate(-scrollCorner.x(), -scrollCorner.y()); 872 IntRect transformedClip = clip; 873 transformedClip.moveBy(scrollCorner.location()); 874 m_renderView.frameView()->paintScrollCorner(&context, transformedClip); 875 context.restore(); 876 } 877 } 878 879 bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const 880 { 881 if (Settings* settings = m_renderView.document().settings()) { 882 if (settings->acceleratedCompositingForFixedRootBackgroundEnabled()) 883 return true; 884 } 885 return false; 886 } 887 888 bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer* layer) const 889 { 890 if (layer != m_renderView.layer()) 891 return false; 892 893 return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed(); 894 } 895 896 GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const 897 { 898 // Get the fixed root background from the RenderView layer's compositedLayerMapping. 899 RenderLayer* viewLayer = m_renderView.layer(); 900 if (!viewLayer) 901 return 0; 902 903 if (viewLayer->compositingState() == PaintsIntoOwnBacking && viewLayer->compositedLayerMapping()->backgroundLayerPaintsFixedRootBackground()) 904 return viewLayer->compositedLayerMapping()->backgroundLayer(); 905 906 return 0; 907 } 908 909 static void resetTrackedRepaintRectsRecursive(GraphicsLayer* graphicsLayer) 910 { 911 if (!graphicsLayer) 912 return; 913 914 graphicsLayer->resetTrackedRepaints(); 915 916 for (size_t i = 0; i < graphicsLayer->children().size(); ++i) 917 resetTrackedRepaintRectsRecursive(graphicsLayer->children()[i]); 918 919 if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer()) 920 resetTrackedRepaintRectsRecursive(replicaLayer); 921 922 if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer()) 923 resetTrackedRepaintRectsRecursive(maskLayer); 924 925 if (GraphicsLayer* clippingMaskLayer = graphicsLayer->contentsClippingMaskLayer()) 926 resetTrackedRepaintRectsRecursive(clippingMaskLayer); 927 } 928 929 void RenderLayerCompositor::resetTrackedRepaintRects() 930 { 931 if (GraphicsLayer* rootLayer = rootGraphicsLayer()) 932 resetTrackedRepaintRectsRecursive(rootLayer); 933 } 934 935 void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints) 936 { 937 ASSERT(lifecycle().state() == DocumentLifecycle::CompositingClean); 938 m_isTrackingRepaints = tracksRepaints; 939 } 940 941 bool RenderLayerCompositor::isTrackingRepaints() const 942 { 943 return m_isTrackingRepaints; 944 } 945 946 static bool shouldCompositeOverflowControls(FrameView* view) 947 { 948 if (Page* page = view->frame().page()) { 949 if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator()) 950 if (scrollingCoordinator->coordinatesScrollingForFrameView(view)) 951 return true; 952 } 953 954 return true; 955 } 956 957 bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const 958 { 959 FrameView* view = m_renderView.frameView(); 960 return shouldCompositeOverflowControls(view) && view->horizontalScrollbar(); 961 } 962 963 bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const 964 { 965 FrameView* view = m_renderView.frameView(); 966 return shouldCompositeOverflowControls(view) && view->verticalScrollbar(); 967 } 968 969 bool RenderLayerCompositor::requiresScrollCornerLayer() const 970 { 971 FrameView* view = m_renderView.frameView(); 972 return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible(); 973 } 974 975 void RenderLayerCompositor::updateOverflowControlsLayers() 976 { 977 #if USE(RUBBER_BANDING) 978 if (m_renderView.frame()->isMainFrame()) { 979 if (!m_layerForOverhangShadow) { 980 m_layerForOverhangShadow = GraphicsLayer::create(graphicsLayerFactory(), this); 981 OverscrollTheme::theme()->setUpOverhangShadowLayer(m_layerForOverhangShadow.get()); 982 OverscrollTheme::theme()->updateOverhangShadowLayer(m_layerForOverhangShadow.get(), m_rootContentLayer.get()); 983 m_scrollLayer->addChild(m_layerForOverhangShadow.get()); 984 } 985 } else { 986 ASSERT(!m_layerForOverhangShadow); 987 } 988 #endif 989 GraphicsLayer* controlsParent = m_rootTransformLayer.get() ? m_rootTransformLayer.get() : m_overflowControlsHostLayer.get(); 990 991 if (requiresHorizontalScrollbarLayer()) { 992 if (!m_layerForHorizontalScrollbar) { 993 m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this); 994 } 995 996 if (m_layerForHorizontalScrollbar->parent() != controlsParent) { 997 controlsParent->addChild(m_layerForHorizontalScrollbar.get()); 998 999 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1000 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar); 1001 } 1002 } else if (m_layerForHorizontalScrollbar) { 1003 m_layerForHorizontalScrollbar->removeFromParent(); 1004 m_layerForHorizontalScrollbar = nullptr; 1005 1006 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1007 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar); 1008 } 1009 1010 if (requiresVerticalScrollbarLayer()) { 1011 if (!m_layerForVerticalScrollbar) { 1012 m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this); 1013 } 1014 1015 if (m_layerForVerticalScrollbar->parent() != controlsParent) { 1016 controlsParent->addChild(m_layerForVerticalScrollbar.get()); 1017 1018 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1019 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar); 1020 } 1021 } else if (m_layerForVerticalScrollbar) { 1022 m_layerForVerticalScrollbar->removeFromParent(); 1023 m_layerForVerticalScrollbar = nullptr; 1024 1025 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1026 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar); 1027 } 1028 1029 if (requiresScrollCornerLayer()) { 1030 if (!m_layerForScrollCorner) { 1031 m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this); 1032 controlsParent->addChild(m_layerForScrollCorner.get()); 1033 } 1034 } else if (m_layerForScrollCorner) { 1035 m_layerForScrollCorner->removeFromParent(); 1036 m_layerForScrollCorner = nullptr; 1037 } 1038 1039 m_renderView.frameView()->positionScrollbarLayers(); 1040 } 1041 1042 void RenderLayerCompositor::ensureRootLayer() 1043 { 1044 RootLayerAttachment expectedAttachment = m_renderView.frame()->isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame; 1045 if (expectedAttachment == m_rootLayerAttachment) 1046 return; 1047 1048 if (!m_rootContentLayer) { 1049 m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this); 1050 IntRect overflowRect = m_renderView.pixelSnappedLayoutOverflowRect(); 1051 m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY())); 1052 m_rootContentLayer->setPosition(FloatPoint()); 1053 m_rootContentLayer->setOwnerNodeId(InspectorNodeIds::idForNode(m_renderView.generatingNode())); 1054 1055 // Need to clip to prevent transformed content showing outside this frame 1056 m_rootContentLayer->setMasksToBounds(true); 1057 } 1058 1059 if (!m_overflowControlsHostLayer) { 1060 ASSERT(!m_scrollLayer); 1061 ASSERT(!m_containerLayer); 1062 1063 // Create a layer to host the clipping layer and the overflow controls layers. 1064 m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), this); 1065 1066 // Create a clipping layer if this is an iframe or settings require to clip. 1067 m_containerLayer = GraphicsLayer::create(graphicsLayerFactory(), this); 1068 bool containerMasksToBounds = !m_renderView.frame()->isMainFrame(); 1069 if (Settings* settings = m_renderView.document().settings()) { 1070 if (settings->mainFrameClipsContent()) 1071 containerMasksToBounds = true; 1072 } 1073 m_containerLayer->setMasksToBounds(containerMasksToBounds); 1074 1075 m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), this); 1076 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1077 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true); 1078 1079 // Hook them up 1080 m_overflowControlsHostLayer->addChild(m_containerLayer.get()); 1081 m_containerLayer->addChild(m_scrollLayer.get()); 1082 m_scrollLayer->addChild(m_rootContentLayer.get()); 1083 1084 frameViewDidChangeSize(); 1085 } 1086 1087 // Check to see if we have to change the attachment 1088 if (m_rootLayerAttachment != RootLayerUnattached) 1089 detachRootLayer(); 1090 1091 attachRootLayer(expectedAttachment); 1092 } 1093 1094 void RenderLayerCompositor::destroyRootLayer() 1095 { 1096 if (!m_rootContentLayer) 1097 return; 1098 1099 detachRootLayer(); 1100 1101 #if USE(RUBBER_BANDING) 1102 if (m_layerForOverhangShadow) { 1103 m_layerForOverhangShadow->removeFromParent(); 1104 m_layerForOverhangShadow = nullptr; 1105 } 1106 #endif 1107 1108 if (m_layerForHorizontalScrollbar) { 1109 m_layerForHorizontalScrollbar->removeFromParent(); 1110 m_layerForHorizontalScrollbar = nullptr; 1111 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1112 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), HorizontalScrollbar); 1113 if (Scrollbar* horizontalScrollbar = m_renderView.frameView()->verticalScrollbar()) 1114 m_renderView.frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size())); 1115 } 1116 1117 if (m_layerForVerticalScrollbar) { 1118 m_layerForVerticalScrollbar->removeFromParent(); 1119 m_layerForVerticalScrollbar = nullptr; 1120 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1121 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView.frameView(), VerticalScrollbar); 1122 if (Scrollbar* verticalScrollbar = m_renderView.frameView()->verticalScrollbar()) 1123 m_renderView.frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size())); 1124 } 1125 1126 if (m_layerForScrollCorner) { 1127 m_layerForScrollCorner = nullptr; 1128 m_renderView.frameView()->invalidateScrollCorner(m_renderView.frameView()->scrollCornerRect()); 1129 } 1130 1131 if (m_overflowControlsHostLayer) { 1132 m_overflowControlsHostLayer = nullptr; 1133 m_containerLayer = nullptr; 1134 m_scrollLayer = nullptr; 1135 } 1136 ASSERT(!m_scrollLayer); 1137 m_rootContentLayer = nullptr; 1138 m_rootTransformLayer = nullptr; 1139 } 1140 1141 void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment) 1142 { 1143 if (!m_rootContentLayer) 1144 return; 1145 1146 switch (attachment) { 1147 case RootLayerUnattached: 1148 ASSERT_NOT_REACHED(); 1149 break; 1150 case RootLayerAttachedViaChromeClient: { 1151 LocalFrame& frame = m_renderView.frameView()->frame(); 1152 Page* page = frame.page(); 1153 if (!page) 1154 return; 1155 page->chrome().client().attachRootGraphicsLayer(rootGraphicsLayer()); 1156 break; 1157 } 1158 case RootLayerAttachedViaEnclosingFrame: { 1159 HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement(); 1160 ASSERT(ownerElement); 1161 // The layer will get hooked up via CompositedLayerMapping::updateGraphicsLayerConfiguration() 1162 // for the frame's renderer in the parent document. 1163 ownerElement->setNeedsCompositingUpdate(); 1164 break; 1165 } 1166 } 1167 1168 m_rootLayerAttachment = attachment; 1169 } 1170 1171 void RenderLayerCompositor::detachRootLayer() 1172 { 1173 if (!m_rootContentLayer || m_rootLayerAttachment == RootLayerUnattached) 1174 return; 1175 1176 switch (m_rootLayerAttachment) { 1177 case RootLayerAttachedViaEnclosingFrame: { 1178 // The layer will get unhooked up via CompositedLayerMapping::updateGraphicsLayerConfiguration() 1179 // for the frame's renderer in the parent document. 1180 if (m_overflowControlsHostLayer) 1181 m_overflowControlsHostLayer->removeFromParent(); 1182 else 1183 m_rootContentLayer->removeFromParent(); 1184 1185 if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) 1186 ownerElement->setNeedsCompositingUpdate(); 1187 break; 1188 } 1189 case RootLayerAttachedViaChromeClient: { 1190 LocalFrame& frame = m_renderView.frameView()->frame(); 1191 Page* page = frame.page(); 1192 if (!page) 1193 return; 1194 page->chrome().client().attachRootGraphicsLayer(0); 1195 } 1196 break; 1197 case RootLayerUnattached: 1198 break; 1199 } 1200 1201 m_rootLayerAttachment = RootLayerUnattached; 1202 } 1203 1204 void RenderLayerCompositor::updateRootLayerAttachment() 1205 { 1206 ensureRootLayer(); 1207 } 1208 1209 ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const 1210 { 1211 if (Page* page = this->page()) 1212 return page->scrollingCoordinator(); 1213 1214 return 0; 1215 } 1216 1217 GraphicsLayerFactory* RenderLayerCompositor::graphicsLayerFactory() const 1218 { 1219 if (Page* page = this->page()) 1220 return page->chrome().client().graphicsLayerFactory(); 1221 return 0; 1222 } 1223 1224 Page* RenderLayerCompositor::page() const 1225 { 1226 return m_renderView.frameView()->frame().page(); 1227 } 1228 1229 DocumentLifecycle& RenderLayerCompositor::lifecycle() const 1230 { 1231 return m_renderView.document().lifecycle(); 1232 } 1233 1234 String RenderLayerCompositor::debugName(const GraphicsLayer* graphicsLayer) 1235 { 1236 String name; 1237 if (graphicsLayer == m_rootContentLayer.get()) { 1238 name = "Content Root Layer"; 1239 } else if (graphicsLayer == m_rootTransformLayer.get()) { 1240 name = "Root Transform Layer"; 1241 #if USE(RUBBER_BANDING) 1242 } else if (graphicsLayer == m_layerForOverhangShadow.get()) { 1243 name = "Overhang Areas Shadow"; 1244 #endif 1245 } else if (graphicsLayer == m_overflowControlsHostLayer.get()) { 1246 name = "Overflow Controls Host Layer"; 1247 } else if (graphicsLayer == m_layerForHorizontalScrollbar.get()) { 1248 name = "Horizontal Scrollbar Layer"; 1249 } else if (graphicsLayer == m_layerForVerticalScrollbar.get()) { 1250 name = "Vertical Scrollbar Layer"; 1251 } else if (graphicsLayer == m_layerForScrollCorner.get()) { 1252 name = "Scroll Corner Layer"; 1253 } else if (graphicsLayer == m_containerLayer.get()) { 1254 name = "LocalFrame Clipping Layer"; 1255 } else if (graphicsLayer == m_scrollLayer.get()) { 1256 name = "LocalFrame Scrolling Layer"; 1257 } else { 1258 ASSERT_NOT_REACHED(); 1259 } 1260 1261 return name; 1262 } 1263 1264 } // namespace WebCore 1265