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 #if USE(ACCELERATED_COMPOSITING) 29 #include "RenderLayerCompositor.h" 30 31 #include "AnimationController.h" 32 #include "CanvasRenderingContext.h" 33 #include "CSSPropertyNames.h" 34 #include "Chrome.h" 35 #include "ChromeClient.h" 36 #include "Frame.h" 37 #include "FrameView.h" 38 #include "GraphicsLayer.h" 39 #include "HTMLCanvasElement.h" 40 #include "HTMLIFrameElement.h" 41 #include "HTMLNames.h" 42 #include "HitTestResult.h" 43 #include "NodeList.h" 44 #include "Page.h" 45 #include "RenderApplet.h" 46 #include "RenderEmbeddedObject.h" 47 #include "RenderFullScreen.h" 48 #include "RenderIFrame.h" 49 #include "RenderLayerBacking.h" 50 #include "RenderReplica.h" 51 #include "RenderVideo.h" 52 #include "RenderView.h" 53 #include "Settings.h" 54 55 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) 56 #include "HTMLMediaElement.h" 57 #endif 58 59 #if PROFILE_LAYER_REBUILD 60 #include <wtf/CurrentTime.h> 61 #endif 62 63 #ifndef NDEBUG 64 #include "RenderTreeAsText.h" 65 #endif 66 67 #if ENABLE(3D_RENDERING) 68 // This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm'). 69 bool WebCoreHas3DRendering = true; 70 #endif 71 72 namespace WebCore { 73 74 using namespace HTMLNames; 75 76 struct CompositingState { 77 CompositingState(RenderLayer* compAncestor) 78 : m_compositingAncestor(compAncestor) 79 , m_subtreeIsCompositing(false) 80 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 81 , m_positionedSibling(false) 82 , m_hasFixedElement(false) 83 #endif 84 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 85 , m_hasScrollableElement(false) 86 #endif 87 #ifndef NDEBUG 88 , m_depth(0) 89 #endif 90 { 91 } 92 93 RenderLayer* m_compositingAncestor; 94 bool m_subtreeIsCompositing; 95 // m_compositingBounds is only used in computeCompositingRequirements. It can be either the 96 // ancestor bounds or the bounds for the sibling layers which are above the composited layer. 97 // It is used to reject creating unnecesary layers. 98 IntRect m_compositingBounds; 99 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 100 bool m_positionedSibling; 101 bool m_hasFixedElement; 102 #endif 103 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 104 bool m_hasScrollableElement; 105 #endif 106 #ifndef NDEBUG 107 int m_depth; 108 #endif 109 }; 110 111 RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView) 112 : m_renderView(renderView) 113 , m_rootPlatformLayer(0) 114 , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired) 115 , m_hasAcceleratedCompositing(true) 116 , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers)) 117 , m_showDebugBorders(false) 118 , m_showRepaintCounter(false) 119 , m_compositingConsultsOverlap(true) 120 , m_compositingDependsOnGeometry(false) 121 , m_compositing(false) 122 , m_compositingLayersNeedRebuild(false) 123 , m_flushingLayers(false) 124 , m_forceCompositingMode(false) 125 , m_rootLayerAttachment(RootLayerUnattached) 126 #if PROFILE_LAYER_REBUILD 127 , m_rootLayerUpdateCount(0) 128 #endif // PROFILE_LAYER_REBUILD 129 { 130 Settings* settings = m_renderView->document()->settings(); 131 132 // Even when forcing compositing mode, ignore child frames, or this will trigger 133 // layer creation from the enclosing RenderIFrame. 134 ASSERT(m_renderView->document()->frame()); 135 if (settings && settings->forceCompositingMode() && settings->acceleratedCompositingEnabled() 136 && !m_renderView->document()->frame()->tree()->parent()) { 137 m_forceCompositingMode = true; 138 enableCompositingMode(); 139 } 140 } 141 142 RenderLayerCompositor::~RenderLayerCompositor() 143 { 144 ASSERT(m_rootLayerAttachment == RootLayerUnattached); 145 } 146 147 void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) 148 { 149 if (enable != m_compositing) { 150 m_compositing = enable; 151 152 if (m_compositing) { 153 ensureRootPlatformLayer(); 154 notifyIFramesOfCompositingChange(); 155 } else 156 destroyRootPlatformLayer(); 157 } 158 } 159 160 void RenderLayerCompositor::cacheAcceleratedCompositingFlags() 161 { 162 bool hasAcceleratedCompositing = false; 163 bool showDebugBorders = false; 164 bool showRepaintCounter = false; 165 166 if (Settings* settings = m_renderView->document()->settings()) { 167 hasAcceleratedCompositing = settings->acceleratedCompositingEnabled(); 168 showDebugBorders = settings->showDebugBorders(); 169 showRepaintCounter = settings->showRepaintCounter(); 170 } 171 172 // We allow the chrome to override the settings, in case the page is rendered 173 // on a chrome that doesn't allow accelerated compositing. 174 if (hasAcceleratedCompositing) { 175 Frame* frame = m_renderView->frameView()->frame(); 176 Page* page = frame ? frame->page() : 0; 177 if (page) { 178 ChromeClient* chromeClient = page->chrome()->client(); 179 m_compositingTriggers = chromeClient->allowedCompositingTriggers(); 180 hasAcceleratedCompositing = m_compositingTriggers; 181 } 182 } 183 184 if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter) 185 setCompositingLayersNeedRebuild(); 186 187 m_hasAcceleratedCompositing = hasAcceleratedCompositing; 188 m_showDebugBorders = showDebugBorders; 189 m_showRepaintCounter = showRepaintCounter; 190 } 191 192 bool RenderLayerCompositor::canRender3DTransforms() const 193 { 194 return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger); 195 } 196 197 void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild) 198 { 199 if (inCompositingMode()) 200 m_compositingLayersNeedRebuild = needRebuild; 201 } 202 203 void RenderLayerCompositor::scheduleLayerFlush() 204 { 205 Frame* frame = m_renderView->frameView()->frame(); 206 Page* page = frame ? frame->page() : 0; 207 if (!page) 208 return; 209 210 page->chrome()->client()->scheduleCompositingLayerSync(); 211 } 212 213 void RenderLayerCompositor::flushPendingLayerChanges() 214 { 215 ASSERT(!m_flushingLayers); 216 m_flushingLayers = true; 217 218 // FIXME: FrameView::syncCompositingStateRecursive() calls this for each 219 // frame, so when compositing layers are connected between frames, we'll 220 // end up syncing subframe's layers multiple times. 221 // https://bugs.webkit.org/show_bug.cgi?id=52489 222 if (GraphicsLayer* rootLayer = rootPlatformLayer()) 223 rootLayer->syncCompositingState(); 224 225 ASSERT(m_flushingLayers); 226 m_flushingLayers = false; 227 } 228 229 RenderLayerCompositor* RenderLayerCompositor::enclosingCompositorFlushingLayers() const 230 { 231 if (!m_renderView->frameView()) 232 return 0; 233 234 for (Frame* frame = m_renderView->frameView()->frame(); frame; frame = frame->tree()->parent()) { 235 RenderLayerCompositor* compositor = frame->contentRenderer() ? frame->contentRenderer()->compositor() : 0; 236 if (compositor->isFlushingLayers()) 237 return compositor; 238 } 239 240 return 0; 241 } 242 243 void RenderLayerCompositor::scheduleCompositingLayerUpdate() 244 { 245 if (!m_updateCompositingLayersTimer.isActive()) 246 m_updateCompositingLayersTimer.startOneShot(0); 247 } 248 249 bool RenderLayerCompositor::compositingLayerUpdatePending() const 250 { 251 return m_updateCompositingLayersTimer.isActive(); 252 } 253 254 void RenderLayerCompositor::updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*) 255 { 256 updateCompositingLayers(); 257 } 258 259 void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot) 260 { 261 m_updateCompositingLayersTimer.stop(); 262 263 if (!m_compositingDependsOnGeometry && !m_compositing) 264 return; 265 266 bool checkForHierarchyUpdate = m_compositingDependsOnGeometry; 267 bool needGeometryUpdate = false; 268 269 switch (updateType) { 270 case CompositingUpdateAfterLayoutOrStyleChange: 271 case CompositingUpdateOnPaitingOrHitTest: 272 checkForHierarchyUpdate = true; 273 break; 274 case CompositingUpdateOnScroll: 275 if (m_compositingConsultsOverlap) 276 checkForHierarchyUpdate = true; // Overlap can change with scrolling, so need to check for hierarchy updates. 277 278 needGeometryUpdate = true; 279 break; 280 } 281 282 if (!checkForHierarchyUpdate && !needGeometryUpdate) 283 return; 284 285 bool needHierarchyUpdate = m_compositingLayersNeedRebuild; 286 if (!updateRoot || m_compositingConsultsOverlap) { 287 // Only clear the flag if we're updating the entire hierarchy. 288 m_compositingLayersNeedRebuild = false; 289 updateRoot = rootRenderLayer(); 290 } 291 292 #if PROFILE_LAYER_REBUILD 293 ++m_rootLayerUpdateCount; 294 295 double startTime = WTF::currentTime(); 296 #endif 297 298 if (checkForHierarchyUpdate) { 299 // Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers. 300 // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex. 301 CompositingState compState(updateRoot); 302 bool layersChanged = false; 303 304 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 305 compState.m_positionedSibling = false; 306 compState.m_hasFixedElement = false; 307 #endif 308 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 309 compState.m_hasScrollableElement = false; 310 #endif 311 if (m_compositingConsultsOverlap) { 312 OverlapMap overlapTestRequestMap; 313 computeCompositingRequirements(updateRoot, &overlapTestRequestMap, compState, layersChanged); 314 } else 315 computeCompositingRequirements(updateRoot, 0, compState, layersChanged); 316 317 needHierarchyUpdate |= layersChanged; 318 } 319 320 if (needHierarchyUpdate) { 321 // Update the hierarchy of the compositing layers. 322 CompositingState compState(updateRoot); 323 Vector<GraphicsLayer*> childList; 324 rebuildCompositingLayerTree(updateRoot, compState, childList); 325 326 // Host the document layer in the RenderView's root layer. 327 if (updateRoot == rootRenderLayer()) { 328 if (childList.isEmpty()) 329 destroyRootPlatformLayer(); 330 else 331 m_rootPlatformLayer->setChildren(childList); 332 } 333 } else if (needGeometryUpdate) { 334 // We just need to do a geometry update. This is only used for position:fixed scrolling; 335 // most of the time, geometry is updated via RenderLayer::styleChanged(). 336 updateLayerTreeGeometry(updateRoot); 337 } 338 339 #if PROFILE_LAYER_REBUILD 340 double endTime = WTF::currentTime(); 341 if (updateRoot == rootRenderLayer()) 342 fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n", 343 m_rootLayerUpdateCount, 1000.0 * (endTime - startTime)); 344 #endif 345 ASSERT(updateRoot || !m_compositingLayersNeedRebuild); 346 347 if (!hasAcceleratedCompositing()) 348 enableCompositingMode(false); 349 } 350 351 bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint) 352 { 353 bool layerChanged = false; 354 355 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 356 if (needsToBeComposited(layer) || layer->shouldComposite()) { 357 #else 358 if (needsToBeComposited(layer)) { 359 #endif 360 enableCompositingMode(); 361 362 // 3D transforms turn off the testing of overlap. 363 if (requiresCompositingForTransform(layer->renderer())) 364 setCompositingConsultsOverlap(false); 365 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 366 // If we are a child of a scrollable layer, ignore the overlap from the 367 // scrollable layer as it can cause child layers to become composited 368 // siblings and will not scroll with the main content layer. 369 if (layer->hasOverflowParent()) 370 setCompositingConsultsOverlap(false); 371 #endif 372 373 if (!layer->backing()) { 374 375 // If we need to repaint, do so before making backing 376 if (shouldRepaint == CompositingChangeRepaintNow) 377 repaintOnCompositingChange(layer); 378 379 layer->ensureBacking(); 380 381 #if PLATFORM(MAC) && USE(CA) 382 if (m_renderView->document()->settings()->acceleratedDrawingEnabled()) 383 layer->backing()->graphicsLayer()->setAcceleratesDrawing(true); 384 else if (layer->renderer()->isCanvas()) { 385 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(layer->renderer()->node()); 386 if (canvas->renderingContext() && canvas->renderingContext()->isAccelerated()) 387 layer->backing()->graphicsLayer()->setAcceleratesDrawing(true); 388 } 389 #endif 390 layerChanged = true; 391 } 392 } else { 393 if (layer->backing()) { 394 // If we're removing backing on a reflection, clear the source GraphicsLayer's pointer to 395 // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection 396 // are both either composited, or not composited. 397 if (layer->isReflection()) { 398 RenderLayer* sourceLayer = toRenderBoxModelObject(layer->renderer()->parent())->layer(); 399 if (RenderLayerBacking* backing = sourceLayer->backing()) { 400 ASSERT(backing->graphicsLayer()->replicaLayer() == layer->backing()->graphicsLayer()); 401 backing->graphicsLayer()->setReplicatedByLayer(0); 402 } 403 } 404 405 layer->clearBacking(); 406 layerChanged = true; 407 408 // The layer's cached repaints rects are relative to the repaint container, so change when 409 // compositing changes; we need to update them here. 410 layer->computeRepaintRects(); 411 412 // If we need to repaint, do so now that we've removed the backing 413 if (shouldRepaint == CompositingChangeRepaintNow) 414 repaintOnCompositingChange(layer); 415 } 416 } 417 418 #if ENABLE(VIDEO) 419 if (layerChanged && layer->renderer()->isVideo()) { 420 // If it's a video, give the media player a chance to hook up to the layer. 421 RenderVideo* video = toRenderVideo(layer->renderer()); 422 video->acceleratedRenderingStateChanged(); 423 } 424 #endif 425 426 if (layerChanged && layer->renderer()->isRenderPart()) { 427 RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer())); 428 if (innerCompositor && innerCompositor->inCompositingMode()) 429 innerCompositor->updateRootLayerAttachment(); 430 } 431 432 return layerChanged; 433 } 434 435 bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint) 436 { 437 bool layerChanged = updateBacking(layer, shouldRepaint); 438 439 // See if we need content or clipping layers. Methods called here should assume 440 // that the compositing state of descendant layers has not been updated yet. 441 if (layer->backing() && layer->backing()->updateGraphicsLayerConfiguration()) 442 layerChanged = true; 443 444 return layerChanged; 445 } 446 447 void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer) 448 { 449 // If the renderer is not attached yet, no need to repaint. 450 if (layer->renderer() != m_renderView && !layer->renderer()->parent()) 451 return; 452 453 RenderBoxModelObject* repaintContainer = layer->renderer()->containerForRepaint(); 454 if (!repaintContainer) 455 repaintContainer = m_renderView; 456 457 layer->repaintIncludingNonCompositingDescendants(repaintContainer); 458 if (repaintContainer == m_renderView) { 459 // The contents of this layer may be moving between the window 460 // and a GraphicsLayer, so we need to make sure the window system 461 // synchronizes those changes on the screen. 462 m_renderView->frameView()->setNeedsOneShotDrawingSynchronization(); 463 } 464 } 465 466 // The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant 467 // RenderLayers that are rendered by the composited RenderLayer. 468 IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) 469 { 470 if (!canBeComposited(layer)) 471 return IntRect(); 472 473 IntRect boundingBoxRect = layer->localBoundingBox(); 474 if (layer->renderer()->isRoot()) { 475 // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited), 476 // then it has to be big enough to cover the viewport in order to display the background. This is akin 477 // to the code in RenderBox::paintRootBoxFillLayers(). 478 if (m_renderView->frameView()) { 479 int rw = m_renderView->frameView()->contentsWidth(); 480 int rh = m_renderView->frameView()->contentsHeight(); 481 482 boundingBoxRect.setWidth(max(boundingBoxRect.width(), rw - boundingBoxRect.x())); 483 boundingBoxRect.setHeight(max(boundingBoxRect.height(), rh - boundingBoxRect.y())); 484 } 485 } 486 487 IntRect unionBounds = boundingBoxRect; 488 489 if (layer->renderer()->hasOverflowClip() || layer->renderer()->hasMask()) { 490 int ancestorRelX = 0, ancestorRelY = 0; 491 layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY); 492 boundingBoxRect.move(ancestorRelX, ancestorRelY); 493 return boundingBoxRect; 494 } 495 496 if (RenderLayer* reflection = layer->reflectionLayer()) { 497 if (!reflection->isComposited()) { 498 IntRect childUnionBounds = calculateCompositedBounds(reflection, layer); 499 unionBounds.unite(childUnionBounds); 500 } 501 } 502 503 ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0)); 504 505 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 506 size_t listSize = negZOrderList->size(); 507 for (size_t i = 0; i < listSize; ++i) { 508 RenderLayer* curLayer = negZOrderList->at(i); 509 if (!curLayer->isComposited()) { 510 IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); 511 unionBounds.unite(childUnionBounds); 512 } 513 } 514 } 515 516 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 517 size_t listSize = posZOrderList->size(); 518 for (size_t i = 0; i < listSize; ++i) { 519 RenderLayer* curLayer = posZOrderList->at(i); 520 if (!curLayer->isComposited()) { 521 IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer); 522 unionBounds.unite(childUnionBounds); 523 } 524 } 525 } 526 527 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 528 size_t listSize = normalFlowList->size(); 529 for (size_t i = 0; i < listSize; ++i) { 530 RenderLayer* curLayer = normalFlowList->at(i); 531 if (!curLayer->isComposited()) { 532 IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer); 533 unionBounds.unite(curAbsBounds); 534 } 535 } 536 } 537 538 if (layer->paintsWithTransform(PaintBehaviorNormal)) { 539 TransformationMatrix* affineTrans = layer->transform(); 540 boundingBoxRect = affineTrans->mapRect(boundingBoxRect); 541 unionBounds = affineTrans->mapRect(unionBounds); 542 } 543 544 int ancestorRelX = 0, ancestorRelY = 0; 545 layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY); 546 unionBounds.move(ancestorRelX, ancestorRelY); 547 548 return unionBounds; 549 } 550 551 void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/) 552 { 553 setCompositingLayersNeedRebuild(); 554 } 555 556 void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child) 557 { 558 if (!child->isComposited() || parent->renderer()->documentBeingDestroyed()) 559 return; 560 561 setCompositingParent(child, 0); 562 563 RenderLayer* compLayer = parent->enclosingCompositingLayer(); 564 if (compLayer) { 565 ASSERT(compLayer->backing()); 566 IntRect compBounds = child->backing()->compositedBounds(); 567 568 int offsetX = 0, offsetY = 0; 569 child->convertToLayerCoords(compLayer, offsetX, offsetY); 570 compBounds.move(offsetX, offsetY); 571 572 compLayer->setBackingNeedsRepaintInRect(compBounds); 573 574 // The contents of this layer may be moving from a GraphicsLayer to the window, 575 // so we need to make sure the window system synchronizes those changes on the screen. 576 m_renderView->frameView()->setNeedsOneShotDrawingSynchronization(); 577 } 578 579 setCompositingLayersNeedRebuild(); 580 } 581 582 RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const 583 { 584 for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) { 585 if (curr->isStackingContext()) 586 return 0; 587 588 if (curr->renderer()->hasOverflowClip() || curr->renderer()->hasClip()) 589 return curr; 590 } 591 return 0; 592 } 593 594 void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed) 595 { 596 if (layer->isRootLayer()) 597 return; 598 599 if (!boundsComputed) { 600 layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); 601 // Empty rects never intersect, but we need them to for the purposes of overlap testing. 602 if (layerBounds.isEmpty()) 603 layerBounds.setSize(IntSize(1, 1)); 604 boundsComputed = true; 605 } 606 607 overlapMap.add(layer, layerBounds); 608 } 609 610 bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, const IntRect& layerBounds) 611 { 612 RenderLayerCompositor::OverlapMap::const_iterator end = overlapMap.end(); 613 for (RenderLayerCompositor::OverlapMap::const_iterator it = overlapMap.begin(); it != end; ++it) { 614 const IntRect& bounds = it->second; 615 if (layerBounds.intersects(bounds)) { 616 return true; 617 } 618 } 619 620 return false; 621 } 622 623 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 624 625 bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* list) 626 { 627 int listSize = list->size(); 628 int haveFixedLayer = -1; 629 bool fixedSibling = false; 630 bool positionedSibling = false; 631 632 #if 0 633 // For absolute positioned elements, we need to check if they are followed 634 // by a composited element; if so, they also need to be composited, as the 635 // layer display rendering might be incorrect (absolute elements being 636 // removed from the flow). 637 for (int i = 0; i < listSize; ++i) { 638 RenderLayer* currentLayer = list->at(i); 639 if (!needsToBeComposited(currentLayer) 640 && !currentLayer->shouldComposite() 641 && currentLayer->renderer()->isPositioned()) { 642 positionedSibling = true; 643 // check if there is a composited layer later, if so we should be 644 // composited. 645 for (int j = i + 1; j < listSize; ++j) { 646 RenderLayer* layer = list->at(j); 647 if (needsToBeComposited(layer)) { 648 currentLayer->setShouldComposite(true); 649 break; 650 } 651 } 652 break; 653 } 654 } 655 #endif 656 657 // If we find a fixed layer, let's mark all the following layers as being 658 // composited. The layers' surfaces will be merged if needed UI-side. 659 for (int j = 0; j < listSize; ++j) { 660 RenderLayer* currentLayer = list->at(j); 661 662 // clear the composited flag first 663 currentLayer->setShouldComposite(false); 664 665 if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) { 666 // Ignore fixed layers with a width or height or 1 or less... 667 IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad( 668 FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox(); 669 if (currentLayerBounds.width() > 1 && currentLayerBounds.height() > 1) { 670 haveFixedLayer = j; 671 fixedSibling = true; 672 } 673 continue; 674 } 675 676 if (haveFixedLayer != -1) 677 currentLayer->setShouldComposite(true); 678 } 679 680 return positionedSibling || fixedSibling; 681 } 682 683 #endif 684 685 // Recurse through the layers in z-index and overflow order (which is equivalent to painting order) 686 // For the z-order children of a compositing layer: 687 // If a child layers has a compositing layer, then all subsequent layers must 688 // be compositing in order to render above that layer. 689 // 690 // If a child in the negative z-order list is compositing, then the layer itself 691 // must be compositing so that its contents render over that child. 692 // This implies that its positive z-index children must also be compositing. 693 // 694 void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, struct CompositingState& compositingState, bool& layersChanged) 695 { 696 layer->updateLayerPosition(); 697 layer->updateZOrderLists(); 698 layer->updateNormalFlowList(); 699 #if PLATFORM(ANDROID) 700 RenderObject* renderer = layer->renderer(); 701 bool intCom = requiresCompositingLayer(layer); 702 layer->setIntrinsicallyComposited(intCom); 703 #endif 704 705 // Clear the flag 706 layer->setHasCompositingDescendant(false); 707 708 bool mustOverlapCompositedLayers = compositingState.m_subtreeIsCompositing; 709 710 bool haveComputedBounds = false; 711 IntRect absBounds; 712 if (overlapMap && !overlapMap->isEmpty()) { 713 // If we're testing for overlap, we only need to composite if we overlap something that is already composited. 714 absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox(); 715 // Empty rects never intersect, but we need them to for the purposes of overlap testing. 716 if (absBounds.isEmpty()) 717 absBounds.setSize(IntSize(1, 1)); 718 haveComputedBounds = true; 719 // If the current subtree is not compositing, and the layer is fully inside the current compositing bounnds, 720 // there is no need to do the overlap test. This reduces the total number of the composited layers. 721 if (compositingState.m_subtreeIsCompositing || !compositingState.m_compositingBounds.contains(absBounds)) 722 mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds); 723 } 724 725 layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers); 726 727 // The children of this layer don't need to composite, unless there is 728 // a compositing layer among them, so start by inheriting the compositing 729 // ancestor with m_subtreeIsCompositing set to false. 730 CompositingState childState(compositingState.m_compositingAncestor); 731 if (compositingState.m_subtreeIsCompositing) 732 childState.m_compositingBounds = absBounds; 733 else 734 childState.m_compositingBounds = compositingState.m_compositingBounds; 735 #ifndef NDEBUG 736 ++childState.m_depth; 737 #endif 738 739 bool willBeComposited = needsToBeComposited(layer); 740 741 #if 0 && ENABLE(COMPOSITED_FIXED_ELEMENTS) 742 willBeComposited |= layer->shouldComposite(); 743 layer->setMustOverlapCompositedLayers(layer->shouldComposite()); 744 #endif 745 746 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 747 // tell the parent it has scrollable descendants. 748 if (layer->hasOverflowScroll()) 749 compositingState.m_hasScrollableElement = true; 750 #endif 751 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 752 if (layer->isFixed()) 753 compositingState.m_hasFixedElement = true; 754 #endif 755 if (willBeComposited) { 756 // Tell the parent it has compositing descendants. 757 compositingState.m_subtreeIsCompositing = true; 758 // This layer now acts as the ancestor for kids. 759 childState.m_compositingAncestor = layer; 760 childState.m_compositingBounds = absBounds; 761 if (overlapMap) 762 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); 763 } 764 765 #if ENABLE(VIDEO) 766 // Video is special. It's a replaced element with a content layer, but has shadow content 767 // for the controller that must render in front. Without this, the controls fail to show 768 // when the video element is a stacking context (e.g. due to opacity or transform). 769 if (willBeComposited && layer->renderer()->isVideo()) 770 childState.m_subtreeIsCompositing = true; 771 #endif 772 773 if (layer->isStackingContext()) { 774 ASSERT(!layer->m_zOrderListsDirty); 775 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 776 size_t listSize = negZOrderList->size(); 777 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 778 childState.m_positionedSibling = compositingState.m_positionedSibling; 779 if (checkForPositionedElements(negZOrderList)) 780 childState.m_positionedSibling = true; 781 #endif 782 for (size_t i = 0; i < listSize; ++i) { 783 RenderLayer* curLayer = negZOrderList->at(i); 784 computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); 785 786 // If we have to make a layer for this child, make one now so we can have a contents layer 787 // (since we need to ensure that the -ve z-order child renders underneath our contents). 788 #ifdef ANDROID 789 // Normally we try to reduce the number of layers by not promoting all fixed 790 // or scrollable elements to their own compositing layer. But in the case that 791 // we have such an element in the negative z-order, we must make it a layer 792 // otherwise the content will be painted at a higher z-index. This breaks pages 793 // that set a large image with a z-index of -1 to implement a background image, 794 // for example. 795 bool childRequiresCompositing = childState.m_hasFixedElement || childState.m_hasScrollableElement; 796 if (!willBeComposited && (childState.m_subtreeIsCompositing || childRequiresCompositing)) { 797 #else 798 if (!willBeComposited && childState.m_subtreeIsCompositing) { 799 #endif 800 // make layer compositing 801 layer->setMustOverlapCompositedLayers(true); 802 childState.m_compositingAncestor = layer; 803 if (overlapMap) 804 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); 805 willBeComposited = true; 806 } 807 } 808 } 809 } 810 811 ASSERT(!layer->m_normalFlowListDirty); 812 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 813 size_t listSize = normalFlowList->size(); 814 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 815 childState.m_positionedSibling = compositingState.m_positionedSibling; 816 if (checkForPositionedElements(normalFlowList)) 817 childState.m_positionedSibling = true; 818 #endif 819 for (size_t i = 0; i < listSize; ++i) { 820 RenderLayer* curLayer = normalFlowList->at(i); 821 computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); 822 } 823 } 824 825 if (layer->isStackingContext()) { 826 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 827 size_t listSize = posZOrderList->size(); 828 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 829 childState.m_positionedSibling = compositingState.m_positionedSibling; 830 if (checkForPositionedElements(posZOrderList)) 831 childState.m_positionedSibling = true; 832 #endif 833 for (size_t i = 0; i < listSize; ++i) { 834 RenderLayer* curLayer = posZOrderList->at(i); 835 computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged); 836 } 837 } 838 } 839 840 // If we just entered compositing mode, the root will have become composited (as long as accelerated compositing is enabled). 841 if (layer->isRootLayer()) { 842 if (inCompositingMode() && m_hasAcceleratedCompositing) 843 willBeComposited = true; 844 } 845 846 ASSERT(willBeComposited == needsToBeComposited(layer)); 847 848 // If we have a software transform, and we have layers under us, we need to also 849 // be composited. Also, if we have opacity < 1, then we need to be a layer so that 850 // the child layers are opaque, then rendered with opacity on this layer. 851 if (!willBeComposited && canBeComposited(layer) && childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) { 852 layer->setMustOverlapCompositedLayers(true); 853 if (overlapMap) 854 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); 855 willBeComposited = true; 856 } 857 858 ASSERT(willBeComposited == needsToBeComposited(layer)); 859 if (layer->reflectionLayer()) 860 layer->reflectionLayer()->setMustOverlapCompositedLayers(willBeComposited); 861 862 // Subsequent layers in the parent stacking context also need to composite. 863 if (childState.m_subtreeIsCompositing) 864 compositingState.m_subtreeIsCompositing = true; 865 866 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 867 if (childState.m_hasFixedElement) 868 compositingState.m_hasFixedElement = true; 869 if (childState.m_positionedSibling) 870 compositingState.m_positionedSibling = true; 871 #endif 872 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 873 if (childState.m_hasScrollableElement) 874 compositingState.m_hasScrollableElement = true; 875 #endif 876 877 // Set the flag to say that this SC has compositing children. 878 layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing); 879 880 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, 881 // so test that again. 882 if (!willBeComposited && canBeComposited(layer) && clipsCompositingDescendants(layer)) { 883 if (overlapMap) 884 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); 885 willBeComposited = true; 886 } 887 888 // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need 889 // to be composited, then we can drop out of compositing mode altogether. 890 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 891 // We also need to check that we don't have a scrollable layer, as this 892 // would not have set the m_subtreeIsCompositing flag 893 if (layer->isRootLayer() && !childState.m_subtreeIsCompositing 894 && !childState.m_hasScrollableElement && !childState.m_positionedSibling && !childState.m_hasFixedElement 895 && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { 896 #else 897 if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode) { 898 #endif 899 enableCompositingMode(false); 900 willBeComposited = false; 901 } 902 903 // If the layer is going into compositing mode, repaint its old location. 904 ASSERT(willBeComposited == needsToBeComposited(layer)); 905 if (!layer->isComposited() && willBeComposited) 906 repaintOnCompositingChange(layer); 907 908 // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree(). 909 if (updateBacking(layer, CompositingChangeRepaintNow)) 910 layersChanged = true; 911 912 if (layer->reflectionLayer() && updateLayerCompositingState(layer->reflectionLayer(), CompositingChangeRepaintNow)) 913 layersChanged = true; 914 } 915 916 void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer) 917 { 918 ASSERT(!parentLayer || childLayer->ancestorCompositingLayer() == parentLayer); 919 ASSERT(childLayer->isComposited()); 920 921 // It's possible to be called with a parent that isn't yet composited when we're doing 922 // partial updates as required by painting or hit testing. Just bail in that case; 923 // we'll do a full layer update soon. 924 if (!parentLayer || !parentLayer->isComposited()) 925 return; 926 927 if (parentLayer) { 928 GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers(); 929 GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers(); 930 931 hostingLayer->addChild(hostedLayer); 932 } else 933 childLayer->backing()->childForSuperlayers()->removeFromParent(); 934 } 935 936 void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer) 937 { 938 ASSERT(layer->isComposited()); 939 940 GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers(); 941 hostingLayer->removeAllChildren(); 942 } 943 944 #if ENABLE(VIDEO) 945 bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const 946 { 947 if (!m_hasAcceleratedCompositing) 948 return false; 949 950 return o->supportsAcceleratedRendering(); 951 } 952 #endif 953 954 void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, const CompositingState& compositingState, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer) 955 { 956 // Make the layer compositing if necessary, and set up clipping and content layers. 957 // Note that we can only do work here that is independent of whether the descendant layers 958 // have been processed. computeCompositingRequirements() will already have done the repaint if necessary. 959 960 RenderLayerBacking* layerBacking = layer->backing(); 961 if (layerBacking) { 962 // The compositing state of all our children has been updated already, so now 963 // we can compute and cache the composited bounds for this layer. 964 layerBacking->updateCompositedBounds(); 965 966 if (RenderLayer* reflection = layer->reflectionLayer()) { 967 if (reflection->backing()) 968 reflection->backing()->updateCompositedBounds(); 969 } 970 971 layerBacking->updateGraphicsLayerConfiguration(); 972 layerBacking->updateGraphicsLayerGeometry(); 973 974 if (!layer->parent()) 975 updateRootLayerPosition(); 976 } 977 978 // If this layer has backing, then we are collecting its children, otherwise appending 979 // to the compositing child list of an enclosing layer. 980 Vector<GraphicsLayer*> layerChildren; 981 Vector<GraphicsLayer*>& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer; 982 983 CompositingState childState = compositingState; 984 if (layer->isComposited()) 985 childState.m_compositingAncestor = layer; 986 987 #ifndef NDEBUG 988 ++childState.m_depth; 989 #endif 990 991 // The children of this stacking context don't need to composite, unless there is 992 // a compositing layer among them, so start by assuming false. 993 childState.m_subtreeIsCompositing = false; 994 995 if (layer->isStackingContext()) { 996 ASSERT(!layer->m_zOrderListsDirty); 997 998 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 999 size_t listSize = negZOrderList->size(); 1000 for (size_t i = 0; i < listSize; ++i) { 1001 RenderLayer* curLayer = negZOrderList->at(i); 1002 rebuildCompositingLayerTree(curLayer, childState, childList); 1003 } 1004 } 1005 1006 // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. 1007 if (layerBacking && layerBacking->foregroundLayer()) 1008 childList.append(layerBacking->foregroundLayer()); 1009 } 1010 1011 ASSERT(!layer->m_normalFlowListDirty); 1012 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 1013 size_t listSize = normalFlowList->size(); 1014 for (size_t i = 0; i < listSize; ++i) { 1015 RenderLayer* curLayer = normalFlowList->at(i); 1016 rebuildCompositingLayerTree(curLayer, childState, childList); 1017 } 1018 } 1019 1020 if (layer->isStackingContext()) { 1021 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 1022 size_t listSize = posZOrderList->size(); 1023 for (size_t i = 0; i < listSize; ++i) { 1024 RenderLayer* curLayer = posZOrderList->at(i); 1025 rebuildCompositingLayerTree(curLayer, childState, childList); 1026 } 1027 } 1028 } 1029 1030 if (layerBacking) { 1031 bool parented = false; 1032 if (layer->renderer()->isRenderPart()) 1033 parented = parentFrameContentLayers(toRenderPart(layer->renderer())); 1034 1035 // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer. 1036 // Otherwise, the overflow control layers are normal children. 1037 if (!layerBacking->hasClippingLayer()) { 1038 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) { 1039 overflowControlLayer->removeFromParent(); 1040 layerChildren.append(overflowControlLayer); 1041 } 1042 1043 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForVerticalScrollbar()) { 1044 overflowControlLayer->removeFromParent(); 1045 layerChildren.append(overflowControlLayer); 1046 } 1047 1048 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForScrollCorner()) { 1049 overflowControlLayer->removeFromParent(); 1050 layerChildren.append(overflowControlLayer); 1051 } 1052 } 1053 1054 if (!parented) 1055 layerBacking->parentForSublayers()->setChildren(layerChildren); 1056 1057 #if ENABLE(FULLSCREEN_API) 1058 // For the sake of clients of the full screen renderer, don't reparent 1059 // the full screen layer out from under them if they're in the middle of 1060 // animating. 1061 if (layer->renderer()->isRenderFullScreen() && toRenderFullScreen(layer->renderer())->isAnimating()) 1062 return; 1063 #endif 1064 childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers()); 1065 } 1066 } 1067 1068 void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset) 1069 { 1070 if (m_overflowControlsHostLayer) 1071 m_overflowControlsHostLayer->setPosition(contentsOffset); 1072 } 1073 1074 void RenderLayerCompositor::frameViewDidChangeSize() 1075 { 1076 if (m_clipLayer) { 1077 FrameView* frameView = m_renderView->frameView(); 1078 m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size()); 1079 1080 IntPoint scrollPosition = frameView->scrollPosition(); 1081 m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y())); 1082 updateOverflowControlsLayers(); 1083 } 1084 } 1085 1086 void RenderLayerCompositor::frameViewDidScroll(const IntPoint& scrollPosition) 1087 { 1088 if (m_scrollLayer) 1089 m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y())); 1090 } 1091 1092 String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo) 1093 { 1094 if (compositingLayerUpdatePending()) 1095 updateCompositingLayers(); 1096 1097 if (!m_rootPlatformLayer) 1098 return String(); 1099 1100 // We skip dumping the scroll and clip layers to keep layerTreeAsText output 1101 // similar between platforms. 1102 return m_rootPlatformLayer->layerTreeAsText(showDebugInfo ? LayerTreeAsTextDebug : LayerTreeAsTextBehaviorNormal); 1103 } 1104 1105 RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer) 1106 { 1107 if (!renderer->node()->isFrameOwnerElement()) 1108 return 0; 1109 1110 HTMLFrameOwnerElement* element = static_cast<HTMLFrameOwnerElement*>(renderer->node()); 1111 if (Document* contentDocument = element->contentDocument()) { 1112 if (RenderView* view = contentDocument->renderView()) 1113 return view->compositor(); 1114 } 1115 return 0; 1116 } 1117 1118 bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer) 1119 { 1120 RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer); 1121 if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame) 1122 return false; 1123 1124 RenderLayer* layer = renderer->layer(); 1125 if (!layer->isComposited()) 1126 return false; 1127 1128 RenderLayerBacking* backing = layer->backing(); 1129 GraphicsLayer* hostingLayer = backing->parentForSublayers(); 1130 GraphicsLayer* rootLayer = innerCompositor->rootPlatformLayer(); 1131 if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) { 1132 hostingLayer->removeAllChildren(); 1133 hostingLayer->addChild(rootLayer); 1134 } 1135 return true; 1136 } 1137 1138 // This just updates layer geometry without changing the hierarchy. 1139 void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer) 1140 { 1141 if (RenderLayerBacking* layerBacking = layer->backing()) { 1142 // The compositing state of all our children has been updated already, so now 1143 // we can compute and cache the composited bounds for this layer. 1144 layerBacking->updateCompositedBounds(); 1145 1146 if (RenderLayer* reflection = layer->reflectionLayer()) { 1147 if (reflection->backing()) 1148 reflection->backing()->updateCompositedBounds(); 1149 } 1150 1151 layerBacking->updateGraphicsLayerConfiguration(); 1152 layerBacking->updateGraphicsLayerGeometry(); 1153 1154 if (!layer->parent()) 1155 updateRootLayerPosition(); 1156 } 1157 1158 if (layer->isStackingContext()) { 1159 ASSERT(!layer->m_zOrderListsDirty); 1160 1161 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 1162 size_t listSize = negZOrderList->size(); 1163 for (size_t i = 0; i < listSize; ++i) 1164 updateLayerTreeGeometry(negZOrderList->at(i)); 1165 } 1166 } 1167 1168 ASSERT(!layer->m_normalFlowListDirty); 1169 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 1170 size_t listSize = normalFlowList->size(); 1171 for (size_t i = 0; i < listSize; ++i) 1172 updateLayerTreeGeometry(normalFlowList->at(i)); 1173 } 1174 1175 if (layer->isStackingContext()) { 1176 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 1177 size_t listSize = posZOrderList->size(); 1178 for (size_t i = 0; i < listSize; ++i) 1179 updateLayerTreeGeometry(posZOrderList->at(i)); 1180 } 1181 } 1182 } 1183 1184 // Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry. 1185 void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth updateDepth) 1186 { 1187 if (layer != compositingAncestor) { 1188 if (RenderLayerBacking* layerBacking = layer->backing()) { 1189 layerBacking->updateCompositedBounds(); 1190 1191 if (RenderLayer* reflection = layer->reflectionLayer()) { 1192 if (reflection->backing()) 1193 reflection->backing()->updateCompositedBounds(); 1194 } 1195 1196 layerBacking->updateGraphicsLayerGeometry(); 1197 if (updateDepth == RenderLayerBacking::CompositingChildren) 1198 return; 1199 } 1200 } 1201 1202 if (layer->reflectionLayer()) 1203 updateCompositingDescendantGeometry(compositingAncestor, layer->reflectionLayer(), updateDepth); 1204 1205 if (!layer->hasCompositingDescendant()) 1206 return; 1207 1208 if (layer->isStackingContext()) { 1209 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 1210 size_t listSize = negZOrderList->size(); 1211 for (size_t i = 0; i < listSize; ++i) 1212 updateCompositingDescendantGeometry(compositingAncestor, negZOrderList->at(i), updateDepth); 1213 } 1214 } 1215 1216 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 1217 size_t listSize = normalFlowList->size(); 1218 for (size_t i = 0; i < listSize; ++i) 1219 updateCompositingDescendantGeometry(compositingAncestor, normalFlowList->at(i), updateDepth); 1220 } 1221 1222 if (layer->isStackingContext()) { 1223 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 1224 size_t listSize = posZOrderList->size(); 1225 for (size_t i = 0; i < listSize; ++i) 1226 updateCompositingDescendantGeometry(compositingAncestor, posZOrderList->at(i), updateDepth); 1227 } 1228 } 1229 } 1230 1231 1232 void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect) 1233 { 1234 recursiveRepaintLayerRect(rootRenderLayer(), absRect); 1235 } 1236 1237 void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect) 1238 { 1239 // FIXME: This method does not work correctly with transforms. 1240 if (layer->isComposited()) 1241 layer->setBackingNeedsRepaintInRect(rect); 1242 1243 if (layer->hasCompositingDescendant()) { 1244 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 1245 size_t listSize = negZOrderList->size(); 1246 for (size_t i = 0; i < listSize; ++i) { 1247 RenderLayer* curLayer = negZOrderList->at(i); 1248 int x = 0; 1249 int y = 0; 1250 curLayer->convertToLayerCoords(layer, x, y); 1251 IntRect childRect(rect); 1252 childRect.move(-x, -y); 1253 recursiveRepaintLayerRect(curLayer, childRect); 1254 } 1255 } 1256 1257 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 1258 size_t listSize = posZOrderList->size(); 1259 for (size_t i = 0; i < listSize; ++i) { 1260 RenderLayer* curLayer = posZOrderList->at(i); 1261 int x = 0; 1262 int y = 0; 1263 curLayer->convertToLayerCoords(layer, x, y); 1264 IntRect childRect(rect); 1265 childRect.move(-x, -y); 1266 recursiveRepaintLayerRect(curLayer, childRect); 1267 } 1268 } 1269 } 1270 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 1271 size_t listSize = normalFlowList->size(); 1272 for (size_t i = 0; i < listSize; ++i) { 1273 RenderLayer* curLayer = normalFlowList->at(i); 1274 int x = 0; 1275 int y = 0; 1276 curLayer->convertToLayerCoords(layer, x, y); 1277 IntRect childRect(rect); 1278 childRect.move(-x, -y); 1279 recursiveRepaintLayerRect(curLayer, childRect); 1280 } 1281 } 1282 } 1283 1284 RenderLayer* RenderLayerCompositor::rootRenderLayer() const 1285 { 1286 return m_renderView->layer(); 1287 } 1288 1289 GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const 1290 { 1291 if (m_overflowControlsHostLayer) 1292 return m_overflowControlsHostLayer.get(); 1293 return m_rootPlatformLayer.get(); 1294 } 1295 1296 void RenderLayerCompositor::didMoveOnscreen() 1297 { 1298 if (!inCompositingMode() || m_rootLayerAttachment != RootLayerUnattached) 1299 return; 1300 1301 RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient; 1302 attachRootPlatformLayer(attachment); 1303 } 1304 1305 void RenderLayerCompositor::willMoveOffscreen() 1306 { 1307 if (!inCompositingMode() || m_rootLayerAttachment == RootLayerUnattached) 1308 return; 1309 1310 detachRootPlatformLayer(); 1311 } 1312 1313 void RenderLayerCompositor::updateRootLayerPosition() 1314 { 1315 if (m_rootPlatformLayer) { 1316 m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); 1317 m_rootPlatformLayer->setPosition(FloatPoint(m_renderView->docLeft(), m_renderView->docTop())); 1318 } 1319 if (m_clipLayer) { 1320 FrameView* frameView = m_renderView->frameView(); 1321 m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size()); 1322 } 1323 } 1324 1325 void RenderLayerCompositor::didStartAcceleratedAnimation(CSSPropertyID property) 1326 { 1327 // If an accelerated animation or transition runs, we have to turn off overlap checking because 1328 // we don't do layout for every frame, but we have to ensure that the layering is 1329 // correct between the animating object and other objects on the page. 1330 if (property == CSSPropertyWebkitTransform) 1331 setCompositingConsultsOverlap(false); 1332 } 1333 1334 bool RenderLayerCompositor::has3DContent() const 1335 { 1336 return layerHas3DContent(rootRenderLayer()); 1337 } 1338 1339 bool RenderLayerCompositor::allowsIndependentlyCompositedFrames(const FrameView* view) 1340 { 1341 #if PLATFORM(MAC) 1342 // frames are only independently composited in Mac pre-WebKit2. 1343 return view->platformWidget(); 1344 #endif 1345 return false; 1346 } 1347 1348 bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingFrame() const 1349 { 1350 #if PLATFORM(ANDROID) 1351 if (enclosingFrameElement() && !allowsIndependentlyCompositedFrames(m_renderView->frameView())) 1352 return true; 1353 #endif 1354 // Parent document content needs to be able to render on top of a composited frame, so correct behavior 1355 // is to have the parent document become composited too. However, this can cause problems on platforms that 1356 // use native views for frames (like Mac), so disable that behavior on those platforms for now. 1357 HTMLFrameOwnerElement* ownerElement = enclosingFrameElement(); 1358 RenderObject* renderer = ownerElement ? ownerElement->renderer() : 0; 1359 1360 // If we are the top-level frame, don't propagate. 1361 if (!ownerElement) 1362 return false; 1363 1364 if (!allowsIndependentlyCompositedFrames(m_renderView->frameView())) 1365 return true; 1366 1367 if (!renderer || !renderer->isRenderPart()) 1368 return false; 1369 1370 // On Mac, only propagate compositing if the frame is overlapped in the parent 1371 // document, or the parent is already compositing, or the main frame is scaled. 1372 Frame* frame = m_renderView->frameView()->frame(); 1373 Page* page = frame ? frame->page() : 0; 1374 if (page->mainFrame()->pageScaleFactor() != 1) 1375 return true; 1376 1377 RenderPart* frameRenderer = toRenderPart(renderer); 1378 if (frameRenderer->widget()) { 1379 ASSERT(frameRenderer->widget()->isFrameView()); 1380 FrameView* view = static_cast<FrameView*>(frameRenderer->widget()); 1381 if (view->isOverlappedIncludingAncestors() || view->hasCompositingAncestor()) 1382 return true; 1383 } 1384 1385 return false; 1386 } 1387 1388 HTMLFrameOwnerElement* RenderLayerCompositor::enclosingFrameElement() const 1389 { 1390 if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement()) 1391 return (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(objectTag)) ? ownerElement : 0; 1392 1393 return 0; 1394 } 1395 1396 bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const 1397 { 1398 if (!canBeComposited(layer)) 1399 return false; 1400 1401 // The root layer always has a compositing layer, but it may not have backing. 1402 #if PLATFORM(ANDROID) 1403 // If we do not have a root platform layer, don't use the 1404 // mustOverlapCompositedLayers() as a cue that this layer needs to be 1405 // composited -- the layers tree has been detached. 1406 // Otherwise we can end up in a cycle where updateBacking() switches composited 1407 // mode on because a layer has mustOverlapCompositedLayers() (by calling 1408 // enableCompositingMode()), while computeCompositingRequirements() will 1409 // (correctly) say that we do not need to be in composited mode and turns it 1410 // off, rince and repeat... 1411 return requiresCompositingLayer(layer) 1412 || (m_rootPlatformLayer && layer->mustOverlapCompositedLayers()) 1413 || (inCompositingMode() && layer->isRootLayer()); 1414 #else 1415 return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers() || (inCompositingMode() && layer->isRootLayer()); 1416 #endif 1417 } 1418 1419 #if PLATFORM(ANDROID) 1420 bool RenderLayerCompositor::requiresCompositingForAndroidLayers(const RenderLayer* layer) const 1421 { 1422 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1423 if (layer->hasOverflowScroll()) 1424 return true; 1425 if (layer->isRootLayer() && m_renderView->frameView()->hasOverflowScroll()) 1426 return true; 1427 #endif 1428 #if ENABLE(COMPOSITED_FIXED_ELEMENTS) 1429 1430 // Enable composited layers (for fixed elements) 1431 if (layer->isFixed()) 1432 return true; 1433 #endif 1434 1435 if (layer->renderer()->isCanvas()) 1436 return true; 1437 1438 if (layer->renderer()->style()->hasFixedBackgroundImage()) 1439 return true; 1440 1441 return false; 1442 } 1443 #endif 1444 1445 // Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. 1446 // Use needsToBeComposited() to determine if a RL actually needs a compositing layer. 1447 // static 1448 bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const 1449 { 1450 RenderObject* renderer = layer->renderer(); 1451 // The compositing state of a reflection should match that of its reflected layer. 1452 if (layer->isReflection()) { 1453 renderer = renderer->parent(); // The RenderReplica's parent is the object being reflected. 1454 layer = toRenderBoxModelObject(renderer)->layer(); 1455 } 1456 return requiresCompositingForTransform(renderer) 1457 #if PLATFORM(ANDROID) 1458 || requiresCompositingForAndroidLayers(layer) 1459 #endif 1460 || requiresCompositingForVideo(renderer) 1461 || requiresCompositingForCanvas(renderer) 1462 || requiresCompositingForPlugin(renderer) 1463 || requiresCompositingForFrame(renderer) 1464 || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden) 1465 || clipsCompositingDescendants(layer) 1466 || requiresCompositingForAnimation(renderer) 1467 || requiresCompositingForFullScreen(renderer); 1468 } 1469 1470 bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const 1471 { 1472 return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer(); 1473 } 1474 1475 // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, 1476 // up to the enclosing compositing ancestor. This is required because compositing layers are parented 1477 // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy. 1478 // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy, 1479 // but a sibling in the z-order hierarchy. 1480 bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const 1481 { 1482 if (!layer->isComposited() || !layer->parent()) 1483 return false; 1484 1485 RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); 1486 if (!compositingAncestor) 1487 return false; 1488 1489 // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(), 1490 // so we only care about clipping between its first child that is our ancestor (the computeClipRoot), 1491 // and layer. 1492 RenderLayer* computeClipRoot = 0; 1493 RenderLayer* curr = layer; 1494 while (curr) { 1495 RenderLayer* next = curr->parent(); 1496 if (next == compositingAncestor) { 1497 computeClipRoot = curr; 1498 break; 1499 } 1500 curr = next; 1501 } 1502 1503 if (!computeClipRoot || computeClipRoot == layer) 1504 return false; 1505 1506 IntRect backgroundRect = layer->backgroundClipRect(computeClipRoot, true); 1507 return backgroundRect != PaintInfo::infiniteRect(); 1508 } 1509 1510 // Return true if the given layer is a stacking context and has compositing child 1511 // layers that it needs to clip. In this case we insert a clipping GraphicsLayer 1512 // into the hierarchy between this layer and its children in the z-order hierarchy. 1513 bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const 1514 { 1515 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1516 if (layer->hasOverflowScroll()) 1517 return false; 1518 #endif 1519 return layer->hasCompositingDescendant() && 1520 (layer->renderer()->hasOverflowClip() || layer->renderer()->hasClip()); 1521 } 1522 1523 bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const 1524 { 1525 if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger)) 1526 return false; 1527 1528 RenderStyle* style = renderer->style(); 1529 // Note that we ask the renderer if it has a transform, because the style may have transforms, 1530 // but the renderer may be an inline that doesn't suppport them. 1531 return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective()); 1532 } 1533 1534 bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const 1535 { 1536 if (!(m_compositingTriggers & ChromeClient::VideoTrigger)) 1537 return false; 1538 #if ENABLE(VIDEO) 1539 if (renderer->isVideo()) { 1540 RenderVideo* video = toRenderVideo(renderer); 1541 return video->shouldDisplayVideo() && canAccelerateVideoRendering(video); 1542 } 1543 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) 1544 else if (renderer->isRenderPart()) { 1545 if (!m_hasAcceleratedCompositing) 1546 return false; 1547 1548 Node* node = renderer->node(); 1549 if (!node || (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag))) 1550 return false; 1551 1552 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node); 1553 return mediaElement->player() ? mediaElement->player()->supportsAcceleratedRendering() : false; 1554 } 1555 #endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO) 1556 #else 1557 UNUSED_PARAM(renderer); 1558 #endif 1559 return false; 1560 } 1561 1562 bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const 1563 { 1564 if (!(m_compositingTriggers & ChromeClient::CanvasTrigger)) 1565 return false; 1566 1567 if (renderer->isCanvas()) { 1568 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); 1569 return canvas->renderingContext() && canvas->renderingContext()->isAccelerated(); 1570 } 1571 return false; 1572 } 1573 1574 bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) const 1575 { 1576 if (!(m_compositingTriggers & ChromeClient::PluginTrigger)) 1577 return false; 1578 1579 bool composite = (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) 1580 || (renderer->isApplet() && toRenderApplet(renderer)->allowsAcceleratedCompositing()); 1581 if (!composite) 1582 return false; 1583 1584 m_compositingDependsOnGeometry = true; 1585 1586 RenderWidget* pluginRenderer = toRenderWidget(renderer); 1587 // If we can't reliably know the size of the plugin yet, don't change compositing state. 1588 if (pluginRenderer->needsLayout()) 1589 return pluginRenderer->hasLayer() && pluginRenderer->layer()->isComposited(); 1590 1591 // Don't go into compositing mode if height or width are zero, or size is 1x1. 1592 IntRect contentBox = pluginRenderer->contentBoxRect(); 1593 #if PLATFORM(ANDROID) 1594 // allow all plugins including 1x1 to be composited, so that they are drawn, 1595 // and acquire an ANativeWindow on the UI thread 1596 return contentBox.height() * contentBox.width() > 0; 1597 #else 1598 return contentBox.height() * contentBox.width() > 1; 1599 #endif 1600 } 1601 1602 bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) const 1603 { 1604 if (!renderer->isRenderPart()) 1605 return false; 1606 1607 RenderPart* frameRenderer = toRenderPart(renderer); 1608 1609 if (!frameRenderer->requiresAcceleratedCompositing()) 1610 return false; 1611 1612 m_compositingDependsOnGeometry = true; 1613 1614 RenderLayerCompositor* innerCompositor = frameContentsCompositor(frameRenderer); 1615 if (!innerCompositor || !innerCompositor->shouldPropagateCompositingToEnclosingFrame()) 1616 return false; 1617 1618 // If we can't reliably know the size of the iframe yet, don't change compositing state. 1619 if (renderer->needsLayout()) 1620 return frameRenderer->hasLayer() && frameRenderer->layer()->isComposited(); 1621 1622 // Don't go into compositing mode if height or width are zero. 1623 IntRect contentBox = frameRenderer->contentBoxRect(); 1624 return contentBox.height() * contentBox.width() > 0; 1625 } 1626 1627 bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const 1628 { 1629 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger)) 1630 return false; 1631 1632 if (AnimationController* animController = renderer->animation()) { 1633 #if PLATFORM(ANDROID) 1634 // android renders an opacity animation much faster if it's composited 1635 return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity)) 1636 #else 1637 return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode()) 1638 #endif 1639 || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform); 1640 } 1641 return false; 1642 } 1643 1644 bool RenderLayerCompositor::requiresCompositingWhenDescendantsAreCompositing(RenderObject* renderer) const 1645 { 1646 return renderer->hasTransform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection(); 1647 } 1648 1649 bool RenderLayerCompositor::requiresCompositingForFullScreen(RenderObject* renderer) const 1650 { 1651 #if ENABLE(FULLSCREEN_API) 1652 return renderer->isRenderFullScreen() && toRenderFullScreen(renderer)->isAnimating(); 1653 #else 1654 UNUSED_PARAM(renderer); 1655 return false; 1656 #endif 1657 } 1658 1659 // If an element has negative z-index children, those children render in front of the 1660 // layer background, so we need an extra 'contents' layer for the foreground of the layer 1661 // object. 1662 bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const 1663 { 1664 return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0); 1665 } 1666 1667 bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) const 1668 { 1669 // We need to handle our own scrolling if we're: 1670 return !m_renderView->frameView()->platformWidget() // viewless (i.e. non-Mac, or Mac in WebKit2) 1671 || attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac 1672 } 1673 1674 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) 1675 { 1676 if (!scrollbar) 1677 return; 1678 1679 context.save(); 1680 const IntRect& scrollbarRect = scrollbar->frameRect(); 1681 context.translate(-scrollbarRect.x(), -scrollbarRect.y()); 1682 IntRect transformedClip = clip; 1683 transformedClip.move(scrollbarRect.x(), scrollbarRect.y()); 1684 scrollbar->paint(&context, transformedClip); 1685 context.restore(); 1686 } 1687 1688 void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip) 1689 { 1690 if (graphicsLayer == layerForHorizontalScrollbar()) 1691 paintScrollbar(m_renderView->frameView()->horizontalScrollbar(), context, clip); 1692 else if (graphicsLayer == layerForVerticalScrollbar()) 1693 paintScrollbar(m_renderView->frameView()->verticalScrollbar(), context, clip); 1694 else if (graphicsLayer == layerForScrollCorner()) { 1695 const IntRect& scrollCorner = m_renderView->frameView()->scrollCornerRect(); 1696 context.save(); 1697 context.translate(-scrollCorner.x(), -scrollCorner.y()); 1698 IntRect transformedClip = clip; 1699 transformedClip.move(scrollCorner.x(), scrollCorner.y()); 1700 m_renderView->frameView()->paintScrollCorner(&context, transformedClip); 1701 context.restore(); 1702 } 1703 } 1704 1705 static bool shouldCompositeOverflowControls(ScrollView* view) 1706 { 1707 if (view->platformWidget()) 1708 return false; 1709 #if !PLATFORM(CHROMIUM) 1710 if (!view->hasOverlayScrollbars()) 1711 return false; 1712 #endif 1713 return true; 1714 } 1715 1716 bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const 1717 { 1718 ScrollView* view = m_renderView->frameView(); 1719 return shouldCompositeOverflowControls(view) && view->horizontalScrollbar(); 1720 } 1721 1722 bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const 1723 { 1724 ScrollView* view = m_renderView->frameView(); 1725 return shouldCompositeOverflowControls(view) && view->verticalScrollbar(); 1726 } 1727 1728 bool RenderLayerCompositor::requiresScrollCornerLayer() const 1729 { 1730 ScrollView* view = m_renderView->frameView(); 1731 return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible(); 1732 } 1733 1734 void RenderLayerCompositor::updateOverflowControlsLayers() 1735 { 1736 bool layersChanged = false; 1737 1738 if (requiresHorizontalScrollbarLayer()) { 1739 m_layerForHorizontalScrollbar = GraphicsLayer::create(this); 1740 #ifndef NDEBUG 1741 m_layerForHorizontalScrollbar->setName("horizontal scrollbar"); 1742 #endif 1743 m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get()); 1744 layersChanged = true; 1745 } else if (m_layerForHorizontalScrollbar) { 1746 m_layerForHorizontalScrollbar->removeFromParent(); 1747 m_layerForHorizontalScrollbar = 0; 1748 layersChanged = true; 1749 } 1750 1751 if (requiresVerticalScrollbarLayer()) { 1752 m_layerForVerticalScrollbar = GraphicsLayer::create(this); 1753 #ifndef NDEBUG 1754 m_layerForVerticalScrollbar->setName("vertical scrollbar"); 1755 #endif 1756 m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get()); 1757 layersChanged = true; 1758 } else if (m_layerForVerticalScrollbar) { 1759 m_layerForVerticalScrollbar->removeFromParent(); 1760 m_layerForVerticalScrollbar = 0; 1761 layersChanged = true; 1762 } 1763 1764 if (requiresScrollCornerLayer()) { 1765 m_layerForScrollCorner = GraphicsLayer::create(this); 1766 #ifndef NDEBUG 1767 m_layerForScrollCorner->setName("scroll corner"); 1768 #endif 1769 m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get()); 1770 layersChanged = true; 1771 } else if (m_layerForScrollCorner) { 1772 m_layerForScrollCorner->removeFromParent(); 1773 m_layerForScrollCorner = 0; 1774 layersChanged = true; 1775 } 1776 1777 if (layersChanged) 1778 m_renderView->frameView()->positionScrollbarLayers(); 1779 } 1780 1781 void RenderLayerCompositor::ensureRootPlatformLayer() 1782 { 1783 RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient; 1784 if (expectedAttachment == m_rootLayerAttachment) 1785 return; 1786 1787 if (!m_rootPlatformLayer) { 1788 m_rootPlatformLayer = GraphicsLayer::create(0); 1789 #ifndef NDEBUG 1790 m_rootPlatformLayer->setName("Root platform"); 1791 #endif 1792 m_rootPlatformLayer->setSize(FloatSize(m_renderView->maxXLayoutOverflow(), m_renderView->maxYLayoutOverflow())); 1793 m_rootPlatformLayer->setPosition(FloatPoint()); 1794 1795 // Need to clip to prevent transformed content showing outside this frame 1796 m_rootPlatformLayer->setMasksToBounds(true); 1797 } 1798 1799 if (requiresScrollLayer(expectedAttachment)) { 1800 if (!m_overflowControlsHostLayer) { 1801 ASSERT(!m_scrollLayer); 1802 ASSERT(!m_clipLayer); 1803 1804 // Create a layer to host the clipping layer and the overflow controls layers. 1805 m_overflowControlsHostLayer = GraphicsLayer::create(0); 1806 #ifndef NDEBUG 1807 m_overflowControlsHostLayer->setName("overflow controls host"); 1808 #endif 1809 1810 // Create a clipping layer if this is an iframe 1811 m_clipLayer = GraphicsLayer::create(this); 1812 #ifndef NDEBUG 1813 m_clipLayer->setName("iframe Clipping"); 1814 #endif 1815 m_clipLayer->setMasksToBounds(true); 1816 1817 m_scrollLayer = GraphicsLayer::create(this); 1818 #ifndef NDEBUG 1819 m_scrollLayer->setName("iframe scrolling"); 1820 #endif 1821 1822 // Hook them up 1823 m_overflowControlsHostLayer->addChild(m_clipLayer.get()); 1824 m_clipLayer->addChild(m_scrollLayer.get()); 1825 m_scrollLayer->addChild(m_rootPlatformLayer.get()); 1826 1827 frameViewDidChangeSize(); 1828 frameViewDidScroll(m_renderView->frameView()->scrollPosition()); 1829 } 1830 } else { 1831 if (m_overflowControlsHostLayer) { 1832 m_overflowControlsHostLayer = 0; 1833 m_clipLayer = 0; 1834 m_scrollLayer = 0; 1835 } 1836 } 1837 1838 // Check to see if we have to change the attachment 1839 if (m_rootLayerAttachment != RootLayerUnattached) 1840 detachRootPlatformLayer(); 1841 1842 attachRootPlatformLayer(expectedAttachment); 1843 } 1844 1845 void RenderLayerCompositor::destroyRootPlatformLayer() 1846 { 1847 if (!m_rootPlatformLayer) 1848 return; 1849 1850 detachRootPlatformLayer(); 1851 1852 if (m_layerForHorizontalScrollbar) { 1853 m_layerForHorizontalScrollbar->removeFromParent(); 1854 m_layerForHorizontalScrollbar = 0; 1855 if (Scrollbar* horizontalScrollbar = m_renderView->frameView()->verticalScrollbar()) 1856 m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size())); 1857 } 1858 1859 if (m_layerForVerticalScrollbar) { 1860 m_layerForVerticalScrollbar->removeFromParent(); 1861 m_layerForVerticalScrollbar = 0; 1862 if (Scrollbar* verticalScrollbar = m_renderView->frameView()->verticalScrollbar()) 1863 m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size())); 1864 } 1865 1866 if (m_layerForScrollCorner) { 1867 m_layerForScrollCorner = 0; 1868 m_renderView->frameView()->invalidateScrollCorner(); 1869 } 1870 1871 if (m_overflowControlsHostLayer) { 1872 m_overflowControlsHostLayer = 0; 1873 m_clipLayer = 0; 1874 m_scrollLayer = 0; 1875 } 1876 ASSERT(!m_scrollLayer); 1877 m_rootPlatformLayer = 0; 1878 } 1879 1880 void RenderLayerCompositor::attachRootPlatformLayer(RootLayerAttachment attachment) 1881 { 1882 if (!m_rootPlatformLayer) 1883 return; 1884 1885 switch (attachment) { 1886 case RootLayerUnattached: 1887 ASSERT_NOT_REACHED(); 1888 break; 1889 case RootLayerAttachedViaChromeClient: { 1890 Frame* frame = m_renderView->frameView()->frame(); 1891 Page* page = frame ? frame->page() : 0; 1892 if (!page) 1893 return; 1894 1895 page->chrome()->client()->attachRootGraphicsLayer(frame, rootPlatformLayer()); 1896 break; 1897 } 1898 case RootLayerAttachedViaEnclosingFrame: { 1899 // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration() 1900 // for the frame's renderer in the parent document. 1901 scheduleNeedsStyleRecalc(m_renderView->document()->ownerElement()); 1902 break; 1903 } 1904 } 1905 1906 m_rootLayerAttachment = attachment; 1907 rootLayerAttachmentChanged(); 1908 } 1909 1910 void RenderLayerCompositor::detachRootPlatformLayer() 1911 { 1912 if (!m_rootPlatformLayer || m_rootLayerAttachment == RootLayerUnattached) 1913 return; 1914 1915 switch (m_rootLayerAttachment) { 1916 case RootLayerAttachedViaEnclosingFrame: { 1917 // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration() 1918 // for the frame's renderer in the parent document. 1919 if (m_overflowControlsHostLayer) 1920 m_overflowControlsHostLayer->removeFromParent(); 1921 else 1922 m_rootPlatformLayer->removeFromParent(); 1923 1924 if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement()) 1925 scheduleNeedsStyleRecalc(ownerElement); 1926 break; 1927 } 1928 case RootLayerAttachedViaChromeClient: { 1929 Frame* frame = m_renderView->frameView()->frame(); 1930 Page* page = frame ? frame->page() : 0; 1931 if (!page) 1932 return; 1933 1934 page->chrome()->client()->attachRootGraphicsLayer(frame, 0); 1935 } 1936 break; 1937 case RootLayerUnattached: 1938 break; 1939 } 1940 1941 m_rootLayerAttachment = RootLayerUnattached; 1942 rootLayerAttachmentChanged(); 1943 } 1944 1945 void RenderLayerCompositor::updateRootLayerAttachment() 1946 { 1947 ensureRootPlatformLayer(); 1948 } 1949 1950 void RenderLayerCompositor::rootLayerAttachmentChanged() 1951 { 1952 // The attachment can affect whether the RenderView layer's paintingGoesToWindow() behavior, 1953 // so call updateGraphicsLayerGeometry() to udpate that. 1954 RenderLayer* layer = m_renderView->layer(); 1955 if (RenderLayerBacking* backing = layer ? layer->backing() : 0) 1956 backing->updateDrawsContent(); 1957 } 1958 1959 static void needsStyleRecalcCallback(Node* node) 1960 { 1961 node->setNeedsStyleRecalc(SyntheticStyleChange); 1962 } 1963 1964 void RenderLayerCompositor::scheduleNeedsStyleRecalc(Element* element) 1965 { 1966 if (ContainerNode::postAttachCallbacksAreSuspended()) 1967 ContainerNode::queuePostAttachCallback(needsStyleRecalcCallback, element); 1968 else 1969 element->setNeedsStyleRecalc(SyntheticStyleChange); 1970 } 1971 1972 // IFrames are special, because we hook compositing layers together across iframe boundaries 1973 // when both parent and iframe content are composited. So when this frame becomes composited, we have 1974 // to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite. 1975 void RenderLayerCompositor::notifyIFramesOfCompositingChange() 1976 { 1977 Frame* frame = m_renderView->frameView() ? m_renderView->frameView()->frame() : 0; 1978 if (!frame) 1979 return; 1980 1981 for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->traverseNext(frame)) { 1982 if (child->document() && child->document()->ownerElement()) 1983 scheduleNeedsStyleRecalc(child->document()->ownerElement()); 1984 } 1985 1986 // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so 1987 // we need to schedule a style recalc in our parent document. 1988 if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement()) 1989 scheduleNeedsStyleRecalc(ownerElement); 1990 } 1991 1992 bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const 1993 { 1994 const RenderStyle* style = layer->renderer()->style(); 1995 1996 if (style && 1997 (style->transformStyle3D() == TransformStyle3DPreserve3D || 1998 style->hasPerspective() || 1999 style->transform().has3DOperation())) 2000 return true; 2001 2002 if (layer->isStackingContext()) { 2003 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 2004 size_t listSize = negZOrderList->size(); 2005 for (size_t i = 0; i < listSize; ++i) { 2006 RenderLayer* curLayer = negZOrderList->at(i); 2007 if (layerHas3DContent(curLayer)) 2008 return true; 2009 } 2010 } 2011 2012 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 2013 size_t listSize = posZOrderList->size(); 2014 for (size_t i = 0; i < listSize; ++i) { 2015 RenderLayer* curLayer = posZOrderList->at(i); 2016 if (layerHas3DContent(curLayer)) 2017 return true; 2018 } 2019 } 2020 } 2021 2022 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 2023 size_t listSize = normalFlowList->size(); 2024 for (size_t i = 0; i < listSize; ++i) { 2025 RenderLayer* curLayer = normalFlowList->at(i); 2026 if (layerHas3DContent(curLayer)) 2027 return true; 2028 } 2029 } 2030 return false; 2031 } 2032 2033 void RenderLayerCompositor::updateContentsScale(float scale, RenderLayer* layer) 2034 { 2035 if (!layer) 2036 layer = rootRenderLayer(); 2037 2038 layer->updateContentsScale(scale); 2039 2040 if (layer->isStackingContext()) { 2041 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) { 2042 size_t listSize = negZOrderList->size(); 2043 for (size_t i = 0; i < listSize; ++i) 2044 updateContentsScale(scale, negZOrderList->at(i)); 2045 } 2046 2047 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) { 2048 size_t listSize = posZOrderList->size(); 2049 for (size_t i = 0; i < listSize; ++i) 2050 updateContentsScale(scale, posZOrderList->at(i)); 2051 } 2052 } 2053 2054 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) { 2055 size_t listSize = normalFlowList->size(); 2056 for (size_t i = 0; i < listSize; ++i) 2057 updateContentsScale(scale, normalFlowList->at(i)); 2058 } 2059 } 2060 2061 } // namespace WebCore 2062 2063 #endif // USE(ACCELERATED_COMPOSITING) 2064