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 "AnimationController.h" 31 #if ENABLE(3D_CANVAS) 32 #include "WebGLRenderingContext.h" 33 #endif 34 #include "CSSPropertyNames.h" 35 #include "CSSStyleSelector.h" 36 #include "FrameView.h" 37 #include "GraphicsContext.h" 38 #include "GraphicsLayer.h" 39 #include "HTMLCanvasElement.h" 40 #include "HTMLElement.h" 41 #include "HTMLNames.h" 42 #include "InspectorTimelineAgent.h" 43 #include "KeyframeList.h" 44 #include "PluginWidget.h" 45 #include "RenderBox.h" 46 #include "RenderImage.h" 47 #include "RenderLayerCompositor.h" 48 #include "RenderEmbeddedObject.h" 49 #include "RenderVideo.h" 50 #include "RenderView.h" 51 #include "Settings.h" 52 53 #include "RenderLayerBacking.h" 54 55 using namespace std; 56 57 namespace WebCore { 58 59 using namespace HTMLNames; 60 61 static bool hasBorderOutlineOrShadow(const RenderStyle*); 62 static bool hasBoxDecorationsOrBackground(const RenderStyle*); 63 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*); 64 65 static inline bool is3DCanvas(RenderObject* renderer) 66 { 67 #if ENABLE(3D_CANVAS) 68 if (renderer->isCanvas()) 69 return static_cast<HTMLCanvasElement*>(renderer->node())->is3D(); 70 #else 71 UNUSED_PARAM(renderer); 72 #endif 73 return false; 74 } 75 76 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer) 77 : m_owningLayer(layer) 78 , m_artificiallyInflatedBounds(false) 79 { 80 createGraphicsLayer(); 81 } 82 83 RenderLayerBacking::~RenderLayerBacking() 84 { 85 updateClippingLayers(false, false); 86 updateForegroundLayer(false); 87 updateMaskLayer(false); 88 destroyGraphicsLayer(); 89 } 90 91 void RenderLayerBacking::createGraphicsLayer() 92 { 93 m_graphicsLayer = GraphicsLayer::create(this); 94 95 #ifndef NDEBUG 96 if (renderer()->node()) { 97 if (renderer()->node()->isDocumentNode()) 98 m_graphicsLayer->setName("Document Node"); 99 else { 100 if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID()) 101 m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->getIDAttribute()); 102 else 103 m_graphicsLayer->setName(renderer()->renderName()); 104 } 105 } else if (m_owningLayer->isReflection()) 106 m_graphicsLayer->setName("Reflection"); 107 else 108 m_graphicsLayer->setName("Anonymous Node"); 109 #endif // NDEBUG 110 111 updateLayerOpacity(renderer()->style()); 112 updateLayerTransform(renderer()->style()); 113 } 114 115 void RenderLayerBacking::destroyGraphicsLayer() 116 { 117 if (m_graphicsLayer) 118 m_graphicsLayer->removeFromParent(); 119 120 m_graphicsLayer = 0; 121 m_foregroundLayer = 0; 122 m_clippingLayer = 0; 123 m_maskLayer = 0; 124 } 125 126 void RenderLayerBacking::updateLayerOpacity(const RenderStyle* style) 127 { 128 m_graphicsLayer->setOpacity(compositingOpacity(style->opacity())); 129 } 130 131 void RenderLayerBacking::updateLayerTransform(const RenderStyle* style) 132 { 133 // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin 134 // baked into it, and we don't want that. 135 TransformationMatrix t; 136 if (m_owningLayer->hasTransform()) { 137 style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin); 138 makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing()); 139 } 140 141 m_graphicsLayer->setTransform(t); 142 } 143 144 static bool hasNonZeroTransformOrigin(const RenderObject* renderer) 145 { 146 RenderStyle* style = renderer->style(); 147 return (style->transformOriginX().type() == Fixed && style->transformOriginX().value()) 148 || (style->transformOriginY().type() == Fixed && style->transformOriginY().value()); 149 } 150 151 void RenderLayerBacking::updateCompositedBounds() 152 { 153 IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer); 154 155 // If the element has a transform-origin that has fixed lengths, and the renderer has zero size, 156 // then we need to ensure that the compositing layer has non-zero size so that we can apply 157 // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value). 158 if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) { 159 layerBounds.setWidth(1); 160 layerBounds.setHeight(1); 161 m_artificiallyInflatedBounds = true; 162 } else 163 m_artificiallyInflatedBounds = false; 164 165 setCompositedBounds(layerBounds); 166 } 167 168 void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth, bool isUpdateRoot) 169 { 170 RenderLayerCompositor* layerCompositor = compositor(); 171 if (!layerCompositor->compositingLayersNeedRebuild()) { 172 // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the 173 // position of this layer's GraphicsLayer depends on the position of our compositing 174 // ancestor's GraphicsLayer. That cannot be determined until all the descendant 175 // RenderLayers of that ancestor have been processed via updateLayerPositions(). 176 // 177 // The solution is to update compositing children of this layer here, 178 // via updateCompositingChildrenGeometry(). 179 updateCompositedBounds(); 180 layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth); 181 182 if (isUpdateRoot) { 183 updateGraphicsLayerGeometry(); 184 layerCompositor->updateRootLayerPosition(); 185 } 186 } 187 } 188 189 bool RenderLayerBacking::updateGraphicsLayerConfiguration() 190 { 191 RenderLayerCompositor* compositor = this->compositor(); 192 193 bool layerConfigChanged = false; 194 if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer))) 195 layerConfigChanged = true; 196 197 if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer))) 198 layerConfigChanged = true; 199 200 if (updateMaskLayer(m_owningLayer->renderer()->hasMask())) 201 m_graphicsLayer->setMaskLayer(m_maskLayer.get()); 202 203 if (m_owningLayer->hasReflection()) { 204 if (m_owningLayer->reflectionLayer()->backing()) { 205 GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer(); 206 m_graphicsLayer->setReplicatedByLayer(reflectionLayer); 207 } 208 } else 209 m_graphicsLayer->setReplicatedByLayer(0); 210 211 if (isDirectlyCompositedImage()) 212 updateImageContents(); 213 214 if (renderer()->isEmbeddedObject() && toRenderEmbeddedObject(renderer())->allowsAcceleratedCompositing()) { 215 PluginWidget* pluginWidget = static_cast<PluginWidget*>(toRenderEmbeddedObject(renderer())->widget()); 216 m_graphicsLayer->setContentsToMedia(pluginWidget->platformLayer()); 217 } 218 219 #if ENABLE(3D_CANVAS) 220 if (is3DCanvas(renderer())) { 221 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer()->node()); 222 WebGLRenderingContext* context = static_cast<WebGLRenderingContext*>(canvas->renderingContext()); 223 if (context->graphicsContext3D()->platformGraphicsContext3D()) 224 m_graphicsLayer->setContentsToGraphicsContext3D(context->graphicsContext3D()); 225 } 226 #endif 227 228 return layerConfigChanged; 229 } 230 231 void RenderLayerBacking::updateGraphicsLayerGeometry() 232 { 233 // If we haven't built z-order lists yet, wait until later. 234 if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty) 235 return; 236 237 // Set transform property, if it is not animating. We have to do this here because the transform 238 // is affected by the layer dimensions. 239 if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform)) 240 updateLayerTransform(renderer()->style()); 241 242 // Set opacity, if it is not animating. 243 if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity)) 244 updateLayerOpacity(renderer()->style()); 245 246 RenderStyle* style = renderer()->style(); 247 m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection()); 248 m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible); 249 250 RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer(); 251 252 // We compute everything relative to the enclosing compositing layer. 253 IntRect ancestorCompositingBounds; 254 if (compAncestor) { 255 ASSERT(compAncestor->backing()); 256 ancestorCompositingBounds = compAncestor->backing()->compositedBounds(); 257 } 258 259 IntRect localCompositingBounds = compositedBounds(); 260 261 IntRect relativeCompositingBounds(localCompositingBounds); 262 int deltaX = 0, deltaY = 0; 263 m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY); 264 relativeCompositingBounds.move(deltaX, deltaY); 265 266 IntPoint graphicsLayerParentLocation; 267 if (compAncestor && compAncestor->backing()->hasClippingLayer()) { 268 // If the compositing ancestor has a layer to clip children, we parent in that, and therefore 269 // position relative to it. 270 graphicsLayerParentLocation = toRenderBox(compAncestor->renderer())->overflowClipRect(0, 0).location(); 271 } else 272 graphicsLayerParentLocation = ancestorCompositingBounds.location(); 273 274 if (compAncestor && m_ancestorClippingLayer) { 275 // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this 276 // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects 277 // for a compositing layer, rootLayer is the layer itself. 278 IntRect parentClipRect = m_owningLayer->backgroundClipRect(compAncestor, true); 279 m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation)); 280 m_ancestorClippingLayer->setSize(parentClipRect.size()); 281 282 // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords. 283 IntSize rendererOffset(parentClipRect.location().x() - deltaX, parentClipRect.location().y() - deltaY); 284 m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset); 285 286 // The primary layer is then parented in, and positioned relative to this clipping layer. 287 graphicsLayerParentLocation = parentClipRect.location(); 288 } 289 290 m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation)); 291 m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint()); 292 293 FloatSize oldSize = m_graphicsLayer->size(); 294 FloatSize newSize = relativeCompositingBounds.size(); 295 if (oldSize != newSize) { 296 m_graphicsLayer->setSize(newSize); 297 // A bounds change will almost always require redisplay. Usually that redisplay 298 // will happen because of a repaint elsewhere, but not always: 299 // e.g. see RenderView::setMaximalOutlineSize() 300 m_graphicsLayer->setNeedsDisplay(); 301 } 302 303 // If we have a layer that clips children, position it. 304 IntRect clippingBox; 305 if (m_clippingLayer) { 306 clippingBox = toRenderBox(renderer())->overflowClipRect(0, 0); 307 m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location())); 308 m_clippingLayer->setSize(clippingBox.size()); 309 m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint()); 310 } 311 312 if (m_maskLayer) { 313 m_maskLayer->setSize(m_graphicsLayer->size()); 314 m_maskLayer->setPosition(FloatPoint()); 315 } 316 317 if (m_owningLayer->hasTransform()) { 318 const IntRect borderBox = toRenderBox(renderer())->borderBoxRect(); 319 320 // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds. 321 IntRect layerBounds = IntRect(deltaX, deltaY, borderBox.width(), borderBox.height()); 322 323 // Update properties that depend on layer dimensions 324 FloatPoint3D transformOrigin = computeTransformOrigin(borderBox); 325 // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set. 326 FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f, 327 relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f, 328 transformOrigin.z()); 329 m_graphicsLayer->setAnchorPoint(anchor); 330 331 RenderStyle* style = renderer()->style(); 332 if (style->hasPerspective()) { 333 TransformationMatrix t = owningLayer()->perspectiveTransform(); 334 335 if (m_clippingLayer) { 336 m_clippingLayer->setChildrenTransform(t); 337 m_graphicsLayer->setChildrenTransform(TransformationMatrix()); 338 } 339 else 340 m_graphicsLayer->setChildrenTransform(t); 341 } else { 342 if (m_clippingLayer) 343 m_clippingLayer->setChildrenTransform(TransformationMatrix()); 344 else 345 m_graphicsLayer->setChildrenTransform(TransformationMatrix()); 346 } 347 } else { 348 m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0)); 349 } 350 351 if (m_foregroundLayer) { 352 FloatPoint foregroundPosition; 353 FloatSize foregroundSize = newSize; 354 IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer(); 355 // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it, 356 // so that it gets correctly sorted with children. In that case, position relative to the clipping layer. 357 if (m_clippingLayer) { 358 foregroundPosition = FloatPoint() + (localCompositingBounds.location() - clippingBox.location()); 359 foregroundSize = FloatSize(clippingBox.size()); 360 foregroundOffset = clippingBox.location() - IntPoint(); 361 } 362 363 m_foregroundLayer->setPosition(foregroundPosition); 364 m_foregroundLayer->setSize(foregroundSize); 365 m_foregroundLayer->setOffsetFromRenderer(foregroundOffset); 366 } 367 368 if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) { 369 RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing(); 370 reflectionBacking->updateGraphicsLayerGeometry(); 371 372 // The reflection layer has the bounds of m_owningLayer->reflectionLayer(), 373 // but the reflected layer is the bounds of this layer, so we need to position it appropriately. 374 FloatRect layerBounds = compositedBounds(); 375 FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds(); 376 reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location())); 377 } 378 379 m_graphicsLayer->setContentsRect(contentsBox()); 380 m_graphicsLayer->setDrawsContent(containsPaintedContent()); 381 } 382 383 void RenderLayerBacking::updateInternalHierarchy() 384 { 385 // m_foregroundLayer has to be inserted in the correct order with child layers, 386 // so it's not inserted here. 387 if (m_ancestorClippingLayer) { 388 m_ancestorClippingLayer->removeAllChildren(); 389 m_graphicsLayer->removeFromParent(); 390 m_ancestorClippingLayer->addChild(m_graphicsLayer.get()); 391 } 392 393 if (m_clippingLayer) { 394 m_clippingLayer->removeFromParent(); 395 m_graphicsLayer->addChild(m_clippingLayer.get()); 396 } 397 } 398 399 // Return true if the layers changed. 400 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip) 401 { 402 bool layersChanged = false; 403 404 if (needsAncestorClip) { 405 if (!m_ancestorClippingLayer) { 406 m_ancestorClippingLayer = GraphicsLayer::create(this); 407 #ifndef NDEBUG 408 m_ancestorClippingLayer->setName("Ancestor clipping Layer"); 409 #endif 410 m_ancestorClippingLayer->setMasksToBounds(true); 411 layersChanged = true; 412 } 413 } else if (m_ancestorClippingLayer) { 414 m_ancestorClippingLayer->removeFromParent(); 415 m_ancestorClippingLayer = 0; 416 layersChanged = true; 417 } 418 419 if (needsDescendantClip) { 420 if (!m_clippingLayer) { 421 m_clippingLayer = GraphicsLayer::create(0); 422 #ifndef NDEBUG 423 m_clippingLayer->setName("Child clipping Layer"); 424 #endif 425 m_clippingLayer->setMasksToBounds(true); 426 layersChanged = true; 427 } 428 } else if (m_clippingLayer) { 429 m_clippingLayer->removeFromParent(); 430 m_clippingLayer = 0; 431 layersChanged = true; 432 } 433 434 if (layersChanged) 435 updateInternalHierarchy(); 436 437 return layersChanged; 438 } 439 440 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer) 441 { 442 bool layerChanged = false; 443 if (needsForegroundLayer) { 444 if (!m_foregroundLayer) { 445 m_foregroundLayer = GraphicsLayer::create(this); 446 #ifndef NDEBUG 447 m_foregroundLayer->setName("Foreground"); 448 #endif 449 m_foregroundLayer->setDrawsContent(true); 450 m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground); 451 layerChanged = true; 452 } 453 } else if (m_foregroundLayer) { 454 m_foregroundLayer->removeFromParent(); 455 m_foregroundLayer = 0; 456 layerChanged = true; 457 } 458 459 if (layerChanged) 460 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 461 462 return layerChanged; 463 } 464 465 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer) 466 { 467 bool layerChanged = false; 468 if (needsMaskLayer) { 469 if (!m_maskLayer) { 470 m_maskLayer = GraphicsLayer::create(this); 471 #ifndef NDEBUG 472 m_maskLayer->setName("Mask"); 473 #endif 474 m_maskLayer->setDrawsContent(true); 475 m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask); 476 layerChanged = true; 477 } 478 } else if (m_maskLayer) { 479 m_maskLayer = 0; 480 layerChanged = true; 481 } 482 483 if (layerChanged) 484 m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer()); 485 486 return layerChanged; 487 } 488 489 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const 490 { 491 unsigned phase = GraphicsLayerPaintBackground; 492 if (!m_foregroundLayer) 493 phase |= GraphicsLayerPaintForeground; 494 if (!m_maskLayer) 495 phase |= GraphicsLayerPaintMask; 496 497 return static_cast<GraphicsLayerPaintingPhase>(phase); 498 } 499 500 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const 501 { 502 float finalOpacity = rendererOpacity; 503 504 for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) { 505 // We only care about parents that are stacking contexts. 506 // Recall that opacity creates stacking context. 507 if (!curr->isStackingContext()) 508 continue; 509 510 // If we found a compositing layer, we want to compute opacity 511 // relative to it. So we can break here. 512 if (curr->isComposited()) 513 break; 514 515 finalOpacity *= curr->renderer()->opacity(); 516 } 517 518 return finalOpacity; 519 } 520 521 static bool hasBorderOutlineOrShadow(const RenderStyle* style) 522 { 523 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow(); 524 } 525 526 static bool hasBoxDecorationsOrBackground(const RenderStyle* style) 527 { 528 return hasBorderOutlineOrShadow(style) || style->hasBackground(); 529 } 530 531 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style) 532 { 533 return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage(); 534 } 535 536 bool RenderLayerBacking::rendererHasBackground() const 537 { 538 // FIXME: share more code here 539 if (renderer()->node() && renderer()->node()->isDocumentNode()) { 540 RenderObject* htmlObject = renderer()->firstChild(); 541 if (!htmlObject) 542 return false; 543 544 RenderStyle* style = htmlObject->style(); 545 if (style->hasBackground()) 546 return true; 547 548 RenderObject* bodyObject = htmlObject->firstChild(); 549 if (!bodyObject) 550 return false; 551 552 style = bodyObject->style(); 553 return style->hasBackground(); 554 } 555 556 return renderer()->style()->hasBackground(); 557 } 558 559 const Color& RenderLayerBacking::rendererBackgroundColor() const 560 { 561 // FIXME: share more code here 562 if (renderer()->node() && renderer()->node()->isDocumentNode()) { 563 RenderObject* htmlObject = renderer()->firstChild(); 564 RenderStyle* style = htmlObject->style(); 565 if (style->hasBackground()) 566 return style->backgroundColor(); 567 568 RenderObject* bodyObject = htmlObject->firstChild(); 569 style = bodyObject->style(); 570 return style->backgroundColor(); 571 } 572 573 return renderer()->style()->backgroundColor(); 574 } 575 576 // A "simple container layer" is a RenderLayer which has no visible content to render. 577 // It may have no children, or all its children may be themselves composited. 578 // This is a useful optimization, because it allows us to avoid allocating backing store. 579 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const 580 { 581 RenderObject* renderObject = renderer(); 582 if (renderObject->isReplaced() || // replaced objects are not containers 583 renderObject->hasMask()) // masks require special treatment 584 return false; 585 586 RenderStyle* style = renderObject->style(); 587 588 // Reject anything that has a border, a border-radius or outline, 589 // or any background (color or image). 590 // FIXME: we could optimize layers for simple backgrounds. 591 if (hasBoxDecorationsOrBackground(style)) 592 return false; 593 594 // If we have got this far and the renderer has no children, then we're ok. 595 if (!renderObject->firstChild()) 596 return true; 597 598 if (renderObject->node() && renderObject->node()->isDocumentNode()) { 599 // Look to see if the root object has a non-simple backgound 600 RenderObject* rootObject = renderObject->document()->documentElement()->renderer(); 601 if (!rootObject) 602 return false; 603 604 style = rootObject->style(); 605 606 // Reject anything that has a border, a border-radius or outline, 607 // or is not a simple background (no background, or solid color). 608 if (hasBoxDecorationsOrBackgroundImage(style)) 609 return false; 610 611 // Now look at the body's renderer. 612 HTMLElement* body = renderObject->document()->body(); 613 RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0; 614 if (!bodyObject) 615 return false; 616 617 style = bodyObject->style(); 618 619 if (hasBoxDecorationsOrBackgroundImage(style)) 620 return false; 621 622 // Ceck to see if all the body's children are compositing layers. 623 if (hasNonCompositingContent()) 624 return false; 625 626 return true; 627 } 628 629 // Check to see if all the renderer's children are compositing layers. 630 if (hasNonCompositingContent()) 631 return false; 632 633 return true; 634 } 635 636 // Conservative test for having no rendered children. 637 bool RenderLayerBacking::hasNonCompositingContent() const 638 { 639 if (m_owningLayer->hasOverflowControls()) 640 return true; 641 642 // Some HTML can cause whitespace text nodes to have renderers, like: 643 // <div> 644 // <img src=...> 645 // </div> 646 // so test for 0x0 RenderTexts here 647 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) { 648 if (!child->hasLayer()) { 649 if (child->isRenderInline() || !child->isBox()) 650 return true; 651 652 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0) 653 return true; 654 } 655 } 656 657 if (m_owningLayer->isStackingContext()) { 658 // Use the m_hasCompositingDescendant bit to optimize? 659 if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) { 660 size_t listSize = negZOrderList->size(); 661 for (size_t i = 0; i < listSize; ++i) { 662 RenderLayer* curLayer = negZOrderList->at(i); 663 if (!curLayer->isComposited()) 664 return true; 665 } 666 } 667 668 if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) { 669 size_t listSize = posZOrderList->size(); 670 for (size_t i = 0; i < listSize; ++i) { 671 RenderLayer* curLayer = posZOrderList->at(i); 672 if (!curLayer->isComposited()) 673 return true; 674 } 675 } 676 } 677 678 if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) { 679 size_t listSize = normalFlowList->size(); 680 for (size_t i = 0; i < listSize; ++i) { 681 RenderLayer* curLayer = normalFlowList->at(i); 682 if (!curLayer->isComposited()) 683 return true; 684 } 685 } 686 687 return false; 688 } 689 690 bool RenderLayerBacking::containsPaintedContent() const 691 { 692 if (isSimpleContainerCompositingLayer() || paintingGoesToWindow() || m_artificiallyInflatedBounds || m_owningLayer->isReflection()) 693 return false; 694 695 if (isDirectlyCompositedImage()) 696 return false; 697 698 // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely, 699 // and set background color on the layer in that case, instead of allocating backing store and painting. 700 if (renderer()->isVideo() || is3DCanvas(renderer())) 701 return hasBoxDecorationsOrBackground(renderer()->style()); 702 703 return true; 704 } 705 706 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations 707 // that require painting. Direct compositing saves backing store. 708 bool RenderLayerBacking::isDirectlyCompositedImage() const 709 { 710 RenderObject* renderObject = renderer(); 711 return renderObject->isImage() && !hasBoxDecorationsOrBackground(renderObject->style()); 712 } 713 714 void RenderLayerBacking::rendererContentChanged() 715 { 716 if (isDirectlyCompositedImage()) { 717 updateImageContents(); 718 return; 719 } 720 721 #if ENABLE(3D_CANVAS) 722 if (is3DCanvas(renderer())) { 723 m_graphicsLayer->setGraphicsContext3DNeedsDisplay(); 724 return; 725 } 726 #endif 727 } 728 729 void RenderLayerBacking::updateImageContents() 730 { 731 ASSERT(renderer()->isImage()); 732 RenderImage* imageRenderer = toRenderImage(renderer()); 733 734 CachedImage* cachedImage = imageRenderer->cachedImage(); 735 if (!cachedImage) 736 return; 737 738 Image* image = cachedImage->image(); 739 if (!image) 740 return; 741 742 // We have to wait until the image is fully loaded before setting it on the layer. 743 if (!cachedImage->isLoaded()) 744 return; 745 746 // This is a no-op if the layer doesn't have an inner layer for the image. 747 m_graphicsLayer->setContentsToImage(image); 748 749 // Image animation is "lazy", in that it automatically stops unless someone is drawing 750 // the image. So we have to kick the animation each time; this has the downside that the 751 // image will keep animating, even if its layer is not visible. 752 image->startAnimation(); 753 } 754 755 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const 756 { 757 RenderStyle* style = renderer()->style(); 758 759 FloatPoint3D origin; 760 origin.setX(style->transformOriginX().calcFloatValue(borderBox.width())); 761 origin.setY(style->transformOriginY().calcFloatValue(borderBox.height())); 762 origin.setZ(style->transformOriginZ()); 763 764 return origin; 765 } 766 767 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const 768 { 769 RenderStyle* style = renderer()->style(); 770 771 float boxWidth = borderBox.width(); 772 float boxHeight = borderBox.height(); 773 774 FloatPoint origin; 775 origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth)); 776 origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight)); 777 778 return origin; 779 } 780 781 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted. 782 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const 783 { 784 return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y()); 785 } 786 787 IntRect RenderLayerBacking::contentsBox() const 788 { 789 if (!renderer()->isBox()) 790 return IntRect(); 791 792 IntRect contentsRect; 793 #if ENABLE(VIDEO) 794 if (renderer()->isVideo()) { 795 RenderVideo* videoRenderer = toRenderVideo(renderer()); 796 contentsRect = videoRenderer->videoBox(); 797 } else 798 #endif 799 contentsRect = toRenderBox(renderer())->contentBoxRect(); 800 801 IntSize contentOffset = contentOffsetInCompostingLayer(); 802 contentsRect.move(contentOffset); 803 return contentsRect; 804 } 805 806 // Map the given point from coordinates in the GraphicsLayer to RenderLayer coordinates. 807 FloatPoint RenderLayerBacking::graphicsLayerToContentsCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point) 808 { 809 return point + FloatSize(graphicsLayer->offsetFromRenderer()); 810 } 811 812 // Map the given point from coordinates in the RenderLayer to GraphicsLayer coordinates. 813 FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point) 814 { 815 return point - FloatSize(graphicsLayer->offsetFromRenderer()); 816 } 817 818 bool RenderLayerBacking::paintingGoesToWindow() const 819 { 820 return m_owningLayer->isRootLayer(); 821 } 822 823 void RenderLayerBacking::setContentsNeedDisplay() 824 { 825 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) 826 m_graphicsLayer->setNeedsDisplay(); 827 828 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) 829 m_foregroundLayer->setNeedsDisplay(); 830 831 if (m_maskLayer && m_maskLayer->drawsContent()) 832 m_maskLayer->setNeedsDisplay(); 833 } 834 835 // r is in the coordinate space of the layer's render object 836 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r) 837 { 838 if (m_graphicsLayer && m_graphicsLayer->drawsContent()) { 839 FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer.get(), FloatPoint(r.x(), r.y())); 840 FloatRect dirtyRect(dirtyOrigin, r.size()); 841 FloatRect bounds(FloatPoint(), m_graphicsLayer->size()); 842 if (bounds.intersects(dirtyRect)) 843 m_graphicsLayer->setNeedsDisplayInRect(dirtyRect); 844 } 845 846 if (m_foregroundLayer && m_foregroundLayer->drawsContent()) { 847 // FIXME: do incremental repaint 848 m_foregroundLayer->setNeedsDisplay(); 849 } 850 851 if (m_maskLayer && m_maskLayer->drawsContent()) { 852 // FIXME: do incremental repaint 853 m_maskLayer->setNeedsDisplay(); 854 } 855 } 856 857 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 858 { 859 if (paintDirtyRect == clipRect) 860 return; 861 p->save(); 862 p->clip(clipRect); 863 } 864 865 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect) 866 { 867 if (paintDirtyRect == clipRect) 868 return; 869 p->restore(); 870 } 871 872 // Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase? 873 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context, 874 const IntRect& paintDirtyRect, // in the coords of rootLayer 875 PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase, 876 RenderObject* paintingRoot) 877 { 878 if (paintingGoesToWindow()) { 879 ASSERT_NOT_REACHED(); 880 return; 881 } 882 883 m_owningLayer->updateLayerListsIfNeeded(); 884 885 // Calculate the clip rects we should use. 886 IntRect layerBounds, damageRect, clipRectToApply, outlineRect; 887 m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect); 888 889 int x = layerBounds.x(); // layerBounds is computed relative to rootLayer 890 int y = layerBounds.y(); 891 int tx = x - m_owningLayer->renderBoxX(); 892 int ty = y - m_owningLayer->renderBoxY(); 893 894 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which 895 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set). 896 // Else, our renderer tree may or may not contain the painting root, so we pass that root along 897 // so it will be tested against as we decend through the renderers. 898 RenderObject *paintingRootForRenderer = 0; 899 if (paintingRoot && !renderer()->isDescendantOf(paintingRoot)) 900 paintingRootForRenderer = paintingRoot; 901 902 bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer(); 903 904 if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) { 905 // If this is the root then we need to send in a bigger bounding box 906 // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()). 907 IntRect paintBox = clipRectToApply; 908 909 // FIXME: do we need this code? 910 if (renderer()->node() && renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) { 911 RenderBox* box = toRenderBox(renderer()); 912 int w = box->width(); 913 int h = box->height(); 914 915 int rw; 916 int rh; 917 if (FrameView* frameView = box->view()->frameView()) { 918 rw = frameView->contentsWidth(); 919 rh = frameView->contentsHeight(); 920 } else { 921 rw = box->view()->width(); 922 rh = box->view()->height(); 923 } 924 925 int bx = tx - box->marginLeft(); 926 int by = ty - box->marginTop(); 927 int bw = max(w + box->marginLeft() + box->marginRight() + box->borderLeft() + box->borderRight(), rw); 928 int bh = max(h + box->marginTop() + box->marginBottom() + box->borderTop() + box->borderBottom(), rh); 929 paintBox = IntRect(bx, by, bw, bh); 930 } 931 932 // Paint our background first, before painting any child layers. 933 // Establish the clip used to paint our background. 934 setClip(context, paintDirtyRect, damageRect); 935 936 RenderObject::PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0); 937 renderer()->paint(info, tx, ty); 938 939 // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with 940 // z-index. We paint after we painted the background/border, so that the scrollbars will 941 // sit above the background/border. 942 m_owningLayer->paintOverflowControls(context, x, y, damageRect); 943 944 // Restore the clip. 945 restoreClip(context, paintDirtyRect, damageRect); 946 } 947 948 bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText; 949 bool selectionOnly = paintBehavior & PaintBehaviorSelectionOnly; 950 951 if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) { 952 // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint. 953 // FIXME: should these be painted as background? 954 Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList(); 955 if (negZOrderList) { 956 for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) 957 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot); 958 } 959 960 // Set up the clip used when painting our children. 961 setClip(context, paintDirtyRect, clipRectToApply); 962 RenderObject::PaintInfo paintInfo(context, clipRectToApply, 963 selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, 964 forceBlackText, paintingRootForRenderer, 0); 965 renderer()->paint(paintInfo, tx, ty); 966 967 if (!selectionOnly) { 968 paintInfo.phase = PaintPhaseFloat; 969 renderer()->paint(paintInfo, tx, ty); 970 971 paintInfo.phase = PaintPhaseForeground; 972 renderer()->paint(paintInfo, tx, ty); 973 974 paintInfo.phase = PaintPhaseChildOutlines; 975 renderer()->paint(paintInfo, tx, ty); 976 } 977 978 // Now restore our clip. 979 restoreClip(context, paintDirtyRect, clipRectToApply); 980 981 if (!outlineRect.isEmpty()) { 982 // Paint our own outline 983 RenderObject::PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0); 984 setClip(context, paintDirtyRect, outlineRect); 985 renderer()->paint(paintInfo, tx, ty); 986 restoreClip(context, paintDirtyRect, outlineRect); 987 } 988 989 // Paint any child layers that have overflow. 990 Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList(); 991 if (normalFlowList) { 992 for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) 993 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot); 994 } 995 996 // Now walk the sorted list of children with positive z-indices. 997 Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList(); 998 if (posZOrderList) { 999 for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) 1000 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot); 1001 } 1002 } 1003 1004 if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) { 1005 if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) { 1006 setClip(context, paintDirtyRect, damageRect); 1007 1008 // Paint the mask. 1009 RenderObject::PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0); 1010 renderer()->paint(paintInfo, tx, ty); 1011 1012 // Restore the clip. 1013 restoreClip(context, paintDirtyRect, damageRect); 1014 } 1015 } 1016 1017 ASSERT(!m_owningLayer->m_usedTransparency); 1018 } 1019 1020 #if ENABLE(INSPECTOR) 1021 static InspectorTimelineAgent* inspectorTimelineAgent(RenderObject* renderer) 1022 { 1023 Frame* frame = renderer->document()->frame(); 1024 if (!frame) 1025 return 0; 1026 Page* page = frame->page(); 1027 if (!page) 1028 return 0; 1029 return page->inspectorTimelineAgent(); 1030 } 1031 #endif 1032 1033 // Up-call from compositing layer drawing callback. 1034 void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip) 1035 { 1036 #if ENABLE(INSPECTOR) 1037 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(m_owningLayer->renderer())) 1038 timelineAgent->willPaint(clip); 1039 #endif 1040 1041 // We have to use the same root as for hit testing, because both methods 1042 // can compute and cache clipRects. 1043 IntRect enclosingBBox = compositedBounds(); 1044 1045 IntRect clipRect(clip); 1046 1047 // Set up the coordinate space to be in the layer's rendering coordinates. 1048 context.translate(-enclosingBBox.x(), -enclosingBBox.y()); 1049 1050 // Offset the clip. 1051 clipRect.move(enclosingBBox.x(), enclosingBBox.y()); 1052 1053 // The dirtyRect is in the coords of the painting root. 1054 IntRect dirtyRect = enclosingBBox; 1055 dirtyRect.intersect(clipRect); 1056 1057 paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer()); 1058 1059 #if ENABLE(INSPECTOR) 1060 if (InspectorTimelineAgent* timelineAgent = inspectorTimelineAgent(m_owningLayer->renderer())) 1061 timelineAgent->didPaint(); 1062 #endif 1063 } 1064 1065 bool RenderLayerBacking::showDebugBorders() const 1066 { 1067 return compositor() ? compositor()->showDebugBorders() : false; 1068 } 1069 1070 bool RenderLayerBacking::showRepaintCounter() const 1071 { 1072 return compositor() ? compositor()->showRepaintCounter() : false; 1073 } 1074 1075 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes) 1076 { 1077 bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity); 1078 bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform); 1079 1080 if (!hasOpacity && !hasTransform) 1081 return false; 1082 1083 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 1084 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 1085 1086 for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) { 1087 const RenderStyle* keyframeStyle = it->style(); 1088 float key = it->key(); 1089 1090 if (!keyframeStyle) 1091 continue; 1092 1093 // get timing function 1094 const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0; 1095 1096 if (hasTransform) 1097 transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf)); 1098 1099 if (hasOpacity) 1100 opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)); 1101 } 1102 1103 bool didAnimateTransform = !hasTransform; 1104 bool didAnimateOpacity = !hasOpacity; 1105 1106 if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) 1107 didAnimateTransform = true; 1108 1109 if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) 1110 didAnimateOpacity = true; 1111 1112 bool runningAcceleratedAnimation = didAnimateTransform && didAnimateOpacity; 1113 if (runningAcceleratedAnimation) 1114 compositor()->didStartAcceleratedAnimation(); 1115 1116 return runningAcceleratedAnimation; 1117 } 1118 1119 bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle) 1120 { 1121 bool didAnimate = false; 1122 ASSERT(property != cAnimateAll); 1123 1124 if (property == (int)CSSPropertyOpacity) { 1125 const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity); 1126 if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) { 1127 KeyframeValueList opacityVector(AnimatedPropertyOpacity); 1128 opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity()))); 1129 opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity()))); 1130 // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here. 1131 if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, String(), timeOffset)) { 1132 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. 1133 updateLayerOpacity(toStyle); 1134 didAnimate = true; 1135 } 1136 } 1137 } 1138 1139 if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) { 1140 const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform); 1141 if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) { 1142 KeyframeValueList transformVector(AnimatedPropertyWebkitTransform); 1143 transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform())); 1144 transformVector.insert(new TransformAnimationValue(1, &toStyle->transform())); 1145 if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, String(), timeOffset)) { 1146 // To ensure that the correct transform is visible when the animation ends, also set the final opacity. 1147 updateLayerTransform(toStyle); 1148 didAnimate = true; 1149 } 1150 } 1151 } 1152 1153 if (didAnimate) 1154 compositor()->didStartAcceleratedAnimation(); 1155 1156 return didAnimate; 1157 } 1158 1159 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time) 1160 { 1161 renderer()->animation()->notifyAnimationStarted(renderer(), time); 1162 } 1163 1164 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*) 1165 { 1166 if (!renderer()->documentBeingDestroyed()) 1167 compositor()->scheduleSync(); 1168 } 1169 1170 void RenderLayerBacking::animationFinished(const String& animationName) 1171 { 1172 m_graphicsLayer->removeAnimationsForKeyframes(animationName); 1173 } 1174 1175 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName) 1176 { 1177 m_graphicsLayer->pauseAnimation(animationName, timeOffset); 1178 } 1179 1180 void RenderLayerBacking::transitionFinished(int property) 1181 { 1182 AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property); 1183 if (animatedProperty != AnimatedPropertyInvalid) 1184 m_graphicsLayer->removeAnimationsForProperty(animatedProperty); 1185 } 1186 1187 void RenderLayerBacking::suspendAnimations(double time) 1188 { 1189 m_graphicsLayer->suspendAnimations(time); 1190 } 1191 1192 void RenderLayerBacking::resumeAnimations() 1193 { 1194 m_graphicsLayer->resumeAnimations(); 1195 } 1196 1197 IntRect RenderLayerBacking::compositedBounds() const 1198 { 1199 return m_compositedBounds; 1200 } 1201 1202 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds) 1203 { 1204 m_compositedBounds = bounds; 1205 1206 } 1207 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property) 1208 { 1209 int cssProperty = CSSPropertyInvalid; 1210 switch (property) { 1211 case AnimatedPropertyWebkitTransform: 1212 cssProperty = CSSPropertyWebkitTransform; 1213 break; 1214 case AnimatedPropertyOpacity: 1215 cssProperty = CSSPropertyOpacity; 1216 break; 1217 case AnimatedPropertyBackgroundColor: 1218 cssProperty = CSSPropertyBackgroundColor; 1219 break; 1220 case AnimatedPropertyInvalid: 1221 ASSERT_NOT_REACHED(); 1222 } 1223 return cssProperty; 1224 } 1225 1226 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty) 1227 { 1228 switch (cssProperty) { 1229 case CSSPropertyWebkitTransform: 1230 return AnimatedPropertyWebkitTransform; 1231 case CSSPropertyOpacity: 1232 return AnimatedPropertyOpacity; 1233 case CSSPropertyBackgroundColor: 1234 return AnimatedPropertyBackgroundColor; 1235 // It's fine if we see other css properties here; they are just not accelerated. 1236 } 1237 return AnimatedPropertyInvalid; 1238 } 1239 1240 } // namespace WebCore 1241 1242 #endif // USE(ACCELERATED_COMPOSITING) 1243