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 63using namespace std; 64 65namespace WebCore { 66 67static void setLayerBorderColor(LayerChromium& layer, const Color& color) 68{ 69 layer.setBorderColor(color); 70} 71 72static void clearBorderColor(LayerChromium& layer) 73{ 74 layer.setBorderColor(static_cast<RGBA32>(0)); 75} 76 77static void setLayerBackgroundColor(LayerChromium& layer, const Color& color) 78{ 79 layer.setBackgroundColor(color); 80} 81 82static void clearLayerBackgroundColor(LayerChromium& layer) 83{ 84 layer.setBackgroundColor(static_cast<RGBA32>(0)); 85} 86 87PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 88{ 89 return new GraphicsLayerChromium(client); 90} 91 92GraphicsLayerChromium::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 102GraphicsLayerChromium::~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 112void 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 120void 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 130bool 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 141void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer) 142{ 143 GraphicsLayer::addChild(childLayer); 144 updateSublayerList(); 145} 146 147void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index) 148{ 149 GraphicsLayer::addChildAtIndex(childLayer, index); 150 updateSublayerList(); 151} 152 153void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) 154{ 155 GraphicsLayer::addChildBelow(childLayer, sibling); 156 updateSublayerList(); 157} 158 159void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling) 160{ 161 GraphicsLayer::addChildAbove(childLayer, sibling); 162 updateSublayerList(); 163} 164 165bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 166{ 167 if (GraphicsLayer::replaceChild(oldChild, newChild)) { 168 updateSublayerList(); 169 return true; 170 } 171 return false; 172} 173 174void GraphicsLayerChromium::removeFromParent() 175{ 176 GraphicsLayer::removeFromParent(); 177 layerForSuperlayer()->removeFromSuperlayer(); 178} 179 180void GraphicsLayerChromium::setPosition(const FloatPoint& point) 181{ 182 GraphicsLayer::setPosition(point); 183 updateLayerPosition(); 184} 185 186void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point) 187{ 188 if (point == m_anchorPoint) 189 return; 190 191 GraphicsLayer::setAnchorPoint(point); 192 updateAnchorPoint(); 193} 194 195void GraphicsLayerChromium::setSize(const FloatSize& size) 196{ 197 if (size == m_size) 198 return; 199 200 GraphicsLayer::setSize(size); 201 updateLayerSize(); 202} 203 204void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform) 205{ 206 if (transform == m_transform) 207 return; 208 209 GraphicsLayer::setTransform(transform); 210 updateTransform(); 211} 212 213void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform) 214{ 215 if (transform == m_childrenTransform) 216 return; 217 218 GraphicsLayer::setChildrenTransform(transform); 219 updateChildrenTransform(); 220} 221 222void GraphicsLayerChromium::setPreserves3D(bool preserves3D) 223{ 224 if (preserves3D == m_preserves3D) 225 return; 226 227 GraphicsLayer::setPreserves3D(preserves3D); 228 updateLayerPreserves3D(); 229} 230 231void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds) 232{ 233 if (masksToBounds == m_masksToBounds) 234 return; 235 236 GraphicsLayer::setMasksToBounds(masksToBounds); 237 updateMasksToBounds(); 238} 239 240void GraphicsLayerChromium::setDrawsContent(bool drawsContent) 241{ 242 if (drawsContent == m_drawsContent) 243 return; 244 245 GraphicsLayer::setDrawsContent(drawsContent); 246 updateLayerDrawsContent(); 247} 248 249void 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 260void GraphicsLayerChromium::clearBackgroundColor() 261{ 262 if (!m_backgroundColorSet) 263 return; 264 265 GraphicsLayer::clearBackgroundColor(); 266 clearLayerBackgroundColor(*m_contentsLayer); 267} 268 269void GraphicsLayerChromium::setContentsOpaque(bool opaque) 270{ 271 if (m_contentsOpaque == opaque) 272 return; 273 274 GraphicsLayer::setContentsOpaque(opaque); 275 updateContentsOpaque(); 276} 277 278void 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 291void GraphicsLayerChromium::setBackfaceVisibility(bool visible) 292{ 293 if (m_backfaceVisibility == visible) 294 return; 295 296 GraphicsLayer::setBackfaceVisibility(visible); 297 updateBackfaceVisibility(); 298} 299 300void 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 311void 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 320void GraphicsLayerChromium::setContentsNeedsDisplay() 321{ 322 if (m_contentsLayer) 323 m_contentsLayer->setNeedsDisplay(); 324} 325 326void GraphicsLayerChromium::setNeedsDisplay() 327{ 328 if (drawsContent()) 329 m_layer->setNeedsDisplay(); 330} 331 332void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect) 333{ 334 if (drawsContent()) 335 m_layer->setNeedsDisplay(rect); 336} 337 338void GraphicsLayerChromium::setContentsRect(const IntRect& rect) 339{ 340 if (rect == m_contentsRect) 341 return; 342 343 GraphicsLayer::setContentsRect(rect); 344 updateContentsRect(); 345} 346 347void 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 374void 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 400void 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 426PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const 427{ 428 return m_transformLayer ? m_transformLayer.get() : m_layer.get(); 429} 430 431PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const 432{ 433 return m_transformLayer ? m_transformLayer.get() : m_layer.get(); 434} 435 436PlatformLayer* GraphicsLayerChromium::platformLayer() const 437{ 438 return primaryLayer(); 439} 440 441void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color) 442{ 443 if (color.isValid()) 444 setLayerBackgroundColor(*m_layer, color); 445 else 446 clearLayerBackgroundColor(*m_layer); 447} 448 449void 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 460void 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 499void 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 508void 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 527void GraphicsLayerChromium::updateAnchorPoint() 528{ 529 primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())); 530 primaryLayer()->setAnchorPointZ(m_anchorPoint.z()); 531 532 updateLayerPosition(); 533} 534 535void GraphicsLayerChromium::updateTransform() 536{ 537 primaryLayer()->setTransform(m_transform); 538} 539 540void GraphicsLayerChromium::updateChildrenTransform() 541{ 542 primaryLayer()->setSublayerTransform(m_childrenTransform); 543} 544 545void GraphicsLayerChromium::updateMasksToBounds() 546{ 547 m_layer->setMasksToBounds(m_masksToBounds); 548 updateDebugIndicators(); 549} 550 551void GraphicsLayerChromium::updateContentsOpaque() 552{ 553 m_layer->setOpaque(m_contentsOpaque); 554} 555 556void GraphicsLayerChromium::updateBackfaceVisibility() 557{ 558 m_layer->setDoubleSided(m_backfaceVisibility); 559} 560 561void 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 610void GraphicsLayerChromium::updateLayerDrawsContent() 611{ 612 if (m_drawsContent) 613 m_layer->setNeedsDisplay(); 614 615 updateDebugIndicators(); 616} 617 618void 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 630void GraphicsLayerChromium::updateContentsVideo() 631{ 632 // FIXME: Implement 633} 634 635void 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 644void 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 675void GraphicsLayerChromium::updateOpacityOnLayer() 676{ 677 primaryLayer()->setOpacity(m_opacity); 678} 679 680} // namespace WebCore 681 682#endif // USE(ACCELERATED_COMPOSITING) 683