1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * Copyright (C) 2009 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 33 /** FIXME 34 * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp 35 * (and hence it includes both copyrights) 36 * Ideally the common code (mostly the code that keeps track of the layer hierarchy) 37 * should be kept separate and shared between platforms. It would be a well worthwhile 38 * effort once the Windows implementation (binaries and headers) of CoreAnimation is 39 * checked in to the WebKit repository. Until then only Apple can make this happen. 40 */ 41 42 #include "config.h" 43 44 #if USE(ACCELERATED_COMPOSITING) 45 46 #include "GraphicsLayerChromium.h" 47 48 #include "Canvas2DLayerChromium.h" 49 #include "ContentLayerChromium.h" 50 #include "DrawingBuffer.h" 51 #include "FloatConversion.h" 52 #include "FloatRect.h" 53 #include "Image.h" 54 #include "ImageLayerChromium.h" 55 #include "LayerChromium.h" 56 #include "PlatformString.h" 57 #include "SystemTime.h" 58 59 #include <wtf/CurrentTime.h> 60 #include <wtf/StringExtras.h> 61 #include <wtf/text/CString.h> 62 63 using namespace std; 64 65 namespace WebCore { 66 67 static void setLayerBorderColor(LayerChromium& layer, const Color& color) 68 { 69 layer.setBorderColor(color); 70 } 71 72 static void clearBorderColor(LayerChromium& layer) 73 { 74 layer.setBorderColor(static_cast<RGBA32>(0)); 75 } 76 77 static void setLayerBackgroundColor(LayerChromium& layer, const Color& color) 78 { 79 layer.setBackgroundColor(color); 80 } 81 82 static void clearLayerBackgroundColor(LayerChromium& layer) 83 { 84 layer.setBackgroundColor(static_cast<RGBA32>(0)); 85 } 86 87 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 88 { 89 return new GraphicsLayerChromium(client); 90 } 91 92 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client) 93 : GraphicsLayer(client) 94 , m_contentsLayerPurpose(NoContentsLayer) 95 , m_contentsLayerHasBackgroundColor(false) 96 { 97 m_layer = ContentLayerChromium::create(this); 98 99 updateDebugIndicators(); 100 } 101 102 GraphicsLayerChromium::~GraphicsLayerChromium() 103 { 104 if (m_layer) 105 m_layer->setOwner(0); 106 if (m_contentsLayer) 107 m_contentsLayer->setOwner(0); 108 if (m_transformLayer) 109 m_transformLayer->setOwner(0); 110 } 111 112 void GraphicsLayerChromium::setName(const String& inName) 113 { 114 m_nameBase = inName; 115 String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName; 116 GraphicsLayer::setName(name); 117 updateNames(); 118 } 119 120 void GraphicsLayerChromium::updateNames() 121 { 122 if (m_layer) 123 m_layer->setName("Layer for " + m_nameBase); 124 if (m_transformLayer) 125 m_transformLayer->setName("TransformLayer for " + m_nameBase); 126 if (m_contentsLayer) 127 m_contentsLayer->setName("ContentsLayer for " + m_nameBase); 128 } 129 130 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children) 131 { 132 bool childrenChanged = GraphicsLayer::setChildren(children); 133 // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which 134 // will end up calling updateSublayerList() N times. 135 if (childrenChanged) 136 updateSublayerList(); 137 138 return childrenChanged; 139 } 140 141 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer) 142 { 143 GraphicsLayer::addChild(childLayer); 144 updateSublayerList(); 145 } 146 147 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index) 148 { 149 GraphicsLayer::addChildAtIndex(childLayer, index); 150 updateSublayerList(); 151 } 152 153 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 154 { 155 GraphicsLayer::addChildBelow(childLayer, sibling); 156 updateSublayerList(); 157 } 158 159 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling) 160 { 161 GraphicsLayer::addChildAbove(childLayer, sibling); 162 updateSublayerList(); 163 } 164 165 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 166 { 167 if (GraphicsLayer::replaceChild(oldChild, newChild)) { 168 updateSublayerList(); 169 return true; 170 } 171 return false; 172 } 173 174 void GraphicsLayerChromium::removeFromParent() 175 { 176 GraphicsLayer::removeFromParent(); 177 layerForSuperlayer()->removeFromSuperlayer(); 178 } 179 180 void GraphicsLayerChromium::setPosition(const FloatPoint& point) 181 { 182 GraphicsLayer::setPosition(point); 183 updateLayerPosition(); 184 } 185 186 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point) 187 { 188 if (point == m_anchorPoint) 189 return; 190 191 GraphicsLayer::setAnchorPoint(point); 192 updateAnchorPoint(); 193 } 194 195 void GraphicsLayerChromium::setSize(const FloatSize& size) 196 { 197 if (size == m_size) 198 return; 199 200 GraphicsLayer::setSize(size); 201 updateLayerSize(); 202 } 203 204 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform) 205 { 206 if (transform == m_transform) 207 return; 208 209 GraphicsLayer::setTransform(transform); 210 updateTransform(); 211 } 212 213 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform) 214 { 215 if (transform == m_childrenTransform) 216 return; 217 218 GraphicsLayer::setChildrenTransform(transform); 219 updateChildrenTransform(); 220 } 221 222 void GraphicsLayerChromium::setPreserves3D(bool preserves3D) 223 { 224 if (preserves3D == m_preserves3D) 225 return; 226 227 GraphicsLayer::setPreserves3D(preserves3D); 228 updateLayerPreserves3D(); 229 } 230 231 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds) 232 { 233 if (masksToBounds == m_masksToBounds) 234 return; 235 236 GraphicsLayer::setMasksToBounds(masksToBounds); 237 updateMasksToBounds(); 238 } 239 240 void GraphicsLayerChromium::setDrawsContent(bool drawsContent) 241 { 242 if (drawsContent == m_drawsContent) 243 return; 244 245 GraphicsLayer::setDrawsContent(drawsContent); 246 updateLayerDrawsContent(); 247 } 248 249 void GraphicsLayerChromium::setBackgroundColor(const Color& color) 250 { 251 if (m_backgroundColorSet && m_backgroundColor == color) 252 return; 253 254 GraphicsLayer::setBackgroundColor(color); 255 256 m_contentsLayerHasBackgroundColor = true; 257 updateLayerBackgroundColor(); 258 } 259 260 void GraphicsLayerChromium::clearBackgroundColor() 261 { 262 if (!m_backgroundColorSet) 263 return; 264 265 GraphicsLayer::clearBackgroundColor(); 266 clearLayerBackgroundColor(*m_contentsLayer); 267 } 268 269 void GraphicsLayerChromium::setContentsOpaque(bool opaque) 270 { 271 if (m_contentsOpaque == opaque) 272 return; 273 274 GraphicsLayer::setContentsOpaque(opaque); 275 updateContentsOpaque(); 276 } 277 278 void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer) 279 { 280 if (maskLayer == m_maskLayer) 281 return; 282 283 GraphicsLayer::setMaskLayer(maskLayer); 284 285 LayerChromium* maskLayerChromium = m_maskLayer ? m_maskLayer->platformLayer() : 0; 286 if (maskLayerChromium) 287 maskLayerChromium->setIsMask(true); 288 m_layer->setMaskLayer(maskLayerChromium); 289 } 290 291 void GraphicsLayerChromium::setBackfaceVisibility(bool visible) 292 { 293 if (m_backfaceVisibility == visible) 294 return; 295 296 GraphicsLayer::setBackfaceVisibility(visible); 297 updateBackfaceVisibility(); 298 } 299 300 void GraphicsLayerChromium::setOpacity(float opacity) 301 { 302 float clampedOpacity = max(min(opacity, 1.0f), 0.0f); 303 304 if (m_opacity == clampedOpacity) 305 return; 306 307 GraphicsLayer::setOpacity(clampedOpacity); 308 primaryLayer()->setOpacity(opacity); 309 } 310 311 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer) 312 { 313 GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer); 314 GraphicsLayer::setReplicatedByLayer(layer); 315 LayerChromium* replicaLayer = layerChromium ? layerChromium->primaryLayer() : 0; 316 primaryLayer()->setReplicaLayer(replicaLayer); 317 } 318 319 320 void GraphicsLayerChromium::setContentsNeedsDisplay() 321 { 322 if (m_contentsLayer) 323 m_contentsLayer->setNeedsDisplay(); 324 } 325 326 void GraphicsLayerChromium::setNeedsDisplay() 327 { 328 if (drawsContent()) 329 m_layer->setNeedsDisplay(); 330 } 331 332 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect) 333 { 334 if (drawsContent()) 335 m_layer->setNeedsDisplay(rect); 336 } 337 338 void GraphicsLayerChromium::setContentsRect(const IntRect& rect) 339 { 340 if (rect == m_contentsRect) 341 return; 342 343 GraphicsLayer::setContentsRect(rect); 344 updateContentsRect(); 345 } 346 347 void GraphicsLayerChromium::setContentsToImage(Image* image) 348 { 349 bool childrenChanged = false; 350 if (image) { 351 if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) { 352 RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this); 353 setupContentsLayer(imageLayer.get()); 354 m_contentsLayer = imageLayer; 355 m_contentsLayerPurpose = ContentsLayerForImage; 356 childrenChanged = true; 357 } 358 ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get()); 359 imageLayer->setContents(image); 360 updateContentsRect(); 361 } else { 362 if (m_contentsLayer) { 363 childrenChanged = true; 364 365 // The old contents layer will be removed via updateSublayerList. 366 m_contentsLayer = 0; 367 } 368 } 369 370 if (childrenChanged) 371 updateSublayerList(); 372 } 373 374 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer) 375 { 376 bool childrenChanged = false; 377 if (platformLayer) { 378 platformLayer->setOwner(this); 379 if (m_contentsLayer.get() != platformLayer) { 380 setupContentsLayer(platformLayer); 381 m_contentsLayer = platformLayer; 382 m_contentsLayerPurpose = ContentsLayerForCanvas; 383 childrenChanged = true; 384 } 385 m_contentsLayer->setNeedsDisplay(); 386 updateContentsRect(); 387 } else { 388 if (m_contentsLayer) { 389 childrenChanged = true; 390 391 // The old contents layer will be removed via updateSublayerList. 392 m_contentsLayer = 0; 393 } 394 } 395 396 if (childrenChanged) 397 updateSublayerList(); 398 } 399 400 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer) 401 { 402 bool childrenChanged = false; 403 if (layer) { 404 if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) { 405 setupContentsLayer(layer); 406 m_contentsLayer = layer; 407 m_contentsLayerPurpose = ContentsLayerForVideo; 408 childrenChanged = true; 409 } 410 layer->setOwner(this); 411 layer->setNeedsDisplay(); 412 updateContentsRect(); 413 } else { 414 if (m_contentsLayer) { 415 childrenChanged = true; 416 417 // The old contents layer will be removed via updateSublayerList. 418 m_contentsLayer = 0; 419 } 420 } 421 422 if (childrenChanged) 423 updateSublayerList(); 424 } 425 426 PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const 427 { 428 return m_transformLayer ? m_transformLayer.get() : m_layer.get(); 429 } 430 431 PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const 432 { 433 return m_transformLayer ? m_transformLayer.get() : m_layer.get(); 434 } 435 436 PlatformLayer* GraphicsLayerChromium::platformLayer() const 437 { 438 return primaryLayer(); 439 } 440 441 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color) 442 { 443 if (color.isValid()) 444 setLayerBackgroundColor(*m_layer, color); 445 else 446 clearLayerBackgroundColor(*m_layer); 447 } 448 449 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth) 450 { 451 if (color.isValid()) { 452 setLayerBorderColor(*m_layer, color); 453 m_layer->setBorderWidth(borderWidth); 454 } else { 455 clearBorderColor(*m_layer); 456 m_layer->setBorderWidth(0); 457 } 458 } 459 460 void GraphicsLayerChromium::updateSublayerList() 461 { 462 Vector<RefPtr<LayerChromium> > newSublayers; 463 464 if (m_transformLayer) { 465 // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind. 466 newSublayers.append(m_layer.get()); 467 } else if (m_contentsLayer) { 468 // FIXME: add the contents layer in the correct order with negative z-order children. 469 // This does not cause visible rendering issues because currently contents layers are only used 470 // for replaced elements that don't have children. 471 newSublayers.append(m_contentsLayer.get()); 472 } 473 474 const Vector<GraphicsLayer*>& childLayers = children(); 475 size_t numChildren = childLayers.size(); 476 for (size_t i = 0; i < numChildren; ++i) { 477 GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]); 478 479 LayerChromium* childLayer = curChild->layerForSuperlayer(); 480 newSublayers.append(childLayer); 481 } 482 483 for (size_t i = 0; i < newSublayers.size(); ++i) 484 newSublayers[i]->removeFromSuperlayer(); 485 486 if (m_transformLayer) { 487 m_transformLayer->setSublayers(newSublayers); 488 489 if (m_contentsLayer) { 490 // If we have a transform layer, then the contents layer is parented in the 491 // primary layer (which is itself a child of the transform layer). 492 m_layer->removeAllSublayers(); 493 m_layer->addSublayer(m_contentsLayer); 494 } 495 } else 496 m_layer->setSublayers(newSublayers); 497 } 498 499 void GraphicsLayerChromium::updateLayerPosition() 500 { 501 // Position is offset on the layer by the layer anchor point. 502 FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), 503 m_position.y() + m_anchorPoint.y() * m_size.height()); 504 505 primaryLayer()->setPosition(layerPosition); 506 } 507 508 void GraphicsLayerChromium::updateLayerSize() 509 { 510 IntSize layerSize(m_size.width(), m_size.height()); 511 if (m_transformLayer) { 512 m_transformLayer->setBounds(layerSize); 513 // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. 514 FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2); 515 m_layer->setPosition(centerPoint); 516 } 517 518 m_layer->setBounds(layerSize); 519 520 // Note that we don't resize m_contentsLayer. It's up the caller to do that. 521 522 // If we've changed the bounds, we need to recalculate the position 523 // of the layer, taking anchor point into account. 524 updateLayerPosition(); 525 } 526 527 void GraphicsLayerChromium::updateAnchorPoint() 528 { 529 primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())); 530 primaryLayer()->setAnchorPointZ(m_anchorPoint.z()); 531 532 updateLayerPosition(); 533 } 534 535 void GraphicsLayerChromium::updateTransform() 536 { 537 primaryLayer()->setTransform(m_transform); 538 } 539 540 void GraphicsLayerChromium::updateChildrenTransform() 541 { 542 primaryLayer()->setSublayerTransform(m_childrenTransform); 543 } 544 545 void GraphicsLayerChromium::updateMasksToBounds() 546 { 547 m_layer->setMasksToBounds(m_masksToBounds); 548 updateDebugIndicators(); 549 } 550 551 void GraphicsLayerChromium::updateContentsOpaque() 552 { 553 m_layer->setOpaque(m_contentsOpaque); 554 } 555 556 void GraphicsLayerChromium::updateBackfaceVisibility() 557 { 558 m_layer->setDoubleSided(m_backfaceVisibility); 559 } 560 561 void GraphicsLayerChromium::updateLayerPreserves3D() 562 { 563 if (m_preserves3D && !m_transformLayer) { 564 // Create the transform layer. 565 m_transformLayer = LayerChromium::create(this); 566 567 // Copy the position from this layer. 568 updateLayerPosition(); 569 updateLayerSize(); 570 updateAnchorPoint(); 571 updateTransform(); 572 updateChildrenTransform(); 573 574 m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f)); 575 576 m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f)); 577 TransformationMatrix identity; 578 m_layer->setTransform(identity); 579 580 // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer. 581 m_layer->setOpacity(1); 582 583 // Move this layer to be a child of the transform layer. 584 if (m_layer->superlayer()) 585 m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get()); 586 m_transformLayer->addSublayer(m_layer.get()); 587 588 updateSublayerList(); 589 } else if (!m_preserves3D && m_transformLayer) { 590 // Relace the transformLayer in the parent with this layer. 591 m_layer->removeFromSuperlayer(); 592 m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get()); 593 594 // Release the transform layer. 595 m_transformLayer = 0; 596 597 updateLayerPosition(); 598 updateLayerSize(); 599 updateAnchorPoint(); 600 updateTransform(); 601 updateChildrenTransform(); 602 603 updateSublayerList(); 604 } 605 606 updateOpacityOnLayer(); 607 updateNames(); 608 } 609 610 void GraphicsLayerChromium::updateLayerDrawsContent() 611 { 612 if (m_drawsContent) 613 m_layer->setNeedsDisplay(); 614 615 updateDebugIndicators(); 616 } 617 618 void GraphicsLayerChromium::updateLayerBackgroundColor() 619 { 620 if (!m_contentsLayer) 621 return; 622 623 // We never create the contents layer just for background color yet. 624 if (m_backgroundColorSet) 625 setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor); 626 else 627 clearLayerBackgroundColor(*m_contentsLayer); 628 } 629 630 void GraphicsLayerChromium::updateContentsVideo() 631 { 632 // FIXME: Implement 633 } 634 635 void GraphicsLayerChromium::updateContentsRect() 636 { 637 if (!m_contentsLayer) 638 return; 639 640 m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y())); 641 m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height())); 642 } 643 644 void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer) 645 { 646 if (contentsLayer == m_contentsLayer) 647 return; 648 649 if (m_contentsLayer) { 650 m_contentsLayer->removeFromSuperlayer(); 651 m_contentsLayer = 0; 652 } 653 654 if (contentsLayer) { 655 m_contentsLayer = contentsLayer; 656 657 m_contentsLayer->setAnchorPoint(FloatPoint(0, 0)); 658 659 // Insert the content layer first. Video elements require this, because they have 660 // shadow content that must display in front of the video. 661 m_layer->insertSublayer(m_contentsLayer.get(), 0); 662 663 updateContentsRect(); 664 665 if (showDebugBorders()) { 666 setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180)); 667 m_contentsLayer->setBorderWidth(1); 668 } 669 } 670 updateDebugIndicators(); 671 updateNames(); 672 } 673 674 // This function simply mimics the operation of GraphicsLayerCA 675 void GraphicsLayerChromium::updateOpacityOnLayer() 676 { 677 primaryLayer()->setOpacity(m_opacity); 678 } 679 680 } // namespace WebCore 681 682 #endif // USE(ACCELERATED_COMPOSITING) 683