1/* 2 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Library General Public 6 License as published by the Free Software Foundation; either 7 version 2 of the License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public License 15 along with this library; see the file COPYING.LIB. If not, write to 16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Boston, MA 02110-1301, USA. 18*/ 19 20#include "config.h" 21#include "GraphicsLayerTextureMapper.h" 22 23#include "GraphicsContext.h" 24#include "GraphicsLayerAnimation.h" 25#include "GraphicsLayerFactory.h" 26#include "ImageBuffer.h" 27#include <wtf/CurrentTime.h> 28 29#if USE(TEXTURE_MAPPER) 30 31namespace WebCore { 32 33TextureMapperLayer* toTextureMapperLayer(GraphicsLayer* layer) 34{ 35 return layer ? toGraphicsLayerTextureMapper(layer)->layer() : 0; 36} 37 38PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) 39{ 40 if (!factory) 41 return adoptPtr(new GraphicsLayerTextureMapper(client)); 42 43 return factory->createGraphicsLayer(client); 44} 45 46PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) 47{ 48 return adoptPtr(new GraphicsLayerTextureMapper(client)); 49} 50 51GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(GraphicsLayerClient* client) 52 : GraphicsLayer(client) 53 , m_layer(adoptPtr(new TextureMapperLayer())) 54 , m_compositedNativeImagePtr(0) 55 , m_changeMask(NoChanges) 56 , m_needsDisplay(false) 57 , m_fixedToViewport(false) 58 , m_debugBorderWidth(0) 59 , m_contentsLayer(0) 60 , m_animationStartTime(0) 61 , m_isScrollable(false) 62{ 63} 64 65void GraphicsLayerTextureMapper::notifyChange(ChangeMask changeMask) 66{ 67 m_changeMask |= changeMask; 68 if (!client()) 69 return; 70 client()->notifyFlushRequired(this); 71} 72 73void GraphicsLayerTextureMapper::setName(const String& name) 74{ 75 GraphicsLayer::setName(name); 76} 77 78GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper() 79{ 80 willBeDestroyed(); 81} 82 83void GraphicsLayerTextureMapper::willBeDestroyed() 84{ 85 GraphicsLayer::willBeDestroyed(); 86} 87 88/* \reimp (GraphicsLayer.h): The current size might change, thus we need to update the whole display. 89*/ 90void GraphicsLayerTextureMapper::setNeedsDisplay() 91{ 92 if (!drawsContent()) 93 return; 94 95 m_needsDisplay = true; 96 notifyChange(DisplayChange); 97 addRepaintRect(FloatRect(FloatPoint(), m_size)); 98} 99 100/* \reimp (GraphicsLayer.h) 101*/ 102void GraphicsLayerTextureMapper::setContentsNeedsDisplay() 103{ 104 notifyChange(DisplayChange); 105 addRepaintRect(contentsRect()); 106} 107 108/* \reimp (GraphicsLayer.h) 109*/ 110void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect) 111{ 112 if (!drawsContent()) 113 return; 114 115 if (m_needsDisplay) 116 return; 117 m_needsDisplayRect.unite(rect); 118 notifyChange(DisplayChange); 119 addRepaintRect(rect); 120} 121 122/* \reimp (GraphicsLayer.h) 123*/ 124bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children) 125{ 126 if (GraphicsLayer::setChildren(children)) { 127 notifyChange(ChildrenChange); 128 return true; 129 } 130 return false; 131} 132 133/* \reimp (GraphicsLayer.h) 134*/ 135void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer) 136{ 137 notifyChange(ChildrenChange); 138 GraphicsLayer::addChild(layer); 139} 140 141/* \reimp (GraphicsLayer.h) 142*/ 143void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index) 144{ 145 GraphicsLayer::addChildAtIndex(layer, index); 146 notifyChange(ChildrenChange); 147} 148 149/* \reimp (GraphicsLayer.h) 150*/ 151void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling) 152{ 153 GraphicsLayer::addChildAbove(layer, sibling); 154 notifyChange(ChildrenChange); 155} 156 157/* \reimp (GraphicsLayer.h) 158*/ 159void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling) 160{ 161 GraphicsLayer::addChildBelow(layer, sibling); 162 notifyChange(ChildrenChange); 163} 164 165/* \reimp (GraphicsLayer.h) 166*/ 167bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) 168{ 169 if (GraphicsLayer::replaceChild(oldChild, newChild)) { 170 notifyChange(ChildrenChange); 171 return true; 172 } 173 return false; 174} 175 176/* \reimp (GraphicsLayer.h) 177*/ 178void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value) 179{ 180 if (value == maskLayer()) 181 return; 182 GraphicsLayer::setMaskLayer(value); 183 notifyChange(MaskLayerChange); 184 185 if (!value) 186 return; 187 value->setSize(size()); 188 value->setContentsVisible(contentsAreVisible()); 189} 190 191 192/* \reimp (GraphicsLayer.h) 193*/ 194void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value) 195{ 196 if (value == replicaLayer()) 197 return; 198 GraphicsLayer::setReplicatedByLayer(value); 199 notifyChange(ReplicaLayerChange); 200} 201 202/* \reimp (GraphicsLayer.h) 203*/ 204void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value) 205{ 206 if (value == position()) 207 return; 208 GraphicsLayer::setPosition(value); 209 notifyChange(PositionChange); 210} 211 212/* \reimp (GraphicsLayer.h) 213*/ 214void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value) 215{ 216 if (value == anchorPoint()) 217 return; 218 GraphicsLayer::setAnchorPoint(value); 219 notifyChange(AnchorPointChange); 220} 221 222/* \reimp (GraphicsLayer.h) 223*/ 224void GraphicsLayerTextureMapper::setSize(const FloatSize& value) 225{ 226 if (value == size()) 227 return; 228 229 GraphicsLayer::setSize(value); 230 if (maskLayer()) 231 maskLayer()->setSize(value); 232 notifyChange(SizeChange); 233} 234 235/* \reimp (GraphicsLayer.h) 236*/ 237void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value) 238{ 239 if (value == transform()) 240 return; 241 242 GraphicsLayer::setTransform(value); 243 notifyChange(TransformChange); 244} 245 246/* \reimp (GraphicsLayer.h) 247*/ 248void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value) 249{ 250 if (value == childrenTransform()) 251 return; 252 GraphicsLayer::setChildrenTransform(value); 253 notifyChange(ChildrenTransformChange); 254} 255 256/* \reimp (GraphicsLayer.h) 257*/ 258void GraphicsLayerTextureMapper::setPreserves3D(bool value) 259{ 260 if (value == preserves3D()) 261 return; 262 GraphicsLayer::setPreserves3D(value); 263 notifyChange(Preserves3DChange); 264} 265 266/* \reimp (GraphicsLayer.h) 267*/ 268void GraphicsLayerTextureMapper::setMasksToBounds(bool value) 269{ 270 if (value == masksToBounds()) 271 return; 272 GraphicsLayer::setMasksToBounds(value); 273 notifyChange(MasksToBoundsChange); 274} 275 276/* \reimp (GraphicsLayer.h) 277*/ 278void GraphicsLayerTextureMapper::setDrawsContent(bool value) 279{ 280 if (value == drawsContent()) 281 return; 282 GraphicsLayer::setDrawsContent(value); 283 notifyChange(DrawsContentChange); 284 285 if (value) 286 setNeedsDisplay(); 287} 288 289/* \reimp (GraphicsLayer.h) 290*/ 291void GraphicsLayerTextureMapper::setContentsVisible(bool value) 292{ 293 if (value == contentsAreVisible()) 294 return; 295 notifyChange(ContentsVisibleChange); 296 GraphicsLayer::setContentsVisible(value); 297 if (maskLayer()) 298 maskLayer()->setContentsVisible(value); 299} 300 301/* \reimp (GraphicsLayer.h) 302*/ 303void GraphicsLayerTextureMapper::setContentsOpaque(bool value) 304{ 305 if (value == contentsOpaque()) 306 return; 307 notifyChange(ContentsOpaqueChange); 308 GraphicsLayer::setContentsOpaque(value); 309} 310 311/* \reimp (GraphicsLayer.h) 312*/ 313void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value) 314{ 315 if (value == backfaceVisibility()) 316 return; 317 GraphicsLayer::setBackfaceVisibility(value); 318 notifyChange(BackfaceVisibilityChange); 319} 320 321/* \reimp (GraphicsLayer.h) 322*/ 323void GraphicsLayerTextureMapper::setOpacity(float value) 324{ 325 if (value == opacity()) 326 return; 327 GraphicsLayer::setOpacity(value); 328 notifyChange(OpacityChange); 329} 330 331/* \reimp (GraphicsLayer.h) 332*/ 333void GraphicsLayerTextureMapper::setContentsRect(const IntRect& value) 334{ 335 if (value == contentsRect()) 336 return; 337 GraphicsLayer::setContentsRect(value); 338 notifyChange(ContentsRectChange); 339} 340 341void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color) 342{ 343 if (color == m_solidColor) 344 return; 345 346 m_solidColor = color; 347 notifyChange(BackgroundColorChange); 348} 349 350 351/* \reimp (GraphicsLayer.h) 352*/ 353void GraphicsLayerTextureMapper::setContentsToImage(Image* image) 354{ 355 if (image) { 356 // Make the decision about whether the image has changed. 357 // This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed. 358 // This assumption is true in Qt, GTK and EFL. 359 NativeImagePtr newNativeImagePtr = image->nativeImageForCurrentFrame(); 360 if (!newNativeImagePtr) 361 return; 362 363 if (newNativeImagePtr == m_compositedNativeImagePtr) 364 return; 365 366 m_compositedNativeImagePtr = newNativeImagePtr; 367 if (!m_compositedImage) 368 m_compositedImage = TextureMapperTiledBackingStore::create(); 369 m_compositedImage->setContentsToImage(image); 370 } else { 371 m_compositedNativeImagePtr = 0; 372 m_compositedImage = 0; 373 } 374 375 setContentsToMedia(m_compositedImage.get()); 376 notifyChange(ContentChange); 377 GraphicsLayer::setContentsToImage(image); 378} 379 380void GraphicsLayerTextureMapper::setContentsToMedia(TextureMapperPlatformLayer* media) 381{ 382 if (media == m_contentsLayer) 383 return; 384 385 GraphicsLayer::setContentsToMedia(media); 386 notifyChange(ContentChange); 387 m_contentsLayer = media; 388 389 m_contentsLayer->setClient(this); 390} 391 392void GraphicsLayerTextureMapper::setShowDebugBorder(bool show) 393{ 394 if (isShowingDebugBorder() == show) 395 return; 396 397 GraphicsLayer::setShowDebugBorder(show); 398 notifyChange(DebugVisualsChange); 399} 400 401void GraphicsLayerTextureMapper::setShowRepaintCounter(bool show) 402{ 403 if (isShowingRepaintCounter() == show) 404 return; 405 406 GraphicsLayer::setShowRepaintCounter(show); 407 notifyChange(DebugVisualsChange); 408} 409 410void GraphicsLayerTextureMapper::didCommitScrollOffset(const IntSize& offset) 411{ 412 if (offset.isZero()) 413 return; 414 415 m_committedScrollOffset = offset; 416 notifyChange(CommittedScrollOffsetChange); 417} 418 419void GraphicsLayerTextureMapper::setIsScrollable(bool isScrollable) 420{ 421 if (m_isScrollable == isScrollable) 422 return; 423 424 m_isScrollable = isScrollable; 425 notifyChange(IsScrollableChange); 426} 427 428/* \reimp (GraphicsLayer.h) 429*/ 430void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly() 431{ 432 prepareBackingStoreIfNeeded(); 433 commitLayerChanges(); 434 m_layer->syncAnimations(); 435 updateBackingStoreIfNeeded(); 436} 437 438void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded() 439{ 440 if (!shouldHaveBackingStore()) { 441 m_backingStore.clear(); 442 m_changeMask |= BackingStoreChange; 443 } else { 444 if (!m_backingStore) { 445 m_backingStore = TextureMapperTiledBackingStore::create(); 446 m_changeMask |= BackingStoreChange; 447 } 448 } 449 450 updateDebugBorderAndRepaintCount(); 451} 452 453void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount() 454{ 455 if (isShowingDebugBorder()) 456 updateDebugIndicators(); 457 458 // When this has its own backing store (e.g. Qt WK1), update the repaint count before calling TextureMapperLayer::flushCompositingStateForThisLayerOnly(). 459 bool needsToRepaint = shouldHaveBackingStore() && (m_needsDisplay || !m_needsDisplayRect.isEmpty()); 460 if (isShowingRepaintCounter() && needsToRepaint) { 461 incrementRepaintCount(); 462 m_changeMask |= RepaintCountChange; 463 } 464} 465 466void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width) 467{ 468 m_debugBorderColor = color; 469 m_debugBorderWidth = width; 470 m_changeMask |= DebugVisualsChange; 471} 472 473static void toTextureMapperLayerVector(const Vector<GraphicsLayer*>& layers, Vector<TextureMapperLayer*>& texmapLayers) 474{ 475 texmapLayers.reserveCapacity(layers.size()); 476 for (size_t i = 0; i < layers.size(); ++i) 477 texmapLayers.append(toTextureMapperLayer(layers[i])); 478} 479 480void GraphicsLayerTextureMapper::commitLayerChanges() 481{ 482 if (m_changeMask == NoChanges) 483 return; 484 485 if (m_changeMask & ChildrenChange) { 486 Vector<TextureMapperLayer*> textureMapperLayerChildren; 487 toTextureMapperLayerVector(children(), textureMapperLayerChildren); 488 m_layer->setChildren(textureMapperLayerChildren); 489 } 490 491 if (m_changeMask & MaskLayerChange) 492 m_layer->setMaskLayer(toTextureMapperLayer(maskLayer())); 493 494 if (m_changeMask & ReplicaLayerChange) 495 m_layer->setReplicaLayer(toTextureMapperLayer(replicaLayer())); 496 497 if (m_changeMask & PositionChange) 498 m_layer->setPosition(position()); 499 500 if (m_changeMask & AnchorPointChange) 501 m_layer->setAnchorPoint(anchorPoint()); 502 503 if (m_changeMask & SizeChange) 504 m_layer->setSize(size()); 505 506 if (m_changeMask & TransformChange) 507 m_layer->setTransform(transform()); 508 509 if (m_changeMask & ChildrenTransformChange) 510 m_layer->setChildrenTransform(childrenTransform()); 511 512 if (m_changeMask & Preserves3DChange) 513 m_layer->setPreserves3D(preserves3D()); 514 515 if (m_changeMask & ContentsRectChange) 516 m_layer->setContentsRect(contentsRect()); 517 518 if (m_changeMask & MasksToBoundsChange) 519 m_layer->setMasksToBounds(masksToBounds()); 520 521 if (m_changeMask & DrawsContentChange) 522 m_layer->setDrawsContent(drawsContent()); 523 524 if (m_changeMask & ContentsVisibleChange) 525 m_layer->setContentsVisible(contentsAreVisible()); 526 527 if (m_changeMask & ContentsOpaqueChange) 528 m_layer->setContentsOpaque(contentsOpaque()); 529 530 if (m_changeMask & BackfaceVisibilityChange) 531 m_layer->setBackfaceVisibility(backfaceVisibility()); 532 533 if (m_changeMask & OpacityChange) 534 m_layer->setOpacity(opacity()); 535 536 if (m_changeMask & BackgroundColorChange) 537 m_layer->setSolidColor(solidColor()); 538 539#if ENABLE(CSS_FILTERS) 540 if (m_changeMask & FilterChange) 541 m_layer->setFilters(filters()); 542#endif 543 544 if (m_changeMask & BackingStoreChange) 545 m_layer->setBackingStore(m_backingStore); 546 547 if (m_changeMask & DebugVisualsChange) 548 m_layer->setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter()); 549 550 if (m_changeMask & RepaintCountChange) 551 m_layer->setRepaintCount(repaintCount()); 552 553 if (m_changeMask & ContentChange) 554 m_layer->setContentsLayer(platformLayer()); 555 556 if (m_changeMask & AnimationChange) 557 m_layer->setAnimations(m_animations); 558 559 if (m_changeMask & AnimationStarted) 560 client()->notifyAnimationStarted(this, m_animationStartTime); 561 562 if (m_changeMask & FixedToViewporChange) 563 m_layer->setFixedToViewport(fixedToViewport()); 564 565 if (m_changeMask & IsScrollableChange) 566 m_layer->setIsScrollable(isScrollable()); 567 568 if (m_changeMask & CommittedScrollOffsetChange) 569 m_layer->didCommitScrollOffset(m_committedScrollOffset); 570 571 m_changeMask = NoChanges; 572} 573 574/* \reimp (GraphicsLayer.h) 575*/ 576void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect) 577{ 578 if (!m_layer->textureMapper()) 579 return; 580 581 flushCompositingStateForThisLayerOnly(); 582 583 if (maskLayer()) 584 maskLayer()->flushCompositingState(rect); 585 if (replicaLayer()) 586 replicaLayer()->flushCompositingState(rect); 587 for (size_t i = 0; i < children().size(); ++i) 588 children()[i]->flushCompositingState(rect); 589} 590 591void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded() 592{ 593 TextureMapper* textureMapper = m_layer->textureMapper(); 594 if (!textureMapper) 595 return; 596 597 if (!shouldHaveBackingStore()) { 598 ASSERT(!m_backingStore); 599 return; 600 } 601 ASSERT(m_backingStore); 602 603 IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size)); 604 if (!m_needsDisplay) 605 dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect)); 606 if (dirtyRect.isEmpty()) 607 return; 608 609#if PLATFORM(QT) && !defined(QT_NO_DYNAMIC_CAST) 610 ASSERT(dynamic_cast<TextureMapperTiledBackingStore*>(m_backingStore.get())); 611#endif 612 TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get()); 613 614 backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData); 615 616 m_needsDisplay = false; 617 m_needsDisplayRect = IntRect(); 618} 619 620bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const 621{ 622 return drawsContent() && contentsAreVisible() && !m_size.isEmpty(); 623} 624 625bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) 626{ 627 ASSERT(!keyframesName.isEmpty()); 628 629 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity)) 630 return false; 631 632 bool listsMatch = false; 633 bool hasBigRotation; 634 635 if (valueList.property() == AnimatedPropertyWebkitTransform) 636 listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0; 637 638 const double currentTime = WTF::currentTime(); 639 m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, currentTime - timeOffset, listsMatch)); 640 // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset. 641 if (timeOffset > 0) 642 m_animationStartTime = currentTime; 643 else 644 m_animationStartTime = currentTime - timeOffset; 645 notifyChange(AnimationChange); 646 notifyChange(AnimationStarted); 647 return true; 648} 649 650void GraphicsLayerTextureMapper::setAnimations(const GraphicsLayerAnimations& animations) 651{ 652 m_animations = animations; 653 notifyChange(AnimationChange); 654} 655 656 657void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset) 658{ 659 m_animations.pause(animationName, timeOffset); 660} 661 662void GraphicsLayerTextureMapper::removeAnimation(const String& animationName) 663{ 664 m_animations.remove(animationName); 665} 666 667#if ENABLE(CSS_FILTERS) 668bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters) 669{ 670 notifyChange(FilterChange); 671 return GraphicsLayer::setFilters(filters); 672} 673#endif 674 675void GraphicsLayerTextureMapper::setFixedToViewport(bool fixed) 676{ 677 if (m_fixedToViewport == fixed) 678 return; 679 680 m_fixedToViewport = fixed; 681 notifyChange(FixedToViewporChange); 682} 683 684void GraphicsLayerTextureMapper::setRepaintCount(int repaintCount) 685{ 686 m_repaintCount = repaintCount; 687 notifyChange(RepaintCountChange); 688} 689 690} 691#endif 692