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 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 "RenderLayerCompositor.h" 29 30#include "AnimationController.h" 31#include "CanvasRenderingContext.h" 32#include "CSSPropertyNames.h" 33#include "Chrome.h" 34#include "ChromeClient.h" 35#include "FlowThreadController.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 "InspectorInstrumentation.h" 44#include "Logging.h" 45#include "MainFrame.h" 46#include "NodeList.h" 47#include "Page.h" 48#include "RenderEmbeddedObject.h" 49#include "RenderFlowThread.h" 50#include "RenderFullScreen.h" 51#include "RenderGeometryMap.h" 52#include "RenderIFrame.h" 53#include "RenderLayerBacking.h" 54#include "RenderNamedFlowFragment.h" 55#include "RenderReplica.h" 56#include "RenderVideo.h" 57#include "RenderView.h" 58#include "ScrollingConstraints.h" 59#include "ScrollingCoordinator.h" 60#include "Settings.h" 61#include "TiledBacking.h" 62#include "TransformState.h" 63#include <wtf/CurrentTime.h> 64#include <wtf/TemporaryChange.h> 65#include <wtf/text/CString.h> 66#include <wtf/text/StringBuilder.h> 67 68#if PLATFORM(IOS) 69#include "LegacyTileCache.h" 70#include "MainFrame.h" 71#include "Region.h" 72#include "RenderScrollbar.h" 73#endif 74 75#ifndef NDEBUG 76#include "RenderTreeAsText.h" 77#endif 78 79#if ENABLE(3D_RENDERING) 80// This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm'). 81bool WebCoreHas3DRendering = true; 82#endif 83 84#if !PLATFORM(MAC) && !PLATFORM(IOS) 85#define WTF_USE_COMPOSITING_FOR_SMALL_CANVASES 1 86#endif 87 88namespace WebCore { 89 90static const int canvasAreaThresholdRequiringCompositing = 50 * 100; 91// During page loading delay layer flushes up to this many seconds to allow them coalesce, reducing workload. 92#if PLATFORM(IOS) 93static const double throttledLayerFlushInitialDelay = .5; 94static const double throttledLayerFlushDelay = 1.5; 95#else 96static const double throttledLayerFlushInitialDelay = .5; 97static const double throttledLayerFlushDelay = .5; 98#endif 99 100using namespace HTMLNames; 101 102class OverlapMapContainer { 103public: 104 void add(const IntRect& bounds) 105 { 106 m_layerRects.append(bounds); 107 m_boundingBox.unite(bounds); 108 } 109 110 bool overlapsLayers(const IntRect& bounds) const 111 { 112 // Checking with the bounding box will quickly reject cases when 113 // layers are created for lists of items going in one direction and 114 // never overlap with each other. 115 if (!bounds.intersects(m_boundingBox)) 116 return false; 117 for (unsigned i = 0; i < m_layerRects.size(); i++) { 118 if (m_layerRects[i].intersects(bounds)) 119 return true; 120 } 121 return false; 122 } 123 124 void unite(const OverlapMapContainer& otherContainer) 125 { 126 m_layerRects.appendVector(otherContainer.m_layerRects); 127 m_boundingBox.unite(otherContainer.m_boundingBox); 128 } 129private: 130 Vector<IntRect> m_layerRects; 131 IntRect m_boundingBox; 132}; 133 134class RenderLayerCompositor::OverlapMap { 135 WTF_MAKE_NONCOPYABLE(OverlapMap); 136public: 137 OverlapMap() 138 : m_geometryMap(UseTransforms) 139 { 140 // Begin assuming the root layer will be composited so that there is 141 // something on the stack. The root layer should also never get an 142 // popCompositingContainer call. 143 pushCompositingContainer(); 144 } 145 146 void add(const RenderLayer* layer, const IntRect& bounds) 147 { 148 // Layers do not contribute to overlap immediately--instead, they will 149 // contribute to overlap as soon as their composited ancestor has been 150 // recursively processed and popped off the stack. 151 ASSERT(m_overlapStack.size() >= 2); 152 m_overlapStack[m_overlapStack.size() - 2].add(bounds); 153 m_layers.add(layer); 154 } 155 156 bool contains(const RenderLayer* layer) 157 { 158 return m_layers.contains(layer); 159 } 160 161 bool overlapsLayers(const IntRect& bounds) const 162 { 163 return m_overlapStack.last().overlapsLayers(bounds); 164 } 165 166 bool isEmpty() 167 { 168 return m_layers.isEmpty(); 169 } 170 171 void pushCompositingContainer() 172 { 173 m_overlapStack.append(OverlapMapContainer()); 174 } 175 176 void popCompositingContainer() 177 { 178 m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last()); 179 m_overlapStack.removeLast(); 180 } 181 182 RenderGeometryMap& geometryMap() { return m_geometryMap; } 183 184private: 185 struct RectList { 186 Vector<IntRect> rects; 187 IntRect boundingRect; 188 189 void append(const IntRect& rect) 190 { 191 rects.append(rect); 192 boundingRect.unite(rect); 193 } 194 195 void append(const RectList& rectList) 196 { 197 rects.appendVector(rectList.rects); 198 boundingRect.unite(rectList.boundingRect); 199 } 200 201 bool intersects(const IntRect& rect) const 202 { 203 if (!rects.size() || !boundingRect.intersects(rect)) 204 return false; 205 206 for (unsigned i = 0; i < rects.size(); i++) { 207 if (rects[i].intersects(rect)) 208 return true; 209 } 210 return false; 211 } 212 }; 213 214 Vector<OverlapMapContainer> m_overlapStack; 215 HashSet<const RenderLayer*> m_layers; 216 RenderGeometryMap m_geometryMap; 217}; 218 219struct CompositingState { 220 CompositingState(RenderLayer* compAncestor, bool testOverlap = true) 221 : m_compositingAncestor(compAncestor) 222 , m_subtreeIsCompositing(false) 223 , m_testingOverlap(testOverlap) 224#if ENABLE(CSS_COMPOSITING) 225 , m_hasNotIsolatedCompositedBlendingDescendants(false) 226#endif 227#ifndef NDEBUG 228 , m_depth(0) 229#endif 230 { 231 } 232 233 CompositingState(const CompositingState& other) 234 : m_compositingAncestor(other.m_compositingAncestor) 235 , m_subtreeIsCompositing(other.m_subtreeIsCompositing) 236 , m_testingOverlap(other.m_testingOverlap) 237#if ENABLE(CSS_COMPOSITING) 238 , m_hasNotIsolatedCompositedBlendingDescendants(other.m_hasNotIsolatedCompositedBlendingDescendants) 239#endif 240#ifndef NDEBUG 241 , m_depth(other.m_depth + 1) 242#endif 243 { 244 } 245 246 RenderLayer* m_compositingAncestor; 247 bool m_subtreeIsCompositing; 248 bool m_testingOverlap; 249#if ENABLE(CSS_COMPOSITING) 250 bool m_hasNotIsolatedCompositedBlendingDescendants; 251#endif 252#ifndef NDEBUG 253 int m_depth; 254#endif 255}; 256 257 258#if !LOG_DISABLED 259static inline bool compositingLogEnabled() 260{ 261 return LogCompositing.state == WTFLogChannelOn; 262} 263#endif 264 265RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView) 266 : m_renderView(renderView) 267 , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired) 268 , m_hasAcceleratedCompositing(true) 269 , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers)) 270 , m_compositedLayerCount(0) 271 , m_showDebugBorders(false) 272 , m_showRepaintCounter(false) 273 , m_acceleratedDrawingEnabled(false) 274 , m_reevaluateCompositingAfterLayout(false) 275 , m_compositing(false) 276 , m_compositingLayersNeedRebuild(false) 277 , m_flushingLayers(false) 278 , m_shouldFlushOnReattach(false) 279 , m_forceCompositingMode(false) 280 , m_inPostLayoutUpdate(false) 281 , m_subframeScrollLayersNeedReattach(false) 282 , m_isTrackingRepaints(false) 283 , m_layersWithTiledBackingCount(0) 284 , m_rootLayerAttachment(RootLayerUnattached) 285 , m_layerFlushTimer(this, &RenderLayerCompositor::layerFlushTimerFired) 286 , m_layerFlushThrottlingEnabled(false) 287 , m_layerFlushThrottlingTemporarilyDisabledForInteraction(false) 288 , m_hasPendingLayerFlush(false) 289 , m_paintRelatedMilestonesTimer(this, &RenderLayerCompositor::paintRelatedMilestonesTimerFired) 290#if !LOG_DISABLED 291 , m_rootLayerUpdateCount(0) 292 , m_obligateCompositedLayerCount(0) 293 , m_secondaryCompositedLayerCount(0) 294 , m_obligatoryBackingStoreBytes(0) 295 , m_secondaryBackingStoreBytes(0) 296#endif 297{ 298} 299 300RenderLayerCompositor::~RenderLayerCompositor() 301{ 302 // Take care that the owned GraphicsLayers are deleted first as their destructors may call back here. 303 m_clipLayer = nullptr; 304 m_scrollLayer = nullptr; 305 ASSERT(m_rootLayerAttachment == RootLayerUnattached); 306} 307 308void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */) 309{ 310 if (enable != m_compositing) { 311 m_compositing = enable; 312 313 if (m_compositing) { 314 ensureRootLayer(); 315 notifyIFramesOfCompositingChange(); 316 } else 317 destroyRootLayer(); 318 } 319} 320 321void RenderLayerCompositor::cacheAcceleratedCompositingFlags() 322{ 323 bool hasAcceleratedCompositing = false; 324 bool showDebugBorders = false; 325 bool showRepaintCounter = false; 326 bool forceCompositingMode = false; 327 bool acceleratedDrawingEnabled = false; 328 329 const Settings& settings = m_renderView.frameView().frame().settings(); 330 hasAcceleratedCompositing = settings.acceleratedCompositingEnabled(); 331 332 // We allow the chrome to override the settings, in case the page is rendered 333 // on a chrome that doesn't allow accelerated compositing. 334 if (hasAcceleratedCompositing) { 335 if (Page* page = this->page()) { 336 m_compositingTriggers = page->chrome().client().allowedCompositingTriggers(); 337 hasAcceleratedCompositing = m_compositingTriggers; 338 } 339 } 340 341 showDebugBorders = settings.showDebugBorders(); 342 showRepaintCounter = settings.showRepaintCounter(); 343 forceCompositingMode = settings.forceCompositingMode() && hasAcceleratedCompositing; 344 345 if (forceCompositingMode && m_renderView.document().ownerElement()) 346 forceCompositingMode = requiresCompositingForScrollableFrame(); 347 348 acceleratedDrawingEnabled = settings.acceleratedDrawingEnabled(); 349 350 if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode) 351 setCompositingLayersNeedRebuild(); 352 353 bool debugBordersChanged = m_showDebugBorders != showDebugBorders; 354 m_hasAcceleratedCompositing = hasAcceleratedCompositing; 355 m_showDebugBorders = showDebugBorders; 356 m_showRepaintCounter = showRepaintCounter; 357 m_forceCompositingMode = forceCompositingMode; 358 m_acceleratedDrawingEnabled = acceleratedDrawingEnabled; 359 360 if (debugBordersChanged) { 361 if (m_layerForHorizontalScrollbar) 362 m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders); 363 364 if (m_layerForVerticalScrollbar) 365 m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders); 366 367 if (m_layerForScrollCorner) 368 m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders); 369 } 370} 371 372bool RenderLayerCompositor::canRender3DTransforms() const 373{ 374 return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger); 375} 376 377void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild) 378{ 379 if (inCompositingMode()) 380 m_compositingLayersNeedRebuild = needRebuild; 381} 382 383void RenderLayerCompositor::customPositionForVisibleRectComputation(const GraphicsLayer* graphicsLayer, FloatPoint& position) const 384{ 385 if (graphicsLayer != m_scrollLayer.get()) 386 return; 387 388 FloatPoint scrollPosition = -position; 389 390 if (m_renderView.frameView().scrollBehaviorForFixedElements() == StickToDocumentBounds) 391 scrollPosition = m_renderView.frameView().constrainScrollPositionForOverhang(roundedIntPoint(scrollPosition)); 392 393 position = -scrollPosition; 394} 395 396void RenderLayerCompositor::notifyFlushRequired(const GraphicsLayer* layer) 397{ 398 scheduleLayerFlush(layer->canThrottleLayerFlush()); 399} 400 401void RenderLayerCompositor::scheduleLayerFlushNow() 402{ 403 m_hasPendingLayerFlush = false; 404 if (Page* page = this->page()) 405 page->chrome().client().scheduleCompositingLayerFlush(); 406} 407 408void RenderLayerCompositor::scheduleLayerFlush(bool canThrottle) 409{ 410 ASSERT(!m_flushingLayers); 411 412 if (canThrottle) 413 startInitialLayerFlushTimerIfNeeded(); 414 415 if (canThrottle && isThrottlingLayerFlushes()) { 416 m_hasPendingLayerFlush = true; 417 return; 418 } 419 scheduleLayerFlushNow(); 420} 421 422#if PLATFORM(IOS) 423ChromeClient* RenderLayerCompositor::chromeClient() const 424{ 425 Page* page = m_renderView.frameView().frame().page(); 426 if (!page) 427 return 0; 428 return &page->chrome().client(); 429} 430#endif 431 432void RenderLayerCompositor::flushPendingLayerChanges(bool isFlushRoot) 433{ 434 // FrameView::flushCompositingStateIncludingSubframes() flushes each subframe, 435 // but GraphicsLayer::flushCompositingState() will cross frame boundaries 436 // if the GraphicsLayers are connected (the RootLayerAttachedViaEnclosingFrame case). 437 // As long as we're not the root of the flush, we can bail. 438 if (!isFlushRoot && rootLayerAttachment() == RootLayerAttachedViaEnclosingFrame) 439 return; 440 441 if (rootLayerAttachment() == RootLayerUnattached) { 442#if PLATFORM(IOS) 443 startLayerFlushTimerIfNeeded(); 444#endif 445 m_shouldFlushOnReattach = true; 446 return; 447 } 448 449 FrameView& frameView = m_renderView.frameView(); 450 AnimationUpdateBlock animationUpdateBlock(&frameView.frame().animation()); 451 452 ASSERT(!m_flushingLayers); 453 m_flushingLayers = true; 454 455 if (GraphicsLayer* rootLayer = rootGraphicsLayer()) { 456#if PLATFORM(IOS) 457 double horizontalMargin = defaultTileWidth / pageScaleFactor(); 458 double verticalMargin = defaultTileHeight / pageScaleFactor(); 459 FloatRect visibleRect = frameView.computeCoverageRect(horizontalMargin, verticalMargin); 460 rootLayer->flushCompositingState(visibleRect); 461#else 462 // Having a m_clipLayer indicates that we're doing scrolling via GraphicsLayers. 463 IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView.unscaledVisibleContentSizeIncludingObscuredArea()) : frameView.visibleContentRect(); 464 if (!frameView.exposedRect().isInfinite()) 465 visibleRect.intersect(IntRect(frameView.exposedRect())); 466 rootLayer->flushCompositingState(visibleRect); 467#endif 468 } 469 470 ASSERT(m_flushingLayers); 471 m_flushingLayers = false; 472 473 updateScrollCoordinatedLayersAfterFlushIncludingSubframes(); 474 475#if PLATFORM(IOS) 476 ChromeClient* client = this->chromeClient(); 477 if (client && isFlushRoot) 478 client->didFlushCompositingLayers(); 479#endif 480 481 startLayerFlushTimerIfNeeded(); 482} 483 484void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlushIncludingSubframes() 485{ 486 updateScrollCoordinatedLayersAfterFlush(); 487 488 Frame& frame = m_renderView.frameView().frame(); 489 for (Frame* subframe = frame.tree().firstChild(); subframe; subframe = subframe->tree().traverseNext(&frame)) { 490 RenderView* view = subframe->contentRenderer(); 491 if (!view) 492 continue; 493 494 view->compositor().updateScrollCoordinatedLayersAfterFlush(); 495 } 496} 497 498void RenderLayerCompositor::updateScrollCoordinatedLayersAfterFlush() 499{ 500#if PLATFORM(IOS) 501 updateCustomLayersAfterFlush(); 502#endif 503 504 for (auto it = m_scrollCoordinatedLayersNeedingUpdate.begin(), end = m_scrollCoordinatedLayersNeedingUpdate.end(); it != end; ++it) 505 updateScrollCoordinatedStatus(**it); 506 507 m_scrollCoordinatedLayersNeedingUpdate.clear(); 508} 509 510#if PLATFORM(IOS) 511static bool scrollbarHasDisplayNone(Scrollbar* scrollbar) 512{ 513 if (!scrollbar || !scrollbar->isCustomScrollbar()) 514 return false; 515 516 RefPtr<RenderStyle> scrollbarStyle = static_cast<RenderScrollbar*>(scrollbar)->getScrollbarPseudoStyle(ScrollbarBGPart, SCROLLBAR); 517 return scrollbarStyle && scrollbarStyle->display() == NONE; 518} 519 520// FIXME: Can we make |layer| const RenderLayer&? 521static void updateScrollingLayerWithClient(RenderLayer& layer, ChromeClient* client) 522{ 523 if (!client) 524 return; 525 526 RenderLayerBacking* backing = layer.backing(); 527 ASSERT(backing); 528 529 bool allowHorizontalScrollbar = !scrollbarHasDisplayNone(layer.horizontalScrollbar()); 530 bool allowVerticalScrollbar = !scrollbarHasDisplayNone(layer.verticalScrollbar()); 531 client->addOrUpdateScrollingLayer(layer.renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer(), 532 layer.scrollableContentsSize(), allowHorizontalScrollbar, allowVerticalScrollbar); 533} 534 535void RenderLayerCompositor::updateCustomLayersAfterFlush() 536{ 537 registerAllViewportConstrainedLayers(); 538 539 if (!m_scrollingLayersNeedingUpdate.isEmpty()) { 540 ChromeClient* chromeClient = this->chromeClient(); 541 542 for (auto it = m_scrollingLayersNeedingUpdate.begin(), end = m_scrollingLayersNeedingUpdate.end(); it != end; ++it) 543 updateScrollingLayerWithClient(**it, chromeClient); 544 m_scrollingLayersNeedingUpdate.clear(); 545 } 546 m_scrollingLayersNeedingUpdate.clear(); 547} 548#endif 549 550void RenderLayerCompositor::didFlushChangesForLayer(RenderLayer& layer, const GraphicsLayer* graphicsLayer) 551{ 552 if (m_scrollCoordinatedLayers.contains(&layer)) 553 m_scrollCoordinatedLayersNeedingUpdate.add(&layer); 554 555#if PLATFORM(IOS) 556 if (m_scrollingLayers.contains(&layer)) 557 m_scrollingLayersNeedingUpdate.add(&layer); 558#endif 559 560 RenderLayerBacking* backing = layer.backing(); 561 if (backing->backgroundLayerPaintsFixedRootBackground() && graphicsLayer == backing->backgroundLayer()) 562 fixedRootBackgroundLayerChanged(); 563} 564 565void RenderLayerCompositor::didPaintBacking(RenderLayerBacking*) 566{ 567 FrameView& frameView = m_renderView.frameView(); 568 frameView.setLastPaintTime(monotonicallyIncreasingTime()); 569 if (frameView.milestonesPendingPaint() && !m_paintRelatedMilestonesTimer.isActive()) 570 m_paintRelatedMilestonesTimer.startOneShot(0); 571} 572 573void RenderLayerCompositor::didChangeVisibleRect() 574{ 575 GraphicsLayer* rootLayer = rootGraphicsLayer(); 576 if (!rootLayer) 577 return; 578 579 const FrameView& frameView = m_renderView.frameView(); 580 581#if PLATFORM(IOS) 582 IntRect visibleRect = enclosingIntRect(frameView.exposedContentRect()); 583#else 584 IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView.contentsSize()) : frameView.visibleContentRect(); 585#endif 586 if (!rootLayer->visibleRectChangeRequiresFlush(visibleRect)) 587 return; 588 scheduleLayerFlushNow(); 589} 590 591void RenderLayerCompositor::notifyFlushBeforeDisplayRefresh(const GraphicsLayer*) 592{ 593 if (!m_layerUpdater) { 594 PlatformDisplayID displayID = 0; 595 if (Page* page = this->page()) 596 displayID = page->chrome().displayID(); 597 598 m_layerUpdater = std::make_unique<GraphicsLayerUpdater>(this, displayID); 599 } 600 601 m_layerUpdater->scheduleUpdate(); 602} 603 604void RenderLayerCompositor::flushLayersSoon(GraphicsLayerUpdater*) 605{ 606 scheduleLayerFlush(true); 607} 608 609void RenderLayerCompositor::layerTiledBackingUsageChanged(const GraphicsLayer* graphicsLayer, bool usingTiledBacking) 610{ 611 if (usingTiledBacking) { 612 ++m_layersWithTiledBackingCount; 613 614 if (Page* page = this->page()) 615 graphicsLayer->tiledBacking()->setIsInWindow(page->isInWindow()); 616 } else { 617 ASSERT(m_layersWithTiledBackingCount > 0); 618 --m_layersWithTiledBackingCount; 619 } 620} 621 622RenderLayerCompositor* RenderLayerCompositor::enclosingCompositorFlushingLayers() const 623{ 624 for (Frame* frame = &m_renderView.frameView().frame(); frame; frame = frame->tree().parent()) { 625 RenderLayerCompositor* compositor = frame->contentRenderer() ? &frame->contentRenderer()->compositor() : nullptr; 626 if (compositor->isFlushingLayers()) 627 return compositor; 628 } 629 630 return 0; 631} 632 633void RenderLayerCompositor::scheduleCompositingLayerUpdate() 634{ 635 if (!m_updateCompositingLayersTimer.isActive()) 636 m_updateCompositingLayersTimer.startOneShot(0); 637} 638 639void RenderLayerCompositor::updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>&) 640{ 641 updateCompositingLayers(CompositingUpdateAfterLayout); 642} 643 644bool RenderLayerCompositor::hasAnyAdditionalCompositedLayers(const RenderLayer& rootLayer) const 645{ 646 return m_compositedLayerCount > (rootLayer.isComposited() ? 1 : 0); 647} 648 649void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot) 650{ 651 m_updateCompositingLayersTimer.stop(); 652 653 ASSERT(!m_renderView.document().inPageCache()); 654 655 // Compositing layers will be updated in Document::implicitClose() if suppressed here. 656 if (!m_renderView.document().visualUpdatesAllowed()) 657 return; 658 659 // Avoid updating the layers with old values. Compositing layers will be updated after the layout is finished. 660 if (m_renderView.needsLayout()) 661 return; 662 663 if (m_forceCompositingMode && !m_compositing) 664 enableCompositingMode(true); 665 666 if (!m_reevaluateCompositingAfterLayout && !m_compositing) 667 return; 668 669 AnimationUpdateBlock animationUpdateBlock(&m_renderView.frameView().frame().animation()); 670 671 TemporaryChange<bool> postLayoutChange(m_inPostLayoutUpdate, true); 672 673 bool checkForHierarchyUpdate = m_reevaluateCompositingAfterLayout; 674 bool needGeometryUpdate = false; 675 676 switch (updateType) { 677 case CompositingUpdateAfterStyleChange: 678 case CompositingUpdateAfterLayout: 679 case CompositingUpdateOnHitTest: 680 checkForHierarchyUpdate = true; 681 break; 682 case CompositingUpdateOnScroll: 683 checkForHierarchyUpdate = true; // Overlap can change with scrolling, so need to check for hierarchy updates. 684 685 needGeometryUpdate = true; 686 break; 687 case CompositingUpdateOnCompositedScroll: 688 needGeometryUpdate = true; 689 break; 690 } 691 692 if (!checkForHierarchyUpdate && !needGeometryUpdate) 693 return; 694 695 bool needHierarchyUpdate = m_compositingLayersNeedRebuild; 696 bool isFullUpdate = !updateRoot; 697 698 // Only clear the flag if we're updating the entire hierarchy. 699 m_compositingLayersNeedRebuild = false; 700 updateRoot = &rootRenderLayer(); 701 702 if (isFullUpdate && updateType == CompositingUpdateAfterLayout) 703 m_reevaluateCompositingAfterLayout = false; 704 705#if !LOG_DISABLED 706 double startTime = 0; 707 if (compositingLogEnabled()) { 708 ++m_rootLayerUpdateCount; 709 startTime = monotonicallyIncreasingTime(); 710 } 711#endif 712 713 if (checkForHierarchyUpdate) { 714 if (m_renderView.hasRenderNamedFlowThreads() && isFullUpdate) 715 m_renderView.flowThreadController().updateFlowThreadsLayerToRegionMappingsIfNeeded(); 716 // Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers. 717 // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex. 718 CompositingState compState(updateRoot); 719 bool layersChanged = false; 720 bool saw3DTransform = false; 721 OverlapMap overlapTestRequestMap; 722 computeCompositingRequirements(nullptr, *updateRoot, &overlapTestRequestMap, compState, layersChanged, saw3DTransform); 723 needHierarchyUpdate |= layersChanged; 724 } 725 726#if !LOG_DISABLED 727 if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) { 728 m_obligateCompositedLayerCount = 0; 729 m_secondaryCompositedLayerCount = 0; 730 m_obligatoryBackingStoreBytes = 0; 731 m_secondaryBackingStoreBytes = 0; 732 733 Frame& frame = m_renderView.frameView().frame(); 734 bool isMainFrame = !m_renderView.document().ownerElement(); 735 LOG(Compositing, "\nUpdate %d of %s.\n", m_rootLayerUpdateCount, isMainFrame ? "main frame" : frame.tree().uniqueName().string().utf8().data()); 736 } 737#endif 738 739 if (needHierarchyUpdate) { 740 // Update the hierarchy of the compositing layers. 741 Vector<GraphicsLayer*> childList; 742 rebuildCompositingLayerTree(*updateRoot, childList, 0); 743 744 // Host the document layer in the RenderView's root layer. 745 if (isFullUpdate) { 746 appendOverlayLayers(childList); 747 // Even when childList is empty, don't drop out of compositing mode if there are 748 // composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden). 749 if (childList.isEmpty() && !hasAnyAdditionalCompositedLayers(*updateRoot)) 750 destroyRootLayer(); 751 else if (m_rootContentLayer) 752 m_rootContentLayer->setChildren(childList); 753 } 754 755 reattachSubframeScrollLayers(); 756 } else if (needGeometryUpdate) { 757 // We just need to do a geometry update. This is only used for position:fixed scrolling; 758 // most of the time, geometry is updated via RenderLayer::styleChanged(). 759 updateLayerTreeGeometry(*updateRoot, 0); 760 ASSERT(!isFullUpdate || !m_subframeScrollLayersNeedReattach); 761 } 762 763#if !LOG_DISABLED 764 if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) { 765 double endTime = monotonicallyIncreasingTime(); 766 LOG(Compositing, "Total layers primary secondary obligatory backing (KB) secondary backing(KB) total backing (KB) update time (ms)\n"); 767 768 LOG(Compositing, "%8d %11d %9d %20.2f %22.2f %22.2f %18.2f\n", 769 m_obligateCompositedLayerCount + m_secondaryCompositedLayerCount, m_obligateCompositedLayerCount, 770 m_secondaryCompositedLayerCount, m_obligatoryBackingStoreBytes / 1024, m_secondaryBackingStoreBytes / 1024, (m_obligatoryBackingStoreBytes + m_secondaryBackingStoreBytes) / 1024, 1000.0 * (endTime - startTime)); 771 } 772#endif 773 ASSERT(updateRoot || !m_compositingLayersNeedRebuild); 774 775 if (!hasAcceleratedCompositing()) 776 enableCompositingMode(false); 777 778 // Inform the inspector that the layer tree has changed. 779 InspectorInstrumentation::layerTreeDidChange(page()); 780} 781 782void RenderLayerCompositor::appendOverlayLayers(Vector<GraphicsLayer*>& childList) 783{ 784 Frame& frame = m_renderView.frameView().frame(); 785 Page* page = frame.page(); 786 if (!page) 787 return; 788 789 if (GraphicsLayer* overlayLayer = page->chrome().client().documentOverlayLayerForFrame(frame)) 790 childList.append(overlayLayer); 791} 792 793void RenderLayerCompositor::layerBecameNonComposited(const RenderLayer& layer) 794{ 795 // Inform the inspector that the given RenderLayer was destroyed. 796 InspectorInstrumentation::renderLayerDestroyed(page(), &layer); 797 798 ASSERT(m_compositedLayerCount > 0); 799 --m_compositedLayerCount; 800} 801 802#if !LOG_DISABLED 803void RenderLayerCompositor::logLayerInfo(const RenderLayer& layer, int depth) 804{ 805 if (!compositingLogEnabled()) 806 return; 807 808 RenderLayerBacking* backing = layer.backing(); 809 if (requiresCompositingLayer(layer) || layer.isRootLayer()) { 810 ++m_obligateCompositedLayerCount; 811 m_obligatoryBackingStoreBytes += backing->backingStoreMemoryEstimate(); 812 } else { 813 ++m_secondaryCompositedLayerCount; 814 m_secondaryBackingStoreBytes += backing->backingStoreMemoryEstimate(); 815 } 816 817 StringBuilder logString; 818 logString.append(String::format("%*p %dx%d %.2fKB", 12 + depth * 2, &layer, 819 backing->compositedBounds().width().round(), backing->compositedBounds().height().round(), 820 backing->backingStoreMemoryEstimate() / 1024)); 821 822 logString.append(" ("); 823 logString.append(logReasonsForCompositing(layer)); 824 logString.append(") "); 825 826 if (backing->graphicsLayer()->contentsOpaque() || backing->paintsIntoCompositedAncestor()) { 827 logString.append('['); 828 if (backing->graphicsLayer()->contentsOpaque()) 829 logString.append("opaque"); 830 if (backing->paintsIntoCompositedAncestor()) 831 logString.append("paints into ancestor"); 832 logString.append("] "); 833 } 834 835 logString.append(layer.name()); 836 837 LOG(Compositing, "%s", logString.toString().utf8().data()); 838} 839#endif 840 841bool RenderLayerCompositor::updateBacking(RenderLayer& layer, CompositingChangeRepaint shouldRepaint) 842{ 843 bool layerChanged = false; 844 RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason; 845 846 if (needsToBeComposited(layer, &viewportConstrainedNotCompositedReason)) { 847 enableCompositingMode(); 848 849 if (!layer.backing()) { 850 // If we need to repaint, do so before making backing 851 if (shouldRepaint == CompositingChangeRepaintNow) 852 repaintOnCompositingChange(layer); 853 854 layer.ensureBacking(); 855 856 // At this time, the ScrollingCoordinator only supports the top-level frame. 857 if (layer.isRootLayer() && !m_renderView.document().ownerElement()) { 858 updateScrollCoordinatedStatus(layer); 859 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 860 scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView()); 861#if ENABLE(RUBBER_BANDING) 862 if (Page* page = this->page()) { 863 updateLayerForHeader(page->headerHeight()); 864 updateLayerForFooter(page->footerHeight()); 865 } 866#endif 867 if (m_renderView.frameView().frame().settings().backgroundShouldExtendBeyondPage()) 868 m_rootContentLayer->setMasksToBounds(false); 869 870 if (TiledBacking* tiledBacking = layer.backing()->tiledBacking()) 871 tiledBacking->setTopContentInset(m_renderView.frameView().topContentInset()); 872 } 873 874 // This layer and all of its descendants have cached repaints rects that are relative to 875 // the repaint container, so change when compositing changes; we need to update them here. 876 if (layer.parent()) 877 layer.computeRepaintRectsIncludingDescendants(); 878 879 layerChanged = true; 880 } 881 } else { 882 if (layer.backing()) { 883 // If we're removing backing on a reflection, clear the source GraphicsLayer's pointer to 884 // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection 885 // are both either composited, or not composited. 886 if (layer.isReflection()) { 887 RenderLayer* sourceLayer = toRenderLayerModelObject(layer.renderer().parent())->layer(); 888 if (RenderLayerBacking* backing = sourceLayer->backing()) { 889 ASSERT(backing->graphicsLayer()->replicaLayer() == layer.backing()->graphicsLayer()); 890 backing->graphicsLayer()->setReplicatedByLayer(0); 891 } 892 } 893 894 removeFromScrollCoordinatedLayers(layer); 895 896 layer.clearBacking(); 897 layerChanged = true; 898 899 // This layer and all of its descendants have cached repaints rects that are relative to 900 // the repaint container, so change when compositing changes; we need to update them here. 901 layer.computeRepaintRectsIncludingDescendants(); 902 903 // If we need to repaint, do so now that we've removed the backing 904 if (shouldRepaint == CompositingChangeRepaintNow) 905 repaintOnCompositingChange(layer); 906 } 907 } 908 909#if ENABLE(VIDEO) 910 if (layerChanged && layer.renderer().isVideo()) { 911 // If it's a video, give the media player a chance to hook up to the layer. 912 toRenderVideo(layer.renderer()).acceleratedRenderingStateChanged(); 913 } 914#endif 915 916 if (layerChanged && layer.renderer().isWidget()) { 917 RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderWidget(&layer.renderer())); 918 if (innerCompositor && innerCompositor->inCompositingMode()) 919 innerCompositor->updateRootLayerAttachment(); 920 } 921 922 if (layerChanged) 923 layer.clearClipRectsIncludingDescendants(PaintingClipRects); 924 925 // If a fixed position layer gained/lost a backing or the reason not compositing it changed, 926 // the scrolling coordinator needs to recalculate whether it can do fast scrolling. 927 if (layer.renderer().style().position() == FixedPosition) { 928 if (layer.viewportConstrainedNotCompositedReason() != viewportConstrainedNotCompositedReason) { 929 layer.setViewportConstrainedNotCompositedReason(viewportConstrainedNotCompositedReason); 930 layerChanged = true; 931 } 932 if (layerChanged) { 933 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 934 scrollingCoordinator->frameViewFixedObjectsDidChange(&m_renderView.frameView()); 935 } 936 } else 937 layer.setViewportConstrainedNotCompositedReason(RenderLayer::NoNotCompositedReason); 938 939 if (layer.backing()) 940 layer.backing()->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter); 941 942 return layerChanged; 943} 944 945bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer& layer, CompositingChangeRepaint shouldRepaint) 946{ 947 bool layerChanged = updateBacking(layer, shouldRepaint); 948 949 // See if we need content or clipping layers. Methods called here should assume 950 // that the compositing state of descendant layers has not been updated yet. 951 if (layer.backing() && layer.backing()->updateConfiguration()) 952 layerChanged = true; 953 954 return layerChanged; 955} 956 957void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer& layer) 958{ 959 // If the renderer is not attached yet, no need to repaint. 960 if (&layer.renderer() != &m_renderView && !layer.renderer().parent()) 961 return; 962 963 RenderLayerModelObject* repaintContainer = layer.renderer().containerForRepaint(); 964 if (!repaintContainer) 965 repaintContainer = &m_renderView; 966 967 layer.repaintIncludingNonCompositingDescendants(repaintContainer); 968 if (repaintContainer == &m_renderView) { 969 // The contents of this layer may be moving between the window 970 // and a GraphicsLayer, so we need to make sure the window system 971 // synchronizes those changes on the screen. 972 m_renderView.frameView().setNeedsOneShotDrawingSynchronization(); 973 } 974} 975 976// This method assumes that layout is up-to-date, unlike repaintOnCompositingChange(). 977void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer& layer, const LayoutRect& rect) 978{ 979 RenderLayer* compositedAncestor = layer.enclosingCompositingLayerForRepaint(ExcludeSelf); 980 if (compositedAncestor) { 981 ASSERT(compositedAncestor->backing()); 982 LayoutRect repaintRect = rect; 983 repaintRect.move(layer.offsetFromAncestor(compositedAncestor)); 984 compositedAncestor->setBackingNeedsRepaintInRect(repaintRect); 985 } 986 987 // The contents of this layer may be moving from a GraphicsLayer to the window, 988 // so we need to make sure the window system synchronizes those changes on the screen. 989 if (compositedAncestor == m_renderView.layer()) 990 m_renderView.frameView().setNeedsOneShotDrawingSynchronization(); 991} 992 993void RenderLayerCompositor::layerWasAdded(RenderLayer&, RenderLayer&) 994{ 995 setCompositingLayersNeedRebuild(); 996} 997 998void RenderLayerCompositor::layerWillBeRemoved(RenderLayer& parent, RenderLayer& child) 999{ 1000 if (!child.isComposited() || parent.renderer().documentBeingDestroyed()) 1001 return; 1002 1003 removeFromScrollCoordinatedLayers(child); 1004 repaintInCompositedAncestor(child, child.backing()->compositedBounds()); 1005 1006 setCompositingParent(child, nullptr); 1007 setCompositingLayersNeedRebuild(); 1008} 1009 1010RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer& layer) const 1011{ 1012 for (RenderLayer* parent = layer.parent(); parent; parent = parent->parent()) { 1013 if (parent->isStackingContainer()) 1014 return nullptr; 1015 if (parent->renderer().hasClipOrOverflowClip()) 1016 return parent; 1017 } 1018 return nullptr; 1019} 1020 1021void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer& layer, IntRect& layerBounds, bool& boundsComputed) 1022{ 1023 if (layer.isRootLayer()) 1024 return; 1025 1026 if (!boundsComputed) { 1027 // FIXME: If this layer's overlap bounds include its children, we don't need to add its 1028 // children's bounds to the overlap map. 1029 layerBounds = enclosingIntRect(overlapMap.geometryMap().absoluteRect(layer.overlapBounds())); 1030 // Empty rects never intersect, but we need them to for the purposes of overlap testing. 1031 if (layerBounds.isEmpty()) 1032 layerBounds.setSize(IntSize(1, 1)); 1033 boundsComputed = true; 1034 } 1035 1036 IntRect clipRect = pixelSnappedIntRect(layer.backgroundClipRect(RenderLayer::ClipRectsContext(&rootRenderLayer(), AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions. 1037 1038 // On iOS, pageScaleFactor() is not applied by RenderView, so we should not scale here. 1039 // FIXME: Set Settings::delegatesPageScaling to true for iOS. 1040#if !PLATFORM(IOS) 1041 const Settings& settings = m_renderView.frameView().frame().settings(); 1042 if (!settings.delegatesPageScaling()) 1043 clipRect.scale(pageScaleFactor()); 1044#endif 1045 clipRect.intersect(layerBounds); 1046 overlapMap.add(&layer, clipRect); 1047} 1048 1049void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, RenderLayer& layer, RenderLayer* ancestorLayer) 1050{ 1051 if (!canBeComposited(layer) || overlapMap.contains(&layer)) 1052 return; 1053 1054 // A null ancestorLayer is an indication that 'layer' has already been pushed. 1055 if (ancestorLayer) 1056 overlapMap.geometryMap().pushMappingsToAncestor(&layer, ancestorLayer); 1057 1058 IntRect bounds; 1059 bool haveComputedBounds = false; 1060 addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds); 1061 1062#if !ASSERT_DISABLED 1063 LayerListMutationDetector mutationChecker(&layer); 1064#endif 1065 1066 if (layer.isStackingContainer()) { 1067 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 1068 for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) 1069 addToOverlapMapRecursive(overlapMap, *negZOrderList->at(i), &layer); 1070 } 1071 } 1072 1073 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 1074 for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) 1075 addToOverlapMapRecursive(overlapMap, *normalFlowList->at(i), &layer); 1076 } 1077 1078 if (layer.isStackingContainer()) { 1079 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 1080 for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) 1081 addToOverlapMapRecursive(overlapMap, *posZOrderList->at(i), &layer); 1082 } 1083 } 1084 1085 if (ancestorLayer) 1086 overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer); 1087} 1088 1089void RenderLayerCompositor::computeCompositingRequirementsForNamedFlowFixed(RenderLayer& layer, OverlapMap* overlapMap, CompositingState& childState, bool& layersChanged, bool& anyDescendantHas3DTransform) 1090{ 1091 if (!layer.isRootLayer()) 1092 return; 1093 1094 if (!layer.renderer().view().hasRenderNamedFlowThreads()) 1095 return; 1096 1097 Vector<RenderLayer*> fixedLayers; 1098 layer.renderer().view().flowThreadController().collectFixedPositionedLayers(fixedLayers); 1099 1100 for (size_t i = 0; i < fixedLayers.size(); ++i) { 1101 RenderLayer* fixedLayer = fixedLayers.at(i); 1102 computeCompositingRequirements(&layer, *fixedLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1103 } 1104} 1105 1106// Recurse through the layers in z-index and overflow order (which is equivalent to painting order) 1107// For the z-order children of a compositing layer: 1108// If a child layers has a compositing layer, then all subsequent layers must 1109// be compositing in order to render above that layer. 1110// 1111// If a child in the negative z-order list is compositing, then the layer itself 1112// must be compositing so that its contents render over that child. 1113// This implies that its positive z-index children must also be compositing. 1114// 1115void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer& layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged, bool& descendantHas3DTransform) 1116{ 1117 layer.updateDescendantDependentFlags(); 1118 layer.updateLayerListsIfNeeded(); 1119 1120 if (layer.isFlowThreadCollectingGraphicsLayersUnderRegions()) { 1121 RenderFlowThread& flowThread = toRenderFlowThread(layer.renderer()); 1122 layer.setHasCompositingDescendant(flowThread.hasCompositingRegionDescendant()); 1123 1124 // Before returning, we need to update the lists of all child layers. This is required because, 1125 // if this flow thread will not be painted (for instance because of having no regions, or only invalid regions), 1126 // the child layers will never have their lists updated (which would normally happen during painting). 1127 layer.updateDescendantsLayerListsIfNeeded(true); 1128 1129 return; 1130 } 1131 1132 if (overlapMap) 1133 overlapMap->geometryMap().pushMappingsToAncestor(&layer, ancestorLayer); 1134 1135 // Clear the flag 1136 layer.setHasCompositingDescendant(false); 1137 layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::None); 1138 1139 // Check if the layer needs to be composited for non-indirect reasons (ex. 3D transform). 1140 // We use this value to avoid checking the overlap-map, if we know for sure the layer 1141 // is already going to be composited for other reasons. 1142 bool willBeComposited = needsToBeComposited(layer); 1143 1144 RenderLayer::IndirectCompositingReason compositingReason = compositingState.m_subtreeIsCompositing ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None; 1145 bool haveComputedBounds = false; 1146 IntRect absBounds; 1147 1148 // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map 1149 if (!willBeComposited && overlapMap && !overlapMap->isEmpty() && compositingState.m_testingOverlap) { 1150 // If we're testing for overlap, we only need to composite if we overlap something that is already composited. 1151 absBounds = enclosingIntRect(overlapMap->geometryMap().absoluteRect(layer.overlapBounds())); 1152 1153 // Empty rects never intersect, but we need them to for the purposes of overlap testing. 1154 if (absBounds.isEmpty()) 1155 absBounds.setSize(IntSize(1, 1)); 1156 haveComputedBounds = true; 1157 compositingReason = overlapMap->overlapsLayers(absBounds) ? RenderLayer::IndirectCompositingReason::Overlap : RenderLayer::IndirectCompositingReason::None; 1158 } 1159 1160#if ENABLE(VIDEO) 1161 // Video is special. It's the only RenderLayer type that can both have 1162 // RenderLayer children and whose children can't use its backing to render 1163 // into. These children (the controls) always need to be promoted into their 1164 // own layers to draw on top of the accelerated video. 1165 if (compositingState.m_compositingAncestor && compositingState.m_compositingAncestor->renderer().isVideo()) 1166 compositingReason = RenderLayer::IndirectCompositingReason::Overlap; 1167#endif 1168 1169 layer.setIndirectCompositingReason(compositingReason); 1170 1171 // Check if the computed indirect reason will force the layer to become composited. 1172 if (!willBeComposited && layer.mustCompositeForIndirectReasons() && canBeComposited(layer)) 1173 willBeComposited = true; 1174 ASSERT(willBeComposited == needsToBeComposited(layer)); 1175 1176 // The children of this layer don't need to composite, unless there is 1177 // a compositing layer among them, so start by inheriting the compositing 1178 // ancestor with m_subtreeIsCompositing set to false. 1179 CompositingState childState(compositingState); 1180 childState.m_subtreeIsCompositing = false; 1181#if ENABLE(CSS_COMPOSITING) 1182 childState.m_hasNotIsolatedCompositedBlendingDescendants = false; 1183#endif 1184 1185 if (willBeComposited) { 1186 // Tell the parent it has compositing descendants. 1187 compositingState.m_subtreeIsCompositing = true; 1188 // This layer now acts as the ancestor for kids. 1189 childState.m_compositingAncestor = &layer; 1190 1191 if (overlapMap) 1192 overlapMap->pushCompositingContainer(); 1193 // This layer is going to be composited, so children can safely ignore the fact that there's an 1194 // animation running behind this layer, meaning they can rely on the overlap map testing again. 1195 childState.m_testingOverlap = true; 1196 } 1197 1198#if !ASSERT_DISABLED 1199 LayerListMutationDetector mutationChecker(&layer); 1200#endif 1201 1202 bool anyDescendantHas3DTransform = false; 1203 1204 if (layer.isStackingContainer()) { 1205 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 1206 for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) { 1207 computeCompositingRequirements(&layer, *negZOrderList->at(i), overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1208 1209 // If we have to make a layer for this child, make one now so we can have a contents layer 1210 // (since we need to ensure that the -ve z-order child renders underneath our contents). 1211 if (!willBeComposited && childState.m_subtreeIsCompositing) { 1212 // make layer compositing 1213 layer.setIndirectCompositingReason(RenderLayer::IndirectCompositingReason::BackgroundLayer); 1214 childState.m_compositingAncestor = &layer; 1215 if (overlapMap) 1216 overlapMap->pushCompositingContainer(); 1217 // This layer is going to be composited, so children can safely ignore the fact that there's an 1218 // animation running behind this layer, meaning they can rely on the overlap map testing again 1219 childState.m_testingOverlap = true; 1220 willBeComposited = true; 1221 } 1222 } 1223 } 1224 } 1225 1226 if (layer.renderer().isRenderNamedFlowFragmentContainer()) { 1227 // We are going to collect layers from the RenderFlowThread into the GraphicsLayer of the parent of the 1228 // anonymous RenderRegion, but first we need to make sure that the parent itself of the region is going to 1229 // have a composited layer. We only want to make regions composited when there's an actual layer that we 1230 // need to move to that region. 1231 computeRegionCompositingRequirements(toRenderBlockFlow(layer.renderer()).renderNamedFlowFragment(), overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1232 } 1233 1234 1235 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 1236 for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) 1237 computeCompositingRequirements(&layer, *normalFlowList->at(i), overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1238 } 1239 1240 if (layer.isStackingContainer()) { 1241 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 1242 for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) 1243 computeCompositingRequirements(&layer, *posZOrderList->at(i), overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1244 } 1245 } 1246 1247 if (layer.isRootLayer()) 1248 computeCompositingRequirementsForNamedFlowFixed(layer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1249 1250 // If we just entered compositing mode, the root will have become composited (as long as accelerated compositing is enabled). 1251 if (layer.isRootLayer()) { 1252 if (inCompositingMode() && m_hasAcceleratedCompositing) 1253 willBeComposited = true; 1254 } 1255 1256 ASSERT(willBeComposited == needsToBeComposited(layer)); 1257 1258 // All layers (even ones that aren't being composited) need to get added to 1259 // the overlap map. Layers that do not composite will draw into their 1260 // compositing ancestor's backing, and so are still considered for overlap. 1261 if (overlapMap && childState.m_compositingAncestor && !childState.m_compositingAncestor->isRootLayer()) 1262 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds); 1263 1264#if ENABLE(CSS_COMPOSITING) 1265 layer.setHasNotIsolatedCompositedBlendingDescendants(childState.m_hasNotIsolatedCompositedBlendingDescendants); 1266 ASSERT(!layer.hasNotIsolatedCompositedBlendingDescendants() || layer.hasNotIsolatedBlendingDescendants()); 1267#endif 1268 // Now check for reasons to become composited that depend on the state of descendant layers. 1269 RenderLayer::IndirectCompositingReason indirectCompositingReason; 1270 if (!willBeComposited && canBeComposited(layer) 1271 && requiresCompositingForIndirectReason(layer.renderer(), childState.m_subtreeIsCompositing, anyDescendantHas3DTransform, indirectCompositingReason)) { 1272 layer.setIndirectCompositingReason(indirectCompositingReason); 1273 childState.m_compositingAncestor = &layer; 1274 if (overlapMap) { 1275 overlapMap->pushCompositingContainer(); 1276 addToOverlapMapRecursive(*overlapMap, layer); 1277 } 1278 willBeComposited = true; 1279 } 1280 1281 ASSERT(willBeComposited == needsToBeComposited(layer)); 1282 if (layer.reflectionLayer()) { 1283 // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer? 1284 layer.reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingReason::Stacking : RenderLayer::IndirectCompositingReason::None); 1285 } 1286 1287 // Subsequent layers in the parent stacking context also need to composite. 1288 if (childState.m_subtreeIsCompositing) 1289 compositingState.m_subtreeIsCompositing = true; 1290 1291 // Set the flag to say that this SC has compositing children. 1292 layer.setHasCompositingDescendant(childState.m_subtreeIsCompositing); 1293 1294 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping, 1295 // so test that again. 1296 bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer); 1297 1298 // Turn overlap testing off for later layers if it's already off, or if we have an animating transform. 1299 // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because 1300 // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map. 1301 if ((!childState.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer.renderer())) 1302 compositingState.m_testingOverlap = false; 1303 1304 if (isCompositedClippingLayer) { 1305 if (!willBeComposited) { 1306 childState.m_compositingAncestor = &layer; 1307 if (overlapMap) { 1308 overlapMap->pushCompositingContainer(); 1309 addToOverlapMapRecursive(*overlapMap, layer); 1310 } 1311 willBeComposited = true; 1312 } 1313 } 1314 1315#if ENABLE(CSS_COMPOSITING) 1316 if ((willBeComposited && layer.hasBlendMode()) 1317 || (layer.hasNotIsolatedCompositedBlendingDescendants() && !layer.isolatesCompositedBlending())) 1318 compositingState.m_hasNotIsolatedCompositedBlendingDescendants = true; 1319#endif 1320 1321 if (overlapMap && childState.m_compositingAncestor == &layer && !layer.isRootLayer()) 1322 overlapMap->popCompositingContainer(); 1323 1324 // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need 1325 // to be composited, then we can drop out of compositing mode altogether. However, don't drop out of compositing mode 1326 // if there are composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden). 1327 if (layer.isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode && !hasAnyAdditionalCompositedLayers(layer)) { 1328 // Don't drop out of compositing on iOS, because we may flash. See <rdar://problem/8348337>. 1329#if !PLATFORM(IOS) 1330 enableCompositingMode(false); 1331 willBeComposited = false; 1332#endif 1333 } 1334 1335 // If the layer is going into compositing mode, repaint its old location. 1336 ASSERT(willBeComposited == needsToBeComposited(layer)); 1337 if (!layer.isComposited() && willBeComposited) 1338 repaintOnCompositingChange(layer); 1339 1340 // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree(). 1341 if (updateBacking(layer, CompositingChangeRepaintNow)) 1342 layersChanged = true; 1343 1344 if (layer.reflectionLayer() && updateLayerCompositingState(*layer.reflectionLayer(), CompositingChangeRepaintNow)) 1345 layersChanged = true; 1346 1347 descendantHas3DTransform |= anyDescendantHas3DTransform || layer.has3DTransform(); 1348 1349 if (overlapMap) 1350 overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer); 1351} 1352 1353void RenderLayerCompositor::computeRegionCompositingRequirements(RenderNamedFlowFragment* region, OverlapMap* overlapMap, CompositingState& childState, bool& layersChanged, bool& anyDescendantHas3DTransform) 1354{ 1355 if (!region->isValid()) 1356 return; 1357 1358 RenderFlowThread* flowThread = region->flowThread(); 1359 1360 if (overlapMap) 1361 overlapMap->geometryMap().pushRenderFlowThread(flowThread); 1362 1363 if (const RenderLayerList* layerList = flowThread->getLayerListForRegion(region)) { 1364 for (size_t i = 0, listSize = layerList->size(); i < listSize; ++i) { 1365 RenderLayer& curLayer = *layerList->at(i); 1366 ASSERT(flowThread->regionForCompositedLayer(curLayer) == region); 1367 computeCompositingRequirements(flowThread->layer(), curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform); 1368 } 1369 } 1370 1371 if (overlapMap) 1372 overlapMap->geometryMap().popMappingsToAncestor(®ion->layerOwner()); 1373} 1374 1375void RenderLayerCompositor::setCompositingParent(RenderLayer& childLayer, RenderLayer* parentLayer) 1376{ 1377 ASSERT(!parentLayer || childLayer.ancestorCompositingLayer() == parentLayer); 1378 ASSERT(childLayer.isComposited()); 1379 1380 // It's possible to be called with a parent that isn't yet composited when we're doing 1381 // partial updates as required by painting or hit testing. Just bail in that case; 1382 // we'll do a full layer update soon. 1383 if (!parentLayer || !parentLayer->isComposited()) 1384 return; 1385 1386 if (parentLayer) { 1387 GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers(); 1388 GraphicsLayer* hostedLayer = childLayer.backing()->childForSuperlayers(); 1389 1390 hostingLayer->addChild(hostedLayer); 1391 } else 1392 childLayer.backing()->childForSuperlayers()->removeFromParent(); 1393} 1394 1395void RenderLayerCompositor::removeCompositedChildren(RenderLayer& layer) 1396{ 1397 ASSERT(layer.isComposited()); 1398 1399 layer.backing()->parentForSublayers()->removeAllChildren(); 1400} 1401 1402#if ENABLE(VIDEO) 1403bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo& video) const 1404{ 1405 if (!m_hasAcceleratedCompositing) 1406 return false; 1407 1408 return video.supportsAcceleratedRendering(); 1409} 1410#endif 1411 1412void RenderLayerCompositor::rebuildCompositingLayerTreeForNamedFlowFixed(RenderLayer& layer, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer, int depth) 1413{ 1414 if (!layer.isRootLayer()) 1415 return; 1416 1417 if (!layer.renderer().view().hasRenderNamedFlowThreads()) 1418 return; 1419 1420 Vector<RenderLayer*> fixedLayers; 1421 layer.renderer().view().flowThreadController().collectFixedPositionedLayers(fixedLayers); 1422 1423 for (size_t i = 0; i < fixedLayers.size(); ++i) { 1424 RenderLayer* fixedLayer = fixedLayers.at(i); 1425 rebuildCompositingLayerTree(*fixedLayer, childGraphicsLayersOfEnclosingLayer, depth); 1426 } 1427} 1428 1429void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer& layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, int depth) 1430{ 1431 // Make the layer compositing if necessary, and set up clipping and content layers. 1432 // Note that we can only do work here that is independent of whether the descendant layers 1433 // have been processed. computeCompositingRequirements() will already have done the repaint if necessary. 1434 1435 // Do not iterate the RenderFlowThread directly. We are going to collect composited layers as part of regions. 1436 if (layer.isFlowThreadCollectingGraphicsLayersUnderRegions()) 1437 return; 1438 1439 RenderLayerBacking* layerBacking = layer.backing(); 1440 if (layerBacking) { 1441 // The compositing state of all our children has been updated already, so now 1442 // we can compute and cache the composited bounds for this layer. 1443 layerBacking->updateCompositedBounds(); 1444 1445 if (RenderLayer* reflection = layer.reflectionLayer()) { 1446 if (reflection->backing()) 1447 reflection->backing()->updateCompositedBounds(); 1448 } 1449 1450 if (layerBacking->updateConfiguration()) 1451 layerBacking->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter); 1452 1453 layerBacking->updateGeometry(); 1454 1455 if (!layer.parent()) 1456 updateRootLayerPosition(); 1457 1458#if !LOG_DISABLED 1459 logLayerInfo(layer, depth); 1460#else 1461 UNUSED_PARAM(depth); 1462#endif 1463 if (layerBacking->hasUnpositionedOverflowControlsLayers()) 1464 layer.positionNewlyCreatedOverflowControls(); 1465 } 1466 1467 // If this layer has backing, then we are collecting its children, otherwise appending 1468 // to the compositing child list of an enclosing layer. 1469 Vector<GraphicsLayer*> layerChildren; 1470 Vector<GraphicsLayer*>& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer; 1471 1472#if !ASSERT_DISABLED 1473 LayerListMutationDetector mutationChecker(&layer); 1474#endif 1475 1476 if (layer.isStackingContainer()) { 1477 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 1478 for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) 1479 rebuildCompositingLayerTree(*negZOrderList->at(i), childList, depth + 1); 1480 } 1481 1482 // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. 1483 if (layerBacking && layerBacking->foregroundLayer()) 1484 childList.append(layerBacking->foregroundLayer()); 1485 } 1486 1487 if (layer.renderer().isRenderNamedFlowFragmentContainer()) 1488 rebuildRegionCompositingLayerTree(toRenderBlockFlow(layer.renderer()).renderNamedFlowFragment(), layerChildren, depth + 1); 1489 1490 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 1491 for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) 1492 rebuildCompositingLayerTree(*normalFlowList->at(i), childList, depth + 1); 1493 } 1494 1495 if (layer.isStackingContainer()) { 1496 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 1497 for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) 1498 rebuildCompositingLayerTree(*posZOrderList->at(i), childList, depth + 1); 1499 } 1500 } 1501 1502 if (layer.isRootLayer()) 1503 rebuildCompositingLayerTreeForNamedFlowFixed(layer, childList, depth + 1); 1504 1505 if (layerBacking) { 1506 bool parented = false; 1507 if (layer.renderer().isWidget()) 1508 parented = parentFrameContentLayers(toRenderWidget(&layer.renderer())); 1509 1510 if (!parented) 1511 layerBacking->parentForSublayers()->setChildren(layerChildren); 1512 1513 // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer. 1514 // Otherwise, the overflow control layers are normal children. 1515 if (!layerBacking->hasClippingLayer() && !layerBacking->hasScrollingLayer()) { 1516 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) { 1517 overflowControlLayer->removeFromParent(); 1518 layerBacking->parentForSublayers()->addChild(overflowControlLayer); 1519 } 1520 1521 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForVerticalScrollbar()) { 1522 overflowControlLayer->removeFromParent(); 1523 layerBacking->parentForSublayers()->addChild(overflowControlLayer); 1524 } 1525 1526 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForScrollCorner()) { 1527 overflowControlLayer->removeFromParent(); 1528 layerBacking->parentForSublayers()->addChild(overflowControlLayer); 1529 } 1530 } 1531 1532 childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers()); 1533 } 1534 1535 if (RenderLayerBacking* layerBacking = layer.backing()) 1536 layerBacking->updateAfterDescendents(); 1537} 1538 1539void RenderLayerCompositor::rebuildRegionCompositingLayerTree(RenderNamedFlowFragment* region, Vector<GraphicsLayer*>& childList, int depth) 1540{ 1541 if (!region->isValid()) 1542 return; 1543 1544 RenderFlowThread* flowThread = region->flowThread(); 1545 ASSERT(flowThread->collectsGraphicsLayersUnderRegions()); 1546 if (const RenderLayerList* layerList = flowThread->getLayerListForRegion(region)) { 1547 for (size_t i = 0, listSize = layerList->size(); i < listSize; ++i) { 1548 RenderLayer& curLayer = *layerList->at(i); 1549 ASSERT(flowThread->regionForCompositedLayer(curLayer) == region); 1550 rebuildCompositingLayerTree(curLayer, childList, depth + 1); 1551 } 1552 } 1553} 1554 1555void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset) 1556{ 1557 if (m_overflowControlsHostLayer) 1558 m_overflowControlsHostLayer->setPosition(contentsOffset); 1559} 1560 1561void RenderLayerCompositor::frameViewDidChangeSize() 1562{ 1563 if (m_clipLayer) { 1564 const FrameView& frameView = m_renderView.frameView(); 1565 m_clipLayer->setSize(frameView.unscaledVisibleContentSizeIncludingObscuredArea()); 1566 m_clipLayer->setPosition(positionForClipLayer()); 1567 1568 frameViewDidScroll(); 1569 updateOverflowControlsLayers(); 1570 1571#if ENABLE(RUBBER_BANDING) 1572 if (m_layerForOverhangAreas) { 1573 m_layerForOverhangAreas->setSize(frameView.frameRect().size()); 1574 m_layerForOverhangAreas->setPosition(FloatPoint(0, m_renderView.frameView().topContentInset())); 1575 } 1576#endif 1577 } 1578} 1579 1580bool RenderLayerCompositor::hasCoordinatedScrolling() const 1581{ 1582 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 1583 return scrollingCoordinator && scrollingCoordinator->coordinatesScrollingForFrameView(&m_renderView.frameView()); 1584} 1585 1586void RenderLayerCompositor::updateScrollLayerPosition() 1587{ 1588 ASSERT(m_scrollLayer); 1589 1590 FrameView& frameView = m_renderView.frameView(); 1591 IntPoint scrollPosition = frameView.scrollPosition(); 1592 1593 m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y())); 1594 1595 if (GraphicsLayer* fixedBackgroundLayer = fixedRootBackgroundLayer()) 1596 fixedBackgroundLayer->setPosition(toLayoutPoint(frameView.scrollOffsetForFixedPosition())); 1597} 1598 1599FloatPoint RenderLayerCompositor::positionForClipLayer() const 1600{ 1601 return FloatPoint(0, FrameView::yPositionForInsetClipLayer(m_renderView.frameView().scrollPosition(), m_renderView.frameView().topContentInset())); 1602} 1603 1604void RenderLayerCompositor::frameViewDidScroll() 1605{ 1606 if (!m_scrollLayer) 1607 return; 1608 1609 // If there's a scrolling coordinator that manages scrolling for this frame view, 1610 // it will also manage updating the scroll layer position. 1611 if (hasCoordinatedScrolling()) { 1612 // We have to schedule a flush in order for the main TiledBacking to update its tile coverage. 1613 scheduleLayerFlushNow(); 1614 return; 1615 } 1616 1617 updateScrollLayerPosition(); 1618} 1619 1620void RenderLayerCompositor::frameViewDidAddOrRemoveScrollbars() 1621{ 1622 updateOverflowControlsLayers(); 1623} 1624 1625void RenderLayerCompositor::frameViewDidLayout() 1626{ 1627 RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing(); 1628 if (renderViewBacking) 1629 renderViewBacking->adjustTiledBackingCoverage(); 1630} 1631 1632void RenderLayerCompositor::rootFixedBackgroundsChanged() 1633{ 1634 RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing(); 1635 if (renderViewBacking && renderViewBacking->usingTiledBacking()) 1636 setCompositingLayersNeedRebuild(); 1637} 1638 1639void RenderLayerCompositor::scrollingLayerDidChange(RenderLayer& layer) 1640{ 1641 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 1642 scrollingCoordinator->scrollableAreaScrollLayerDidChange(&layer); 1643} 1644 1645void RenderLayerCompositor::fixedRootBackgroundLayerChanged() 1646{ 1647 if (m_renderView.documentBeingDestroyed()) 1648 return; 1649 1650 if (m_renderView.layer()->isComposited()) 1651 updateScrollCoordinatedStatus(*m_renderView.layer()); 1652} 1653 1654String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags) 1655{ 1656 updateCompositingLayers(CompositingUpdateAfterLayout); 1657 1658 if (!m_rootContentLayer) 1659 return String(); 1660 1661 flushPendingLayerChanges(true); 1662 1663 LayerTreeAsTextBehavior layerTreeBehavior = LayerTreeAsTextBehaviorNormal; 1664 if (flags & LayerTreeFlagsIncludeDebugInfo) 1665 layerTreeBehavior |= LayerTreeAsTextDebug; 1666 if (flags & LayerTreeFlagsIncludeVisibleRects) 1667 layerTreeBehavior |= LayerTreeAsTextIncludeVisibleRects; 1668 if (flags & LayerTreeFlagsIncludeTileCaches) 1669 layerTreeBehavior |= LayerTreeAsTextIncludeTileCaches; 1670 if (flags & LayerTreeFlagsIncludeRepaintRects) 1671 layerTreeBehavior |= LayerTreeAsTextIncludeRepaintRects; 1672 if (flags & LayerTreeFlagsIncludePaintingPhases) 1673 layerTreeBehavior |= LayerTreeAsTextIncludePaintingPhases; 1674 if (flags & LayerTreeFlagsIncludeContentLayers) 1675 layerTreeBehavior |= LayerTreeAsTextIncludeContentLayers; 1676 1677 // We skip dumping the scroll and clip layers to keep layerTreeAsText output 1678 // similar between platforms. 1679 String layerTreeText = m_rootContentLayer->layerTreeAsText(layerTreeBehavior); 1680 1681 // Dump an empty layer tree only if the only composited layer is the main frame's tiled backing, 1682 // so that tests expecting us to drop out of accelerated compositing when there are no layers succeed. 1683 if (!hasAnyAdditionalCompositedLayers(rootRenderLayer()) && mainFrameBackingIsTiled() && !(layerTreeBehavior & LayerTreeAsTextIncludeTileCaches)) 1684 layerTreeText = ""; 1685 1686 // The true root layer is not included in the dump, so if we want to report 1687 // its repaint rects, they must be included here. 1688 if (flags & LayerTreeFlagsIncludeRepaintRects) 1689 return m_renderView.frameView().trackedRepaintRectsAsText() + layerTreeText; 1690 1691 return layerTreeText; 1692} 1693 1694RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderWidget* renderer) 1695{ 1696 if (Document* contentDocument = renderer->frameOwnerElement().contentDocument()) { 1697 if (RenderView* view = contentDocument->renderView()) 1698 return &view->compositor(); 1699 } 1700 return 0; 1701} 1702 1703bool RenderLayerCompositor::parentFrameContentLayers(RenderWidget* renderer) 1704{ 1705 RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer); 1706 if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame) 1707 return false; 1708 1709 RenderLayer* layer = renderer->layer(); 1710 if (!layer->isComposited()) 1711 return false; 1712 1713 RenderLayerBacking* backing = layer->backing(); 1714 GraphicsLayer* hostingLayer = backing->parentForSublayers(); 1715 GraphicsLayer* rootLayer = innerCompositor->rootGraphicsLayer(); 1716 if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) { 1717 hostingLayer->removeAllChildren(); 1718 hostingLayer->addChild(rootLayer); 1719 } 1720 return true; 1721} 1722 1723// This just updates layer geometry without changing the hierarchy. 1724void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer& layer, int depth) 1725{ 1726 if (RenderLayerBacking* layerBacking = layer.backing()) { 1727 // The compositing state of all our children has been updated already, so now 1728 // we can compute and cache the composited bounds for this layer. 1729 layerBacking->updateCompositedBounds(); 1730 1731 if (RenderLayer* reflection = layer.reflectionLayer()) { 1732 if (reflection->backing()) 1733 reflection->backing()->updateCompositedBounds(); 1734 } 1735 1736 layerBacking->updateConfiguration(); 1737 layerBacking->updateGeometry(); 1738 1739 if (!layer.parent()) 1740 updateRootLayerPosition(); 1741 1742#if !LOG_DISABLED 1743 logLayerInfo(layer, depth); 1744#else 1745 UNUSED_PARAM(depth); 1746#endif 1747 } 1748 1749#if !ASSERT_DISABLED 1750 LayerListMutationDetector mutationChecker(&layer); 1751#endif 1752 1753 if (layer.isStackingContainer()) { 1754 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 1755 for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) 1756 updateLayerTreeGeometry(*negZOrderList->at(i), depth + 1); 1757 } 1758 } 1759 1760 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 1761 for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) 1762 updateLayerTreeGeometry(*normalFlowList->at(i), depth + 1); 1763 } 1764 1765 if (layer.isStackingContainer()) { 1766 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 1767 for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) 1768 updateLayerTreeGeometry(*posZOrderList->at(i), depth + 1); 1769 } 1770 } 1771 1772 if (RenderLayerBacking* layerBacking = layer.backing()) 1773 layerBacking->updateAfterDescendents(); 1774} 1775 1776// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry. 1777void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer& compositingAncestor, RenderLayer& layer, bool compositedChildrenOnly) 1778{ 1779 if (&layer != &compositingAncestor) { 1780 if (RenderLayerBacking* layerBacking = layer.backing()) { 1781 layerBacking->updateCompositedBounds(); 1782 1783 if (RenderLayer* reflection = layer.reflectionLayer()) { 1784 if (reflection->backing()) 1785 reflection->backing()->updateCompositedBounds(); 1786 } 1787 1788 layerBacking->updateGeometry(); 1789 if (compositedChildrenOnly) { 1790 layerBacking->updateAfterDescendents(); 1791 return; 1792 } 1793 } 1794 } 1795 1796 if (layer.reflectionLayer()) 1797 updateCompositingDescendantGeometry(compositingAncestor, *layer.reflectionLayer(), compositedChildrenOnly); 1798 1799 if (!layer.hasCompositingDescendant()) 1800 return; 1801 1802#if !ASSERT_DISABLED 1803 LayerListMutationDetector mutationChecker(&layer); 1804#endif 1805 1806 if (layer.isStackingContainer()) { 1807 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 1808 size_t listSize = negZOrderList->size(); 1809 for (size_t i = 0; i < listSize; ++i) 1810 updateCompositingDescendantGeometry(compositingAncestor, *negZOrderList->at(i), compositedChildrenOnly); 1811 } 1812 } 1813 1814 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 1815 size_t listSize = normalFlowList->size(); 1816 for (size_t i = 0; i < listSize; ++i) 1817 updateCompositingDescendantGeometry(compositingAncestor, *normalFlowList->at(i), compositedChildrenOnly); 1818 } 1819 1820 if (layer.isStackingContainer()) { 1821 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 1822 size_t listSize = posZOrderList->size(); 1823 for (size_t i = 0; i < listSize; ++i) 1824 updateCompositingDescendantGeometry(compositingAncestor, *posZOrderList->at(i), compositedChildrenOnly); 1825 } 1826 } 1827 1828 if (&layer != &compositingAncestor) { 1829 if (RenderLayerBacking* layerBacking = layer.backing()) 1830 layerBacking->updateAfterDescendents(); 1831 } 1832} 1833 1834void RenderLayerCompositor::repaintCompositedLayers() 1835{ 1836 recursiveRepaintLayer(rootRenderLayer()); 1837} 1838 1839void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer& layer) 1840{ 1841 // FIXME: This method does not work correctly with transforms. 1842 if (layer.isComposited() && !layer.backing()->paintsIntoCompositedAncestor()) 1843 layer.setBackingNeedsRepaint(); 1844 1845#if !ASSERT_DISABLED 1846 LayerListMutationDetector mutationChecker(&layer); 1847#endif 1848 1849 if (layer.hasCompositingDescendant()) { 1850 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 1851 for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) 1852 recursiveRepaintLayer(*negZOrderList->at(i)); 1853 } 1854 1855 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 1856 for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) 1857 recursiveRepaintLayer(*posZOrderList->at(i)); 1858 } 1859 } 1860 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 1861 for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) 1862 recursiveRepaintLayer(*normalFlowList->at(i)); 1863 } 1864} 1865 1866RenderLayer& RenderLayerCompositor::rootRenderLayer() const 1867{ 1868 return *m_renderView.layer(); 1869} 1870 1871GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const 1872{ 1873 if (m_overflowControlsHostLayer) 1874 return m_overflowControlsHostLayer.get(); 1875 return m_rootContentLayer.get(); 1876} 1877 1878GraphicsLayer* RenderLayerCompositor::scrollLayer() const 1879{ 1880 return m_scrollLayer.get(); 1881} 1882 1883GraphicsLayer* RenderLayerCompositor::clipLayer() const 1884{ 1885 return m_clipLayer.get(); 1886} 1887 1888GraphicsLayer* RenderLayerCompositor::rootContentLayer() const 1889{ 1890 return m_rootContentLayer.get(); 1891} 1892 1893#if ENABLE(RUBBER_BANDING) 1894GraphicsLayer* RenderLayerCompositor::headerLayer() const 1895{ 1896 return m_layerForHeader.get(); 1897} 1898 1899GraphicsLayer* RenderLayerCompositor::footerLayer() const 1900{ 1901 return m_layerForFooter.get(); 1902} 1903#endif 1904 1905void RenderLayerCompositor::setIsInWindowForLayerIncludingDescendants(RenderLayer& layer, bool isInWindow) 1906{ 1907 if (layer.isComposited() && layer.backing()->usingTiledBacking()) 1908 layer.backing()->tiledBacking()->setIsInWindow(isInWindow); 1909 1910 // No need to recurse if we don't have any other tiled layers. 1911 if (hasNonMainLayersWithTiledBacking()) 1912 return; 1913 1914 for (RenderLayer* childLayer = layer.firstChild(); childLayer; childLayer = childLayer->nextSibling()) 1915 setIsInWindowForLayerIncludingDescendants(*childLayer, isInWindow); 1916} 1917 1918void RenderLayerCompositor::setIsInWindow(bool isInWindow) 1919{ 1920 setIsInWindowForLayerIncludingDescendants(*m_renderView.layer(), isInWindow); 1921 1922 if (!inCompositingMode()) 1923 return; 1924 1925 if (isInWindow) { 1926 if (m_rootLayerAttachment != RootLayerUnattached) 1927 return; 1928 1929 RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient; 1930 attachRootLayer(attachment); 1931#if PLATFORM(IOS) 1932 registerAllViewportConstrainedLayers(); 1933 registerAllScrollingLayers(); 1934#endif 1935 } else { 1936 if (m_rootLayerAttachment == RootLayerUnattached) 1937 return; 1938 1939 detachRootLayer(); 1940#if PLATFORM(IOS) 1941 unregisterAllViewportConstrainedLayers(); 1942 unregisterAllScrollingLayers(); 1943#endif 1944 } 1945} 1946 1947void RenderLayerCompositor::clearBackingForLayerIncludingDescendants(RenderLayer& layer) 1948{ 1949 if (layer.isComposited()) { 1950 removeFromScrollCoordinatedLayers(layer); 1951 layer.clearBacking(); 1952 } 1953 1954 for (RenderLayer* childLayer = layer.firstChild(); childLayer; childLayer = childLayer->nextSibling()) 1955 clearBackingForLayerIncludingDescendants(*childLayer); 1956} 1957 1958void RenderLayerCompositor::clearBackingForAllLayers() 1959{ 1960 clearBackingForLayerIncludingDescendants(*m_renderView.layer()); 1961} 1962 1963void RenderLayerCompositor::updateRootLayerPosition() 1964{ 1965 if (m_rootContentLayer) { 1966 const IntRect& documentRect = m_renderView.documentRect(); 1967 m_rootContentLayer->setSize(documentRect.size()); 1968 m_rootContentLayer->setPosition(FloatPoint(documentRect.x(), documentRect.y() 1969 + FrameView::yPositionForRootContentLayer(m_renderView.frameView().scrollPosition(), m_renderView.frameView().topContentInset(), m_renderView.frameView().headerHeight()))); 1970 m_rootContentLayer->setAnchorPoint(FloatPoint3D()); 1971 } 1972 if (m_clipLayer) { 1973 m_clipLayer->setSize(m_renderView.frameView().unscaledVisibleContentSizeIncludingObscuredArea()); 1974 m_clipLayer->setPosition(positionForClipLayer()); 1975 } 1976 1977#if ENABLE(RUBBER_BANDING) 1978 if (m_contentShadowLayer) { 1979 m_contentShadowLayer->setPosition(m_rootContentLayer->position()); 1980 m_contentShadowLayer->setSize(m_rootContentLayer->size()); 1981 } 1982 1983 updateLayerForTopOverhangArea(m_layerForTopOverhangArea != nullptr); 1984 updateLayerForBottomOverhangArea(m_layerForBottomOverhangArea != nullptr); 1985 updateLayerForHeader(m_layerForHeader != nullptr); 1986 updateLayerForFooter(m_layerForFooter != nullptr); 1987#endif 1988} 1989 1990bool RenderLayerCompositor::has3DContent() const 1991{ 1992 return layerHas3DContent(rootRenderLayer()); 1993} 1994 1995bool RenderLayerCompositor::allowsIndependentlyCompositedFrames(const FrameView* view) 1996{ 1997#if PLATFORM(MAC) 1998 // frames are only independently composited in Mac pre-WebKit2. 1999 return view->platformWidget(); 2000#else 2001 UNUSED_PARAM(view); 2002#endif 2003 return false; 2004} 2005 2006bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingFrame() const 2007{ 2008 // Parent document content needs to be able to render on top of a composited frame, so correct behavior 2009 // is to have the parent document become composited too. However, this can cause problems on platforms that 2010 // use native views for frames (like Mac), so disable that behavior on those platforms for now. 2011 HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement(); 2012 RenderElement* renderer = ownerElement ? ownerElement->renderer() : 0; 2013 2014 // If we are the top-level frame, don't propagate. 2015 if (!ownerElement) 2016 return false; 2017 2018 if (!allowsIndependentlyCompositedFrames(&m_renderView.frameView())) 2019 return true; 2020 2021 if (!renderer || !renderer->isWidget()) 2022 return false; 2023 2024 // On Mac, only propagate compositing if the frame is overlapped in the parent 2025 // document, or the parent is already compositing, or the main frame is scaled. 2026 Page* page = this->page(); 2027 if (page && page->pageScaleFactor() != 1) 2028 return true; 2029 2030 RenderWidget* frameRenderer = toRenderWidget(renderer); 2031 if (frameRenderer->widget()) { 2032 ASSERT(frameRenderer->widget()->isFrameView()); 2033 FrameView* view = toFrameView(frameRenderer->widget()); 2034 if (view->isOverlappedIncludingAncestors() || view->hasCompositingAncestor()) 2035 return true; 2036 } 2037 2038 return false; 2039} 2040 2041bool RenderLayerCompositor::needsToBeComposited(const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const 2042{ 2043 if (!canBeComposited(layer)) 2044 return false; 2045 2046 return requiresCompositingLayer(layer, viewportConstrainedNotCompositedReason) || layer.mustCompositeForIndirectReasons() || (inCompositingMode() && layer.isRootLayer()); 2047} 2048 2049// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons. 2050// Use needsToBeComposited() to determine if a RL actually needs a compositing layer. 2051// static 2052bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const 2053{ 2054 auto renderer = &layer.renderer(); 2055 2056 // The compositing state of a reflection should match that of its reflected layer. 2057 if (layer.isReflection()) 2058 renderer = toRenderLayerModelObject(renderer->parent()); // The RenderReplica's parent is the object being reflected. 2059 2060 // The root layer always has a compositing layer, but it may not have backing. 2061 return requiresCompositingForTransform(*renderer) 2062 || requiresCompositingForVideo(*renderer) 2063 || requiresCompositingForCanvas(*renderer) 2064 || requiresCompositingForPlugin(*renderer) 2065 || requiresCompositingForFrame(*renderer) 2066 || requiresCompositingForBackfaceVisibility(*renderer) 2067 || clipsCompositingDescendants(*renderer->layer()) 2068 || requiresCompositingForAnimation(*renderer) 2069 || requiresCompositingForFilters(*renderer) 2070 || requiresCompositingForPosition(*renderer, *renderer->layer(), viewportConstrainedNotCompositedReason) 2071#if PLATFORM(IOS) 2072 || requiresCompositingForScrolling(*renderer->layer()) 2073#endif 2074 || requiresCompositingForOverflowScrolling(*renderer->layer()); 2075} 2076 2077bool RenderLayerCompositor::canBeComposited(const RenderLayer& layer) const 2078{ 2079 if (m_hasAcceleratedCompositing && layer.isSelfPaintingLayer()) { 2080 if (!layer.isInsideFlowThread()) 2081 return true; 2082 2083 // CSS Regions flow threads do not need to be composited as we use composited RenderRegions 2084 // to render the background of the RenderFlowThread. 2085 if (layer.isRenderFlowThread()) 2086 return false; 2087 2088 return true; 2089 } 2090 return false; 2091} 2092 2093bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer& layer, const RenderLayer* compositingAncestorLayer, const LayoutRect& layerCompositedBoundsInAncestor, const LayoutRect& ancestorCompositedBounds) const 2094{ 2095 auto& renderer = layer.renderer(); 2096 2097 if (compositingAncestorLayer 2098 && !(compositingAncestorLayer->backing()->graphicsLayer()->drawsContent() 2099 || compositingAncestorLayer->backing()->paintsIntoWindow() 2100 || compositingAncestorLayer->backing()->paintsIntoCompositedAncestor())) 2101 return true; 2102 2103 if (layer.isRootLayer() 2104 || layer.transform() // note: excludes perspective and transformStyle3D. 2105 || requiresCompositingForVideo(renderer) 2106 || requiresCompositingForCanvas(renderer) 2107 || requiresCompositingForPlugin(renderer) 2108 || requiresCompositingForFrame(renderer) 2109 || requiresCompositingForBackfaceVisibility(renderer) 2110 || requiresCompositingForAnimation(renderer) 2111 || requiresCompositingForFilters(renderer) 2112 || requiresCompositingForPosition(renderer, layer) 2113 || requiresCompositingForOverflowScrolling(layer) 2114 || renderer.isTransparent() 2115 || renderer.hasMask() 2116 || renderer.hasReflection() 2117 || renderer.hasFilter() 2118#if PLATFORM(IOS) 2119 || requiresCompositingForScrolling(layer) 2120#endif 2121 ) 2122 return true; 2123 2124 2125 if (layer.mustCompositeForIndirectReasons()) { 2126 RenderLayer::IndirectCompositingReason reason = layer.indirectCompositingReason(); 2127 return reason == RenderLayer::IndirectCompositingReason::Overlap 2128 || reason == RenderLayer::IndirectCompositingReason::Stacking 2129 || reason == RenderLayer::IndirectCompositingReason::BackgroundLayer 2130 || reason == RenderLayer::IndirectCompositingReason::GraphicalEffect 2131 || reason == RenderLayer::IndirectCompositingReason::Preserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect. 2132 } 2133 2134 if (!ancestorCompositedBounds.contains(layerCompositedBoundsInAncestor)) 2135 return true; 2136 2137 return false; 2138} 2139 2140CompositingReasons RenderLayerCompositor::reasonsForCompositing(const RenderLayer& layer) const 2141{ 2142 CompositingReasons reasons = CompositingReasonNone; 2143 2144 if (!layer.isComposited()) 2145 return reasons; 2146 2147 auto renderer = &layer.renderer(); 2148 if (layer.isReflection()) 2149 renderer = toRenderLayerModelObject(renderer->parent()); 2150 2151 if (requiresCompositingForTransform(*renderer)) 2152 reasons |= CompositingReason3DTransform; 2153 2154 if (requiresCompositingForVideo(*renderer)) 2155 reasons |= CompositingReasonVideo; 2156 else if (requiresCompositingForCanvas(*renderer)) 2157 reasons |= CompositingReasonCanvas; 2158 else if (requiresCompositingForPlugin(*renderer)) 2159 reasons |= CompositingReasonPlugin; 2160 else if (requiresCompositingForFrame(*renderer)) 2161 reasons |= CompositingReasonIFrame; 2162 2163 if ((canRender3DTransforms() && renderer->style().backfaceVisibility() == BackfaceVisibilityHidden)) 2164 reasons |= CompositingReasonBackfaceVisibilityHidden; 2165 2166 if (clipsCompositingDescendants(*renderer->layer())) 2167 reasons |= CompositingReasonClipsCompositingDescendants; 2168 2169 if (requiresCompositingForAnimation(*renderer)) 2170 reasons |= CompositingReasonAnimation; 2171 2172 if (requiresCompositingForFilters(*renderer)) 2173 reasons |= CompositingReasonFilters; 2174 2175 if (requiresCompositingForPosition(*renderer, *renderer->layer())) 2176 reasons |= renderer->style().position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky; 2177 2178#if PLATFORM(IOS) 2179 if (requiresCompositingForScrolling(*renderer->layer())) 2180 reasons |= CompositingReasonOverflowScrollingTouch; 2181#endif 2182 2183 if (requiresCompositingForOverflowScrolling(*renderer->layer())) 2184 reasons |= CompositingReasonOverflowScrollingTouch; 2185 2186 switch (renderer->layer()->indirectCompositingReason()) { 2187 case RenderLayer::IndirectCompositingReason::None: 2188 break; 2189 case RenderLayer::IndirectCompositingReason::Stacking: 2190 reasons |= CompositingReasonStacking; 2191 break; 2192 case RenderLayer::IndirectCompositingReason::Overlap: 2193 reasons |= CompositingReasonOverlap; 2194 break; 2195 case RenderLayer::IndirectCompositingReason::BackgroundLayer: 2196 reasons |= CompositingReasonNegativeZIndexChildren; 2197 break; 2198 case RenderLayer::IndirectCompositingReason::GraphicalEffect: 2199 if (renderer->layer()->transform()) 2200 reasons |= CompositingReasonTransformWithCompositedDescendants; 2201 2202 if (renderer->isTransparent()) 2203 reasons |= CompositingReasonOpacityWithCompositedDescendants; 2204 2205 if (renderer->hasMask()) 2206 reasons |= CompositingReasonMaskWithCompositedDescendants; 2207 2208 if (renderer->hasReflection()) 2209 reasons |= CompositingReasonReflectionWithCompositedDescendants; 2210 2211 if (renderer->hasFilter()) 2212 reasons |= CompositingReasonFilterWithCompositedDescendants; 2213 2214#if ENABLE(CSS_COMPOSITING) 2215 if (layer.isolatesCompositedBlending()) 2216 reasons |= CompositingReasonIsolatesCompositedBlendingDescendants; 2217 2218 if (layer.hasBlendMode()) 2219 reasons |= CompositingReasonBlendingWithCompositedDescendants; 2220#endif 2221 break; 2222 case RenderLayer::IndirectCompositingReason::Perspective: 2223 reasons |= CompositingReasonPerspective; 2224 break; 2225 case RenderLayer::IndirectCompositingReason::Preserve3D: 2226 reasons |= CompositingReasonPreserve3D; 2227 break; 2228 } 2229 2230 if (inCompositingMode() && renderer->layer()->isRootLayer()) 2231 reasons |= CompositingReasonRoot; 2232 2233 return reasons; 2234} 2235 2236#if !LOG_DISABLED 2237const char* RenderLayerCompositor::logReasonsForCompositing(const RenderLayer& layer) 2238{ 2239 CompositingReasons reasons = reasonsForCompositing(layer); 2240 2241 if (reasons & CompositingReason3DTransform) 2242 return "3D transform"; 2243 2244 if (reasons & CompositingReasonVideo) 2245 return "video"; 2246 else if (reasons & CompositingReasonCanvas) 2247 return "canvas"; 2248 else if (reasons & CompositingReasonPlugin) 2249 return "plugin"; 2250 else if (reasons & CompositingReasonIFrame) 2251 return "iframe"; 2252 2253 if (reasons & CompositingReasonBackfaceVisibilityHidden) 2254 return "backface-visibility: hidden"; 2255 2256 if (reasons & CompositingReasonClipsCompositingDescendants) 2257 return "clips compositing descendants"; 2258 2259 if (reasons & CompositingReasonAnimation) 2260 return "animation"; 2261 2262 if (reasons & CompositingReasonFilters) 2263 return "filters"; 2264 2265 if (reasons & CompositingReasonPositionFixed) 2266 return "position: fixed"; 2267 2268 if (reasons & CompositingReasonPositionSticky) 2269 return "position: sticky"; 2270 2271 if (reasons & CompositingReasonOverflowScrollingTouch) 2272 return "-webkit-overflow-scrolling: touch"; 2273 2274 if (reasons & CompositingReasonStacking) 2275 return "stacking"; 2276 2277 if (reasons & CompositingReasonOverlap) 2278 return "overlap"; 2279 2280 if (reasons & CompositingReasonNegativeZIndexChildren) 2281 return "negative z-index children"; 2282 2283 if (reasons & CompositingReasonTransformWithCompositedDescendants) 2284 return "transform with composited descendants"; 2285 2286 if (reasons & CompositingReasonOpacityWithCompositedDescendants) 2287 return "opacity with composited descendants"; 2288 2289 if (reasons & CompositingReasonMaskWithCompositedDescendants) 2290 return "mask with composited descendants"; 2291 2292 if (reasons & CompositingReasonReflectionWithCompositedDescendants) 2293 return "reflection with composited descendants"; 2294 2295 if (reasons & CompositingReasonFilterWithCompositedDescendants) 2296 return "filter with composited descendants"; 2297 2298#if ENABLE(CSS_COMPOSITING) 2299 if (reasons & CompositingReasonBlendingWithCompositedDescendants) 2300 return "blending with composited descendants"; 2301 2302 if (reasons & CompositingReasonIsolatesCompositedBlendingDescendants) 2303 return "isolates composited blending descendants"; 2304#endif 2305 2306 if (reasons & CompositingReasonPerspective) 2307 return "perspective"; 2308 2309 if (reasons & CompositingReasonPreserve3D) 2310 return "preserve-3d"; 2311 2312 if (reasons & CompositingReasonRoot) 2313 return "root"; 2314 2315 return ""; 2316} 2317#endif 2318 2319// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, 2320// up to the enclosing compositing ancestor. This is required because compositing layers are parented 2321// according to the z-order hierarchy, yet clipping goes down the renderer hierarchy. 2322// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy, 2323// but a sibling in the z-order hierarchy. 2324bool RenderLayerCompositor::clippedByAncestor(RenderLayer& layer) const 2325{ 2326 if (!layer.isComposited() || !layer.parent()) 2327 return false; 2328 2329 RenderLayer* compositingAncestor = layer.ancestorCompositingLayer(); 2330 if (!compositingAncestor) 2331 return false; 2332 2333 // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(), 2334 // so we only care about clipping between its first child that is our ancestor (the computeClipRoot), 2335 // and layer. The exception is when the compositingAncestor isolates composited blending children, 2336 // in this case it is not allowed to clipsCompositingDescendants() and each of its children 2337 // will be clippedByAncestor()s, including the compositingAncestor. 2338 RenderLayer* computeClipRoot = compositingAncestor; 2339 if (!compositingAncestor->isolatesCompositedBlending()) { 2340 computeClipRoot = nullptr; 2341 RenderLayer* parent = &layer; 2342 while (parent) { 2343 RenderLayer* next = parent->parent(); 2344 if (next == compositingAncestor) { 2345 computeClipRoot = parent; 2346 break; 2347 } 2348 parent = next; 2349 } 2350 2351 if (!computeClipRoot || computeClipRoot == &layer) 2352 return false; 2353 } 2354 2355 return layer.backgroundClipRect(RenderLayer::ClipRectsContext(computeClipRoot, TemporaryClipRects)).rect() != LayoutRect::infiniteRect(); // FIXME: Incorrect for CSS regions. 2356} 2357 2358// Return true if the given layer is a stacking context and has compositing child 2359// layers that it needs to clip. In this case we insert a clipping GraphicsLayer 2360// into the hierarchy between this layer and its children in the z-order hierarchy. 2361bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer& layer) const 2362{ 2363 return layer.hasCompositingDescendant() && layer.renderer().hasClipOrOverflowClip() && !layer.isolatesCompositedBlending(); 2364} 2365 2366bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const 2367{ 2368 // Need this done first to determine overflow. 2369 ASSERT(!m_renderView.needsLayout()); 2370 HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement(); 2371 if (!ownerElement) 2372 return false; 2373 2374 if (!(m_compositingTriggers & ChromeClient::ScrollableInnerFrameTrigger)) 2375 return false; 2376 2377 return m_renderView.frameView().isScrollable(); 2378} 2379 2380bool RenderLayerCompositor::requiresCompositingForTransform(RenderLayerModelObject& renderer) const 2381{ 2382 if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger)) 2383 return false; 2384 2385 // Note that we ask the renderer if it has a transform, because the style may have transforms, 2386 // but the renderer may be an inline that doesn't suppport them. 2387 return renderer.hasTransform() && renderer.style().transform().has3DOperation(); 2388} 2389 2390bool RenderLayerCompositor::requiresCompositingForBackfaceVisibility(RenderLayerModelObject& renderer) const 2391{ 2392 if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger)) 2393 return false; 2394 2395 if (renderer.style().backfaceVisibility() != BackfaceVisibilityHidden) 2396 return false; 2397 2398 if (renderer.layer()->has3DTransformedAncestor()) 2399 return true; 2400 2401 // FIXME: workaround for webkit.org/b/132801 2402 RenderLayer* stackingContext = renderer.layer()->stackingContainer(); 2403 if (stackingContext && stackingContext->renderer().style().transformStyle3D() == TransformStyle3DPreserve3D) 2404 return true; 2405 2406 return false; 2407} 2408 2409bool RenderLayerCompositor::requiresCompositingForVideo(RenderLayerModelObject& renderer) const 2410{ 2411 if (!(m_compositingTriggers & ChromeClient::VideoTrigger)) 2412 return false; 2413#if ENABLE(VIDEO) 2414 if (renderer.isVideo()) { 2415 RenderVideo& video = toRenderVideo(renderer); 2416 return (video.requiresImmediateCompositing() || video.shouldDisplayVideo()) && canAccelerateVideoRendering(video); 2417 } 2418#else 2419 UNUSED_PARAM(renderer); 2420#endif 2421 return false; 2422} 2423 2424bool RenderLayerCompositor::requiresCompositingForCanvas(RenderLayerModelObject& renderer) const 2425{ 2426 if (!(m_compositingTriggers & ChromeClient::CanvasTrigger)) 2427 return false; 2428 2429 if (renderer.isCanvas()) { 2430#if USE(COMPOSITING_FOR_SMALL_CANVASES) 2431 bool isCanvasLargeEnoughToForceCompositing = true; 2432#else 2433 HTMLCanvasElement* canvas = toHTMLCanvasElement(renderer.element()); 2434 bool isCanvasLargeEnoughToForceCompositing = canvas->size().area() >= canvasAreaThresholdRequiringCompositing; 2435#endif 2436 CanvasCompositingStrategy compositingStrategy = canvasCompositingStrategy(renderer); 2437 return compositingStrategy == CanvasAsLayerContents || (compositingStrategy == CanvasPaintedToLayer && isCanvasLargeEnoughToForceCompositing); 2438 } 2439 2440 return false; 2441} 2442 2443bool RenderLayerCompositor::requiresCompositingForPlugin(RenderLayerModelObject& renderer) const 2444{ 2445 if (!(m_compositingTriggers & ChromeClient::PluginTrigger)) 2446 return false; 2447 2448 bool composite = renderer.isEmbeddedObject() && toRenderEmbeddedObject(&renderer)->allowsAcceleratedCompositing(); 2449 if (!composite) 2450 return false; 2451 2452 m_reevaluateCompositingAfterLayout = true; 2453 2454 RenderWidget& pluginRenderer = *toRenderWidget(&renderer); 2455 // If we can't reliably know the size of the plugin yet, don't change compositing state. 2456 if (pluginRenderer.needsLayout()) 2457 return pluginRenderer.hasLayer() && pluginRenderer.layer()->isComposited(); 2458 2459 // Don't go into compositing mode if height or width are zero, or size is 1x1. 2460 IntRect contentBox = pixelSnappedIntRect(pluginRenderer.contentBoxRect()); 2461 return contentBox.height() * contentBox.width() > 1; 2462} 2463 2464bool RenderLayerCompositor::requiresCompositingForFrame(RenderLayerModelObject& renderer) const 2465{ 2466 if (!renderer.isWidget()) 2467 return false; 2468 2469 RenderWidget& frameRenderer = *toRenderWidget(&renderer); 2470 2471 if (!frameRenderer.requiresAcceleratedCompositing()) 2472 return false; 2473 2474 m_reevaluateCompositingAfterLayout = true; 2475 2476 RenderLayerCompositor* innerCompositor = frameContentsCompositor(&frameRenderer); 2477 if (!innerCompositor || !innerCompositor->shouldPropagateCompositingToEnclosingFrame()) 2478 return false; 2479 2480 // If we can't reliably know the size of the iframe yet, don't change compositing state. 2481 if (!frameRenderer.parent() || frameRenderer.needsLayout()) 2482 return frameRenderer.hasLayer() && frameRenderer.layer()->isComposited(); 2483 2484 // Don't go into compositing mode if height or width are zero. 2485 return !pixelSnappedIntRect(frameRenderer.contentBoxRect()).isEmpty(); 2486} 2487 2488bool RenderLayerCompositor::requiresCompositingForAnimation(RenderLayerModelObject& renderer) const 2489{ 2490 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger)) 2491 return false; 2492 2493 const AnimationBase::RunningState activeAnimationState = AnimationBase::Running | AnimationBase::Paused | AnimationBase::FillingFowards; 2494 AnimationController& animController = renderer.animation(); 2495 return (animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyOpacity, activeAnimationState) 2496 && (inCompositingMode() || (m_compositingTriggers & ChromeClient::AnimatedOpacityTrigger))) 2497#if ENABLE(CSS_FILTERS) 2498 || animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitFilter, activeAnimationState) 2499#endif // CSS_FILTERS 2500 || animController.isRunningAnimationOnRenderer(&renderer, CSSPropertyWebkitTransform, activeAnimationState); 2501} 2502 2503bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderLayerModelObject& renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const 2504{ 2505 RenderLayer& layer = *toRenderBoxModelObject(renderer).layer(); 2506 2507 // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented 2508 // via compositing so that they also apply to those composited descendants. 2509 if (hasCompositedDescendants && (layer.isolatesCompositedBlending() || layer.transform() || renderer.createsGroup() || renderer.hasReflection() || renderer.isRenderNamedFlowFragmentContainer())) { 2510 reason = RenderLayer::IndirectCompositingReason::GraphicalEffect; 2511 return true; 2512 } 2513 2514 // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that 2515 // will be affected by the preserve-3d or perspective. 2516 if (has3DTransformedDescendants) { 2517 if (renderer.style().transformStyle3D() == TransformStyle3DPreserve3D) { 2518 reason = RenderLayer::IndirectCompositingReason::Preserve3D; 2519 return true; 2520 } 2521 2522 if (renderer.style().hasPerspective()) { 2523 reason = RenderLayer::IndirectCompositingReason::Perspective; 2524 return true; 2525 } 2526 } 2527 2528 reason = RenderLayer::IndirectCompositingReason::None; 2529 return false; 2530} 2531 2532bool RenderLayerCompositor::requiresCompositingForFilters(RenderLayerModelObject& renderer) const 2533{ 2534#if ENABLE(CSS_FILTERS) 2535 if (!(m_compositingTriggers & ChromeClient::FilterTrigger)) 2536 return false; 2537 2538 return renderer.hasFilter(); 2539#else 2540 UNUSED_PARAM(renderer); 2541 return false; 2542#endif 2543} 2544 2545bool RenderLayerCompositor::isAsyncScrollableStickyLayer(const RenderLayer& layer, const RenderLayer** enclosingAcceleratedOverflowLayer) const 2546{ 2547 ASSERT(layer.renderer().isStickyPositioned()); 2548 2549 RenderLayer* enclosingOverflowLayer = layer.enclosingOverflowClipLayer(ExcludeSelf); 2550 2551#if PLATFORM(IOS) 2552 if (enclosingOverflowLayer && enclosingOverflowLayer->hasTouchScrollableOverflow()) { 2553 if (enclosingAcceleratedOverflowLayer) 2554 *enclosingAcceleratedOverflowLayer = enclosingOverflowLayer; 2555 return true; 2556 } 2557#else 2558 UNUSED_PARAM(enclosingAcceleratedOverflowLayer); 2559#endif 2560 // If the layer is inside normal overflow, it's not async-scrollable. 2561 if (enclosingOverflowLayer) 2562 return false; 2563 2564 // No overflow ancestor, so see if the frame supports async scrolling. 2565 if (hasCoordinatedScrolling()) 2566 return true; 2567 2568#if PLATFORM(IOS) 2569 // iOS WK1 has fixed/sticky support in the main frame via WebFixedPositionContent. 2570 return m_renderView.frameView().frame().isMainFrame(); 2571#else 2572 return false; 2573#endif 2574} 2575 2576bool RenderLayerCompositor::isViewportConstrainedFixedOrStickyLayer(const RenderLayer& layer) const 2577{ 2578 if (layer.renderer().isStickyPositioned()) 2579 return isAsyncScrollableStickyLayer(layer); 2580 2581 if (layer.renderer().style().position() != FixedPosition) 2582 return false; 2583 2584 // FIXME: Handle fixed inside of a transform, which should not behave as fixed. 2585 for (RenderLayer* stackingContainer = layer.stackingContainer(); stackingContainer; stackingContainer = stackingContainer->stackingContainer()) { 2586 if (stackingContainer->isComposited() && stackingContainer->renderer().style().position() == FixedPosition) 2587 return false; 2588 } 2589 2590 return true; 2591} 2592 2593static bool useCoordinatedScrollingForLayer(RenderView& view, const RenderLayer& layer) 2594{ 2595 if (layer.isRootLayer() && view.frameView().frame().isMainFrame()) 2596 return true; 2597 2598#if PLATFORM(IOS) 2599 return layer.hasTouchScrollableOverflow(); 2600#else 2601 return layer.needsCompositedScrolling(); 2602#endif 2603} 2604 2605bool RenderLayerCompositor::requiresCompositingForPosition(RenderLayerModelObject& renderer, const RenderLayer& layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const 2606{ 2607 // position:fixed elements that create their own stacking context (e.g. have an explicit z-index, 2608 // opacity, transform) can get their own composited layer. A stacking context is required otherwise 2609 // z-index and clipping will be broken. 2610 if (!renderer.isPositioned()) 2611 return false; 2612 2613 EPosition position = renderer.style().position(); 2614 bool isFixed = renderer.isOutOfFlowPositioned() && position == FixedPosition; 2615 if (isFixed && !layer.isStackingContainer()) 2616 return false; 2617 2618 bool isSticky = renderer.isInFlowPositioned() && position == StickyPosition; 2619 if (!isFixed && !isSticky) 2620 return false; 2621 2622 // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled(). 2623 const Settings& settings = m_renderView.frameView().frame().settings(); 2624 if (!settings.acceleratedCompositingForFixedPositionEnabled()) 2625 return false; 2626 2627 if (isSticky) 2628 return isAsyncScrollableStickyLayer(layer); 2629 2630 auto container = renderer.container(); 2631 // If the renderer is not hooked up yet then we have to wait until it is. 2632 if (!container) { 2633 m_reevaluateCompositingAfterLayout = true; 2634 return false; 2635 } 2636 2637 // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements. 2638 // They will stay fixed wrt the container rather than the enclosing frame. 2639 if (container != &m_renderView && !renderer.fixedPositionedWithNamedFlowContainingBlock()) { 2640 if (viewportConstrainedNotCompositedReason) 2641 *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer; 2642 return false; 2643 } 2644 2645 // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done. 2646 if (!m_inPostLayoutUpdate) { 2647 m_reevaluateCompositingAfterLayout = true; 2648 return layer.isComposited(); 2649 } 2650 2651 bool paintsContent = layer.isVisuallyNonEmpty() || layer.hasVisibleDescendant(); 2652 if (!paintsContent) { 2653 if (viewportConstrainedNotCompositedReason) 2654 *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent; 2655 return false; 2656 } 2657 2658 // Fixed position elements that are invisible in the current view don't get their own layer. 2659 LayoutRect viewBounds = m_renderView.frameView().viewportConstrainedVisibleContentRect(); 2660 LayoutRect layerBounds = layer.calculateLayerBounds(&layer, LayoutSize(), RenderLayer::UseLocalClipRectIfPossible | RenderLayer::IncludeLayerFilterOutsets | RenderLayer::UseFragmentBoxesExcludingCompositing 2661 | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants); 2662 // Map to m_renderView to ignore page scale. 2663 FloatRect absoluteBounds = layer.renderer().localToContainerQuad(FloatRect(layerBounds), &m_renderView).boundingBox(); 2664 if (!viewBounds.intersects(enclosingIntRect(absoluteBounds))) { 2665 if (viewportConstrainedNotCompositedReason) 2666 *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView; 2667 return false; 2668 } 2669 2670 return true; 2671} 2672 2673bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer& layer) const 2674{ 2675 return layer.needsCompositedScrolling(); 2676} 2677 2678#if PLATFORM(IOS) 2679bool RenderLayerCompositor::requiresCompositingForScrolling(const RenderLayer& layer) const 2680{ 2681 if (!layer.hasAcceleratedTouchScrolling()) 2682 return false; 2683 2684 if (!m_inPostLayoutUpdate) { 2685 m_reevaluateCompositingAfterLayout = true; 2686 return layer.isComposited(); 2687 } 2688 2689 return layer.hasTouchScrollableOverflow(); 2690} 2691#endif 2692 2693bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderLayerModelObject& renderer) const 2694{ 2695 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger)) 2696 return false; 2697 2698 return renderer.animation().isRunningAcceleratedAnimationOnRenderer(&renderer, CSSPropertyWebkitTransform, AnimationBase::Running | AnimationBase::Paused); 2699} 2700 2701// If an element has negative z-index children, those children render in front of the 2702// layer background, so we need an extra 'contents' layer for the foreground of the layer 2703// object. 2704bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer& layer) const 2705{ 2706 return layer.hasNegativeZOrderList(); 2707} 2708 2709bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) const 2710{ 2711 FrameView& frameView = m_renderView.frameView(); 2712 2713 // This applies when the application UI handles scrolling, in which case RenderLayerCompositor doesn't need to manage it. 2714 if (frameView.delegatesScrolling() && frameView.frame().isMainFrame()) 2715 return false; 2716 2717 // We need to handle our own scrolling if we're: 2718 return !m_renderView.frameView().platformWidget() // viewless (i.e. non-Mac, or Mac in WebKit2) 2719 || attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac 2720} 2721 2722static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) 2723{ 2724 if (!scrollbar) 2725 return; 2726 2727 context.save(); 2728 const IntRect& scrollbarRect = scrollbar->frameRect(); 2729 context.translate(-scrollbarRect.x(), -scrollbarRect.y()); 2730 IntRect transformedClip = clip; 2731 transformedClip.moveBy(scrollbarRect.location()); 2732 scrollbar->paint(&context, transformedClip); 2733 context.restore(); 2734} 2735 2736void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const FloatRect& clip) 2737{ 2738 IntRect pixelSnappedRectForIntegralPositionedItems = pixelSnappedIntRect(LayoutRect(clip)); 2739 if (graphicsLayer == layerForHorizontalScrollbar()) 2740 paintScrollbar(m_renderView.frameView().horizontalScrollbar(), context, pixelSnappedRectForIntegralPositionedItems); 2741 else if (graphicsLayer == layerForVerticalScrollbar()) 2742 paintScrollbar(m_renderView.frameView().verticalScrollbar(), context, pixelSnappedRectForIntegralPositionedItems); 2743 else if (graphicsLayer == layerForScrollCorner()) { 2744 const IntRect& scrollCorner = m_renderView.frameView().scrollCornerRect(); 2745 context.save(); 2746 context.translate(-scrollCorner.x(), -scrollCorner.y()); 2747 IntRect transformedClip = pixelSnappedRectForIntegralPositionedItems; 2748 transformedClip.moveBy(scrollCorner.location()); 2749 m_renderView.frameView().paintScrollCorner(&context, transformedClip); 2750 context.restore(); 2751 } 2752} 2753 2754bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const 2755{ 2756 RenderLayerBacking* renderViewBacking = m_renderView.layer()->backing(); 2757 return renderViewBacking && renderViewBacking->usingTiledBacking(); 2758} 2759 2760bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer& layer) const 2761{ 2762 if (&layer != m_renderView.layer()) 2763 return false; 2764 2765 if (m_renderView.frameView().frame().settings().fixedBackgroundsPaintRelativeToDocument()) 2766 return false; 2767 2768 return supportsFixedRootBackgroundCompositing() && m_renderView.rootBackgroundIsEntirelyFixed(); 2769} 2770 2771GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const 2772{ 2773 // Get the fixed root background from the RenderView layer's backing. 2774 RenderLayer* viewLayer = m_renderView.layer(); 2775 if (!viewLayer) 2776 return nullptr; 2777 2778 if (viewLayer->isComposited() && viewLayer->backing()->backgroundLayerPaintsFixedRootBackground()) 2779 return viewLayer->backing()->backgroundLayer(); 2780 2781 return nullptr; 2782} 2783 2784static void resetTrackedRepaintRectsRecursive(GraphicsLayer& graphicsLayer) 2785{ 2786 graphicsLayer.resetTrackedRepaints(); 2787 2788 for (size_t i = 0, size = graphicsLayer.children().size(); i < size; ++i) 2789 resetTrackedRepaintRectsRecursive(*graphicsLayer.children()[i]); 2790 2791 if (GraphicsLayer* replicaLayer = graphicsLayer.replicaLayer()) 2792 resetTrackedRepaintRectsRecursive(*replicaLayer); 2793 2794 if (GraphicsLayer* maskLayer = graphicsLayer.maskLayer()) 2795 resetTrackedRepaintRectsRecursive(*maskLayer); 2796} 2797 2798void RenderLayerCompositor::resetTrackedRepaintRects() 2799{ 2800 if (GraphicsLayer* rootLayer = rootGraphicsLayer()) 2801 resetTrackedRepaintRectsRecursive(*rootLayer); 2802} 2803 2804void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints) 2805{ 2806 m_isTrackingRepaints = tracksRepaints; 2807} 2808 2809bool RenderLayerCompositor::isTrackingRepaints() const 2810{ 2811 return m_isTrackingRepaints; 2812} 2813 2814float RenderLayerCompositor::deviceScaleFactor() const 2815{ 2816 Page* page = this->page(); 2817 return page ? page->deviceScaleFactor() : 1; 2818} 2819 2820float RenderLayerCompositor::pageScaleFactor() const 2821{ 2822 Page* page = this->page(); 2823 return page ? page->pageScaleFactor() : 1; 2824} 2825 2826float RenderLayerCompositor::zoomedOutPageScaleFactor() const 2827{ 2828 Page* page = this->page(); 2829 return page ? page->zoomedOutPageScaleFactor() : 0; 2830} 2831 2832float RenderLayerCompositor::contentsScaleMultiplierForNewTiles(const GraphicsLayer*) const 2833{ 2834#if PLATFORM(IOS) 2835 LegacyTileCache* tileCache = nullptr; 2836 if (Page* page = this->page()) { 2837 if (FrameView* frameView = page->mainFrame().view()) 2838 tileCache = frameView->legacyTileCache(); 2839 } 2840 2841 if (!tileCache) 2842 return 1; 2843 2844 return tileCache->tileControllerShouldUseLowScaleTiles() ? 0.125 : 1; 2845#else 2846 return 1; 2847#endif 2848} 2849 2850void RenderLayerCompositor::didCommitChangesForLayer(const GraphicsLayer*) const 2851{ 2852 // Nothing to do here yet. 2853} 2854 2855bool RenderLayerCompositor::mainFrameBackingIsTiled() const 2856{ 2857 RenderLayer* layer = m_renderView.layer(); 2858 if (!layer) 2859 return false; 2860 2861 RenderLayerBacking* backing = layer->backing(); 2862 if (!backing) 2863 return false; 2864 2865 return backing->usingTiledBacking(); 2866} 2867 2868bool RenderLayerCompositor::shouldCompositeOverflowControls() const 2869{ 2870 FrameView& frameView = m_renderView.frameView(); 2871 2872 if (frameView.platformWidget()) 2873 return false; 2874 2875 if (frameView.delegatesScrolling()) 2876 return false; 2877 2878 if (mainFrameBackingIsTiled()) 2879 return true; 2880 2881 if (!frameView.hasOverlayScrollbars()) 2882 return false; 2883 2884 return true; 2885} 2886 2887bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const 2888{ 2889 return shouldCompositeOverflowControls() && m_renderView.frameView().horizontalScrollbar(); 2890} 2891 2892bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const 2893{ 2894 return shouldCompositeOverflowControls() && m_renderView.frameView().verticalScrollbar(); 2895} 2896 2897bool RenderLayerCompositor::requiresScrollCornerLayer() const 2898{ 2899 return shouldCompositeOverflowControls() && m_renderView.frameView().isScrollCornerVisible(); 2900} 2901 2902#if ENABLE(RUBBER_BANDING) 2903bool RenderLayerCompositor::requiresOverhangAreasLayer() const 2904{ 2905 // We don't want a layer if this is a subframe. 2906 if (m_renderView.document().ownerElement()) 2907 return false; 2908 2909 // We do want a layer if we're using tiled drawing and can scroll. 2910 if (mainFrameBackingIsTiled() && m_renderView.frameView().hasOpaqueBackground() && !m_renderView.frameView().prohibitsScrolling()) 2911 return true; 2912 2913 return false; 2914} 2915 2916bool RenderLayerCompositor::requiresContentShadowLayer() const 2917{ 2918 // We don't want a layer if this is a subframe. 2919 if (m_renderView.document().ownerElement()) 2920 return false; 2921 2922#if PLATFORM(COCOA) 2923 if (viewHasTransparentBackground()) 2924 return false; 2925 2926 // If the background is going to extend, then it doesn't make sense to have a shadow layer. 2927 if (m_renderView.frameView().frame().settings().backgroundShouldExtendBeyondPage()) 2928 return false; 2929 2930 // On Mac, we want a content shadow layer if we're using tiled drawing and can scroll. 2931 if (mainFrameBackingIsTiled() && !m_renderView.frameView().prohibitsScrolling()) 2932 return true; 2933#endif 2934 2935 return false; 2936} 2937 2938GraphicsLayer* RenderLayerCompositor::updateLayerForTopOverhangArea(bool wantsLayer) 2939{ 2940 if (m_renderView.document().ownerElement()) 2941 return 0; 2942 2943 if (!wantsLayer) { 2944 if (m_layerForTopOverhangArea) { 2945 m_layerForTopOverhangArea->removeFromParent(); 2946 m_layerForTopOverhangArea = nullptr; 2947 } 2948 return 0; 2949 } 2950 2951 if (!m_layerForTopOverhangArea) { 2952 m_layerForTopOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), *this); 2953#ifndef NDEBUG 2954 m_layerForTopOverhangArea->setName("top overhang area"); 2955#endif 2956 m_scrollLayer->addChildBelow(m_layerForTopOverhangArea.get(), m_rootContentLayer.get()); 2957 } 2958 2959 return m_layerForTopOverhangArea.get(); 2960} 2961 2962GraphicsLayer* RenderLayerCompositor::updateLayerForBottomOverhangArea(bool wantsLayer) 2963{ 2964 if (m_renderView.document().ownerElement()) 2965 return 0; 2966 2967 if (!wantsLayer) { 2968 if (m_layerForBottomOverhangArea) { 2969 m_layerForBottomOverhangArea->removeFromParent(); 2970 m_layerForBottomOverhangArea = nullptr; 2971 } 2972 return 0; 2973 } 2974 2975 if (!m_layerForBottomOverhangArea) { 2976 m_layerForBottomOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), *this); 2977#ifndef NDEBUG 2978 m_layerForBottomOverhangArea->setName("bottom overhang area"); 2979#endif 2980 m_scrollLayer->addChildBelow(m_layerForBottomOverhangArea.get(), m_rootContentLayer.get()); 2981 } 2982 2983 m_layerForBottomOverhangArea->setPosition(FloatPoint(0, m_rootContentLayer->size().height() + m_renderView.frameView().headerHeight() 2984 + m_renderView.frameView().footerHeight() + m_renderView.frameView().topContentInset())); 2985 return m_layerForBottomOverhangArea.get(); 2986} 2987 2988GraphicsLayer* RenderLayerCompositor::updateLayerForHeader(bool wantsLayer) 2989{ 2990 if (m_renderView.document().ownerElement()) 2991 return 0; 2992 2993 if (!wantsLayer) { 2994 if (m_layerForHeader) { 2995 m_layerForHeader->removeFromParent(); 2996 m_layerForHeader = nullptr; 2997 2998 // The ScrollingTree knows about the header layer, and the position of the root layer is affected 2999 // by the header layer, so if we remove the header, we need to tell the scrolling tree. 3000 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3001 scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView()); 3002 } 3003 return 0; 3004 } 3005 3006 if (!m_layerForHeader) { 3007 m_layerForHeader = GraphicsLayer::create(graphicsLayerFactory(), *this); 3008#ifndef NDEBUG 3009 m_layerForHeader->setName("header"); 3010#endif 3011 m_scrollLayer->addChildAbove(m_layerForHeader.get(), m_rootContentLayer.get()); 3012 m_renderView.frameView().addPaintPendingMilestones(DidFirstFlushForHeaderLayer); 3013 } 3014 3015 m_layerForHeader->setPosition(FloatPoint(0, 3016 FrameView::yPositionForHeaderLayer(m_renderView.frameView().scrollPosition(), m_renderView.frameView().topContentInset()))); 3017 m_layerForHeader->setAnchorPoint(FloatPoint3D()); 3018 m_layerForHeader->setSize(FloatSize(m_renderView.frameView().visibleWidth(), m_renderView.frameView().headerHeight())); 3019 3020 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3021 scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView()); 3022 3023 if (Page* page = this->page()) 3024 page->chrome().client().didAddHeaderLayer(m_layerForHeader.get()); 3025 3026 return m_layerForHeader.get(); 3027} 3028 3029GraphicsLayer* RenderLayerCompositor::updateLayerForFooter(bool wantsLayer) 3030{ 3031 if (m_renderView.document().ownerElement()) 3032 return 0; 3033 3034 if (!wantsLayer) { 3035 if (m_layerForFooter) { 3036 m_layerForFooter->removeFromParent(); 3037 m_layerForFooter = nullptr; 3038 3039 // The ScrollingTree knows about the footer layer, and the total scrollable size is affected 3040 // by the footer layer, so if we remove the footer, we need to tell the scrolling tree. 3041 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3042 scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView()); 3043 } 3044 return 0; 3045 } 3046 3047 if (!m_layerForFooter) { 3048 m_layerForFooter = GraphicsLayer::create(graphicsLayerFactory(), *this); 3049#ifndef NDEBUG 3050 m_layerForFooter->setName("footer"); 3051#endif 3052 m_scrollLayer->addChildAbove(m_layerForFooter.get(), m_rootContentLayer.get()); 3053 } 3054 3055 float totalContentHeight = m_rootContentLayer->size().height() + m_renderView.frameView().headerHeight() + m_renderView.frameView().footerHeight(); 3056 m_layerForFooter->setPosition(FloatPoint(0, FrameView::yPositionForFooterLayer(m_renderView.frameView().scrollPosition(), 3057 m_renderView.frameView().topContentInset(), totalContentHeight, m_renderView.frameView().footerHeight()))); 3058 m_layerForFooter->setAnchorPoint(FloatPoint3D()); 3059 m_layerForFooter->setSize(FloatSize(m_renderView.frameView().visibleWidth(), m_renderView.frameView().footerHeight())); 3060 3061 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3062 scrollingCoordinator->frameViewRootLayerDidChange(&m_renderView.frameView()); 3063 3064 if (Page* page = this->page()) 3065 page->chrome().client().didAddFooterLayer(m_layerForFooter.get()); 3066 3067 return m_layerForFooter.get(); 3068} 3069 3070#endif 3071 3072bool RenderLayerCompositor::viewHasTransparentBackground(Color* backgroundColor) const 3073{ 3074 if (m_renderView.frameView().isTransparent()) { 3075 if (backgroundColor) 3076 *backgroundColor = Color(); // Return an invalid color. 3077 return true; 3078 } 3079 3080 Color documentBackgroundColor = m_renderView.frameView().documentBackgroundColor(); 3081 if (!documentBackgroundColor.isValid()) 3082 documentBackgroundColor = Color::white; 3083 3084 if (backgroundColor) 3085 *backgroundColor = documentBackgroundColor; 3086 3087 return documentBackgroundColor.hasAlpha(); 3088} 3089 3090void RenderLayerCompositor::setRootExtendedBackgroundColor(const Color& color) 3091{ 3092 if (color == m_rootExtendedBackgroundColor) 3093 return; 3094 3095 m_rootExtendedBackgroundColor = color; 3096 3097 if (Page* page = this->page()) 3098 page->chrome().client().pageExtendedBackgroundColorDidChange(color); 3099 3100#if ENABLE(RUBBER_BANDING) 3101 if (!m_layerForOverhangAreas) 3102 return; 3103 3104 m_layerForOverhangAreas->setBackgroundColor(m_rootExtendedBackgroundColor); 3105 3106 if (!m_rootExtendedBackgroundColor.isValid()) 3107 m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::ScrollingOverhang); 3108#endif 3109} 3110 3111void RenderLayerCompositor::updateOverflowControlsLayers() 3112{ 3113#if ENABLE(RUBBER_BANDING) 3114 if (requiresOverhangAreasLayer()) { 3115 if (!m_layerForOverhangAreas) { 3116 m_layerForOverhangAreas = GraphicsLayer::create(graphicsLayerFactory(), *this); 3117#ifndef NDEBUG 3118 m_layerForOverhangAreas->setName("overhang areas"); 3119#endif 3120 m_layerForOverhangAreas->setDrawsContent(false); 3121 3122 float topContentInset = m_renderView.frameView().topContentInset(); 3123 IntSize overhangAreaSize = m_renderView.frameView().frameRect().size(); 3124 overhangAreaSize.setHeight(overhangAreaSize.height() - topContentInset); 3125 m_layerForOverhangAreas->setSize(overhangAreaSize); 3126 m_layerForOverhangAreas->setPosition(FloatPoint(0, topContentInset)); 3127 m_layerForOverhangAreas->setAnchorPoint(FloatPoint3D()); 3128 3129 if (m_renderView.frameView().frame().settings().backgroundShouldExtendBeyondPage()) 3130 m_layerForOverhangAreas->setBackgroundColor(m_renderView.frameView().documentBackgroundColor()); 3131 else 3132 m_layerForOverhangAreas->setCustomAppearance(GraphicsLayer::ScrollingOverhang); 3133 3134 // We want the overhang areas layer to be positioned below the frame contents, 3135 // so insert it below the clip layer. 3136 m_overflowControlsHostLayer->addChildBelow(m_layerForOverhangAreas.get(), m_clipLayer.get()); 3137 } 3138 } else if (m_layerForOverhangAreas) { 3139 m_layerForOverhangAreas->removeFromParent(); 3140 m_layerForOverhangAreas = nullptr; 3141 } 3142 3143 if (requiresContentShadowLayer()) { 3144 if (!m_contentShadowLayer) { 3145 m_contentShadowLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); 3146#ifndef NDEBUG 3147 m_contentShadowLayer->setName("content shadow"); 3148#endif 3149 m_contentShadowLayer->setSize(m_rootContentLayer->size()); 3150 m_contentShadowLayer->setPosition(m_rootContentLayer->position()); 3151 m_contentShadowLayer->setAnchorPoint(FloatPoint3D()); 3152 m_contentShadowLayer->setCustomAppearance(GraphicsLayer::ScrollingShadow); 3153 3154 m_scrollLayer->addChildBelow(m_contentShadowLayer.get(), m_rootContentLayer.get()); 3155 } 3156 } else if (m_contentShadowLayer) { 3157 m_contentShadowLayer->removeFromParent(); 3158 m_contentShadowLayer = nullptr; 3159 } 3160#endif 3161 3162 if (requiresHorizontalScrollbarLayer()) { 3163 if (!m_layerForHorizontalScrollbar) { 3164 m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this); 3165 m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders); 3166#ifndef NDEBUG 3167 m_layerForHorizontalScrollbar->setName("horizontal scrollbar container"); 3168 3169#endif 3170#if PLATFORM(COCOA) && USE(CA) 3171 m_layerForHorizontalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled()); 3172#endif 3173 m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get()); 3174 3175 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3176 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), HorizontalScrollbar); 3177 } 3178 } else if (m_layerForHorizontalScrollbar) { 3179 m_layerForHorizontalScrollbar->removeFromParent(); 3180 m_layerForHorizontalScrollbar = nullptr; 3181 3182 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3183 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), HorizontalScrollbar); 3184 } 3185 3186 if (requiresVerticalScrollbarLayer()) { 3187 if (!m_layerForVerticalScrollbar) { 3188 m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), *this); 3189 m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders); 3190#ifndef NDEBUG 3191 m_layerForVerticalScrollbar->setName("vertical scrollbar container"); 3192#endif 3193#if PLATFORM(COCOA) && USE(CA) 3194 m_layerForVerticalScrollbar->setAcceleratesDrawing(acceleratedDrawingEnabled()); 3195#endif 3196 m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get()); 3197 3198 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3199 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), VerticalScrollbar); 3200 } 3201 } else if (m_layerForVerticalScrollbar) { 3202 m_layerForVerticalScrollbar->removeFromParent(); 3203 m_layerForVerticalScrollbar = nullptr; 3204 3205 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3206 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), VerticalScrollbar); 3207 } 3208 3209 if (requiresScrollCornerLayer()) { 3210 if (!m_layerForScrollCorner) { 3211 m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), *this); 3212 m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders); 3213#ifndef NDEBUG 3214 m_layerForScrollCorner->setName("scroll corner"); 3215#endif 3216#if PLATFORM(COCOA) && USE(CA) 3217 m_layerForScrollCorner->setAcceleratesDrawing(acceleratedDrawingEnabled()); 3218#endif 3219 m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get()); 3220 } 3221 } else if (m_layerForScrollCorner) { 3222 m_layerForScrollCorner->removeFromParent(); 3223 m_layerForScrollCorner = nullptr; 3224 } 3225 3226 m_renderView.frameView().positionScrollbarLayers(); 3227} 3228 3229void RenderLayerCompositor::ensureRootLayer() 3230{ 3231 RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient; 3232 if (expectedAttachment == m_rootLayerAttachment) 3233 return; 3234 3235 if (!m_rootContentLayer) { 3236 m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); 3237#ifndef NDEBUG 3238 m_rootContentLayer->setName("content root"); 3239#endif 3240 IntRect overflowRect = m_renderView.pixelSnappedLayoutOverflowRect(); 3241 m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY())); 3242 m_rootContentLayer->setPosition(FloatPoint()); 3243 3244#if PLATFORM(IOS) || PLATFORM(EFL) 3245 // Page scale is applied above this on iOS, so we'll just say that our root layer applies it. 3246 Frame& frame = m_renderView.frameView().frame(); 3247 if (frame.isMainFrame()) 3248 m_rootContentLayer->setAppliesPageScale(); 3249#endif 3250 3251 // Need to clip to prevent transformed content showing outside this frame 3252 m_rootContentLayer->setMasksToBounds(true); 3253 } 3254 3255 if (requiresScrollLayer(expectedAttachment)) { 3256 if (!m_overflowControlsHostLayer) { 3257 ASSERT(!m_scrollLayer); 3258 ASSERT(!m_clipLayer); 3259 3260 // Create a layer to host the clipping layer and the overflow controls layers. 3261 m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); 3262#ifndef NDEBUG 3263 m_overflowControlsHostLayer->setName("overflow controls host"); 3264#endif 3265 3266 // Create a clipping layer if this is an iframe 3267 m_clipLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); 3268#ifndef NDEBUG 3269 m_clipLayer->setName("frame clipping"); 3270#endif 3271 m_clipLayer->setMasksToBounds(true); 3272 3273 m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), *this); 3274#ifndef NDEBUG 3275 m_scrollLayer->setName("frame scrolling"); 3276#endif 3277 // Hook them up 3278 m_overflowControlsHostLayer->addChild(m_clipLayer.get()); 3279 m_clipLayer->addChild(m_scrollLayer.get()); 3280 m_scrollLayer->addChild(m_rootContentLayer.get()); 3281 3282 m_clipLayer->setSize(m_renderView.frameView().unscaledVisibleContentSizeIncludingObscuredArea()); 3283 m_clipLayer->setPosition(positionForClipLayer()); 3284 m_clipLayer->setAnchorPoint(FloatPoint3D()); 3285 3286 updateOverflowControlsLayers(); 3287 3288 if (hasCoordinatedScrolling()) 3289 scheduleLayerFlush(true); 3290 else 3291 updateScrollLayerPosition(); 3292 } 3293 } else { 3294 if (m_overflowControlsHostLayer) { 3295 m_overflowControlsHostLayer = nullptr; 3296 m_clipLayer = nullptr; 3297 m_scrollLayer = nullptr; 3298 } 3299 } 3300 3301 // Check to see if we have to change the attachment 3302 if (m_rootLayerAttachment != RootLayerUnattached) 3303 detachRootLayer(); 3304 3305 attachRootLayer(expectedAttachment); 3306} 3307 3308void RenderLayerCompositor::destroyRootLayer() 3309{ 3310 if (!m_rootContentLayer) 3311 return; 3312 3313 detachRootLayer(); 3314 3315#if ENABLE(RUBBER_BANDING) 3316 if (m_layerForOverhangAreas) { 3317 m_layerForOverhangAreas->removeFromParent(); 3318 m_layerForOverhangAreas = nullptr; 3319 } 3320#endif 3321 3322 if (m_layerForHorizontalScrollbar) { 3323 m_layerForHorizontalScrollbar->removeFromParent(); 3324 m_layerForHorizontalScrollbar = nullptr; 3325 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3326 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), HorizontalScrollbar); 3327 if (Scrollbar* horizontalScrollbar = m_renderView.frameView().verticalScrollbar()) 3328 m_renderView.frameView().invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size())); 3329 } 3330 3331 if (m_layerForVerticalScrollbar) { 3332 m_layerForVerticalScrollbar->removeFromParent(); 3333 m_layerForVerticalScrollbar = nullptr; 3334 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) 3335 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(&m_renderView.frameView(), VerticalScrollbar); 3336 if (Scrollbar* verticalScrollbar = m_renderView.frameView().verticalScrollbar()) 3337 m_renderView.frameView().invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size())); 3338 } 3339 3340 if (m_layerForScrollCorner) { 3341 m_layerForScrollCorner = nullptr; 3342 m_renderView.frameView().invalidateScrollCorner(m_renderView.frameView().scrollCornerRect()); 3343 } 3344 3345 if (m_overflowControlsHostLayer) { 3346 m_overflowControlsHostLayer = nullptr; 3347 m_clipLayer = nullptr; 3348 m_scrollLayer = nullptr; 3349 } 3350 ASSERT(!m_scrollLayer); 3351 m_rootContentLayer = nullptr; 3352 3353 m_layerUpdater = nullptr; 3354} 3355 3356void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment) 3357{ 3358 if (!m_rootContentLayer) 3359 return; 3360 3361 switch (attachment) { 3362 case RootLayerUnattached: 3363 ASSERT_NOT_REACHED(); 3364 break; 3365 case RootLayerAttachedViaChromeClient: { 3366 Frame& frame = m_renderView.frameView().frame(); 3367 Page* page = frame.page(); 3368 if (!page) 3369 return; 3370 3371 page->chrome().client().attachRootGraphicsLayer(&frame, rootGraphicsLayer()); 3372 break; 3373 } 3374 case RootLayerAttachedViaEnclosingFrame: { 3375 // The layer will get hooked up via RenderLayerBacking::updateConfiguration() 3376 // for the frame's renderer in the parent document. 3377 m_renderView.document().ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange); 3378 break; 3379 } 3380 } 3381 3382 m_rootLayerAttachment = attachment; 3383 rootLayerAttachmentChanged(); 3384 3385 if (m_shouldFlushOnReattach) { 3386 scheduleLayerFlushNow(); 3387 m_shouldFlushOnReattach = false; 3388 } 3389} 3390 3391void RenderLayerCompositor::detachRootLayer() 3392{ 3393 if (!m_rootContentLayer || m_rootLayerAttachment == RootLayerUnattached) 3394 return; 3395 3396 switch (m_rootLayerAttachment) { 3397 case RootLayerAttachedViaEnclosingFrame: { 3398 // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration() 3399 // for the frame's renderer in the parent document. 3400 if (m_overflowControlsHostLayer) 3401 m_overflowControlsHostLayer->removeFromParent(); 3402 else 3403 m_rootContentLayer->removeFromParent(); 3404 3405 if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) 3406 ownerElement->scheduleSetNeedsStyleRecalc(SyntheticStyleChange); 3407 break; 3408 } 3409 case RootLayerAttachedViaChromeClient: { 3410 Frame& frame = m_renderView.frameView().frame(); 3411 Page* page = frame.page(); 3412 if (!page) 3413 return; 3414 3415 page->chrome().client().attachRootGraphicsLayer(&frame, 0); 3416 } 3417 break; 3418 case RootLayerUnattached: 3419 break; 3420 } 3421 3422 m_rootLayerAttachment = RootLayerUnattached; 3423 rootLayerAttachmentChanged(); 3424} 3425 3426void RenderLayerCompositor::updateRootLayerAttachment() 3427{ 3428 ensureRootLayer(); 3429} 3430 3431void RenderLayerCompositor::rootLayerAttachmentChanged() 3432{ 3433 // The attachment can affect whether the RenderView layer's paintsIntoWindow() behavior, 3434 // so call updateDrawsContent() to update that. 3435 RenderLayer* layer = m_renderView.layer(); 3436 if (RenderLayerBacking* backing = layer ? layer->backing() : 0) 3437 backing->updateDrawsContent(); 3438 3439 // The document-relative page overlay layer (which is pinned to the main frame's layer tree) 3440 // is moved between different RenderLayerCompositors' layer trees, and needs to be 3441 // reattached whenever we swap in a new RenderLayerCompositor. 3442 if (m_rootLayerAttachment == RootLayerUnattached) 3443 return; 3444 3445 Frame& frame = m_renderView.frameView().frame(); 3446 Page* page = frame.page(); 3447 if (!page) 3448 return; 3449 3450 if (GraphicsLayer* overlayLayer = page->chrome().client().documentOverlayLayerForFrame(frame)) 3451 m_rootContentLayer->addChild(overlayLayer); 3452} 3453 3454// IFrames are special, because we hook compositing layers together across iframe boundaries 3455// when both parent and iframe content are composited. So when this frame becomes composited, we have 3456// to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite. 3457void RenderLayerCompositor::notifyIFramesOfCompositingChange() 3458{ 3459 Frame& frame = m_renderView.frameView().frame(); 3460 for (Frame* child = frame.tree().firstChild(); child; child = child->tree().traverseNext(&frame)) { 3461 if (child->document() && child->document()->ownerElement()) 3462 child->document()->ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange); 3463 } 3464 3465 // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so 3466 // we need to schedule a style recalc in our parent document. 3467 if (HTMLFrameOwnerElement* ownerElement = m_renderView.document().ownerElement()) 3468 ownerElement->scheduleSetNeedsStyleRecalc(SyntheticStyleChange); 3469} 3470 3471bool RenderLayerCompositor::layerHas3DContent(const RenderLayer& layer) const 3472{ 3473 const RenderStyle& style = layer.renderer().style(); 3474 3475 if (style.transformStyle3D() == TransformStyle3DPreserve3D || style.hasPerspective() || style.transform().has3DOperation()) 3476 return true; 3477 3478 const_cast<RenderLayer&>(layer).updateLayerListsIfNeeded(); 3479 3480#if !ASSERT_DISABLED 3481 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(&layer)); 3482#endif 3483 3484 if (layer.isStackingContainer()) { 3485 if (Vector<RenderLayer*>* negZOrderList = layer.negZOrderList()) { 3486 for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) { 3487 if (layerHas3DContent(*negZOrderList->at(i))) 3488 return true; 3489 } 3490 } 3491 3492 if (Vector<RenderLayer*>* posZOrderList = layer.posZOrderList()) { 3493 for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) { 3494 if (layerHas3DContent(*posZOrderList->at(i))) 3495 return true; 3496 } 3497 } 3498 } 3499 3500 if (Vector<RenderLayer*>* normalFlowList = layer.normalFlowList()) { 3501 for (size_t i = 0, size = normalFlowList->size(); i < size; ++i) { 3502 if (layerHas3DContent(*normalFlowList->at(i))) 3503 return true; 3504 } 3505 } 3506 3507 return false; 3508} 3509 3510void RenderLayerCompositor::deviceOrPageScaleFactorChanged() 3511{ 3512 // Page scale will only be applied at to the RenderView and sublayers, but the device scale factor 3513 // needs to be applied at the level of rootGraphicsLayer(). 3514 GraphicsLayer* rootLayer = rootGraphicsLayer(); 3515 if (rootLayer) 3516 rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants(); 3517} 3518 3519void RenderLayerCompositor::updateScrollCoordinatedStatus(RenderLayer& layer) 3520{ 3521 ScrollCoordinationReasons coordinationReasons = 0; 3522 if (isViewportConstrainedFixedOrStickyLayer(layer)) 3523 coordinationReasons |= FixedOrSticky; 3524 3525 if (useCoordinatedScrollingForLayer(m_renderView, layer)) 3526 coordinationReasons |= Scrolling; 3527 3528 if (coordinationReasons) { 3529 if (m_scrollCoordinatedLayers.add(&layer).isNewEntry) 3530 m_subframeScrollLayersNeedReattach = true; 3531 3532 updateScrollCoordinatedLayer(layer, coordinationReasons); 3533 } else 3534 removeFromScrollCoordinatedLayers(layer); 3535} 3536 3537void RenderLayerCompositor::removeFromScrollCoordinatedLayers(RenderLayer& layer) 3538{ 3539 if (!m_scrollCoordinatedLayers.contains(&layer)) 3540 return; 3541 3542 m_subframeScrollLayersNeedReattach = true; 3543 3544 m_scrollCoordinatedLayers.remove(&layer); 3545 m_scrollCoordinatedLayersNeedingUpdate.remove(&layer); 3546 3547 detachScrollCoordinatedLayer(layer); 3548} 3549 3550FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportConstraints(RenderLayer& layer) const 3551{ 3552 ASSERT(layer.isComposited()); 3553 3554 GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer(); 3555 LayoutRect viewportRect = m_renderView.frameView().viewportConstrainedVisibleContentRect(); 3556 3557 FixedPositionViewportConstraints constraints; 3558 constraints.setLayerPositionAtLastLayout(graphicsLayer->position()); 3559 constraints.setViewportRectAtLastLayout(viewportRect); 3560 constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset()); 3561 3562 const RenderStyle& style = layer.renderer().style(); 3563 if (!style.left().isAuto()) 3564 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft); 3565 3566 if (!style.right().isAuto()) 3567 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight); 3568 3569 if (!style.top().isAuto()) 3570 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop); 3571 3572 if (!style.bottom().isAuto()) 3573 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom); 3574 3575 // If left and right are auto, use left. 3576 if (style.left().isAuto() && style.right().isAuto()) 3577 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft); 3578 3579 // If top and bottom are auto, use top. 3580 if (style.top().isAuto() && style.bottom().isAuto()) 3581 constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop); 3582 3583 return constraints; 3584} 3585 3586StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportConstraints(RenderLayer& layer) const 3587{ 3588 ASSERT(layer.isComposited()); 3589#if !PLATFORM(IOS) 3590 // We should never get here for stickies constrained by an enclosing clipping layer. 3591 // FIXME: Why does this assertion fail on iOS? 3592 ASSERT(!layer.enclosingOverflowClipLayer(ExcludeSelf)); 3593#endif 3594 3595 RenderBoxModelObject& renderer = toRenderBoxModelObject(layer.renderer()); 3596 3597 StickyPositionViewportConstraints constraints; 3598 renderer.computeStickyPositionConstraints(constraints, renderer.constrainingRectForStickyPosition()); 3599 3600 GraphicsLayer* graphicsLayer = layer.backing()->graphicsLayer(); 3601 3602 constraints.setLayerPositionAtLastLayout(graphicsLayer->position()); 3603 constraints.setStickyOffsetAtLastLayout(renderer.stickyPositionOffset()); 3604 constraints.setAlignmentOffset(graphicsLayer->pixelAlignmentOffset()); 3605 3606 return constraints; 3607} 3608 3609static ScrollingNodeID enclosingScrollingNodeID(RenderLayer& layer, IncludeSelfOrNot includeSelf) 3610{ 3611 RenderLayer* currLayer = includeSelf == IncludeSelf ? &layer : layer.parent(); 3612 while (currLayer) { 3613 if (RenderLayerBacking* backing = currLayer->backing()) { 3614 if (ScrollingNodeID nodeID = backing->scrollingNodeIDForChildren()) 3615 return nodeID; 3616 } 3617 currLayer = currLayer->parent(); 3618 } 3619 3620 return 0; 3621} 3622 3623static ScrollingNodeID scrollCoordinatedAncestorInParentOfFrame(Frame& frame) 3624{ 3625 if (!frame.document() || !frame.view()) 3626 return 0; 3627 3628 // Find the frame's enclosing layer in our render tree. 3629 HTMLFrameOwnerElement* ownerElement = frame.document()->ownerElement(); 3630 RenderElement* frameRenderer = ownerElement ? ownerElement->renderer() : nullptr; 3631 if (!frameRenderer) 3632 return 0; 3633 3634 RenderLayer* layerInParentDocument = frameRenderer->enclosingLayer(); 3635 if (!layerInParentDocument) 3636 return 0; 3637 3638 return enclosingScrollingNodeID(*layerInParentDocument, IncludeSelf); 3639} 3640 3641void RenderLayerCompositor::reattachSubframeScrollLayers() 3642{ 3643 if (!m_subframeScrollLayersNeedReattach) 3644 return; 3645 3646 m_subframeScrollLayersNeedReattach = false; 3647 3648 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 3649 3650 for (Frame* child = m_renderView.frameView().frame().tree().firstChild(); child; child = child->tree().nextSibling()) { 3651 if (!child->document() || !child->view()) 3652 continue; 3653 3654 // Ignore frames that are not scroll-coordinated. 3655 FrameView* childFrameView = child->view(); 3656 ScrollingNodeID frameScrollingNodeID = childFrameView->scrollLayerID(); 3657 if (!frameScrollingNodeID) 3658 continue; 3659 3660 ScrollingNodeID parentNodeID = scrollCoordinatedAncestorInParentOfFrame(*child); 3661 if (!parentNodeID) 3662 continue; 3663 3664 scrollingCoordinator->attachToStateTree(FrameScrollingNode, frameScrollingNodeID, parentNodeID); 3665 } 3666} 3667 3668ScrollingNodeID RenderLayerCompositor::attachScrollingNode(RenderLayer& layer, ScrollingNodeType nodeType, ScrollingNodeID parentNodeID) 3669{ 3670 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 3671 RenderLayerBacking* backing = layer.backing(); 3672 3673 ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(nodeType); 3674 if (!nodeID) 3675 nodeID = scrollingCoordinator->uniqueScrollLayerID(); 3676 3677 nodeID = scrollingCoordinator->attachToStateTree(nodeType, nodeID, parentNodeID); 3678 if (!nodeID) 3679 return 0; 3680 3681 backing->setScrollingNodeIDForRole(nodeID, nodeType); 3682 m_scrollingNodeToLayerMap.add(nodeID, &layer); 3683 3684 return nodeID; 3685} 3686 3687void RenderLayerCompositor::updateScrollCoordinationForThisFrame(ScrollingNodeID parentNodeID) 3688{ 3689 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 3690 ASSERT(scrollingCoordinator->coordinatesScrollingForFrameView(&m_renderView.frameView())); 3691 3692 ScrollingNodeID nodeID = attachScrollingNode(*m_renderView.layer(), FrameScrollingNode, parentNodeID); 3693 scrollingCoordinator->updateFrameScrollingNode(nodeID, m_scrollLayer.get(), m_rootContentLayer.get(), fixedRootBackgroundLayer(), clipLayer()); 3694} 3695 3696void RenderLayerCompositor::updateScrollCoordinatedLayer(RenderLayer& layer, ScrollCoordinationReasons reasons) 3697{ 3698 ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator(); 3699 if (!scrollingCoordinator || !scrollingCoordinator->coordinatesScrollingForFrameView(&m_renderView.frameView())) 3700 return; 3701 3702 bool isRootLayer = &layer == m_renderView.layer(); 3703 3704 // FIXME: Remove supportsFixedPositionLayers() since all platforms support them now. 3705 if (!scrollingCoordinator->supportsFixedPositionLayers() || (!layer.parent() && !isRootLayer)) 3706 return; 3707 3708 ASSERT(m_scrollCoordinatedLayers.contains(&layer)); 3709 ASSERT(layer.isComposited()); 3710 3711 RenderLayerBacking* backing = layer.backing(); 3712 if (!backing) 3713 return; 3714 3715 if (!m_renderView.frame().isMainFrame()) { 3716 ScrollingNodeID parentDocumentHostingNodeID = scrollCoordinatedAncestorInParentOfFrame(m_renderView.frame()); 3717 if (!parentDocumentHostingNodeID) 3718 return; 3719 3720 updateScrollCoordinationForThisFrame(parentDocumentHostingNodeID); 3721 if (!(reasons & FixedOrSticky) && isRootLayer) 3722 return; 3723 } 3724 3725 ScrollingNodeID parentNodeID = enclosingScrollingNodeID(layer, ExcludeSelf); 3726 if (!parentNodeID && !isRootLayer) 3727 return; 3728 3729 // Always call this even if the backing is already attached because the parent may have changed. 3730 // If a node plays both roles, fixed/sticky is always the ancestor node of scrolling. 3731 if (reasons & FixedOrSticky) { 3732 ScrollingNodeType nodeType = FrameScrollingNode; 3733 if (layer.renderer().style().position() == FixedPosition) 3734 nodeType = FixedNode; 3735 else if (layer.renderer().style().position() == StickyPosition) 3736 nodeType = StickyNode; 3737 else 3738 ASSERT_NOT_REACHED(); 3739 3740 ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID); 3741 if (!nodeID) 3742 return; 3743 3744 switch (nodeType) { 3745 case FixedNode: 3746 scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeFixedViewportConstraints(layer), backing->graphicsLayer()); 3747 break; 3748 case StickyNode: 3749 scrollingCoordinator->updateViewportConstrainedNode(nodeID, computeStickyViewportConstraints(layer), backing->graphicsLayer()); 3750 break; 3751 case FrameScrollingNode: 3752 case OverflowScrollingNode: 3753 break; 3754 } 3755 3756 parentNodeID = nodeID; 3757 } 3758 3759 if (reasons & Scrolling) { 3760 if (isRootLayer) 3761 updateScrollCoordinationForThisFrame(parentNodeID); 3762 else { 3763 ScrollingNodeType nodeType = OverflowScrollingNode; 3764 ScrollingNodeID nodeID = attachScrollingNode(layer, nodeType, parentNodeID); 3765 if (!nodeID) 3766 return; 3767 3768 ScrollingCoordinator::ScrollingGeometry scrollingGeometry; 3769 scrollingGeometry.scrollOrigin = layer.scrollOrigin(); 3770 scrollingGeometry.scrollPosition = layer.scrollPosition(); 3771 scrollingGeometry.scrollableAreaSize = layer.visibleSize(); 3772 scrollingGeometry.contentSize = layer.contentsSize(); 3773 scrollingGeometry.reachableContentSize = layer.scrollableContentsSize(); 3774 scrollingCoordinator->updateOverflowScrollingNode(nodeID, backing->scrollingLayer(), backing->scrollingContentsLayer(), &scrollingGeometry); 3775 } 3776 } 3777} 3778 3779void RenderLayerCompositor::detachScrollCoordinatedLayer(RenderLayer& layer) 3780{ 3781 RenderLayerBacking* backing = layer.backing(); 3782 if (!backing) 3783 return; 3784 3785 if (ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(FrameScrollingNode)) 3786 m_scrollingNodeToLayerMap.remove(nodeID); 3787 3788 if (ScrollingNodeID nodeID = backing->scrollingNodeIDForRole(FixedNode)) 3789 m_scrollingNodeToLayerMap.remove(nodeID); 3790 3791 backing->detachFromScrollingCoordinator(); 3792} 3793 3794ScrollableArea* RenderLayerCompositor::scrollableAreaForScrollLayerID(ScrollingNodeID nodeID) const 3795{ 3796 if (!nodeID) 3797 return nullptr; 3798 3799 return m_scrollingNodeToLayerMap.get(nodeID); 3800} 3801 3802#if PLATFORM(IOS) 3803typedef HashMap<PlatformLayer*, std::unique_ptr<ViewportConstraints>> LayerMap; 3804typedef HashMap<PlatformLayer*, PlatformLayer*> StickyContainerMap; 3805 3806void RenderLayerCompositor::registerAllViewportConstrainedLayers() 3807{ 3808 // Only the main frame should register fixed/sticky layers. 3809 if (m_renderView.document().ownerElement()) 3810 return; 3811 3812 if (scrollingCoordinator()) 3813 return; 3814 3815 LayerMap layerMap; 3816 StickyContainerMap stickyContainerMap; 3817 3818 for (auto it = m_scrollCoordinatedLayers.begin(), end = m_scrollCoordinatedLayers.end(); it != end; ++it) { 3819 RenderLayer& layer = **it; 3820 ASSERT(layer.isComposited()); 3821 3822 std::unique_ptr<ViewportConstraints> constraints; 3823 if (layer.renderer().isStickyPositioned()) { 3824 constraints = std::make_unique<StickyPositionViewportConstraints>(computeStickyViewportConstraints(layer)); 3825 const RenderLayer* enclosingTouchScrollableLayer = nullptr; 3826 if (isAsyncScrollableStickyLayer(layer, &enclosingTouchScrollableLayer) && enclosingTouchScrollableLayer) { 3827 ASSERT(enclosingTouchScrollableLayer->isComposited()); 3828 stickyContainerMap.add(layer.backing()->graphicsLayer()->platformLayer(), enclosingTouchScrollableLayer->backing()->scrollingLayer()->platformLayer()); 3829 } 3830 } else if (layer.renderer().style().position() == FixedPosition) 3831 constraints = std::make_unique<FixedPositionViewportConstraints>(computeFixedViewportConstraints(layer)); 3832 else 3833 continue; 3834 3835 layerMap.add(layer.backing()->graphicsLayer()->platformLayer(), WTF::move(constraints)); 3836 } 3837 3838 if (ChromeClient* client = this->chromeClient()) 3839 client->updateViewportConstrainedLayers(layerMap, stickyContainerMap); 3840} 3841 3842void RenderLayerCompositor::unregisterAllViewportConstrainedLayers() 3843{ 3844 // Only the main frame should register fixed/sticky layers. 3845 if (m_renderView.document().ownerElement()) 3846 return; 3847 3848 if (scrollingCoordinator()) 3849 return; 3850 3851 if (ChromeClient* client = this->chromeClient()) { 3852 LayerMap layerMap; 3853 StickyContainerMap stickyContainerMap; 3854 client->updateViewportConstrainedLayers(layerMap, stickyContainerMap); 3855 } 3856} 3857 3858void RenderLayerCompositor::registerAllScrollingLayers() 3859{ 3860 ChromeClient* client = this->chromeClient(); 3861 if (!client) 3862 return; 3863 3864 for (auto it = m_scrollingLayers.begin(), end = m_scrollingLayers.end(); it != end; ++it) 3865 updateScrollingLayerWithClient(**it, client); 3866} 3867 3868void RenderLayerCompositor::unregisterAllScrollingLayers() 3869{ 3870 ChromeClient* client = this->chromeClient(); 3871 if (!client) 3872 return; 3873 3874 for (auto it = m_scrollingLayers.begin(), end = m_scrollingLayers.end(); it != end; ++it) { 3875 RenderLayer& layer = **it; 3876 RenderLayerBacking* backing = layer.backing(); 3877 ASSERT(backing); 3878 client->removeScrollingLayer(layer.renderer().element(), backing->scrollingLayer()->platformLayer(), backing->scrollingContentsLayer()->platformLayer()); 3879 } 3880} 3881#endif 3882 3883void RenderLayerCompositor::willRemoveScrollingLayerWithBacking(RenderLayer& layer, RenderLayerBacking& backing) 3884{ 3885 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) { 3886 backing.detachFromScrollingCoordinator(); 3887 3888 // For Coordinated Graphics. 3889 scrollingCoordinator->scrollableAreaScrollLayerDidChange(&layer); 3890 return; 3891 } 3892 3893#if PLATFORM(IOS) 3894 m_scrollingLayersNeedingUpdate.remove(&layer); 3895 m_scrollingLayers.remove(&layer); 3896 3897 if (m_renderView.document().inPageCache()) 3898 return; 3899 3900 if (ChromeClient* client = this->chromeClient()) { 3901 PlatformLayer* scrollingLayer = backing.scrollingLayer()->platformLayer(); 3902 PlatformLayer* contentsLayer = backing.scrollingContentsLayer()->platformLayer(); 3903 client->removeScrollingLayer(layer.renderer().element(), scrollingLayer, contentsLayer); 3904 } 3905#endif 3906} 3907 3908void RenderLayerCompositor::didAddScrollingLayer(RenderLayer& layer) 3909{ 3910 updateScrollCoordinatedStatus(layer); 3911 3912 if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) { 3913 // For Coordinated Graphics. 3914 scrollingCoordinator->scrollableAreaScrollLayerDidChange(&layer); 3915 return; 3916 } 3917 3918#if PLATFORM(IOS) 3919 ASSERT(!m_renderView.document().inPageCache()); 3920 m_scrollingLayers.add(&layer); 3921#endif 3922} 3923 3924void RenderLayerCompositor::windowScreenDidChange(PlatformDisplayID displayID) 3925{ 3926 if (m_layerUpdater) 3927 m_layerUpdater->screenDidChange(displayID); 3928} 3929 3930ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const 3931{ 3932 if (Page* page = this->page()) 3933 return page->scrollingCoordinator(); 3934 3935 return 0; 3936} 3937 3938GraphicsLayerFactory* RenderLayerCompositor::graphicsLayerFactory() const 3939{ 3940 if (Page* page = this->page()) 3941 return page->chrome().client().graphicsLayerFactory(); 3942 3943 return 0; 3944} 3945 3946Page* RenderLayerCompositor::page() const 3947{ 3948 return m_renderView.frameView().frame().page(); 3949} 3950 3951void RenderLayerCompositor::setLayerFlushThrottlingEnabled(bool enabled) 3952{ 3953 m_layerFlushThrottlingEnabled = enabled; 3954 if (m_layerFlushThrottlingEnabled) 3955 return; 3956 m_layerFlushTimer.stop(); 3957 if (!m_hasPendingLayerFlush) 3958 return; 3959 scheduleLayerFlushNow(); 3960} 3961 3962void RenderLayerCompositor::disableLayerFlushThrottlingTemporarilyForInteraction() 3963{ 3964 if (m_layerFlushThrottlingTemporarilyDisabledForInteraction) 3965 return; 3966 m_layerFlushThrottlingTemporarilyDisabledForInteraction = true; 3967} 3968 3969bool RenderLayerCompositor::isThrottlingLayerFlushes() const 3970{ 3971 if (!m_layerFlushThrottlingEnabled) 3972 return false; 3973 if (!m_layerFlushTimer.isActive()) 3974 return false; 3975 if (m_layerFlushThrottlingTemporarilyDisabledForInteraction) 3976 return false; 3977 return true; 3978} 3979 3980void RenderLayerCompositor::startLayerFlushTimerIfNeeded() 3981{ 3982 m_layerFlushThrottlingTemporarilyDisabledForInteraction = false; 3983 m_layerFlushTimer.stop(); 3984 if (!m_layerFlushThrottlingEnabled) 3985 return; 3986 m_layerFlushTimer.startOneShot(throttledLayerFlushDelay); 3987} 3988 3989void RenderLayerCompositor::startInitialLayerFlushTimerIfNeeded() 3990{ 3991 if (!m_layerFlushThrottlingEnabled) 3992 return; 3993 if (m_layerFlushTimer.isActive()) 3994 return; 3995 m_layerFlushTimer.startOneShot(throttledLayerFlushInitialDelay); 3996} 3997 3998void RenderLayerCompositor::layerFlushTimerFired(Timer<RenderLayerCompositor>&) 3999{ 4000 if (!m_hasPendingLayerFlush) 4001 return; 4002 scheduleLayerFlushNow(); 4003} 4004 4005void RenderLayerCompositor::paintRelatedMilestonesTimerFired(Timer<RenderLayerCompositor>&) 4006{ 4007 Frame& frame = m_renderView.frameView().frame(); 4008 Page* page = frame.page(); 4009 if (!page) 4010 return; 4011 4012 // If the layer tree is frozen, we'll paint when it's unfrozen and schedule the timer again. 4013 if (page->chrome().client().layerTreeStateIsFrozen()) 4014 return; 4015 4016 m_renderView.frameView().firePaintRelatedMilestonesIfNeeded(); 4017} 4018 4019#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR) 4020PassRefPtr<DisplayRefreshMonitor> RenderLayerCompositor::createDisplayRefreshMonitor(PlatformDisplayID displayID) const 4021{ 4022 Frame& frame = m_renderView.frameView().frame(); 4023 Page* page = frame.page(); 4024 if (!page) 4025 return nullptr; 4026 4027 return page->chrome().client().createDisplayRefreshMonitor(displayID); 4028} 4029#endif 4030 4031} // namespace WebCore 4032