1/* 2 * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#if USE(ACCELERATED_COMPOSITING) 29 30#include "RenderLayerBacking.h" 31 32#include "AnimationController.h" 33#include "CanvasRenderingContext.h" 34#include "CSSPropertyNames.h" 35#include "CachedImage.h" 36#include "Chrome.h" 37#include "FontCache.h" 38#include "FrameView.h" 39#include "GraphicsContext.h" 40#include "GraphicsLayer.h" 41#include "HTMLCanvasElement.h" 42#include "HTMLIFrameElement.h" 43#include "HTMLMediaElement.h" 44#include "HTMLNames.h" 45#include "HTMLPlugInElement.h" 46#include "InspectorInstrumentation.h" 47#include "KeyframeList.h" 48#include "PluginViewBase.h" 49#include "ProgressTracker.h" 50#include "RenderApplet.h" 51#include "RenderIFrame.h" 52#include "RenderImage.h" 53#include "RenderLayerCompositor.h" 54#include "RenderEmbeddedObject.h" 55#include "RenderVideo.h" 56#include "RenderView.h" 57#include "ScrollingCoordinator.h" 58#include "Settings.h" 59#include "StyleResolver.h" 60#include "TiledBacking.h" 61#include <wtf/text/StringBuilder.h> 62 63#if ENABLE(CSS_FILTERS) 64#include "FilterEffectRenderer.h" 65#if ENABLE(CSS_SHADERS) 66#include "CustomFilterOperation.h" 67#endif 68#endif 69 70#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 71#include "GraphicsContext3D.h" 72#endif 73 74using namespace std; 75 76namespace WebCore { 77 78using namespace HTMLNames; 79 80static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*); 81static IntRect clipBox(RenderBox* renderer); 82 83static inline bool isAcceleratedCanvas(RenderObject* renderer) 84{ 85#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 86 if (renderer->isCanvas()) { 87 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); 88 if (CanvasRenderingContext* context = canvas->renderingContext()) 89 return context->isAccelerated(); 90 } 91#else 92 UNUSED_PARAM(renderer); 93#endif 94 return false; 95} 96 97// Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor. 98static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer* layer) 99{ 100 Page* page = layer->renderer()->frame()->page(); 101 if (!page) 102 return 0; 103 104 return page->scrollingCoordinator(); 105} 106 107bool RenderLayerBacking::m_creatingPrimaryGraphicsLayer = false; 108 109RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) 110 : m_owningLayer(layer) 111 , m_scrollLayerID(0) 112 , m_artificiallyInflatedBounds(false) 113 , m_isMainFrameRenderViewLayer(false) 114 , m_usingTiledCacheLayer(false) 115 , m_requiresOwnBackingStore(true) 116#if ENABLE(CSS_FILTERS) 117 , m_canCompositeFilters(false) 118#endif 119 , m_backgroundLayerPaintsFixedRootBackground(false) 120 , m_didSwitchToFullTileCoverageDuringLoading(false) 121{ 122 if (layer->isRootLayer()) { 123 Frame* frame = toRenderView(renderer())->frameView()->frame(); 124 Page* page = frame ? frame->page() : 0; 125 if (page && frame && page->mainFrame() == frame) { 126 m_isMainFrameRenderViewLayer = true; 127 128#if PLATFORM(MAC) 129 // FIXME: It's a little weird that we base this decision on whether there's a scrolling coordinator or not. 130 if (page->scrollingCoordinator()) 131 m_usingTiledCacheLayer = true; 132#endif 133 } 134 } 135 136 createPrimaryGraphicsLayer(); 137 138 if (m_usingTiledCacheLayer) { 139 TiledBacking* tiledBacking = this->tiledBacking(); 140 if (Page* page = renderer()->frame()->page()) { 141 Frame* frame = renderer()->frame(); 142 tiledBacking->setIsInWindow(page->isInWindow()); 143 144 if (m_isMainFrameRenderViewLayer) 145 tiledBacking->setUnparentsOffscreenTiles(true); 146 147 tiledBacking->setScrollingPerformanceLoggingEnabled(frame->settings() && frame->settings()->scrollingPerformanceLoggingEnabled()); 148 adjustTiledBackingCoverage(); 149 } 150 } 151} 152 153RenderLayerBacking::~RenderLayerBacking() 154{ 155 updateClippingLayers(false, false); 156 updateOverflowControlsLayers(false, false, false); 157 updateForegroundLayer(false); 158 updateBackgroundLayer(false); 159 updateMaskLayer(false); 160 updateScrollingLayers(false); 161 detachFromScrollingCoordinator(); 162 destroyGraphicsLayers(); 163} 164 165void RenderLayerBacking::willDestroyLayer(const GraphicsLayer* layer) 166{ 167 if (layer && layer->usingTiledBacking()) { 168 if (RenderLayerCompositor* compositor = this->compositor()) 169 compositor->layerTiledBackingUsageChanged(layer, false); 170 } 171} 172 173PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name) 174{ 175 GraphicsLayerFactory* graphicsLayerFactory = 0; 176 if (Page* page = renderer()->frame()->page()) 177 graphicsLayerFactory = page->chrome().client()->graphicsLayerFactory(); 178 179 OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this); 180 181#ifndef NDEBUG 182 graphicsLayer->setName(name); 183#else 184 UNUSED_PARAM(name); 185#endif 186 graphicsLayer->setMaintainsPixelAlignment(compositor()->keepLayersPixelAligned()); 187 188#if PLATFORM(MAC) && USE(CA) 189 graphicsLayer->setAcceleratesDrawing(compositor()->acceleratedDrawingEnabled()); 190#endif 191 192 return graphicsLayer.release(); 193} 194 195bool RenderLayerBacking::shouldUseTiledBacking(const GraphicsLayer*) const 196{ 197 return m_usingTiledCacheLayer && m_creatingPrimaryGraphicsLayer; 198} 199 200void RenderLayerBacking::tiledBackingUsageChanged(const GraphicsLayer* layer, bool usingTiledBacking) 201{ 202 compositor()->layerTiledBackingUsageChanged(layer, usingTiledBacking); 203} 204 205TiledBacking* RenderLayerBacking::tiledBacking() const 206{ 207 return m_graphicsLayer->tiledBacking(); 208} 209 210static TiledBacking::TileCoverage computeTileCoverage(RenderLayerBacking* backing) 211{ 212 // FIXME: When we use TiledBacking for overflow, this should look at RenderView scrollability. 213 Frame* frame = backing->owningLayer()->renderer()->frame(); 214 if (!frame) 215 return TiledBacking::CoverageForVisibleArea; 216 217 TiledBacking::TileCoverage tileCoverage = TiledBacking::CoverageForVisibleArea; 218 FrameView* frameView = frame->view(); 219 bool useMinimalTilesDuringLiveResize = frameView->inLiveResize(); 220 bool useMinimalTilesDuringLoading = false; 221 // Avoid churn. 222 if (!backing->didSwitchToFullTileCoverageDuringLoading()) { 223 useMinimalTilesDuringLoading = !frameView->isVisuallyNonEmpty() || (frame->page()->progress()->isMainLoadProgressing() && !frameView->wasScrolledByUser()); 224 if (!useMinimalTilesDuringLoading) 225 backing->setDidSwitchToFullTileCoverageDuringLoading(); 226 } 227 if (!(useMinimalTilesDuringLoading || useMinimalTilesDuringLiveResize)) { 228 bool clipsToExposedRect = backing->tiledBacking()->clipsToExposedRect(); 229 if (frameView->horizontalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect) 230 tileCoverage |= TiledBacking::CoverageForHorizontalScrolling; 231 232 if (frameView->verticalScrollbarMode() != ScrollbarAlwaysOff || clipsToExposedRect) 233 tileCoverage |= TiledBacking::CoverageForVerticalScrolling; 234 } 235 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(backing->owningLayer())) { 236 // Ask our TiledBacking for large tiles unless the only reason we're main-thread-scrolling 237 // is a page overlay (find-in-page, the Web Inspector highlight mechanism, etc.). 238 if (scrollingCoordinator->mainThreadScrollingReasons() & ~ScrollingCoordinator::ForcedOnMainThread) 239 tileCoverage |= TiledBacking::CoverageForSlowScrolling; 240 } 241 return tileCoverage; 242} 243 244void RenderLayerBacking::adjustTiledBackingCoverage() 245{ 246 if (!m_usingTiledCacheLayer) 247 return; 248 249 TiledBacking::TileCoverage tileCoverage = computeTileCoverage(this); 250 tiledBacking()->setTileCoverage(tileCoverage); 251} 252 253void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter) 254{ 255 m_graphicsLayer->setShowDebugBorder(showBorder); 256 m_graphicsLayer->setShowRepaintCounter(showRepaintCounter); 257 258 if (m_ancestorClippingLayer) 259 m_ancestorClippingLayer->setShowDebugBorder(showBorder); 260 261 if (m_foregroundLayer) { 262 m_foregroundLayer->setShowDebugBorder(showBorder); 263 m_foregroundLayer->setShowRepaintCounter(showRepaintCounter); 264 } 265 266 if (m_contentsContainmentLayer) 267 m_contentsContainmentLayer->setShowDebugBorder(showBorder); 268 269 if (m_backgroundLayer) { 270 m_backgroundLayer->setShowDebugBorder(showBorder); 271 m_backgroundLayer->setShowRepaintCounter(showRepaintCounter); 272 } 273 274 if (m_maskLayer) { 275 m_maskLayer->setShowDebugBorder(showBorder); 276 m_maskLayer->setShowRepaintCounter(showRepaintCounter); 277 } 278 279 if (m_layerForHorizontalScrollbar) 280 m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder); 281 282 if (m_layerForVerticalScrollbar) 283 m_layerForVerticalScrollbar->setShowDebugBorder(showBorder); 284 285 if (m_layerForScrollCorner) 286 m_layerForScrollCorner->setShowDebugBorder(showBorder); 287 288 if (m_scrollingLayer) 289 m_scrollingLayer->setShowDebugBorder(showBorder); 290 291 if (m_scrollingContentsLayer) { 292 m_scrollingContentsLayer->setShowDebugBorder(showBorder); 293 m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter); 294 } 295} 296 297void RenderLayerBacking::createPrimaryGraphicsLayer() 298{ 299 String layerName; 300#ifndef NDEBUG 301 layerName = m_owningLayer->name(); 302#endif 303 304 // The call to createGraphicsLayer ends calling back into here as 305 // a GraphicsLayerClient to ask if it shouldUseTiledBacking(). We only want 306 // the tile cache on our main layer. This is pretty ugly, but saves us from 307 // exposing the API to all clients. 308 309 m_creatingPrimaryGraphicsLayer = true; 310 m_graphicsLayer = createGraphicsLayer(layerName); 311 m_creatingPrimaryGraphicsLayer = false; 312 313 if (m_usingTiledCacheLayer) 314 m_childContainmentLayer = createGraphicsLayer("TiledBacking Flattening Layer"); 315 316 if (m_isMainFrameRenderViewLayer) { 317 m_graphicsLayer->setContentsOpaque(true); 318 m_graphicsLayer->setAppliesPageScale(); 319 } 320 321#if PLATFORM(MAC) && USE(CA) 322 if (!compositor()->acceleratedDrawingEnabled() && renderer()->isCanvas()) { 323 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); 324 if (canvas->shouldAccelerate(canvas->size())) 325 m_graphicsLayer->setAcceleratesDrawing(true); 326 } 327#endif 328 329 updateOpacity(renderer()->style()); 330 updateTransform(renderer()->style()); 331#if ENABLE(CSS_FILTERS) 332 updateFilters(renderer()->style()); 333#endif 334#if ENABLE(CSS_COMPOSITING) 335 updateLayerBlendMode(renderer()->style()); 336#endif 337} 338 339void RenderLayerBacking::destroyGraphicsLayers() 340{ 341 if (m_graphicsLayer) { 342 willDestroyLayer(m_graphicsLayer.get()); 343 m_graphicsLayer->removeFromParent(); 344 } 345 346 m_ancestorClippingLayer = nullptr; 347 m_contentsContainmentLayer = nullptr; 348 m_graphicsLayer = nullptr; 349 m_foregroundLayer = nullptr; 350 m_backgroundLayer = nullptr; 351 m_childContainmentLayer = nullptr; 352 m_maskLayer = nullptr; 353 354 m_scrollingLayer = nullptr; 355 m_scrollingContentsLayer = nullptr; 356} 357 358void RenderLayerBacking::updateOpacity(const RenderStyle* style) 359{ 360 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity())); 361} 362 363void RenderLayerBacking::updateTransform(const RenderStyle* style) 364{ 365 // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin 366 // baked into it, and we don't want that. 367 TransformationMatrix t; 368 if (m_owningLayer->hasTransform()) { 369 style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); 370 makeMatrixRenderable(t, compositor()->canRender3DTransforms()); 371 } 372 373 if (m_contentsContainmentLayer) { 374 m_contentsContainmentLayer->setTransform(t); 375 m_graphicsLayer->setTransform(TransformationMatrix()); 376 } else 377 m_graphicsLayer->setTransform(t); 378} 379 380#if ENABLE(CSS_FILTERS) 381void RenderLayerBacking::updateFilters(const RenderStyle* style) 382{ 383 m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer()->computeFilterOperations(style)); 384} 385#endif 386 387#if ENABLE(CSS_COMPOSITING) 388void RenderLayerBacking::updateLayerBlendMode(const RenderStyle*) 389{ 390} 391#endif 392 393static bool hasNonZeroTransformOrigin(const RenderObject* renderer) 394{ 395 RenderStyle* style = renderer->style(); 396 return (style->transformOriginX().type() == Fixed && style->transformOriginX().value()) 397 || (style->transformOriginY().type() == Fixed && style->transformOriginY().value()); 398} 399 400static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer) 401{ 402 for (RenderLayer* curr = layer; curr; curr = curr->parent()) { 403 if (curr->hasTransform() || curr->needsCompositedScrolling()) 404 return true; 405 } 406 407 return false; 408} 409 410bool RenderLayerBacking::shouldClipCompositedBounds() const 411{ 412 // Scrollbar layers use this layer for relative positioning, so don't clip. 413 if (layerForHorizontalScrollbar() || layerForVerticalScrollbar()) 414 return false; 415 416 if (m_usingTiledCacheLayer) 417 return false; 418 419 if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer)) 420 return false; 421 422 return true; 423} 424 425void RenderLayerBacking::updateCompositedBounds() 426{ 427 IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); 428 429 // Clip to the size of the document or enclosing overflow-scroll layer. 430 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with. 431 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist. 432 if (shouldClipCompositedBounds()) { 433 RenderView* view = m_owningLayer->renderer()->view(); 434 RenderLayer* rootLayer = view->layer(); 435 436 LayoutRect clippingBounds; 437 if (renderer()->style()->position() == FixedPosition && renderer()->container() == view) 438 clippingBounds = view->frameView()->viewportConstrainedVisibleContentRect(); 439 else 440 clippingBounds = view->unscaledDocumentRect(); 441 442 if (m_owningLayer != rootLayer) 443 clippingBounds.intersect(m_owningLayer->backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions. 444 445 LayoutPoint delta; 446 m_owningLayer->convertToLayerCoords(rootLayer, delta, RenderLayer::AdjustForColumns); 447 clippingBounds.move(-delta.x(), -delta.y()); 448 449 layerBounds.intersect(pixelSnappedIntRect(clippingBounds)); 450 } 451 452 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size, 453 // then we need to ensure that the compositing layer has non-zero size so that we can apply 454 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value). 455 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) { 456 layerBounds.setWidth(1); 457 layerBounds.setHeight(1); 458 m_artificiallyInflatedBounds = true; 459 } else 460 m_artificiallyInflatedBounds = false; 461 462 setCompositedBounds(layerBounds); 463} 464 465void RenderLayerBacking::updateAfterWidgetResize() 466{ 467 if (renderer()->isRenderPart()) { 468 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) { 469 innerCompositor->frameViewDidChangeSize(); 470 innerCompositor->frameViewDidChangeLocation(contentsBox().location()); 471 } 472 } 473} 474 475void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags) 476{ 477 RenderLayerCompositor* layerCompositor = compositor(); 478 if (!layerCompositor->compositingLayersNeedRebuild()) { 479 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the 480 // position of this layer's GraphicsLayer depends on the position of our compositing 481 // ancestor's GraphicsLayer. That cannot be determined until all the descendant 482 // RenderLayers of that ancestor have been processed via updateLayerPositions(). 483 // 484 // The solution is to update compositing children of this layer here, 485 // via updateCompositingChildrenGeometry(). 486 updateCompositedBounds(); 487 layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly); 488 489 if (flags & IsUpdateRoot) { 490 updateGraphicsLayerGeometry(); 491 layerCompositor->updateRootLayerPosition(); 492 RenderLayer* stackingContainer = m_owningLayer->enclosingStackingContainer(); 493 if (!layerCompositor->compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != m_owningLayer)) 494 layerCompositor->updateCompositingDescendantGeometry(stackingContainer, stackingContainer, flags & CompositingChildrenOnly); 495 } 496 } 497 498 if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor()) 499 setContentsNeedDisplay(); 500} 501 502bool RenderLayerBacking::updateGraphicsLayerConfiguration() 503{ 504 RenderLayerCompositor* compositor = this->compositor(); 505 RenderObject* renderer = this->renderer(); 506 507 m_owningLayer->updateDescendantDependentFlags(); 508 m_owningLayer->updateZOrderLists(); 509 510 bool layerConfigChanged = false; 511 setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(m_owningLayer)); 512 513 // The background layer is currently only used for fixed root backgrounds. 514 if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground)) 515 layerConfigChanged = true; 516 517 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer))) 518 layerConfigChanged = true; 519 520 bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer); 521 522 // Our scrolling layer will clip. 523 if (m_owningLayer->needsCompositedScrolling()) 524 needsDescendentsClippingLayer = false; 525 526 if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer)) 527 layerConfigChanged = true; 528 529 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer())) 530 layerConfigChanged = true; 531 532 if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling())) 533 layerConfigChanged = true; 534 535 if (layerConfigChanged) 536 updateInternalHierarchy(); 537 538 if (GraphicsLayer* flatteningLayer = tileCacheFlatteningLayer()) { 539 flatteningLayer->removeFromParent(); 540 m_graphicsLayer->addChild(flatteningLayer); 541 } 542 543 if (updateMaskLayer(renderer->hasMask())) 544 m_graphicsLayer->setMaskLayer(m_maskLayer.get()); 545 546 if (m_owningLayer->hasReflection()) { 547 if (m_owningLayer->reflectionLayer()->backing()) { 548 GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer(); 549 m_graphicsLayer->setReplicatedByLayer(reflectionLayer); 550 } 551 } else 552 m_graphicsLayer->setReplicatedByLayer(0); 553 554 bool isSimpleContainer = isSimpleContainerCompositingLayer(); 555 bool didUpdateContentsRect = false; 556 updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect); 557 558 updateRootLayerConfiguration(); 559 560 if (isDirectlyCompositedImage()) 561 updateImageContents(); 562 563 if (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) { 564 PluginViewBase* pluginViewBase = toPluginViewBase(toRenderWidget(renderer)->widget()); 565 if (!pluginViewBase->shouldNotAddLayer()) 566 m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer()); 567 } 568#if ENABLE(VIDEO) 569 else if (renderer->isVideo()) { 570 HTMLMediaElement* mediaElement = toMediaElement(renderer->node()); 571 m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer()); 572 } 573#endif 574#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 575 else if (isAcceleratedCanvas(renderer)) { 576 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); 577 if (CanvasRenderingContext* context = canvas->renderingContext()) 578 m_graphicsLayer->setContentsToCanvas(context->platformLayer()); 579 layerConfigChanged = true; 580 } 581#endif 582 if (renderer->isRenderPart()) 583 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer)); 584 585 return layerConfigChanged; 586} 587 588static IntRect clipBox(RenderBox* renderer) 589{ 590 LayoutRect result = PaintInfo::infiniteRect(); 591 if (renderer->hasOverflowClip()) 592 result = renderer->overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions. 593 594 if (renderer->hasClip()) 595 result.intersect(renderer->clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions. 596 597 return pixelSnappedIntRect(result); 598} 599 600void RenderLayerBacking::updateGraphicsLayerGeometry() 601{ 602 // If we haven't built z-order lists yet, wait until later. 603 if (m_owningLayer->isStackingContainer() && m_owningLayer->m_zOrderListsDirty) 604 return; 605 606 // Set transform property, if it is not animating. We have to do this here because the transform 607 // is affected by the layer dimensions. 608 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform)) 609 updateTransform(renderer()->style()); 610 611 // Set opacity, if it is not animating. 612 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity)) 613 updateOpacity(renderer()->style()); 614 615#if ENABLE(CSS_FILTERS) 616 updateFilters(renderer()->style()); 617#endif 618 619#if ENABLE(CSS_COMPOSITING) 620 updateLayerBlendMode(renderer()->style()); 621#endif 622 623 bool isSimpleContainer = isSimpleContainerCompositingLayer(); 624 625 m_owningLayer->updateDescendantDependentFlags(); 626 627 // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing 628 // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any 629 // non-compositing visible layers. 630 m_graphicsLayer->setContentsVisible(m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers()); 631 632 RenderStyle* style = renderer()->style(); 633 // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959 634 bool preserves3D = style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection(); 635 m_graphicsLayer->setPreserves3D(preserves3D); 636 m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible); 637 638 RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer(); 639 640 // We compute everything relative to the enclosing compositing layer. 641 IntRect ancestorCompositingBounds; 642 if (compAncestor) { 643 ASSERT(compAncestor->backing()); 644 ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds()); 645 } 646 647 LayoutRect localRawCompositingBounds = compositedBounds(); 648 IntRect localCompositingBounds = pixelSnappedIntRect(localRawCompositingBounds); 649 650 IntRect relativeCompositingBounds(localCompositingBounds); 651 IntPoint delta; 652 m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta, RenderLayer::AdjustForColumns); 653 relativeCompositingBounds.moveBy(delta); 654 655 IntPoint graphicsLayerParentLocation; 656 if (compAncestor && compAncestor->backing()->hasClippingLayer()) { 657 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore 658 // position relative to it. 659 IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer())); 660 graphicsLayerParentLocation = clippingBox.location(); 661 } else if (compAncestor) 662 graphicsLayerParentLocation = ancestorCompositingBounds.location(); 663 else 664 graphicsLayerParentLocation = renderer()->view()->documentRect().location(); 665 666 if (compAncestor && compAncestor->needsCompositedScrolling()) { 667 RenderBox* renderBox = toRenderBox(compAncestor->renderer()); 668 IntSize scrollOffset = compAncestor->scrolledContentOffset(); 669 IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop()); 670 graphicsLayerParentLocation = scrollOrigin - scrollOffset; 671 } 672 673 if (compAncestor && m_ancestorClippingLayer) { 674 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this 675 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects 676 // for a compositing layer, rootLayer is the layer itself. 677 RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip); 678 IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions. 679 ASSERT(parentClipRect != PaintInfo::infiniteRect()); 680 m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation)); 681 m_ancestorClippingLayer->setSize(parentClipRect.size()); 682 683 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. 684 m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta); 685 686 // The primary layer is then parented in, and positioned relative to this clipping layer. 687 graphicsLayerParentLocation = parentClipRect.location(); 688 } 689 690 FloatSize contentsSize = relativeCompositingBounds.size(); 691 692 if (m_contentsContainmentLayer) { 693 m_contentsContainmentLayer->setPreserves3D(preserves3D); 694 m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation)); 695 // Use the same size as m_graphicsLayer so transforms behave correctly. 696 m_contentsContainmentLayer->setSize(contentsSize); 697 graphicsLayerParentLocation = relativeCompositingBounds.location(); 698 } 699 700 m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation)); 701 m_graphicsLayer->setSize(contentsSize); 702 m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location())); 703 704 if (!m_isMainFrameRenderViewLayer) { 705 // For non-root layers, background is always painted by the primary graphics layer. 706 ASSERT(!m_backgroundLayer); 707 bool hadSubpixelRounding = LayoutSize(relativeCompositingBounds.size()) != localRawCompositingBounds.size(); 708 m_graphicsLayer->setContentsOpaque(!hadSubpixelRounding && m_owningLayer->backgroundIsKnownToBeOpaqueInRect(localCompositingBounds)); 709 } 710 711 // If we have a layer that clips children, position it. 712 IntRect clippingBox; 713 if (GraphicsLayer* clipLayer = clippingLayer()) { 714 clippingBox = clipBox(toRenderBox(renderer())); 715 clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location())); 716 clipLayer->setSize(clippingBox.size()); 717 clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location())); 718 } 719 720 if (m_maskLayer) { 721 m_maskLayer->setSize(m_graphicsLayer->size()); 722 m_maskLayer->setPosition(FloatPoint()); 723 m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); 724 } 725 726 if (m_owningLayer->hasTransform()) { 727 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect(); 728 729 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds. 730 IntRect layerBounds = IntRect(delta, borderBox.size()); 731 732 // Update properties that depend on layer dimensions 733 FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); 734 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set. 735 FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f, 736 relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f, 737 transformOrigin.z()); 738 if (m_contentsContainmentLayer) 739 m_contentsContainmentLayer->setAnchorPoint(anchor); 740 else 741 m_graphicsLayer->setAnchorPoint(anchor); 742 743 RenderStyle* style = renderer()->style(); 744 GraphicsLayer* clipLayer = clippingLayer(); 745 if (style->hasPerspective()) { 746 TransformationMatrix t = owningLayer()->perspectiveTransform(); 747 748 if (clipLayer) { 749 clipLayer->setChildrenTransform(t); 750 m_graphicsLayer->setChildrenTransform(TransformationMatrix()); 751 } 752 else 753 m_graphicsLayer->setChildrenTransform(t); 754 } else { 755 if (clipLayer) 756 clipLayer->setChildrenTransform(TransformationMatrix()); 757 else 758 m_graphicsLayer->setChildrenTransform(TransformationMatrix()); 759 } 760 } else { 761 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); 762 if (m_contentsContainmentLayer) 763 m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); 764 } 765 766 if (m_foregroundLayer) { 767 FloatPoint foregroundPosition; 768 FloatSize foregroundSize = contentsSize; 769 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); 770 if (hasClippingLayer()) { 771 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it, 772 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer. 773 foregroundSize = FloatSize(clippingBox.size()); 774 foregroundOffset = toIntSize(clippingBox.location()); 775 } 776 777 m_foregroundLayer->setPosition(foregroundPosition); 778 m_foregroundLayer->setSize(foregroundSize); 779 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset); 780 } 781 782 if (m_backgroundLayer) { 783 FloatPoint backgroundPosition; 784 FloatSize backgroundSize = contentsSize; 785 if (backgroundLayerPaintsFixedRootBackground()) { 786 FrameView* frameView = toRenderView(renderer())->frameView(); 787 backgroundPosition = IntPoint(frameView->scrollOffsetForFixedPosition()); 788 backgroundSize = frameView->visibleContentRect().size(); 789 } 790 m_backgroundLayer->setPosition(backgroundPosition); 791 m_backgroundLayer->setSize(backgroundSize); 792 m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer()); 793 } 794 795 if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) { 796 RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing(); 797 reflectionBacking->updateGraphicsLayerGeometry(); 798 799 // The reflection layer has the bounds of m_owningLayer->reflectionLayer(), 800 // but the reflected layer is the bounds of this layer, so we need to position it appropriately. 801 FloatRect layerBounds = compositedBounds(); 802 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds(); 803 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location())); 804 } 805 806 if (m_scrollingLayer) { 807 ASSERT(m_scrollingContentsLayer); 808 RenderBox* renderBox = toRenderBox(renderer()); 809 IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom()); 810 IntSize scrollOffset = m_owningLayer->scrollOffset(); 811 812 m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location())); 813 814 m_scrollingLayer->setSize(paddingBox.size()); 815 m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height())); 816 817 IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer(); 818 m_scrollingLayer->setOffsetFromRenderer(-toIntSize(paddingBox.location())); 819 820 bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer(); 821 822 IntSize scrollSize(m_owningLayer->scrollWidth(), m_owningLayer->scrollHeight()); 823 if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged) 824 m_scrollingContentsLayer->setNeedsDisplay(); 825 826 IntSize scrollingContentsOffset = toIntSize(paddingBox.location() - scrollOffset); 827 if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size()) 828 compositor()->scrollingLayerDidChange(m_owningLayer); 829 830 m_scrollingContentsLayer->setSize(scrollSize); 831 // FIXME: The paint offset and the scroll offset should really be separate concepts. 832 m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay); 833 834 if (m_foregroundLayer) { 835 m_foregroundLayer->setSize(m_scrollingContentsLayer->size()); 836 m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer()); 837 } 838 } 839 840 // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store. 841 setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor, relativeCompositingBounds, ancestorCompositingBounds)); 842 843 bool didUpdateContentsRect = false; 844 updateDirectlyCompositedContents(isSimpleContainer, didUpdateContentsRect); 845 if (!didUpdateContentsRect) 846 resetContentsRect(); 847 848 updateDrawsContent(isSimpleContainer); 849 updateAfterWidgetResize(); 850 registerScrollingLayers(); 851} 852 853void RenderLayerBacking::updateDirectlyCompositedContents(bool isSimpleContainer, bool& didUpdateContentsRect) 854{ 855 if (!m_owningLayer->hasVisibleContent()) 856 return; 857 858 // The order of operations here matters, since the last valid type of contents needs 859 // to also update the contentsRect. 860 updateDirectlyCompositedBackgroundColor(isSimpleContainer, didUpdateContentsRect); 861 updateDirectlyCompositedBackgroundImage(isSimpleContainer, didUpdateContentsRect); 862} 863 864void RenderLayerBacking::registerScrollingLayers() 865{ 866 // Register fixed position layers and their containers with the scrolling coordinator. 867 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); 868 if (!scrollingCoordinator) 869 return; 870 871 compositor()->updateViewportConstraintStatus(m_owningLayer); 872 873 if (!scrollingCoordinator->supportsFixedPositionLayers()) 874 return; 875 876 scrollingCoordinator->updateLayerPositionConstraint(m_owningLayer); 877 878 // Page scale is applied as a transform on the root render view layer. Because the scroll 879 // layer is further up in the hierarchy, we need to avoid marking the root render view 880 // layer as a container. 881 bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer(); 882 scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer); 883} 884 885void RenderLayerBacking::updateInternalHierarchy() 886{ 887 // m_foregroundLayer has to be inserted in the correct order with child layers, 888 // so it's not inserted here. 889 if (m_ancestorClippingLayer) 890 m_ancestorClippingLayer->removeAllChildren(); 891 892 if (m_contentsContainmentLayer) { 893 m_contentsContainmentLayer->removeAllChildren(); 894 if (m_ancestorClippingLayer) 895 m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get()); 896 } 897 898 if (m_backgroundLayer) 899 m_contentsContainmentLayer->addChild(m_backgroundLayer.get()); 900 901 m_graphicsLayer->removeFromParent(); 902 if (m_contentsContainmentLayer) 903 m_contentsContainmentLayer->addChild(m_graphicsLayer.get()); 904 else if (m_ancestorClippingLayer) 905 m_ancestorClippingLayer->addChild(m_graphicsLayer.get()); 906 907 if (m_childContainmentLayer) { 908 m_childContainmentLayer->removeFromParent(); 909 m_graphicsLayer->addChild(m_childContainmentLayer.get()); 910 } 911 912 if (m_scrollingLayer) { 913 GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get(); 914 m_scrollingLayer->removeFromParent(); 915 superlayer->addChild(m_scrollingLayer.get()); 916 } 917 918 // The clip for child layers does not include space for overflow controls, so they exist as 919 // siblings of the clipping layer if we have one. Normal children of this layer are set as 920 // children of the clipping layer. 921 if (m_layerForHorizontalScrollbar) { 922 m_layerForHorizontalScrollbar->removeFromParent(); 923 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get()); 924 } 925 if (m_layerForVerticalScrollbar) { 926 m_layerForVerticalScrollbar->removeFromParent(); 927 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get()); 928 } 929 if (m_layerForScrollCorner) { 930 m_layerForScrollCorner->removeFromParent(); 931 m_graphicsLayer->addChild(m_layerForScrollCorner.get()); 932 } 933} 934 935void RenderLayerBacking::resetContentsRect() 936{ 937 IntRect rect = contentsBox(); 938 m_graphicsLayer->setContentsRect(rect); 939 m_graphicsLayer->setContentsTileSize(IntSize()); 940 m_graphicsLayer->setContentsTilePhase(IntPoint()); 941} 942 943void RenderLayerBacking::updateDrawsContent() 944{ 945 updateDrawsContent(isSimpleContainerCompositingLayer()); 946} 947 948void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer) 949{ 950 if (m_scrollingLayer) { 951 // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere. 952 // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint. 953 // m_scrollingLayer never has backing store. 954 // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint. 955 bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground(); 956 m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent); 957 958 bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren()); 959 m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent); 960 return; 961 } 962 963 bool hasPaintedContent = !isSimpleContainer && containsPaintedContent(); 964 965 // FIXME: we could refine this to only allocate backing for one of these layers if possible. 966 m_graphicsLayer->setDrawsContent(hasPaintedContent); 967 if (m_foregroundLayer) 968 m_foregroundLayer->setDrawsContent(hasPaintedContent); 969 970 if (m_backgroundLayer) 971 m_backgroundLayer->setDrawsContent(hasPaintedContent); 972} 973 974// Return true if the layers changed. 975bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip) 976{ 977 bool layersChanged = false; 978 979 if (needsAncestorClip) { 980 if (!m_ancestorClippingLayer) { 981 m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer"); 982 m_ancestorClippingLayer->setMasksToBounds(true); 983 layersChanged = true; 984 } 985 } else if (m_ancestorClippingLayer) { 986 willDestroyLayer(m_ancestorClippingLayer.get()); 987 m_ancestorClippingLayer->removeFromParent(); 988 m_ancestorClippingLayer = nullptr; 989 layersChanged = true; 990 } 991 992 if (needsDescendantClip) { 993 if (!m_childContainmentLayer && !m_usingTiledCacheLayer) { 994 m_childContainmentLayer = createGraphicsLayer("Child clipping Layer"); 995 m_childContainmentLayer->setMasksToBounds(true); 996 layersChanged = true; 997 } 998 } else if (hasClippingLayer()) { 999 willDestroyLayer(m_childContainmentLayer.get()); 1000 m_childContainmentLayer->removeFromParent(); 1001 m_childContainmentLayer = nullptr; 1002 layersChanged = true; 1003 } 1004 1005 return layersChanged; 1006} 1007 1008void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground) 1009{ 1010 m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground; 1011} 1012 1013bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const 1014{ 1015 if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling()) 1016 return false; 1017 return m_owningLayer->horizontalScrollbar(); 1018} 1019 1020bool RenderLayerBacking::requiresVerticalScrollbarLayer() const 1021{ 1022 if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling()) 1023 return false; 1024 return m_owningLayer->verticalScrollbar(); 1025} 1026 1027bool RenderLayerBacking::requiresScrollCornerLayer() const 1028{ 1029 if (!m_owningLayer->hasOverlayScrollbars() && !m_owningLayer->needsCompositedScrolling()) 1030 return false; 1031 return !m_owningLayer->scrollCornerAndResizerRect().isEmpty(); 1032} 1033 1034bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer) 1035{ 1036 bool horizontalScrollbarLayerChanged = false; 1037 if (needsHorizontalScrollbarLayer) { 1038 if (!m_layerForHorizontalScrollbar) { 1039 m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar"); 1040 horizontalScrollbarLayerChanged = true; 1041 } 1042 } else if (m_layerForHorizontalScrollbar) { 1043 willDestroyLayer(m_layerForHorizontalScrollbar.get()); 1044 m_layerForHorizontalScrollbar = nullptr; 1045 horizontalScrollbarLayerChanged = true; 1046 } 1047 1048 bool verticalScrollbarLayerChanged = false; 1049 if (needsVerticalScrollbarLayer) { 1050 if (!m_layerForVerticalScrollbar) { 1051 m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar"); 1052 verticalScrollbarLayerChanged = true; 1053 } 1054 } else if (m_layerForVerticalScrollbar) { 1055 willDestroyLayer(m_layerForVerticalScrollbar.get()); 1056 m_layerForVerticalScrollbar = nullptr; 1057 verticalScrollbarLayerChanged = true; 1058 } 1059 1060 bool scrollCornerLayerChanged = false; 1061 if (needsScrollCornerLayer) { 1062 if (!m_layerForScrollCorner) { 1063 m_layerForScrollCorner = createGraphicsLayer("scroll corner"); 1064 scrollCornerLayerChanged = true; 1065 } 1066 } else if (m_layerForScrollCorner) { 1067 willDestroyLayer(m_layerForScrollCorner.get()); 1068 m_layerForScrollCorner = nullptr; 1069 scrollCornerLayerChanged = true; 1070 } 1071 1072 if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) { 1073 if (horizontalScrollbarLayerChanged) 1074 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar); 1075 if (verticalScrollbarLayerChanged) 1076 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar); 1077 } 1078 1079 return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged; 1080} 1081 1082void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFromRoot) 1083{ 1084 IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer(); 1085 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) { 1086 Scrollbar* hBar = m_owningLayer->horizontalScrollbar(); 1087 if (hBar) { 1088 layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer); 1089 layer->setSize(hBar->frameRect().size()); 1090 if (layer->hasContentsLayer()) 1091 layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size())); 1092 } 1093 layer->setDrawsContent(hBar && !layer->hasContentsLayer()); 1094 } 1095 1096 if (GraphicsLayer* layer = layerForVerticalScrollbar()) { 1097 Scrollbar* vBar = m_owningLayer->verticalScrollbar(); 1098 if (vBar) { 1099 layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer); 1100 layer->setSize(vBar->frameRect().size()); 1101 if (layer->hasContentsLayer()) 1102 layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size())); 1103 } 1104 layer->setDrawsContent(vBar && !layer->hasContentsLayer()); 1105 } 1106 1107 if (GraphicsLayer* layer = layerForScrollCorner()) { 1108 const LayoutRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect(); 1109 layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer); 1110 layer->setSize(scrollCornerAndResizer.size()); 1111 layer->setDrawsContent(!scrollCornerAndResizer.isEmpty()); 1112 } 1113} 1114 1115bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const 1116{ 1117 if (GraphicsLayer* layer = layerForHorizontalScrollbar()) 1118 if (!layer->drawsContent()) 1119 return true; 1120 1121 if (GraphicsLayer* layer = layerForVerticalScrollbar()) 1122 if (!layer->drawsContent()) 1123 return true; 1124 1125 if (GraphicsLayer* layer = layerForScrollCorner()) 1126 if (!layer->drawsContent()) 1127 return true; 1128 1129 return false; 1130} 1131 1132bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer) 1133{ 1134 bool layerChanged = false; 1135 if (needsForegroundLayer) { 1136 if (!m_foregroundLayer) { 1137 String layerName; 1138#ifndef NDEBUG 1139 layerName = m_owningLayer->name() + " (foreground)"; 1140#endif 1141 m_foregroundLayer = createGraphicsLayer(layerName); 1142 m_foregroundLayer->setDrawsContent(true); 1143 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground); 1144 layerChanged = true; 1145 } 1146 } else if (m_foregroundLayer) { 1147 willDestroyLayer(m_foregroundLayer.get()); 1148 m_foregroundLayer->removeFromParent(); 1149 m_foregroundLayer = nullptr; 1150 layerChanged = true; 1151 } 1152 1153 if (layerChanged) { 1154 m_graphicsLayer->setNeedsDisplay(); 1155 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 1156 } 1157 1158 return layerChanged; 1159} 1160 1161bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer) 1162{ 1163 bool layerChanged = false; 1164 if (needsBackgroundLayer) { 1165 if (!m_backgroundLayer) { 1166 String layerName; 1167#ifndef NDEBUG 1168 layerName = m_owningLayer->name() + " (background)"; 1169#endif 1170 m_backgroundLayer = createGraphicsLayer(layerName); 1171 m_backgroundLayer->setDrawsContent(true); 1172 m_backgroundLayer->setAnchorPoint(FloatPoint3D()); 1173 m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground); 1174 layerChanged = true; 1175 } 1176 1177 if (!m_contentsContainmentLayer) { 1178 String layerName; 1179#ifndef NDEBUG 1180 layerName = m_owningLayer->name() + " (contents containment)"; 1181#endif 1182 m_contentsContainmentLayer = createGraphicsLayer(layerName); 1183 m_contentsContainmentLayer->setAppliesPageScale(true); 1184 m_graphicsLayer->setAppliesPageScale(false); 1185 layerChanged = true; 1186 } 1187 } else { 1188 if (m_backgroundLayer) { 1189 willDestroyLayer(m_backgroundLayer.get()); 1190 m_backgroundLayer->removeFromParent(); 1191 m_backgroundLayer = nullptr; 1192 layerChanged = true; 1193 } 1194 if (m_contentsContainmentLayer) { 1195 willDestroyLayer(m_contentsContainmentLayer.get()); 1196 m_contentsContainmentLayer->removeFromParent(); 1197 m_contentsContainmentLayer = nullptr; 1198 layerChanged = true; 1199 m_graphicsLayer->setAppliesPageScale(true); 1200 } 1201 } 1202 1203 if (layerChanged) { 1204 m_graphicsLayer->setNeedsDisplay(); 1205 // This assumes that the background layer is only used for fixed backgrounds, which is currently a correct assumption. 1206 if (renderer()->view()) 1207 compositor()->fixedRootBackgroundLayerChanged(); 1208 } 1209 1210 return layerChanged; 1211} 1212 1213bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer) 1214{ 1215 bool layerChanged = false; 1216 if (needsMaskLayer) { 1217 if (!m_maskLayer) { 1218 m_maskLayer = createGraphicsLayer("Mask"); 1219 m_maskLayer->setDrawsContent(true); 1220 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask); 1221 layerChanged = true; 1222 } 1223 } else if (m_maskLayer) { 1224 willDestroyLayer(m_maskLayer.get()); 1225 m_maskLayer = nullptr; 1226 layerChanged = true; 1227 } 1228 1229 if (layerChanged) 1230 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 1231 1232 return layerChanged; 1233} 1234 1235bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers) 1236{ 1237 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); 1238 1239 bool layerChanged = false; 1240 if (needsScrollingLayers) { 1241 if (!m_scrollingLayer) { 1242 // Outer layer which corresponds with the scroll view. 1243 m_scrollingLayer = createGraphicsLayer("Scrolling container"); 1244 m_scrollingLayer->setDrawsContent(false); 1245 m_scrollingLayer->setMasksToBounds(true); 1246 1247 // Inner layer which renders the content that scrolls. 1248 m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents"); 1249 m_scrollingContentsLayer->setDrawsContent(true); 1250 GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll; 1251 if (!m_foregroundLayer) 1252 paintPhase |= GraphicsLayerPaintForeground; 1253 m_scrollingContentsLayer->setPaintingPhase(paintPhase); 1254 m_scrollingLayer->addChild(m_scrollingContentsLayer.get()); 1255 1256 layerChanged = true; 1257 if (scrollingCoordinator) 1258 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer); 1259 } 1260 } else if (m_scrollingLayer) { 1261 willDestroyLayer(m_scrollingLayer.get()); 1262 willDestroyLayer(m_scrollingContentsLayer.get()); 1263 m_scrollingLayer = nullptr; 1264 m_scrollingContentsLayer = nullptr; 1265 layerChanged = true; 1266 if (scrollingCoordinator) 1267 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer); 1268 } 1269 1270 if (layerChanged) { 1271 updateInternalHierarchy(); 1272 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 1273 m_graphicsLayer->setNeedsDisplay(); 1274 if (renderer()->view()) 1275 compositor()->scrollingLayerDidChange(m_owningLayer); 1276 } 1277 1278 return layerChanged; 1279} 1280 1281void RenderLayerBacking::attachToScrollingCoordinatorWithParent(RenderLayerBacking* parent) 1282{ 1283 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); 1284 if (!scrollingCoordinator) 1285 return; 1286 1287 // FIXME: When we support overflow areas, we will have to refine this for overflow areas that are also 1288 // positon:fixed. 1289 ScrollingNodeType nodeType; 1290 if (renderer()->style()->position() == FixedPosition) 1291 nodeType = FixedNode; 1292 else if (renderer()->style()->position() == StickyPosition) 1293 nodeType = StickyNode; 1294 else 1295 nodeType = ScrollingNode; 1296 1297 ScrollingNodeID parentID = parent ? parent->scrollLayerID() : 0; 1298 m_scrollLayerID = scrollingCoordinator->attachToStateTree(nodeType, m_scrollLayerID ? m_scrollLayerID : scrollingCoordinator->uniqueScrollLayerID(), parentID); 1299} 1300 1301void RenderLayerBacking::detachFromScrollingCoordinator() 1302{ 1303 // If m_scrollLayerID is 0, then this backing is not attached to the ScrollingCoordinator. 1304 if (!m_scrollLayerID) 1305 return; 1306 1307 ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer); 1308 if (!scrollingCoordinator) 1309 return; 1310 1311 scrollingCoordinator->detachFromStateTree(m_scrollLayerID); 1312 m_scrollLayerID = 0; 1313} 1314 1315GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const 1316{ 1317 unsigned phase = 0; 1318 if (!m_backgroundLayer) 1319 phase |= GraphicsLayerPaintBackground; 1320 if (!m_foregroundLayer) 1321 phase |= GraphicsLayerPaintForeground; 1322 if (!m_maskLayer) 1323 phase |= GraphicsLayerPaintMask; 1324 1325 if (m_scrollingContentsLayer) { 1326 phase &= ~GraphicsLayerPaintForeground; 1327 phase |= GraphicsLayerPaintCompositedScroll; 1328 } 1329 1330 return static_cast<GraphicsLayerPaintingPhase>(phase); 1331} 1332 1333float RenderLayerBacking::compositingOpacity(float rendererOpacity) const 1334{ 1335 float finalOpacity = rendererOpacity; 1336 1337 for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) { 1338 // We only care about parents that are stacking contexts. 1339 // Recall that opacity creates stacking context. 1340 if (!curr->isStackingContainer()) 1341 continue; 1342 1343 // If we found a compositing layer, we want to compute opacity 1344 // relative to it. So we can break here. 1345 if (curr->isComposited()) 1346 break; 1347 1348 finalOpacity *= curr->renderer()->opacity(); 1349 } 1350 1351 return finalOpacity; 1352} 1353 1354static bool hasBoxDecorations(const RenderStyle* style) 1355{ 1356 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter(); 1357} 1358 1359static bool canCreateTiledImage(const RenderStyle*); 1360 1361static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style) 1362{ 1363 if (hasBoxDecorations(style)) 1364 return true; 1365 1366 if (!style->hasBackgroundImage()) 1367 return false; 1368 1369 return !GraphicsLayer::supportsContentsTiling() || !canCreateTiledImage(style); 1370} 1371 1372static bool hasPerspectiveOrPreserves3D(const RenderStyle* style) 1373{ 1374 return style->hasPerspective() || style->preserves3D(); 1375} 1376 1377Color RenderLayerBacking::rendererBackgroundColor() const 1378{ 1379 RenderObject* backgroundRenderer = renderer(); 1380 if (backgroundRenderer->isRoot()) 1381 backgroundRenderer = backgroundRenderer->rendererForRootBackground(); 1382 1383 return backgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor); 1384} 1385 1386void RenderLayerBacking::updateDirectlyCompositedBackgroundColor(bool isSimpleContainer, bool& didUpdateContentsRect) 1387{ 1388 if (!isSimpleContainer) { 1389 m_graphicsLayer->setContentsToSolidColor(Color()); 1390 return; 1391 } 1392 1393 Color backgroundColor = rendererBackgroundColor(); 1394 1395 // An unset (invalid) color will remove the solid color. 1396 m_graphicsLayer->setContentsToSolidColor(backgroundColor); 1397 m_graphicsLayer->setContentsRect(backgroundBox()); 1398 didUpdateContentsRect = true; 1399} 1400 1401bool canCreateTiledImage(const RenderStyle* style) 1402{ 1403 const FillLayer* fillLayer = style->backgroundLayers(); 1404 if (fillLayer->next()) 1405 return false; 1406 1407 if (!fillLayer->imagesAreLoaded()) 1408 return false; 1409 1410 if (fillLayer->attachment() != ScrollBackgroundAttachment) 1411 return false; 1412 1413 Color color = style->visitedDependentColor(CSSPropertyBackgroundColor); 1414 1415 // FIXME: Allow color+image compositing when it makes sense. 1416 // For now bailing out. 1417 if (color.isValid() && color.alpha()) 1418 return false; 1419 1420 StyleImage* styleImage = fillLayer->image(); 1421 1422 // FIXME: support gradients with isGeneratedImage. 1423 if (!styleImage->isCachedImage()) 1424 return false; 1425 1426 Image* image = styleImage->cachedImage()->image(); 1427 if (!image->isBitmapImage()) 1428 return false; 1429 1430 return true; 1431} 1432 1433void RenderLayerBacking::updateDirectlyCompositedBackgroundImage(bool isSimpleContainer, bool& didUpdateContentsRect) 1434{ 1435 if (!GraphicsLayer::supportsContentsTiling()) 1436 return; 1437 1438 if (isDirectlyCompositedImage()) 1439 return; 1440 1441 const RenderStyle* style = renderer()->style(); 1442 1443 if (!isSimpleContainer || !style->hasBackgroundImage()) { 1444 m_graphicsLayer->setContentsToImage(0); 1445 return; 1446 } 1447 1448 IntRect destRect = backgroundBox(); 1449 IntPoint phase; 1450 IntSize tileSize; 1451 1452 RefPtr<Image> image = style->backgroundLayers()->image()->cachedImage()->image(); 1453 toRenderBox(renderer())->getGeometryForBackgroundImage(m_owningLayer->renderer(), destRect, phase, tileSize); 1454 m_graphicsLayer->setContentsTileSize(tileSize); 1455 m_graphicsLayer->setContentsTilePhase(phase); 1456 m_graphicsLayer->setContentsRect(destRect); 1457 m_graphicsLayer->setContentsToImage(image.get()); 1458 didUpdateContentsRect = true; 1459} 1460 1461void RenderLayerBacking::updateRootLayerConfiguration() 1462{ 1463 if (!m_usingTiledCacheLayer) 1464 return; 1465 1466 Color backgroundColor; 1467 bool viewIsTransparent = compositor()->viewHasTransparentBackground(&backgroundColor); 1468 1469 if (m_backgroundLayerPaintsFixedRootBackground && m_backgroundLayer) { 1470 m_backgroundLayer->setBackgroundColor(backgroundColor); 1471 m_backgroundLayer->setContentsOpaque(!viewIsTransparent); 1472 1473 m_graphicsLayer->setBackgroundColor(Color()); 1474 m_graphicsLayer->setContentsOpaque(false); 1475 } else { 1476 m_graphicsLayer->setBackgroundColor(backgroundColor); 1477 m_graphicsLayer->setContentsOpaque(!viewIsTransparent); 1478 } 1479} 1480 1481static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer) 1482{ 1483 if (!GraphicsLayer::supportsBackgroundColorContent()) 1484 return false; 1485 1486 if (renderer->hasClip()) 1487 return false; 1488 1489 if (hasBoxDecorationsOrBackgroundImage(renderer->style())) 1490 return false; 1491 1492 // FIXME: We can't create a directly composited background if this 1493 // layer will have children that intersect with the background layer. 1494 // A better solution might be to introduce a flattening layer if 1495 // we do direct box decoration composition. 1496 // https://bugs.webkit.org/show_bug.cgi?id=119461 1497 if (hasPerspectiveOrPreserves3D(renderer->style())) 1498 return false; 1499 1500 // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now. 1501 if (renderer->style()->backgroundComposite() != CompositeSourceOver) 1502 return false; 1503 1504 if (renderer->style()->backgroundClip() == TextFillBox) 1505 return false; 1506 1507 return true; 1508} 1509 1510bool RenderLayerBacking::paintsBoxDecorations() const 1511{ 1512 if (!m_owningLayer->hasVisibleBoxDecorations()) 1513 return false; 1514 1515 if (!supportsDirectBoxDecorationsComposition(renderer())) 1516 return true; 1517 1518 return false; 1519} 1520 1521bool RenderLayerBacking::paintsChildren() const 1522{ 1523 if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers()) 1524 return true; 1525 1526 if (hasVisibleNonCompositingDescendantLayers()) 1527 return true; 1528 1529 return false; 1530} 1531 1532static bool isRestartedPlugin(RenderObject* renderer) 1533{ 1534 if (!renderer->isEmbeddedObject()) 1535 return false; 1536 1537 Element* element = toElement(renderer->node()); 1538 if (!element || !element->isPluginElement()) 1539 return false; 1540 1541 return toHTMLPlugInElement(element)->isRestartedPlugin(); 1542} 1543 1544static bool isCompositedPlugin(RenderObject* renderer) 1545{ 1546 return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing(); 1547} 1548 1549// A "simple container layer" is a RenderLayer which has no visible content to render. 1550// It may have no children, or all its children may be themselves composited. 1551// This is a useful optimization, because it allows us to avoid allocating backing store. 1552bool RenderLayerBacking::isSimpleContainerCompositingLayer() const 1553{ 1554 RenderObject* renderObject = renderer(); 1555 if (renderObject->hasMask()) // masks require special treatment 1556 return false; 1557 1558 if (renderObject->isReplaced() && (!isCompositedPlugin(renderObject) || isRestartedPlugin(renderObject))) 1559 return false; 1560 1561 if (paintsBoxDecorations() || paintsChildren()) 1562 return false; 1563 1564 if (renderObject->isRenderRegion()) 1565 return false; 1566 1567 if (renderObject->node() && renderObject->node()->isDocumentNode()) { 1568 // Look to see if the root object has a non-simple background 1569 RenderObject* rootObject = renderObject->document()->documentElement() ? renderObject->document()->documentElement()->renderer() : 0; 1570 if (!rootObject) 1571 return false; 1572 1573 RenderStyle* style = rootObject->style(); 1574 1575 // Reject anything that has a border, a border-radius or outline, 1576 // or is not a simple background (no background, or solid color). 1577 if (hasBoxDecorationsOrBackgroundImage(style)) 1578 return false; 1579 1580 // Now look at the body's renderer. 1581 HTMLElement* body = renderObject->document()->body(); 1582 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; 1583 if (!bodyObject) 1584 return false; 1585 1586 style = bodyObject->style(); 1587 1588 if (hasBoxDecorationsOrBackgroundImage(style)) 1589 return false; 1590 } 1591 1592 return true; 1593} 1594 1595static bool hasVisibleNonCompositingDescendant(RenderLayer* parent) 1596{ 1597 // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512. 1598 parent->updateLayerListsIfNeeded(); 1599 1600#if !ASSERT_DISABLED 1601 LayerListMutationDetector mutationChecker(parent); 1602#endif 1603 1604 if (Vector<RenderLayer*>* normalFlowList = parent->normalFlowList()) { 1605 size_t listSize = normalFlowList->size(); 1606 for (size_t i = 0; i < listSize; ++i) { 1607 RenderLayer* curLayer = normalFlowList->at(i); 1608 if (!curLayer->isComposited() 1609 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))) 1610 return true; 1611 } 1612 } 1613 1614 if (parent->isStackingContainer()) { 1615 if (!parent->hasVisibleDescendant()) 1616 return false; 1617 1618 // Use the m_hasCompositingDescendant bit to optimize? 1619 if (Vector<RenderLayer*>* negZOrderList = parent->negZOrderList()) { 1620 size_t listSize = negZOrderList->size(); 1621 for (size_t i = 0; i < listSize; ++i) { 1622 RenderLayer* curLayer = negZOrderList->at(i); 1623 if (!curLayer->isComposited() 1624 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))) 1625 return true; 1626 } 1627 } 1628 1629 if (Vector<RenderLayer*>* posZOrderList = parent->posZOrderList()) { 1630 size_t listSize = posZOrderList->size(); 1631 for (size_t i = 0; i < listSize; ++i) { 1632 RenderLayer* curLayer = posZOrderList->at(i); 1633 if (!curLayer->isComposited() 1634 && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer))) 1635 return true; 1636 } 1637 } 1638 } 1639 1640 return false; 1641} 1642 1643// Conservative test for having no rendered children. 1644bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const 1645{ 1646 return hasVisibleNonCompositingDescendant(m_owningLayer); 1647} 1648 1649bool RenderLayerBacking::containsPaintedContent() const 1650{ 1651 if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection()) 1652 return false; 1653 1654 if (isDirectlyCompositedImage()) 1655 return false; 1656 1657 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely, 1658 // and set background color on the layer in that case, instead of allocating backing store and painting. 1659#if ENABLE(VIDEO) 1660 if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo()) 1661 return m_owningLayer->hasBoxDecorationsOrBackground(); 1662#endif 1663#if PLATFORM(MAC) && USE(CA) && (PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) 1664#elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 1665 if (isAcceleratedCanvas(renderer())) 1666 return m_owningLayer->hasBoxDecorationsOrBackground(); 1667#endif 1668 1669 return true; 1670} 1671 1672// An image can be directly compositing if it's the sole content of the layer, and has no box decorations 1673// that require painting. Direct compositing saves backing store. 1674bool RenderLayerBacking::isDirectlyCompositedImage() const 1675{ 1676 RenderObject* renderObject = renderer(); 1677 1678 if (!renderObject->isRenderImage() || renderObject->isMedia() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip()) 1679 return false; 1680 1681 RenderImage* imageRenderer = toRenderImage(renderObject); 1682 if (CachedImage* cachedImage = imageRenderer->cachedImage()) { 1683 if (!cachedImage->hasImage()) 1684 return false; 1685 1686 Image* image = cachedImage->imageForRenderer(imageRenderer); 1687 if (!image->isBitmapImage()) 1688 return false; 1689 1690 return m_graphicsLayer->shouldDirectlyCompositeImage(image); 1691 } 1692 1693 return false; 1694} 1695 1696void RenderLayerBacking::contentChanged(ContentChangeType changeType) 1697{ 1698 if ((changeType == ImageChanged) && isDirectlyCompositedImage()) { 1699 updateImageContents(); 1700 return; 1701 } 1702 1703 if ((changeType == BackgroundImageChanged) && canCreateTiledImage(renderer()->style())) 1704 updateGraphicsLayerGeometry(); 1705 1706 if ((changeType == MaskImageChanged) && m_maskLayer) { 1707 // The composited layer bounds relies on box->maskClipRect(), which changes 1708 // when the mask image becomes available. 1709 updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot); 1710 } 1711 1712#if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 1713 if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) { 1714 m_graphicsLayer->setContentsNeedsDisplay(); 1715 return; 1716 } 1717#endif 1718} 1719 1720void RenderLayerBacking::updateImageContents() 1721{ 1722 ASSERT(renderer()->isRenderImage()); 1723 RenderImage* imageRenderer = toRenderImage(renderer()); 1724 1725 CachedImage* cachedImage = imageRenderer->cachedImage(); 1726 if (!cachedImage) 1727 return; 1728 1729 Image* image = cachedImage->imageForRenderer(imageRenderer); 1730 if (!image) 1731 return; 1732 1733 // We have to wait until the image is fully loaded before setting it on the layer. 1734 if (!cachedImage->isLoaded()) 1735 return; 1736 1737 // This is a no-op if the layer doesn't have an inner layer for the image. 1738 m_graphicsLayer->setContentsToImage(image); 1739 bool isSimpleContainer = false; 1740 updateDrawsContent(isSimpleContainer); 1741 1742 // Image animation is "lazy", in that it automatically stops unless someone is drawing 1743 // the image. So we have to kick the animation each time; this has the downside that the 1744 // image will keep animating, even if its layer is not visible. 1745 image->startAnimation(); 1746} 1747 1748FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const 1749{ 1750 RenderStyle* style = renderer()->style(); 1751 1752 FloatPoint3D origin; 1753 origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width())); 1754 origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height())); 1755 origin.setZ(style->transformOriginZ()); 1756 1757 return origin; 1758} 1759 1760FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const 1761{ 1762 RenderStyle* style = renderer()->style(); 1763 1764 float boxWidth = borderBox.width(); 1765 float boxHeight = borderBox.height(); 1766 1767 FloatPoint origin; 1768 origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth)); 1769 origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight)); 1770 1771 return origin; 1772} 1773 1774// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted. 1775IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const 1776{ 1777 return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y()); 1778} 1779 1780IntRect RenderLayerBacking::contentsBox() const 1781{ 1782 if (!renderer()->isBox()) 1783 return IntRect(); 1784 1785 IntRect contentsRect; 1786#if ENABLE(VIDEO) 1787 if (renderer()->isVideo()) { 1788 RenderVideo* videoRenderer = toRenderVideo(renderer()); 1789 contentsRect = videoRenderer->videoBox(); 1790 } else 1791#endif 1792 contentsRect = pixelSnappedIntRect(toRenderBox(renderer())->contentBoxRect()); 1793 1794 contentsRect.move(contentOffsetInCompostingLayer()); 1795 return contentsRect; 1796} 1797 1798static LayoutRect backgroundRectForBox(const RenderBox* box) 1799{ 1800 switch (box->style()->backgroundClip()) { 1801 case BorderFillBox: 1802 return box->borderBoxRect(); 1803 case PaddingFillBox: 1804 return box->paddingBoxRect(); 1805 case ContentFillBox: 1806 return box->contentBoxRect(); 1807 case TextFillBox: 1808 break; 1809 } 1810 1811 ASSERT_NOT_REACHED(); 1812 return LayoutRect(); 1813} 1814 1815IntRect RenderLayerBacking::backgroundBox() const 1816{ 1817 if (!renderer()->isBox()) 1818 return IntRect(); 1819 1820 IntRect pixelSnappedBackgroundBox = pixelSnappedIntRect(backgroundRectForBox(toRenderBox(renderer()))); 1821 pixelSnappedBackgroundBox.move(contentOffsetInCompostingLayer()); 1822 return pixelSnappedBackgroundBox; 1823} 1824 1825GraphicsLayer* RenderLayerBacking::parentForSublayers() const 1826{ 1827 if (m_scrollingContentsLayer) 1828 return m_scrollingContentsLayer.get(); 1829 1830 return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get(); 1831} 1832 1833GraphicsLayer* RenderLayerBacking::childForSuperlayers() const 1834{ 1835 if (m_ancestorClippingLayer) 1836 return m_ancestorClippingLayer.get(); 1837 1838 if (m_contentsContainmentLayer) 1839 return m_contentsContainmentLayer.get(); 1840 1841 return m_graphicsLayer.get(); 1842} 1843 1844bool RenderLayerBacking::paintsIntoWindow() const 1845{ 1846 if (m_usingTiledCacheLayer) 1847 return false; 1848 1849 if (m_owningLayer->isRootLayer()) { 1850#if PLATFORM(BLACKBERRY) || USE(COORDINATED_GRAPHICS) 1851 if (compositor()->inForcedCompositingMode()) 1852 return false; 1853#endif 1854 1855 return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame; 1856 } 1857 1858 return false; 1859} 1860 1861void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking) 1862{ 1863 if (requiresOwnBacking == m_requiresOwnBackingStore) 1864 return; 1865 1866 m_requiresOwnBackingStore = requiresOwnBacking; 1867 1868 // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects 1869 // cached clip rects, so when it changes we have to clear clip rects on descendants. 1870 m_owningLayer->clearClipRectsIncludingDescendants(PaintingClipRects); 1871 m_owningLayer->computeRepaintRectsIncludingDescendants(); 1872 1873 compositor()->repaintInCompositedAncestor(m_owningLayer, compositedBounds()); 1874} 1875 1876#if ENABLE(CSS_COMPOSITING) 1877void RenderLayerBacking::setBlendMode(BlendMode) 1878{ 1879} 1880#endif 1881 1882void RenderLayerBacking::setContentsNeedDisplay() 1883{ 1884 ASSERT(!paintsIntoCompositedAncestor()); 1885 1886 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) 1887 m_graphicsLayer->setNeedsDisplay(); 1888 1889 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) 1890 m_foregroundLayer->setNeedsDisplay(); 1891 1892 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) 1893 m_backgroundLayer->setNeedsDisplay(); 1894 1895 if (m_maskLayer && m_maskLayer->drawsContent()) 1896 m_maskLayer->setNeedsDisplay(); 1897 1898 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) 1899 m_scrollingContentsLayer->setNeedsDisplay(); 1900} 1901 1902// r is in the coordinate space of the layer's render object 1903void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) 1904{ 1905 ASSERT(!paintsIntoCompositedAncestor()); 1906 1907 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { 1908 IntRect layerDirtyRect = r; 1909 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer()); 1910 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect); 1911 } 1912 1913 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) { 1914 IntRect layerDirtyRect = r; 1915 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer()); 1916 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect); 1917 } 1918 1919 // FIXME: need to split out repaints for the background. 1920 if (m_backgroundLayer && m_backgroundLayer->drawsContent()) { 1921 IntRect layerDirtyRect = r; 1922 layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer()); 1923 m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect); 1924 } 1925 1926 if (m_maskLayer && m_maskLayer->drawsContent()) { 1927 IntRect layerDirtyRect = r; 1928 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer()); 1929 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect); 1930 } 1931 1932 if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) { 1933 IntRect layerDirtyRect = r; 1934 layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer()); 1935 m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect); 1936 } 1937} 1938 1939void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context, 1940 const IntRect& paintDirtyRect, // In the coords of rootLayer. 1941 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase) 1942{ 1943 if (paintsIntoWindow() || paintsIntoCompositedAncestor()) { 1944 ASSERT_NOT_REACHED(); 1945 return; 1946 } 1947 1948 FontCachePurgePreventer fontCachePurgePreventer; 1949 1950 RenderLayer::PaintLayerFlags paintFlags = 0; 1951 if (paintingPhase & GraphicsLayerPaintBackground) 1952 paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase; 1953 if (paintingPhase & GraphicsLayerPaintForeground) 1954 paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase; 1955 if (paintingPhase & GraphicsLayerPaintMask) 1956 paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase; 1957 if (paintingPhase & GraphicsLayerPaintOverflowContents) 1958 paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents; 1959 if (paintingPhase & GraphicsLayerPaintCompositedScroll) 1960 paintFlags |= RenderLayer::PaintLayerPaintingCompositingScrollingPhase; 1961 1962 if (graphicsLayer == m_backgroundLayer) 1963 paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers. 1964 else if (compositor()->fixedRootBackgroundLayer()) 1965 paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground; 1966 1967 // FIXME: GraphicsLayers need a way to split for RenderRegions. 1968 RenderLayer::LayerPaintingInfo paintingInfo(m_owningLayer, paintDirtyRect, paintBehavior, LayoutSize()); 1969 m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags); 1970 1971 if (m_owningLayer->containsDirtyOverlayScrollbars()) 1972 m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars); 1973 1974 compositor()->didPaintBacking(this); 1975 1976 ASSERT(!m_owningLayer->m_usedTransparency); 1977} 1978 1979static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) 1980{ 1981 if (!scrollbar) 1982 return; 1983 1984 context.save(); 1985 const IntRect& scrollbarRect = scrollbar->frameRect(); 1986 context.translate(-scrollbarRect.x(), -scrollbarRect.y()); 1987 IntRect transformedClip = clip; 1988 transformedClip.moveBy(scrollbarRect.location()); 1989 scrollbar->paint(&context, transformedClip); 1990 context.restore(); 1991} 1992 1993// Up-call from compositing layer drawing callback. 1994void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) 1995{ 1996#ifndef NDEBUG 1997 if (Page* page = renderer()->frame()->page()) 1998 page->setIsPainting(true); 1999#endif 2000 2001 if (graphicsLayer == m_graphicsLayer.get() 2002 || graphicsLayer == m_foregroundLayer.get() 2003 || graphicsLayer == m_backgroundLayer.get() 2004 || graphicsLayer == m_maskLayer.get() 2005 || graphicsLayer == m_scrollingContentsLayer.get()) { 2006 InspectorInstrumentation::willPaint(renderer()); 2007 2008 // The dirtyRect is in the coords of the painting root. 2009 IntRect dirtyRect = clip; 2010 if (!(paintingPhase & GraphicsLayerPaintOverflowContents)) 2011 dirtyRect.intersect(compositedBounds()); 2012 2013 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects. 2014 paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase); 2015 2016 InspectorInstrumentation::didPaint(renderer(), &context, clip); 2017 } else if (graphicsLayer == layerForHorizontalScrollbar()) { 2018 paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip); 2019 } else if (graphicsLayer == layerForVerticalScrollbar()) { 2020 paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip); 2021 } else if (graphicsLayer == layerForScrollCorner()) { 2022 const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect(); 2023 context.save(); 2024 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y()); 2025 IntRect transformedClip = clip; 2026 transformedClip.moveBy(scrollCornerAndResizer.location()); 2027 m_owningLayer->paintScrollCorner(&context, IntPoint(), transformedClip); 2028 m_owningLayer->paintResizer(&context, IntPoint(), transformedClip); 2029 context.restore(); 2030 } 2031#ifndef NDEBUG 2032 if (Page* page = renderer()->frame()->page()) 2033 page->setIsPainting(false); 2034#endif 2035} 2036 2037float RenderLayerBacking::pageScaleFactor() const 2038{ 2039 return compositor()->pageScaleFactor(); 2040} 2041 2042float RenderLayerBacking::deviceScaleFactor() const 2043{ 2044 return compositor()->deviceScaleFactor(); 2045} 2046 2047void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const 2048{ 2049 compositor()->didFlushChangesForLayer(m_owningLayer, layer); 2050} 2051 2052bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const 2053{ 2054 GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get(); 2055 if (graphicsLayer != transformedLayer) 2056 return false; 2057 2058 if (m_owningLayer->hasTransform()) { 2059 transform = m_owningLayer->currentTransform(RenderStyle::ExcludeTransformOrigin); 2060 return true; 2061 } 2062 return false; 2063} 2064 2065bool RenderLayerBacking::isTrackingRepaints() const 2066{ 2067 GraphicsLayerClient* client = compositor(); 2068 return client ? client->isTrackingRepaints() : false; 2069} 2070 2071#ifndef NDEBUG 2072void RenderLayerBacking::verifyNotPainting() 2073{ 2074 ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting()); 2075} 2076#endif 2077 2078bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes) 2079{ 2080 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); 2081 bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform); 2082#if ENABLE(CSS_FILTERS) 2083 bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter); 2084#else 2085 bool hasFilter = false; 2086#endif 2087 2088 if (!hasOpacity && !hasTransform && !hasFilter) 2089 return false; 2090 2091 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 2092 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 2093#if ENABLE(CSS_FILTERS) 2094 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter); 2095#endif 2096 2097 size_t numKeyframes = keyframes.size(); 2098 for (size_t i = 0; i < numKeyframes; ++i) { 2099 const KeyframeValue& currentKeyframe = keyframes[i]; 2100 const RenderStyle* keyframeStyle = currentKeyframe.style(); 2101 float key = currentKeyframe.key(); 2102 2103 if (!keyframeStyle) 2104 continue; 2105 2106 // Get timing function. 2107 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0; 2108 2109 bool isFirstOrLastKeyframe = key == 0 || key == 1; 2110 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform)) 2111 transformVector.insert(TransformAnimationValue::create(key, keyframeStyle->transform(), tf)); 2112 2113 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity)) 2114 opacityVector.insert(FloatAnimationValue::create(key, keyframeStyle->opacity(), tf)); 2115 2116#if ENABLE(CSS_FILTERS) 2117 if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter)) 2118 filterVector.insert(FilterAnimationValue::create(key, keyframeStyle->filter(), tf)); 2119#endif 2120 } 2121 2122 bool didAnimate = false; 2123 2124 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) 2125 didAnimate = true; 2126 2127 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) 2128 didAnimate = true; 2129 2130#if ENABLE(CSS_FILTERS) 2131 if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset)) 2132 didAnimate = true; 2133#endif 2134 2135 return didAnimate; 2136} 2137 2138void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName) 2139{ 2140 m_graphicsLayer->pauseAnimation(animationName, timeOffset); 2141} 2142 2143void RenderLayerBacking::animationFinished(const String& animationName) 2144{ 2145 m_graphicsLayer->removeAnimation(animationName); 2146} 2147 2148bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle) 2149{ 2150 bool didAnimate = false; 2151 2152 ASSERT(property != CSSPropertyInvalid); 2153 2154 if (property == CSSPropertyOpacity) { 2155 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity); 2156 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) { 2157 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 2158 opacityVector.insert(FloatAnimationValue::create(0, compositingOpacity(fromStyle->opacity()))); 2159 opacityVector.insert(FloatAnimationValue::create(1, compositingOpacity(toStyle->opacity()))); 2160 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. 2161 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { 2162 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. 2163 updateOpacity(toStyle); 2164 didAnimate = true; 2165 } 2166 } 2167 } 2168 2169 if (property == CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) { 2170 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform); 2171 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) { 2172 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 2173 transformVector.insert(TransformAnimationValue::create(0, fromStyle->transform())); 2174 transformVector.insert(TransformAnimationValue::create(1, toStyle->transform())); 2175 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { 2176 // To ensure that the correct transform is visible when the animation ends, also set the final transform. 2177 updateTransform(toStyle); 2178 didAnimate = true; 2179 } 2180 } 2181 } 2182 2183#if ENABLE(CSS_FILTERS) 2184 if (property == CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) { 2185 const Animation* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter); 2186 if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) { 2187 KeyframeValueList filterVector(AnimatedPropertyWebkitFilter); 2188 filterVector.insert(FilterAnimationValue::create(0, fromStyle->filter())); 2189 filterVector.insert(FilterAnimationValue::create(1, toStyle->filter())); 2190 if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) { 2191 // To ensure that the correct filter is visible when the animation ends, also set the final filter. 2192 updateFilters(toStyle); 2193 didAnimate = true; 2194 } 2195 } 2196 } 2197#endif 2198 2199 return didAnimate; 2200} 2201 2202void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property) 2203{ 2204 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 2205 if (animatedProperty != AnimatedPropertyInvalid) 2206 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset); 2207} 2208 2209void RenderLayerBacking::transitionFinished(CSSPropertyID property) 2210{ 2211 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 2212 if (animatedProperty != AnimatedPropertyInvalid) 2213 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty)); 2214} 2215 2216void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time) 2217{ 2218 renderer()->animation()->notifyAnimationStarted(renderer(), time); 2219} 2220 2221void RenderLayerBacking::notifyFlushRequired(const GraphicsLayer* layer) 2222{ 2223 if (renderer()->documentBeingDestroyed()) 2224 return; 2225 compositor()->scheduleLayerFlush(layer->canThrottleLayerFlush()); 2226} 2227 2228void RenderLayerBacking::notifyFlushBeforeDisplayRefresh(const GraphicsLayer* layer) 2229{ 2230 compositor()->notifyFlushBeforeDisplayRefresh(layer); 2231} 2232 2233// This is used for the 'freeze' API, for testing only. 2234void RenderLayerBacking::suspendAnimations(double time) 2235{ 2236 m_graphicsLayer->suspendAnimations(time); 2237} 2238 2239void RenderLayerBacking::resumeAnimations() 2240{ 2241 m_graphicsLayer->resumeAnimations(); 2242} 2243 2244IntRect RenderLayerBacking::compositedBounds() const 2245{ 2246 return m_compositedBounds; 2247} 2248 2249void RenderLayerBacking::setCompositedBounds(const IntRect& bounds) 2250{ 2251 m_compositedBounds = bounds; 2252} 2253 2254CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property) 2255{ 2256 CSSPropertyID cssProperty = CSSPropertyInvalid; 2257 switch (property) { 2258 case AnimatedPropertyWebkitTransform: 2259 cssProperty = CSSPropertyWebkitTransform; 2260 break; 2261 case AnimatedPropertyOpacity: 2262 cssProperty = CSSPropertyOpacity; 2263 break; 2264 case AnimatedPropertyBackgroundColor: 2265 cssProperty = CSSPropertyBackgroundColor; 2266 break; 2267 case AnimatedPropertyWebkitFilter: 2268#if ENABLE(CSS_FILTERS) 2269 cssProperty = CSSPropertyWebkitFilter; 2270#else 2271 ASSERT_NOT_REACHED(); 2272#endif 2273 break; 2274 case AnimatedPropertyInvalid: 2275 ASSERT_NOT_REACHED(); 2276 } 2277 return cssProperty; 2278} 2279 2280AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty) 2281{ 2282 switch (cssProperty) { 2283 case CSSPropertyWebkitTransform: 2284 return AnimatedPropertyWebkitTransform; 2285 case CSSPropertyOpacity: 2286 return AnimatedPropertyOpacity; 2287 case CSSPropertyBackgroundColor: 2288 return AnimatedPropertyBackgroundColor; 2289#if ENABLE(CSS_FILTERS) 2290 case CSSPropertyWebkitFilter: 2291 return AnimatedPropertyWebkitFilter; 2292#endif 2293 default: 2294 // It's fine if we see other css properties here; they are just not accelerated. 2295 break; 2296 } 2297 return AnimatedPropertyInvalid; 2298} 2299 2300CompositingLayerType RenderLayerBacking::compositingLayerType() const 2301{ 2302 if (m_graphicsLayer->hasContentsLayer()) 2303 return MediaCompositingLayer; 2304 2305 if (m_graphicsLayer->drawsContent()) 2306 return m_graphicsLayer->usingTiledBacking() ? TiledCompositingLayer : NormalCompositingLayer; 2307 2308 return ContainerCompositingLayer; 2309} 2310 2311double RenderLayerBacking::backingStoreMemoryEstimate() const 2312{ 2313 double backingMemory; 2314 2315 // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing. 2316 backingMemory = m_graphicsLayer->backingStoreMemoryEstimate(); 2317 if (m_foregroundLayer) 2318 backingMemory += m_foregroundLayer->backingStoreMemoryEstimate(); 2319 if (m_backgroundLayer) 2320 backingMemory += m_backgroundLayer->backingStoreMemoryEstimate(); 2321 if (m_maskLayer) 2322 backingMemory += m_maskLayer->backingStoreMemoryEstimate(); 2323 2324 if (m_scrollingContentsLayer) 2325 backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate(); 2326 2327 if (m_layerForHorizontalScrollbar) 2328 backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate(); 2329 2330 if (m_layerForVerticalScrollbar) 2331 backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate(); 2332 2333 if (m_layerForScrollCorner) 2334 backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate(); 2335 2336 return backingMemory; 2337} 2338 2339} // namespace WebCore 2340 2341#endif // USE(ACCELERATED_COMPOSITING) 2342