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