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 PLATFORM(ANDROID) 1118 if (shouldPaint && ((paintingPhase & GraphicsLayerPaintBackground) 1119 || (paintingPhase & GraphicsLayerPaintBackgroundDecorations))) { 1120 #else 1121 if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) { 1122 #endif 1123 // Paint our background first, before painting any child layers. 1124 // Establish the clip used to paint our background. 1125 setClip(context, paintDirtyRect, damageRect); 1126 1127 #if PLATFORM(ANDROID) 1128 PaintPhase phase = PaintPhaseBlockBackground; 1129 if (paintingPhase & GraphicsLayerPaintBackgroundDecorations) 1130 phase = PaintPhaseBlockBackgroundDecorations; 1131 PaintInfo info(context, damageRect, phase, false, paintingRootForRenderer, 0); 1132 #else 1133 PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0); 1134 #endif 1135 renderer()->paint(info, tx, ty); 1136 1137 // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with 1138 // z-index. We paint after we painted the background/border, so that the scrollbars will 1139 // sit above the background/border. 1140 m_owningLayer->paintOverflowControls(context, x, y, damageRect); 1141 1142 // Restore the clip. 1143 restoreClip(context, paintDirtyRect, damageRect); 1144 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1145 // Paint the outline as part of the background phase in order for the 1146 // outline to not be a part of the scrollable content. 1147 if (!outlineRect.isEmpty()) { 1148 // Paint our own outline 1149 PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 1150 setClip(context, paintDirtyRect, outlineRect); 1151 renderer()->paint(paintInfo, tx, ty); 1152 restoreClip(context, paintDirtyRect, outlineRect); 1153 } 1154 #endif 1155 1156 // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint. 1157 m_owningLayer->paintList(m_owningLayer->negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); 1158 } 1159 1160 bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; 1161 bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; 1162 1163 if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) { 1164 // Set up the clip used when painting our children. 1165 setClip(context, paintDirtyRect, clipRectToApply); 1166 PaintInfo paintInfo(context, clipRectToApply, 1167 selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, 1168 forceBlackText, paintingRootForRenderer, 0); 1169 renderer()->paint(paintInfo, tx, ty); 1170 1171 if (!selectionOnly) { 1172 paintInfo.phase = PaintPhaseFloat; 1173 renderer()->paint(paintInfo, tx, ty); 1174 1175 paintInfo.phase = PaintPhaseForeground; 1176 renderer()->paint(paintInfo, tx, ty); 1177 1178 paintInfo.phase = PaintPhaseChildOutlines; 1179 renderer()->paint(paintInfo, tx, ty); 1180 } 1181 1182 // Now restore our clip. 1183 restoreClip(context, paintDirtyRect, clipRectToApply); 1184 1185 #if !ENABLE(ANDROID_OVERFLOW_SCROLL) 1186 // Do not paint the outline as part of the foreground since it will 1187 // appear inside the scrollable content. 1188 if (!outlineRect.isEmpty()) { 1189 // Paint our own outline 1190 PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 1191 setClip(context, paintDirtyRect, outlineRect); 1192 renderer()->paint(paintInfo, tx, ty); 1193 restoreClip(context, paintDirtyRect, outlineRect); 1194 } 1195 #endif 1196 1197 // Paint any child layers that have overflow. 1198 m_owningLayer->paintList(m_owningLayer->normalFlowList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); 1199 1200 // Now walk the sorted list of children with positive z-indices. 1201 m_owningLayer->paintList(m_owningLayer->posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0); 1202 } 1203 1204 if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) { 1205 if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) { 1206 setClip(context, paintDirtyRect, damageRect); 1207 1208 // Paint the mask. 1209 PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0); 1210 renderer()->paint(paintInfo, tx, ty); 1211 1212 // Restore the clip. 1213 restoreClip(context, paintDirtyRect, damageRect); 1214 } 1215 } 1216 1217 ASSERT(!m_owningLayer->m_usedTransparency); 1218 } 1219 1220 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip) 1221 { 1222 if (!scrollbar) 1223 return; 1224 1225 context.save(); 1226 const IntRect& scrollbarRect = scrollbar->frameRect(); 1227 context.translate(-scrollbarRect.x(), -scrollbarRect.y()); 1228 IntRect transformedClip = clip; 1229 transformedClip.move(scrollbarRect.x(), scrollbarRect.y()); 1230 scrollbar->paint(&context, transformedClip); 1231 context.restore(); 1232 } 1233 1234 // Up-call from compositing layer drawing callback. 1235 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) 1236 { 1237 if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) { 1238 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip); 1239 1240 IntSize offset = graphicsLayer->offsetFromRenderer(); 1241 context.translate(-offset); 1242 1243 IntRect clipRect(clip); 1244 clipRect.move(offset); 1245 1246 // The dirtyRect is in the coords of the painting root. 1247 IntRect dirtyRect = compositedBounds(); 1248 dirtyRect.intersect(clipRect); 1249 1250 #if ENABLE(ANDROID_OVERFLOW_SCROLL) 1251 // If we encounter a scrollable layer, layers inside the scrollable layer 1252 // will need their entire content recorded. 1253 if (m_owningLayer->hasOverflowParent()) 1254 dirtyRect.setSize(clip.size()); 1255 #endif 1256 1257 // We have to use the same root as for hit testing, because both methods can compute and cache clipRects. 1258 paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer()); 1259 1260 InspectorInstrumentation::didPaint(cookie); 1261 } else if (graphicsLayer == layerForHorizontalScrollbar()) { 1262 paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip); 1263 } else if (graphicsLayer == layerForVerticalScrollbar()) { 1264 paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip); 1265 } else if (graphicsLayer == layerForScrollCorner()) { 1266 const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect(); 1267 context.save(); 1268 context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y()); 1269 IntRect transformedClip = clip; 1270 transformedClip.move(scrollCornerAndResizer.x(), scrollCornerAndResizer.y()); 1271 m_owningLayer->paintScrollCorner(&context, 0, 0, transformedClip); 1272 m_owningLayer->paintResizer(&context, 0, 0, transformedClip); 1273 context.restore(); 1274 } 1275 } 1276 1277 bool RenderLayerBacking::showDebugBorders() const 1278 { 1279 return compositor() ? compositor()->compositorShowDebugBorders() : false; 1280 } 1281 1282 bool RenderLayerBacking::showRepaintCounter() const 1283 { 1284 return compositor() ? compositor()->compositorShowRepaintCounter() : false; 1285 } 1286 1287 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes) 1288 { 1289 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); 1290 bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform); 1291 1292 if (!hasOpacity && !hasTransform) 1293 return false; 1294 1295 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 1296 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 1297 1298 size_t numKeyframes = keyframes.size(); 1299 for (size_t i = 0; i < numKeyframes; ++i) { 1300 const KeyframeValue& currentKeyframe = keyframes[i]; 1301 const RenderStyle* keyframeStyle = currentKeyframe.style(); 1302 float key = currentKeyframe.key(); 1303 1304 if (!keyframeStyle) 1305 continue; 1306 1307 // Get timing function. 1308 RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0; 1309 1310 bool isFirstOrLastKeyframe = key == 0 || key == 1; 1311 if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform)) 1312 transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf)); 1313 1314 if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity)) 1315 opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)); 1316 } 1317 1318 bool didAnimateTransform = false; 1319 bool didAnimateOpacity = false; 1320 1321 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) { 1322 didAnimateTransform = true; 1323 compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); 1324 } 1325 1326 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) { 1327 didAnimateOpacity = true; 1328 compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); 1329 } 1330 1331 return didAnimateTransform || didAnimateOpacity; 1332 } 1333 1334 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName) 1335 { 1336 m_graphicsLayer->pauseAnimation(animationName, timeOffset); 1337 } 1338 1339 void RenderLayerBacking::animationFinished(const String& animationName) 1340 { 1341 m_graphicsLayer->removeAnimation(animationName); 1342 } 1343 1344 bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle) 1345 { 1346 bool didAnimateOpacity = false; 1347 bool didAnimateTransform = false; 1348 ASSERT(property != cAnimateAll); 1349 1350 if (property == (int)CSSPropertyOpacity) { 1351 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity); 1352 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) { 1353 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 1354 opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity()))); 1355 opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity()))); 1356 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. 1357 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { 1358 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. 1359 updateLayerOpacity(toStyle); 1360 didAnimateOpacity = true; 1361 } 1362 } 1363 } 1364 1365 if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) { 1366 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform); 1367 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) { 1368 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 1369 transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform())); 1370 transformVector.insert(new TransformAnimationValue(1, &toStyle->transform())); 1371 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { 1372 // To ensure that the correct transform is visible when the animation ends, also set the final opacity. 1373 updateLayerTransform(toStyle); 1374 didAnimateTransform = true; 1375 } 1376 } 1377 } 1378 1379 if (didAnimateOpacity) 1380 compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); 1381 1382 if (didAnimateTransform) 1383 compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); 1384 1385 return didAnimateOpacity || didAnimateTransform; 1386 } 1387 1388 void RenderLayerBacking::transitionPaused(double timeOffset, int property) 1389 { 1390 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 1391 if (animatedProperty != AnimatedPropertyInvalid) 1392 m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset); 1393 } 1394 1395 void RenderLayerBacking::transitionFinished(int property) 1396 { 1397 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 1398 if (animatedProperty != AnimatedPropertyInvalid) 1399 m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty)); 1400 } 1401 1402 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time) 1403 { 1404 renderer()->animation()->notifyAnimationStarted(renderer(), time); 1405 } 1406 1407 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*) 1408 { 1409 if (!renderer()->documentBeingDestroyed()) 1410 compositor()->scheduleLayerFlush(); 1411 } 1412 1413 // This is used for the 'freeze' API, for testing only. 1414 void RenderLayerBacking::suspendAnimations(double time) 1415 { 1416 m_graphicsLayer->suspendAnimations(time); 1417 } 1418 1419 void RenderLayerBacking::resumeAnimations() 1420 { 1421 m_graphicsLayer->resumeAnimations(); 1422 } 1423 1424 IntRect RenderLayerBacking::compositedBounds() const 1425 { 1426 return m_compositedBounds; 1427 } 1428 1429 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds) 1430 { 1431 m_compositedBounds = bounds; 1432 1433 } 1434 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property) 1435 { 1436 int cssProperty = CSSPropertyInvalid; 1437 switch (property) { 1438 case AnimatedPropertyWebkitTransform: 1439 cssProperty = CSSPropertyWebkitTransform; 1440 break; 1441 case AnimatedPropertyOpacity: 1442 cssProperty = CSSPropertyOpacity; 1443 break; 1444 case AnimatedPropertyBackgroundColor: 1445 cssProperty = CSSPropertyBackgroundColor; 1446 break; 1447 case AnimatedPropertyInvalid: 1448 ASSERT_NOT_REACHED(); 1449 } 1450 return cssProperty; 1451 } 1452 1453 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty) 1454 { 1455 switch (cssProperty) { 1456 case CSSPropertyWebkitTransform: 1457 return AnimatedPropertyWebkitTransform; 1458 case CSSPropertyOpacity: 1459 return AnimatedPropertyOpacity; 1460 case CSSPropertyBackgroundColor: 1461 return AnimatedPropertyBackgroundColor; 1462 // It's fine if we see other css properties here; they are just not accelerated. 1463 } 1464 return AnimatedPropertyInvalid; 1465 } 1466 1467 #ifndef NDEBUG 1468 String RenderLayerBacking::nameForLayer() const 1469 { 1470 String name = renderer()->renderName(); 1471 if (Node* node = renderer()->node()) { 1472 if (node->isElementNode()) 1473 name += " " + static_cast<Element*>(node)->tagName(); 1474 if (node->hasID()) 1475 name += " \'" + static_cast<Element*>(node)->getIdAttribute() + "\'"; 1476 } 1477 1478 if (m_owningLayer->isReflection()) 1479 name += " (reflection)"; 1480 1481 return name; 1482 } 1483 #endif 1484 1485 CompositingLayerType RenderLayerBacking::compositingLayerType() const 1486 { 1487 if (m_graphicsLayer->hasContentsLayer()) 1488 return MediaCompositingLayer; 1489 1490 if (m_graphicsLayer->drawsContent()) 1491 return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer; 1492 1493 return ContainerCompositingLayer; 1494 } 1495 1496 void RenderLayerBacking::updateContentsScale(float scale) 1497 { 1498 if (m_graphicsLayer) 1499 m_graphicsLayer->setContentsScale(scale); 1500 1501 if (m_foregroundLayer) 1502 m_foregroundLayer->setContentsScale(scale); 1503 1504 if (m_maskLayer) 1505 m_maskLayer->setContentsScale(scale); 1506 } 1507 1508 } // namespace WebCore 1509 1510 #endif // USE(ACCELERATED_COMPOSITING) 1511