1 /* 2 * Copyright (C) 2009 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 "CanvasRenderingContext2D.h" 35 #include "CSSPropertyNames.h" 36 #include "CSSStyleSelector.h" 37 #include "FrameView.h" 38 #include "GraphicsContext.h" 39 #include "GraphicsLayer.h" 40 #include "HTMLCanvasElement.h" 41 #include "HTMLElement.h" 42 #include "HTMLIFrameElement.h" 43 #include "HTMLMediaElement.h" 44 #include "HTMLNames.h" 45 #include "InspectorInstrumentation.h" 46 #include "KeyframeList.h" 47 #include "PluginViewBase.h" 48 #include "RenderApplet.h" 49 #include "RenderBox.h" 50 #include "RenderIFrame.h" 51 #include "RenderImage.h" 52 #include "RenderLayerCompositor.h" 53 #include "RenderEmbeddedObject.h" 54 #include "RenderVideo.h" 55 #include "RenderView.h" 56 #include "Settings.h" 57 58 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 59 #include "GraphicsContext3D.h" 60 #endif 61 62 using namespace std; 63 64 namespace WebCore { 65 66 using namespace HTMLNames; 67 68 static bool hasBorderOutlineOrShadow(const RenderStyle*); 69 static bool hasBoxDecorationsOrBackground(const RenderObject*); 70 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*); 71 static IntRect clipBox(RenderBox* renderer); 72 73 static inline bool isAcceleratedCanvas(RenderObject* renderer) 74 { 75 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 76 if (renderer->isCanvas()) { 77 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); 78 if (CanvasRenderingContext* context = canvas->renderingContext()) 79 return context->isAccelerated(); 80 } 81 #else 82 UNUSED_PARAM(renderer); 83 #endif 84 return false; 85 } 86 87 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) 88 : m_owningLayer(layer) 89 , m_artificiallyInflatedBounds(false) 90 { 91 createGraphicsLayer(); 92 } 93 94 RenderLayerBacking::~RenderLayerBacking() 95 { 96 updateClippingLayers(false, false); 97 updateOverflowControlsLayers(false, false, false); 98 updateForegroundLayer(false); 99 updateMaskLayer(false); 100 destroyGraphicsLayer(); 101 } 102 103 void RenderLayerBacking::createGraphicsLayer() 104 { 105 m_graphicsLayer = GraphicsLayer::create(this); 106 107 #ifndef NDEBUG 108 m_graphicsLayer->setName(nameForLayer()); 109 #endif // NDEBUG 110 111 #if USE(ACCELERATED_COMPOSITING) 112 ASSERT(renderer() && renderer()->document() && renderer()->document()->frame()); 113 if (Frame* frame = renderer()->document()->frame()) 114 m_graphicsLayer->setContentsScale(frame->pageScaleFactor()); 115 #endif 116 117 updateLayerOpacity(renderer()->style()); 118 updateLayerTransform(renderer()->style()); 119 } 120 121 void RenderLayerBacking::destroyGraphicsLayer() 122 { 123 if (m_graphicsLayer) 124 m_graphicsLayer->removeFromParent(); 125 126 m_graphicsLayer = 0; 127 m_foregroundLayer = 0; 128 m_clippingLayer = 0; 129 m_maskLayer = 0; 130 } 131 132 void RenderLayerBacking::updateLayerOpacity(const RenderStyle* style) 133 { 134 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity())); 135 } 136 137 void RenderLayerBacking::updateLayerTransform(const RenderStyle* style) 138 { 139 // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin 140 // baked into it, and we don't want that. 141 TransformationMatrix t; 142 if (m_owningLayer->hasTransform()) { 143 style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); 144 makeMatrixRenderable(t, compositor()->canRender3DTransforms()); 145 } 146 147 m_graphicsLayer->setTransform(t); 148 } 149 150 static bool hasNonZeroTransformOrigin(const RenderObject* renderer) 151 { 152 RenderStyle* style = renderer->style(); 153 return (style->transformOriginX().type() == Fixed && style->transformOriginX().value()) 154 || (style->transformOriginY().type() == Fixed && style->transformOriginY().value()); 155 } 156 157 static bool layerOrAncestorIsTransformed(RenderLayer* layer) 158 { 159 for (RenderLayer* curr = layer; curr; curr = curr->parent()) { 160 if (curr->hasTransform()) 161 return true; 162 } 163 164 return false; 165 } 166 167 #if ENABLE(FULLSCREEN_API) 168 static bool layerOrAncestorIsFullScreen(RenderLayer* layer) 169 { 170 // Don't traverse through the render layer tree if we do not yet have a full screen renderer. 171 if (!layer->renderer()->document()->fullScreenRenderer()) 172 return false; 173 174 for (RenderLayer* curr = layer; curr; curr = curr->parent()) { 175 if (curr->renderer()->isRenderFullScreen()) 176 return true; 177 } 178 179 return false; 180 } 181 #endif 182 183 void RenderLayerBacking::updateCompositedBounds() 184 { 185 IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); 186 187 // Clip to the size of the document or enclosing overflow-scroll layer. 188 // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with. 189 // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist. If this 190 // is a fullscreen renderer, don't clip to the viewport, as the renderer will be asked to 191 // display outside of the viewport bounds. 192 if (compositor()->compositingConsultsOverlap() && !layerOrAncestorIsTransformed(m_owningLayer) 193 #if ENABLE(FULLSCREEN_API) 194 && !layerOrAncestorIsFullScreen(m_owningLayer) 195 #endif 196 ) { 197 RenderView* view = m_owningLayer->renderer()->view(); 198 RenderLayer* rootLayer = view->layer(); 199 200 // Start by clipping to the view's bounds. 201 IntRect clippingBounds = view->layoutOverflowRect(); 202 203 if (m_owningLayer != rootLayer) 204 clippingBounds.intersect(m_owningLayer->backgroundClipRect(rootLayer, true)); 205 206 int deltaX = 0; 207 int deltaY = 0; 208 m_owningLayer->convertToLayerCoords(rootLayer, deltaX, deltaY); 209 clippingBounds.move(-deltaX, -deltaY); 210 211 layerBounds.intersect(clippingBounds); 212 } 213 214 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size, 215 // then we need to ensure that the compositing layer has non-zero size so that we can apply 216 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value). 217 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) { 218 layerBounds.setWidth(1); 219 layerBounds.setHeight(1); 220 m_artificiallyInflatedBounds = true; 221 } else 222 m_artificiallyInflatedBounds = false; 223 224 setCompositedBounds(layerBounds); 225 } 226 227 void RenderLayerBacking::updateAfterWidgetResize() 228 { 229 if (renderer()->isRenderPart()) { 230 if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) { 231 innerCompositor->frameViewDidChangeSize(); 232 innerCompositor->frameViewDidChangeLocation(contentsBox().location()); 233 } 234 } 235 } 236 237 void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth, bool isUpdateRoot) 238 { 239 RenderLayerCompositor* layerCompositor = compositor(); 240 if (!layerCompositor->compositingLayersNeedRebuild()) { 241 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the 242 // position of this layer's GraphicsLayer depends on the position of our compositing 243 // ancestor's GraphicsLayer. That cannot be determined until all the descendant 244 // RenderLayers of that ancestor have been processed via updateLayerPositions(). 245 // 246 // The solution is to update compositing children of this layer here, 247 // via updateCompositingChildrenGeometry(). 248 updateCompositedBounds(); 249 layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth); 250 251 if (isUpdateRoot) { 252 updateGraphicsLayerGeometry(); 253 layerCompositor->updateRootLayerPosition(); 254 } 255 } 256 } 257 258 bool RenderLayerBacking::updateGraphicsLayerConfiguration() 259 { 260 RenderLayerCompositor* compositor = this->compositor(); 261 RenderObject* renderer = this->renderer(); 262 263 bool layerConfigChanged = false; 264 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer))) 265 layerConfigChanged = true; 266 267 if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer))) 268 layerConfigChanged = true; 269 270 if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer())) 271 layerConfigChanged = true; 272 273 if (layerConfigChanged) 274 updateInternalHierarchy(); 275 276 if (updateMaskLayer(renderer->hasMask())) 277 m_graphicsLayer->setMaskLayer(m_maskLayer.get()); 278 279 if (m_owningLayer->hasReflection()) { 280 if (m_owningLayer->reflectionLayer()->backing()) { 281 GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer(); 282 m_graphicsLayer->setReplicatedByLayer(reflectionLayer); 283 } 284 } else 285 m_graphicsLayer->setReplicatedByLayer(0); 286 287 if (isDirectlyCompositedImage()) 288 updateImageContents(); 289 290 if ((renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) 291 || (renderer->isApplet() && toRenderApplet(renderer)->allowsAcceleratedCompositing())) { 292 PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(toRenderWidget(renderer)->widget()); 293 m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer()); 294 } 295 #if ENABLE(VIDEO) 296 else if (renderer->isVideo()) { 297 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer->node()); 298 m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer()); 299 } 300 #endif 301 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 302 else if (isAcceleratedCanvas(renderer)) { 303 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node()); 304 if (CanvasRenderingContext* context = canvas->renderingContext()) 305 m_graphicsLayer->setContentsToCanvas(context->platformLayer()); 306 layerConfigChanged = true; 307 } 308 #endif 309 310 if (renderer->isRenderPart()) 311 layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer)); 312 313 return layerConfigChanged; 314 } 315 316 static IntRect clipBox(RenderBox* renderer) 317 { 318 IntRect result = PaintInfo::infiniteRect(); 319 if (renderer->hasOverflowClip()) 320 result = renderer->overflowClipRect(0, 0); 321 322 if (renderer->hasClip()) 323 result.intersect(renderer->clipRect(0, 0)); 324 325 return result; 326 } 327 328 void RenderLayerBacking::updateGraphicsLayerGeometry() 329 { 330 // If we haven't built z-order lists yet, wait until later. 331 if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty) 332 return; 333 334 // Set transform property, if it is not animating. We have to do this here because the transform 335 // is affected by the layer dimensions. 336 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform)) 337 updateLayerTransform(renderer()->style()); 338 339 // Set opacity, if it is not animating. 340 if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity)) 341 updateLayerOpacity(renderer()->style()); 342 343 RenderStyle* style = renderer()->style(); 344 m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection()); 345 m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible); 346 347 RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer(); 348 349 // We compute everything relative to the enclosing compositing layer. 350 IntRect ancestorCompositingBounds; 351 if (compAncestor) { 352 ASSERT(compAncestor->backing()); 353 ancestorCompositingBounds = compAncestor->backing()->compositedBounds(); 354 } 355 356 IntRect localCompositingBounds = compositedBounds(); 357 358 IntRect relativeCompositingBounds(localCompositingBounds); 359 int deltaX = 0, deltaY = 0; 360 m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY); 361 relativeCompositingBounds.move(deltaX, deltaY); 362 363 IntPoint graphicsLayerParentLocation; 364 if (compAncestor && compAncestor->backing()->hasClippingLayer()) { 365 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore 366 // position relative to it. 367 IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer())); 368 graphicsLayerParentLocation = clippingBox.location(); 369 } else 370 graphicsLayerParentLocation = ancestorCompositingBounds.location(); 371 372 if (compAncestor && m_ancestorClippingLayer) { 373 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this 374 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects 375 // for a compositing layer, rootLayer is the layer itself. 376 IntRect parentClipRect = m_owningLayer->backgroundClipRect(compAncestor, true); 377 ASSERT(parentClipRect != PaintInfo::infiniteRect()); 378 m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation)); 379 m_ancestorClippingLayer->setSize(parentClipRect.size()); 380 381 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. 382 IntSize rendererOffset(parentClipRect.location().x() - deltaX, parentClipRect.location().y() - deltaY); 383 m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset); 384 385 // The primary layer is then parented in, and positioned relative to this clipping layer. 386 graphicsLayerParentLocation = parentClipRect.location(); 387 } 388 389 m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation)); 390 391 IntSize oldOffsetFromRenderer = m_graphicsLayer->offsetFromRenderer(); 392 m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint()); 393 394 // If the compositing layer offset changes, we need to repaint. 395 if (oldOffsetFromRenderer != m_graphicsLayer->offsetFromRenderer()) 396 m_graphicsLayer->setNeedsDisplay(); 397 398 FloatSize oldSize = m_graphicsLayer->size(); 399 FloatSize newSize = relativeCompositingBounds.size(); 400 if (oldSize != newSize) { 401 m_graphicsLayer->setSize(newSize); 402 // A bounds change will almost always require redisplay. Usually that redisplay 403 // will happen because of a repaint elsewhere, but not always: 404 // e.g. see RenderView::setMaximalOutlineSize() 405 m_graphicsLayer->setNeedsDisplay(); 406 } 407 408 // If we have a layer that clips children, position it. 409 IntRect clippingBox; 410 if (m_clippingLayer) { 411 clippingBox = clipBox(toRenderBox(renderer())); 412 m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location())); 413 m_clippingLayer->setSize(clippingBox.size()); 414 m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint()); 415 } 416 417 if (m_maskLayer) { 418 if (m_maskLayer->size() != m_graphicsLayer->size()) { 419 m_maskLayer->setSize(m_graphicsLayer->size()); 420 m_maskLayer->setNeedsDisplay(); 421 } 422 m_maskLayer->setPosition(FloatPoint()); 423 } 424 425 if (m_owningLayer->hasTransform()) { 426 const IntRect borderBox = toRenderBox(renderer())->borderBoxRect(); 427 428 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds. 429 IntRect layerBounds = IntRect(deltaX, deltaY, borderBox.width(), borderBox.height()); 430 431 // Update properties that depend on layer dimensions 432 FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); 433 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set. 434 FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f, 435 relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f, 436 transformOrigin.z()); 437 m_graphicsLayer->setAnchorPoint(anchor); 438 439 RenderStyle* style = renderer()->style(); 440 if (style->hasPerspective()) { 441 TransformationMatrix t = owningLayer()->perspectiveTransform(); 442 443 if (m_clippingLayer) { 444 m_clippingLayer->setChildrenTransform(t); 445 m_graphicsLayer->setChildrenTransform(TransformationMatrix()); 446 } 447 else 448 m_graphicsLayer->setChildrenTransform(t); 449 } else { 450 if (m_clippingLayer) 451 m_clippingLayer->setChildrenTransform(TransformationMatrix()); 452 else 453 m_graphicsLayer->setChildrenTransform(TransformationMatrix()); 454 } 455 } else { 456 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); 457 } 458 459 if (m_foregroundLayer) { 460 FloatPoint foregroundPosition; 461 FloatSize foregroundSize = newSize; 462 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); 463 if (m_clippingLayer) { 464 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it, 465 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer. 466 foregroundSize = FloatSize(clippingBox.size()); 467 foregroundOffset = clippingBox.location() - IntPoint(); 468 } 469 470 m_foregroundLayer->setPosition(foregroundPosition); 471 m_foregroundLayer->setSize(foregroundSize); 472 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset); 473 } 474 475 if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) { 476 RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing(); 477 reflectionBacking->updateGraphicsLayerGeometry(); 478 479 // The reflection layer has the bounds of m_owningLayer->reflectionLayer(), 480 // but the reflected layer is the bounds of this layer, so we need to position it appropriately. 481 FloatRect layerBounds = compositedBounds(); 482 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds(); 483 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location())); 484 } 485 486 m_graphicsLayer->setContentsRect(contentsBox()); 487 updateDrawsContent(); 488 updateAfterWidgetResize(); 489 } 490 491 void RenderLayerBacking::updateInternalHierarchy() 492 { 493 // m_foregroundLayer has to be inserted in the correct order with child layers, 494 // so it's not inserted here. 495 if (m_ancestorClippingLayer) { 496 m_ancestorClippingLayer->removeAllChildren(); 497 m_graphicsLayer->removeFromParent(); 498 m_ancestorClippingLayer->addChild(m_graphicsLayer.get()); 499 } 500 501 if (m_clippingLayer) { 502 m_clippingLayer->removeFromParent(); 503 m_graphicsLayer->addChild(m_clippingLayer.get()); 504 505 // The clip for child layers does not include space for overflow controls, so they exist as 506 // siblings of the clipping layer if we have one. Normal children of this layer are set as 507 // children of the clipping layer. 508 if (m_layerForHorizontalScrollbar) { 509 m_layerForHorizontalScrollbar->removeFromParent(); 510 m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get()); 511 } 512 if (m_layerForVerticalScrollbar) { 513 m_layerForVerticalScrollbar->removeFromParent(); 514 m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get()); 515 } 516 if (m_layerForScrollCorner) { 517 m_layerForScrollCorner->removeFromParent(); 518 m_graphicsLayer->addChild(m_layerForScrollCorner.get()); 519 } 520 } 521 } 522 523 void RenderLayerBacking::updateDrawsContent() 524 { 525 m_graphicsLayer->setDrawsContent(containsPaintedContent()); 526 } 527 528 // Return true if the layers changed. 529 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip) 530 { 531 bool layersChanged = false; 532 533 if (needsAncestorClip) { 534 if (!m_ancestorClippingLayer) { 535 m_ancestorClippingLayer = GraphicsLayer::create(this); 536 #ifndef NDEBUG 537 m_ancestorClippingLayer->setName("Ancestor clipping Layer"); 538 #endif 539 m_ancestorClippingLayer->setMasksToBounds(true); 540 layersChanged = true; 541 } 542 } else if (m_ancestorClippingLayer) { 543 m_ancestorClippingLayer->removeFromParent(); 544 m_ancestorClippingLayer = 0; 545 layersChanged = true; 546 } 547 548 if (needsDescendantClip) { 549 if (!m_clippingLayer) { 550 m_clippingLayer = GraphicsLayer::create(this); 551 #ifndef NDEBUG 552 m_clippingLayer->setName("Child clipping Layer"); 553 #endif 554 m_clippingLayer->setMasksToBounds(true); 555 layersChanged = true; 556 } 557 } else if (m_clippingLayer) { 558 m_clippingLayer->removeFromParent(); 559 m_clippingLayer = 0; 560 layersChanged = true; 561 } 562 563 return layersChanged; 564 } 565 566 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const 567 { 568 #if !PLATFORM(CHROMIUM) 569 if (!m_owningLayer->hasOverlayScrollbars()) 570 return false; 571 #endif 572 return m_owningLayer->horizontalScrollbar(); 573 } 574 575 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const 576 { 577 #if !PLATFORM(CHROMIUM) 578 if (!m_owningLayer->hasOverlayScrollbars()) 579 return false; 580 #endif 581 return m_owningLayer->verticalScrollbar(); 582 } 583 584 bool RenderLayerBacking::requiresScrollCornerLayer() const 585 { 586 #if !PLATFORM(CHROMIUM) 587 if (!m_owningLayer->hasOverlayScrollbars()) 588 return false; 589 #endif 590 return !m_owningLayer->scrollCornerAndResizerRect().isEmpty(); 591 } 592 593 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer) 594 { 595 bool layersChanged = false; 596 if (needsHorizontalScrollbarLayer) { 597 if (!m_layerForHorizontalScrollbar) { 598 m_layerForHorizontalScrollbar = GraphicsLayer::create(this); 599 #ifndef NDEBUG 600 m_layerForHorizontalScrollbar ->setName("horizontal scrollbar"); 601 #endif 602 layersChanged = true; 603 } 604 } else if (m_layerForHorizontalScrollbar) { 605 m_layerForHorizontalScrollbar.clear(); 606 layersChanged = true; 607 } 608 609 if (needsVerticalScrollbarLayer) { 610 if (!m_layerForVerticalScrollbar) { 611 m_layerForVerticalScrollbar = GraphicsLayer::create(this); 612 #ifndef NDEBUG 613 m_layerForVerticalScrollbar->setName("vertical scrollbar"); 614 #endif 615 layersChanged = true; 616 } 617 } else if (m_layerForVerticalScrollbar) { 618 m_layerForVerticalScrollbar.clear(); 619 layersChanged = true; 620 } 621 622 if (needsScrollCornerLayer) { 623 if (!m_layerForScrollCorner) { 624 m_layerForScrollCorner = GraphicsLayer::create(this); 625 #ifndef NDEBUG 626 m_layerForScrollCorner->setName("scroll corner"); 627 #endif 628 layersChanged = true; 629 } 630 } else if (m_layerForScrollCorner) { 631 m_layerForScrollCorner.clear(); 632 layersChanged = true; 633 } 634 635 return layersChanged; 636 } 637 638 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer) 639 { 640 bool layerChanged = false; 641 if (needsForegroundLayer) { 642 if (!m_foregroundLayer) { 643 m_foregroundLayer = GraphicsLayer::create(this); 644 #ifndef NDEBUG 645 m_foregroundLayer->setName(nameForLayer() + " (foreground)"); 646 #endif 647 m_foregroundLayer->setDrawsContent(true); 648 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground); 649 if (Frame* frame = renderer()->document()->frame()) 650 m_foregroundLayer->setContentsScale(frame->pageScaleFactor()); 651 layerChanged = true; 652 } 653 } else if (m_foregroundLayer) { 654 m_foregroundLayer->removeFromParent(); 655 m_foregroundLayer = 0; 656 layerChanged = true; 657 } 658 659 if (layerChanged) 660 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 661 662 return layerChanged; 663 } 664 665 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer) 666 { 667 bool layerChanged = false; 668 if (needsMaskLayer) { 669 if (!m_maskLayer) { 670 m_maskLayer = GraphicsLayer::create(this); 671 #ifndef NDEBUG 672 m_maskLayer->setName("Mask"); 673 #endif 674 m_maskLayer->setDrawsContent(true); 675 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask); 676 if (Frame* frame = renderer()->document()->frame()) 677 m_maskLayer->setContentsScale(frame->pageScaleFactor()); 678 layerChanged = true; 679 } 680 } else if (m_maskLayer) { 681 m_maskLayer = 0; 682 layerChanged = true; 683 } 684 685 if (layerChanged) 686 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 687 688 return layerChanged; 689 } 690 691 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const 692 { 693 unsigned phase = GraphicsLayerPaintBackground; 694 if (!m_foregroundLayer) 695 phase |= GraphicsLayerPaintForeground; 696 if (!m_maskLayer) 697 phase |= GraphicsLayerPaintMask; 698 699 return static_cast<GraphicsLayerPaintingPhase>(phase); 700 } 701 702 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const 703 { 704 float finalOpacity = rendererOpacity; 705 706 for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) { 707 // We only care about parents that are stacking contexts. 708 // Recall that opacity creates stacking context. 709 if (!curr->isStackingContext()) 710 continue; 711 712 // If we found a compositing layer, we want to compute opacity 713 // relative to it. So we can break here. 714 if (curr->isComposited()) 715 break; 716 717 finalOpacity *= curr->renderer()->opacity(); 718 } 719 720 return finalOpacity; 721 } 722 723 static bool hasBorderOutlineOrShadow(const RenderStyle* style) 724 { 725 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow(); 726 } 727 728 static bool hasBoxDecorationsOrBackground(const RenderObject* renderer) 729 { 730 return hasBorderOutlineOrShadow(renderer->style()) || renderer->hasBackground(); 731 } 732 733 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style) 734 { 735 return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage(); 736 } 737 738 bool RenderLayerBacking::rendererHasBackground() const 739 { 740 // FIXME: share more code here 741 if (renderer()->node() && renderer()->node()->isDocumentNode()) { 742 RenderObject* htmlObject = renderer()->firstChild(); 743 if (!htmlObject) 744 return false; 745 746 if (htmlObject->hasBackground()) 747 return true; 748 749 RenderObject* bodyObject = htmlObject->firstChild(); 750 if (!bodyObject) 751 return false; 752 753 return bodyObject->hasBackground(); 754 } 755 756 return renderer()->hasBackground(); 757 } 758 759 const Color RenderLayerBacking::rendererBackgroundColor() const 760 { 761 // FIXME: share more code here 762 if (renderer()->node() && renderer()->node()->isDocumentNode()) { 763 RenderObject* htmlObject = renderer()->firstChild(); 764 if (htmlObject->hasBackground()) 765 return htmlObject->style()->visitedDependentColor(CSSPropertyBackgroundColor); 766 767 RenderObject* bodyObject = htmlObject->firstChild(); 768 return bodyObject->style()->visitedDependentColor(CSSPropertyBackgroundColor); 769 } 770 771 return renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor); 772 } 773 774 // A "simple container layer" is a RenderLayer which has no visible content to render. 775 // It may have no children, or all its children may be themselves composited. 776 // This is a useful optimization, because it allows us to avoid allocating backing store. 777 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const 778 { 779 RenderObject* renderObject = renderer(); 780 if (renderObject->isReplaced() || // replaced objects are not containers 781 renderObject->hasMask()) // masks require special treatment 782 return false; 783 784 RenderStyle* style = renderObject->style(); 785 786 // Reject anything that has a border, a border-radius or outline, 787 // or any background (color or image). 788 // FIXME: we could optimize layers for simple backgrounds. 789 if (hasBoxDecorationsOrBackground(renderObject)) 790 return false; 791 792 if (m_owningLayer->hasOverflowControls()) 793 return false; 794 795 // If we have got this far and the renderer has no children, then we're ok. 796 if (!renderObject->firstChild()) 797 return true; 798 799 if (renderObject->node() && renderObject->node()->isDocumentNode()) { 800 // Look to see if the root object has a non-simple backgound 801 RenderObject* rootObject = renderObject->document()->documentElement()->renderer(); 802 if (!rootObject) 803 return false; 804 805 style = rootObject->style(); 806 807 // Reject anything that has a border, a border-radius or outline, 808 // or is not a simple background (no background, or solid color). 809 if (hasBoxDecorationsOrBackgroundImage(style)) 810 return false; 811 812 // Now look at the body's renderer. 813 HTMLElement* body = renderObject->document()->body(); 814 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; 815 if (!bodyObject) 816 return false; 817 818 style = bodyObject->style(); 819 820 if (hasBoxDecorationsOrBackgroundImage(style)) 821 return false; 822 823 // Check to see if all the body's children are compositing layers. 824 if (hasNonCompositingDescendants()) 825 return false; 826 827 return true; 828 } 829 830 // Check to see if all the renderer's children are compositing layers. 831 if (hasNonCompositingDescendants()) 832 return false; 833 834 return true; 835 } 836 837 // Conservative test for having no rendered children. 838 bool RenderLayerBacking::hasNonCompositingDescendants() const 839 { 840 // Some HTML can cause whitespace text nodes to have renderers, like: 841 // <div> 842 // <img src=...> 843 // </div> 844 // so test for 0x0 RenderTexts here 845 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) { 846 if (!child->hasLayer()) { 847 if (child->isRenderInline() || !child->isBox()) 848 return true; 849 850 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0) 851 return true; 852 } 853 } 854 855 if (m_owningLayer->isStackingContext()) { 856 // Use the m_hasCompositingDescendant bit to optimize? 857 if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) { 858 size_t listSize = negZOrderList->size(); 859 for (size_t i = 0; i < listSize; ++i) { 860 RenderLayer* curLayer = negZOrderList->at(i); 861 if (!curLayer->isComposited()) 862 return true; 863 } 864 } 865 866 if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) { 867 size_t listSize = posZOrderList->size(); 868 for (size_t i = 0; i < listSize; ++i) { 869 RenderLayer* curLayer = posZOrderList->at(i); 870 if (!curLayer->isComposited()) 871 return true; 872 } 873 } 874 } 875 876 if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) { 877 size_t listSize = normalFlowList->size(); 878 for (size_t i = 0; i < listSize; ++i) { 879 RenderLayer* curLayer = normalFlowList->at(i); 880 if (!curLayer->isComposited()) 881 return true; 882 } 883 } 884 885 return false; 886 } 887 888 bool RenderLayerBacking::containsPaintedContent() const 889 { 890 if (isSimpleContainerCompositingLayer() || paintingGoesToWindow() || m_artificiallyInflatedBounds || m_owningLayer->isReflection()) 891 return false; 892 893 if (isDirectlyCompositedImage()) 894 return false; 895 896 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely, 897 // and set background color on the layer in that case, instead of allocating backing store and painting. 898 #if ENABLE(VIDEO) 899 if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo()) 900 return hasBoxDecorationsOrBackground(renderer()); 901 #endif 902 #if PLATFORM(MAC) && USE(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) 903 #elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 904 if (isAcceleratedCanvas(renderer())) 905 return hasBoxDecorationsOrBackground(renderer()); 906 #endif 907 908 return true; 909 } 910 911 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations 912 // that require painting. Direct compositing saves backing store. 913 bool RenderLayerBacking::isDirectlyCompositedImage() const 914 { 915 RenderObject* renderObject = renderer(); 916 917 if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip()) 918 return false; 919 920 RenderImage* imageRenderer = toRenderImage(renderObject); 921 if (CachedImage* cachedImage = imageRenderer->cachedImage()) { 922 if (cachedImage->hasImage()) 923 return cachedImage->image()->isBitmapImage(); 924 } 925 926 return false; 927 } 928 929 void RenderLayerBacking::contentChanged(RenderLayer::ContentChangeType changeType) 930 { 931 if ((changeType == RenderLayer::ImageChanged) && isDirectlyCompositedImage()) { 932 updateImageContents(); 933 return; 934 } 935 936 if ((changeType == RenderLayer::MaskImageChanged) && m_maskLayer) { 937 // The composited layer bounds relies on box->maskClipRect(), which changes 938 // when the mask image becomes available. 939 bool isUpdateRoot = true; 940 updateAfterLayout(CompositingChildren, isUpdateRoot); 941 } 942 943 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS) 944 if ((changeType == RenderLayer::CanvasChanged) && isAcceleratedCanvas(renderer())) { 945 m_graphicsLayer->setContentsNeedsDisplay(); 946 return; 947 } 948 #endif 949 } 950 951 void RenderLayerBacking::updateImageContents() 952 { 953 ASSERT(renderer()->isImage()); 954 RenderImage* imageRenderer = toRenderImage(renderer()); 955 956 CachedImage* cachedImage = imageRenderer->cachedImage(); 957 if (!cachedImage) 958 return; 959 960 Image* image = cachedImage->image(); 961 if (!image) 962 return; 963 964 // We have to wait until the image is fully loaded before setting it on the layer. 965 if (!cachedImage->isLoaded()) 966 return; 967 968 // This is a no-op if the layer doesn't have an inner layer for the image. 969 m_graphicsLayer->setContentsToImage(image); 970 971 // Image animation is "lazy", in that it automatically stops unless someone is drawing 972 // the image. So we have to kick the animation each time; this has the downside that the 973 // image will keep animating, even if its layer is not visible. 974 image->startAnimation(); 975 } 976 977 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const 978 { 979 RenderStyle* style = renderer()->style(); 980 981 FloatPoint3D origin; 982 origin.setX(style->transformOriginX().calcFloatValue(borderBox.width())); 983 origin.setY(style->transformOriginY().calcFloatValue(borderBox.height())); 984 origin.setZ(style->transformOriginZ()); 985 986 return origin; 987 } 988 989 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const 990 { 991 RenderStyle* style = renderer()->style(); 992 993 float boxWidth = borderBox.width(); 994 float boxHeight = borderBox.height(); 995 996 FloatPoint origin; 997 origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth)); 998 origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight)); 999 1000 return origin; 1001 } 1002 1003 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted. 1004 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const 1005 { 1006 return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y()); 1007 } 1008 1009 IntRect RenderLayerBacking::contentsBox() const 1010 { 1011 if (!renderer()->isBox()) 1012 return IntRect(); 1013 1014 IntRect contentsRect; 1015 #if ENABLE(VIDEO) 1016 if (renderer()->isVideo()) { 1017 RenderVideo* videoRenderer = toRenderVideo(renderer()); 1018 contentsRect = videoRenderer->videoBox(); 1019 } else 1020 #endif 1021 contentsRect = toRenderBox(renderer())->contentBoxRect(); 1022 1023 IntSize contentOffset = contentOffsetInCompostingLayer(); 1024 contentsRect.move(contentOffset); 1025 return contentsRect; 1026 } 1027 1028 bool RenderLayerBacking::paintingGoesToWindow() const 1029 { 1030 if (m_owningLayer->isRootLayer()) 1031 return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame; 1032 1033 return false; 1034 } 1035 1036 void RenderLayerBacking::setContentsNeedDisplay() 1037 { 1038 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) 1039 m_graphicsLayer->setNeedsDisplay(); 1040 1041 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) 1042 m_foregroundLayer->setNeedsDisplay(); 1043 1044 if (m_maskLayer && m_maskLayer->drawsContent()) 1045 m_maskLayer->setNeedsDisplay(); 1046 } 1047 1048 // r is in the coordinate space of the layer's render object 1049 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) 1050 { 1051 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { 1052 IntRect layerDirtyRect = r; 1053 layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer()); 1054 m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect); 1055 } 1056 1057 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) { 1058 IntRect layerDirtyRect = r; 1059 layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer()); 1060 m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect); 1061 } 1062 1063 if (m_maskLayer && m_maskLayer->drawsContent()) { 1064 IntRect layerDirtyRect = r; 1065 layerDirtyRect.move(-m_maskLayer->offsetFromRenderer()); 1066 m_maskLayer->setNeedsDisplayInRect(layerDirtyRect); 1067 } 1068 } 1069 1070 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 1071 { 1072 if (paintDirtyRect == clipRect) 1073 return; 1074 p->save(); 1075 p->clip(clipRect); 1076 } 1077 1078 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 1079 { 1080 if (paintDirtyRect == clipRect) 1081 return; 1082 p->restore(); 1083 } 1084 1085 // Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase? 1086 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context, 1087 const IntRect& paintDirtyRect, // in the coords of rootLayer 1088 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase, 1089 RenderObject* paintingRoot) 1090 { 1091 if (paintingGoesToWindow()) { 1092 ASSERT_NOT_REACHED(); 1093 return; 1094 } 1095 1096 m_owningLayer->updateLayerListsIfNeeded(); 1097 1098 // Calculate the clip rects we should use. 1099 IntRect layerBounds, damageRect, clipRectToApply, outlineRect; 1100 m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect); 1101 1102 int x = layerBounds.x(); // layerBounds is computed relative to rootLayer 1103 int y = layerBounds.y(); 1104 int tx = x - m_owningLayer->renderBoxX(); 1105 int ty = y - m_owningLayer->renderBoxY(); 1106 1107 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which 1108 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). 1109 // Else, our renderer tree may or may not contain the painting root, so we pass that root along 1110 // so it will be tested against as we decend through the renderers. 1111 RenderObject *paintingRootForRenderer = 0; 1112 if (paintingRoot && !renderer()->isDescendantOf(paintingRoot)) 1113 paintingRootForRenderer = paintingRoot; 1114 1115 bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer(); 1116 1117 if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) { 1118 // Paint our background first, before painting any child layers. 1119 // Establish the clip used to paint our background. 1120 setClip(context, paintDirtyRect, damageRect); 1121 1122 PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0); 1123 renderer()->paint(info, tx, ty); 1124 1125 // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with 1126 // z-index. We paint after we painted the background/border, so that the scrollbars will 1127 // sit above the background/border. 1128 m_owningLayer->paintOverflowControls(context, x, y, damageRect); 1129 1130 // Restore the clip. 1131 restoreClip(context, paintDirtyRect, damageRect); 1132 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1133 // Paint the outline as part of the background phase in order for the 1134 // outline to not be a part of the scrollable content. 1135 if (!outlineRect.isEmpty()) { 1136 // Paint our own outline 1137 PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 1138 setClip(context, paintDirtyRect, outlineRect); 1139 renderer()->paint(paintInfo, tx, ty); 1140 restoreClip(context, paintDirtyRect, outlineRect); 1141 } 1142 #endif 1143 1144 // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint. 1145 m_owningLayer->paintList(m_owningLayer->negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); 1146 } 1147 1148 bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; 1149 bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; 1150 1151 if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) { 1152 // Set up the clip used when painting our children. 1153 setClip(context, paintDirtyRect, clipRectToApply); 1154 PaintInfo paintInfo(context, clipRectToApply, 1155 selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, 1156 forceBlackText, paintingRootForRenderer, 0); 1157 renderer()->paint(paintInfo, tx, ty); 1158 1159 if (!selectionOnly) { 1160 paintInfo.phase = PaintPhaseFloat; 1161 renderer()->paint(paintInfo, tx, ty); 1162 1163 paintInfo.phase = PaintPhaseForeground; 1164 renderer()->paint(paintInfo, tx, ty); 1165 1166 paintInfo.phase = PaintPhaseChildOutlines; 1167 renderer()->paint(paintInfo, tx, ty); 1168 } 1169 1170 // Now restore our clip. 1171 restoreClip(context, paintDirtyRect, clipRectToApply); 1172 1173 #if !ENABLE(ANDROID_OVERFLOW_SCROLL) 1174 // Do not paint the outline as part of the foreground since it will 1175 // appear inside the scrollable content. 1176 if (!outlineRect.isEmpty()) { 1177 // Paint our own outline 1178 PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 1179 setClip(context, paintDirtyRect, outlineRect); 1180 renderer()->paint(paintInfo, tx, ty); 1181 restoreClip(context, paintDirtyRect, outlineRect); 1182 } 1183 #endif 1184 1185 // Paint any child layers that have overflow. 1186 m_owningLayer->paintList(m_owningLayer->normalFlowList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); 1187 1188 // Now walk the sorted list of children with positive z-indices. 1189 m_owningLayer->paintList(m_owningLayer->posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); 1190 } 1191 1192 if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) { 1193 if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) { 1194 setClip(context, paintDirtyRect, damageRect); 1195 1196 // Paint the mask. 1197 PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0); 1198 renderer()->paint(paintInfo, tx, ty); 1199 1200 // Restore the clip. 1201 restoreClip(context, paintDirtyRect, damageRect); 1202 } 1203 } 1204 1205 ASSERT(!m_owningLayer->m_usedTransparency); 1206 } 1207 1208 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) 1209 { 1210 if (!scrollbar) 1211 return; 1212 1213 context.save(); 1214 const IntRect& scrollbarRect = scrollbar->frameRect(); 1215 context.translate(-scrollbarRect.x(), -scrollbarRect.y()); 1216 IntRect transformedClip = clip; 1217 transformedClip.move(scrollbarRect.x(), scrollbarRect.y()); 1218 scrollbar->paint(&context, transformedClip); 1219 context.restore(); 1220 } 1221 1222 // Up-call from compositing layer drawing callback. 1223 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) 1224 { 1225 if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) { 1226 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip); 1227 1228 IntSize offset = graphicsLayer->offsetFromRenderer(); 1229 context.translate(-offset); 1230 1231 IntRect clipRect(clip); 1232 clipRect.move(offset); 1233 1234 // The dirtyRect is in the coords of the painting root. 1235 IntRect dirtyRect = compositedBounds(); 1236 dirtyRect.intersect(clipRect); 1237 1238 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1239 // If we encounter a scrollable layer, layers inside the scrollable layer 1240 // will need their entire content recorded. 1241 if (m_owningLayer->hasOverflowParent()) 1242 dirtyRect.setSize(clip.size()); 1243 #endif 1244 1245 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects. 1246 paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer()); 1247 1248 InspectorInstrumentation::didPaint(cookie); 1249 } else if (graphicsLayer == layerForHorizontalScrollbar()) { 1250 paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip); 1251 } else if (graphicsLayer == layerForVerticalScrollbar()) { 1252 paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip); 1253 } else if (graphicsLayer == layerForScrollCorner()) { 1254 const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect(); 1255 context.save(); 1256 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y()); 1257 IntRect transformedClip = clip; 1258 transformedClip.move(scrollCornerAndResizer.x(), scrollCornerAndResizer.y()); 1259 m_owningLayer->paintScrollCorner(&context, 0, 0, transformedClip); 1260 m_owningLayer->paintResizer(&context, 0, 0, transformedClip); 1261 context.restore(); 1262 } 1263 } 1264 1265 bool RenderLayerBacking::showDebugBorders() const 1266 { 1267 return compositor() ? compositor()->compositorShowDebugBorders() : false; 1268 } 1269 1270 bool RenderLayerBacking::showRepaintCounter() const 1271 { 1272 return compositor() ? compositor()->compositorShowRepaintCounter() : false; 1273 } 1274 1275 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes) 1276 { 1277 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); 1278 bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform); 1279 1280 if (!hasOpacity && !hasTransform) 1281 return false; 1282 1283 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 1284 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 1285 1286 size_t numKeyframes = keyframes.size(); 1287 for (size_t i = 0; i < numKeyframes; ++i) { 1288 const KeyframeValue& currentKeyframe = keyframes[i]; 1289 const RenderStyle* keyframeStyle = currentKeyframe.style(); 1290 float key = currentKeyframe.key(); 1291 1292 if (!keyframeStyle) 1293 continue; 1294 1295 // Get timing function. 1296 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0; 1297 1298 bool isFirstOrLastKeyframe = key == 0 || key == 1; 1299 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform)) 1300 transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf)); 1301 1302 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity)) 1303 opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)); 1304 } 1305 1306 bool didAnimateTransform = false; 1307 bool didAnimateOpacity = false; 1308 1309 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) { 1310 didAnimateTransform = true; 1311 compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); 1312 } 1313 1314 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) { 1315 didAnimateOpacity = true; 1316 compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); 1317 } 1318 1319 return didAnimateTransform || didAnimateOpacity; 1320 } 1321 1322 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName) 1323 { 1324 m_graphicsLayer->pauseAnimation(animationName, timeOffset); 1325 } 1326 1327 void RenderLayerBacking::animationFinished(const String& animationName) 1328 { 1329 m_graphicsLayer->removeAnimation(animationName); 1330 } 1331 1332 bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle) 1333 { 1334 bool didAnimateOpacity = false; 1335 bool didAnimateTransform = false; 1336 ASSERT(property != cAnimateAll); 1337 1338 if (property == (int)CSSPropertyOpacity) { 1339 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity); 1340 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) { 1341 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 1342 opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity()))); 1343 opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity()))); 1344 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. 1345 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { 1346 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. 1347 updateLayerOpacity(toStyle); 1348 didAnimateOpacity = true; 1349 } 1350 } 1351 } 1352 1353 if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) { 1354 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform); 1355 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) { 1356 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 1357 transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform())); 1358 transformVector.insert(new TransformAnimationValue(1, &toStyle->transform())); 1359 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { 1360 // To ensure that the correct transform is visible when the animation ends, also set the final opacity. 1361 updateLayerTransform(toStyle); 1362 didAnimateTransform = true; 1363 } 1364 } 1365 } 1366 1367 if (didAnimateOpacity) 1368 compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); 1369 1370 if (didAnimateTransform) 1371 compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); 1372 1373 return didAnimateOpacity || didAnimateTransform; 1374 } 1375 1376 void RenderLayerBacking::transitionPaused(double timeOffset, int property) 1377 { 1378 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 1379 if (animatedProperty != AnimatedPropertyInvalid) 1380 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset); 1381 } 1382 1383 void RenderLayerBacking::transitionFinished(int property) 1384 { 1385 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 1386 if (animatedProperty != AnimatedPropertyInvalid) 1387 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty)); 1388 } 1389 1390 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time) 1391 { 1392 renderer()->animation()->notifyAnimationStarted(renderer(), time); 1393 } 1394 1395 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*) 1396 { 1397 if (!renderer()->documentBeingDestroyed()) 1398 compositor()->scheduleLayerFlush(); 1399 } 1400 1401 // This is used for the 'freeze' API, for testing only. 1402 void RenderLayerBacking::suspendAnimations(double time) 1403 { 1404 m_graphicsLayer->suspendAnimations(time); 1405 } 1406 1407 void RenderLayerBacking::resumeAnimations() 1408 { 1409 m_graphicsLayer->resumeAnimations(); 1410 } 1411 1412 IntRect RenderLayerBacking::compositedBounds() const 1413 { 1414 return m_compositedBounds; 1415 } 1416 1417 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds) 1418 { 1419 m_compositedBounds = bounds; 1420 1421 } 1422 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property) 1423 { 1424 int cssProperty = CSSPropertyInvalid; 1425 switch (property) { 1426 case AnimatedPropertyWebkitTransform: 1427 cssProperty = CSSPropertyWebkitTransform; 1428 break; 1429 case AnimatedPropertyOpacity: 1430 cssProperty = CSSPropertyOpacity; 1431 break; 1432 case AnimatedPropertyBackgroundColor: 1433 cssProperty = CSSPropertyBackgroundColor; 1434 break; 1435 case AnimatedPropertyInvalid: 1436 ASSERT_NOT_REACHED(); 1437 } 1438 return cssProperty; 1439 } 1440 1441 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty) 1442 { 1443 switch (cssProperty) { 1444 case CSSPropertyWebkitTransform: 1445 return AnimatedPropertyWebkitTransform; 1446 case CSSPropertyOpacity: 1447 return AnimatedPropertyOpacity; 1448 case CSSPropertyBackgroundColor: 1449 return AnimatedPropertyBackgroundColor; 1450 // It's fine if we see other css properties here; they are just not accelerated. 1451 } 1452 return AnimatedPropertyInvalid; 1453 } 1454 1455 #ifndef NDEBUG 1456 String RenderLayerBacking::nameForLayer() const 1457 { 1458 String name = renderer()->renderName(); 1459 if (Node* node = renderer()->node()) { 1460 if (node->isElementNode()) 1461 name += " " + static_cast<Element*>(node)->tagName(); 1462 if (node->hasID()) 1463 name += " \'" + static_cast<Element*>(node)->getIdAttribute() + "\'"; 1464 } 1465 1466 if (m_owningLayer->isReflection()) 1467 name += " (reflection)"; 1468 1469 return name; 1470 } 1471 #endif 1472 1473 CompositingLayerType RenderLayerBacking::compositingLayerType() const 1474 { 1475 if (m_graphicsLayer->hasContentsLayer()) 1476 return MediaCompositingLayer; 1477 1478 if (m_graphicsLayer->drawsContent()) 1479 return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer; 1480 1481 return ContainerCompositingLayer; 1482 } 1483 1484 void RenderLayerBacking::updateContentsScale(float scale) 1485 { 1486 if (m_graphicsLayer) 1487 m_graphicsLayer->setContentsScale(scale); 1488 1489 if (m_foregroundLayer) 1490 m_foregroundLayer->setContentsScale(scale); 1491 1492 if (m_maskLayer) 1493 m_maskLayer->setContentsScale(scale); 1494 } 1495 1496 } // namespace WebCore 1497 1498 #endif // USE(ACCELERATED_COMPOSITING) 1499