1/* 2 Copyright (C) 2010 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 "TextureMapperNode.h" 22 23#include "GraphicsLayerTextureMapper.h" 24 25namespace WebCore { 26 27class TextureMapperCache { 28public: 29 void mark(BitmapTexture* texture); 30 31 class Entry { 32 public: 33 RefPtr<BitmapTexture> texture; 34 Entry() : previousCost(0) { } 35 inline int computeCost() const 36 { 37 if (!texture || !texture->isValid() || texture->isPacked()) 38 return 0; 39 const IntSize textureSize = texture->size(); 40 // An image's cost in bytes is width * height * bytes per pixel (4). 41 return textureSize.width() * textureSize.height() * 4; 42 } 43 Entry(BitmapTexture* newTexture) 44 : texture(newTexture) 45 { 46 } 47 bool operator==(const Entry& other) const { return texture == other.texture; } 48 int previousCost; 49 }; 50 51 TextureMapperCache() 52 : m_totalCost(0) 53 { 54 } 55 56 void purge(); 57 Vector<Entry> m_data; 58 int m_totalCost; 59#ifndef TEXMAP_TEXTURE_CACHE_KBS 60#define TEXMAP_TEXTURE_CACHE_KBS 24 * 1024 61#endif 62 static const int MaxCost = TEXMAP_TEXTURE_CACHE_KBS * 1024; 63 static const int PurgeAmount = MaxCost / 4; 64}; 65 66 67void TextureMapperCache::purge() 68{ 69 const int size = m_data.size(); 70 71 if (m_totalCost <= TextureMapperCache::MaxCost) 72 return; 73 74 // Ensure that we have the right count. It might be inaccurate if content changed size. 75 // We only do this when we're actually ready to purge. 76 m_totalCost = 0; 77 for (int i = 0; i < size; ++i) 78 m_totalCost += m_data[i].computeCost(); 79 80 for (int i = size-1; i >= 0 && m_totalCost > TextureMapperCache::MaxCost - TextureMapperCache::PurgeAmount; --i) { 81 Entry& entry = m_data[i]; 82 if (entry.texture->isLocked() || !entry.texture->isValid() || entry.texture->isPacked()) 83 continue; 84 m_totalCost -= entry.previousCost; 85 entry.texture->pack(); 86 m_data.remove(i); 87 } 88} 89 90void TextureMapperCache::mark(BitmapTexture* texture) 91{ 92 if (!texture || !texture->isValid()) 93 return; 94 95 Entry entry(texture); 96 size_t index = m_data.find(entry); 97 if (!index) 98 return; 99 100 int previousCost = 0; 101 102 if (index < m_data.size()) { 103 previousCost = m_data[index].previousCost; 104 m_data.remove(index); 105 } 106 const int cost = entry.computeCost(); 107 m_totalCost -= previousCost; 108 m_totalCost += (entry.previousCost = cost); 109 m_data.prepend(entry); 110} 111 112class TextureMapperCacheLock { 113public: 114 TextureMapperCacheLock(BitmapTexture* texture) : m_texture(texture) 115 { 116 if (m_texture) 117 m_texture->lock(); 118 } 119 ~TextureMapperCacheLock() 120 { 121 if (m_texture) 122 m_texture->unlock(); 123 } 124 125private: 126 RefPtr<BitmapTexture> m_texture; 127}; 128 129 130TextureMapperCache* TextureMapperNode::cache() 131{ 132 TextureMapperNode* root = rootLayer(); 133 if (!root) 134 return 0; 135 if (!root->m_cache) 136 root->m_cache = new TextureMapperCache; 137 return root->m_cache; 138} 139 140void TextureMapperNode::setNeedsDisplayInRect(IntRect rect) 141{ 142 if (m_platformClient) { 143 if (m_state.hasSurfaceDescendants) { 144 m_platformClient->setNeedsDisplay(); 145 return; 146 } 147 rect.intersect(IntRect(0, 0, m_size.width(), m_size.height())); 148 if (rect.isEmpty()) 149 return; 150 m_platformClient->setNeedsDisplayInRect(rect); 151 return; 152 } 153 154 if (!m_parent) 155 return; 156 157 m_parent->setNeedsDisplayInRect(rect); 158} 159 160void TextureMapperNode::setNeedsDisplay() 161{ 162 if (m_effectTarget) 163 m_effectTarget->setNeedsDisplay(); 164 if (m_transforms.targetBoundingRect.isEmpty()) 165 return; 166 if (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) 167 setNeedsDisplayInRect(m_transforms.targetBoundingRect); 168} 169 170void TextureMapperNode::setPlatformLayerClient(TextureMapperLayerClient* client) 171{ 172 m_platformClient = client; 173} 174 175int TextureMapperNode::compareGraphicsLayersZValue(const void* a, const void* b) 176{ 177 typedef const TextureMapperNode* NodePtr; 178 const NodePtr* nodeA = static_cast<const NodePtr*>(a); 179 const NodePtr* nodeB = static_cast<const NodePtr*>(b); 180 return int(((*nodeA)->m_transforms.centerZ - (*nodeB)->m_transforms.centerZ) * 1000); 181} 182 183void TextureMapperNode::sortByZOrder(Vector<TextureMapperNode* >& array, int first, int last) 184{ 185 qsort(array.data(), array.size(), sizeof(TextureMapperNode*), TextureMapperNode::compareGraphicsLayersZValue); 186} 187 188bool TextureMapperNode::hasSurfaceDescendants() const 189{ 190 if (m_layerType == ClipLayer || m_layerType == TransparencyLayer || m_state.replicaLayer) 191 return true; 192 193 const int size = m_children.size(); 194 for (int i = 0; i < size; ++i) { 195 if (TextureMapperNode* child = m_children[i]) { 196 if (child->hasSurfaceDescendants()) 197 return true; 198 } 199 } 200 return false; 201} 202 203int TextureMapperNode::countDescendantsWithContent() const 204{ 205 if (!m_state.visible || m_state.opacity < 0.001) 206 return 0; 207 208 int descendantsWithContent = (m_state.drawsContent || m_currentContent.contentType != HTMLContentType) ? 1 : 0; 209 210 const int size = m_children.size(); 211 for (int i = 0; i < size; ++i) { 212 if (TextureMapperNode* child = m_children[i]) 213 descendantsWithContent += child->countDescendantsWithContent(); 214 } 215 216 return descendantsWithContent; 217} 218 219TextureMapperNode* TextureMapperNode::toTextureMapperNode(GraphicsLayer* layer) 220{ 221 return layer ? static_cast<TextureMapperNode*>(layer->platformLayer()) : 0; 222} 223 224void TextureMapperNode::computeLayerType() 225{ 226 const bool selfHasContent = m_state.drawsContent || (m_currentContent.contentType != HTMLContentType); 227 const bool hasDescendantsWithContent = m_state.descendantsWithContent - (selfHasContent ? 1 : 0); 228 const bool hasTransparency = m_state.opacity < 0.99 || m_state.maskLayer; 229 const bool hasReplica = m_state.replicaLayer; 230 231 // DefaultLayer: draws itself and its children directly to the current framebuffer. 232 // any layer that doesn't conform to the other rules is a DefaultLayer. 233 m_layerType = DefaultLayer; 234 235 // RootLayer: the top level. Draws to a framebuffer, and the target texture draws into the viewport. 236 // only one layer is the root layer. 237 if (!m_parent && !m_effectTarget) { 238 m_layerType = RootLayer; 239 return; 240 } 241 242 // A layer with no contents is always a default layer. 243 if (!m_state.descendantsWithContent) 244 return; 245 246 // ClipLayer: creates a new framebuffer, the size of the layer, and then paints it to the enclosing BitmapTexture with the layer's transform/opacity. 247 // A clip layer is a layer that masks to bounds, doesn't preserve 3D, has children, and has a transparency/mask or a non-rectangular transform. 248 if (hasDescendantsWithContent && m_state.maskLayer) { 249 m_layerType = ClipLayer; 250 return; 251 } 252 253 // ScissorLayer: draws to the current framebuffer, and applies an extra scissor before drawing its children. 254 // A scissor layer is a layer with children that masks to bounds, is not a transparency layer, and has a rectangular clip. 255 if (m_state.masksToBounds && hasDescendantsWithContent) { 256 if (hasTransparency || !m_state.transform.isIdentityOrTranslation() || m_parent->m_state.preserves3D) 257 m_layerType = ClipLayer; 258 else 259 m_layerType = ScissorLayer; 260 return; 261 } 262 263 // TransparencyLayer: creates a new framebuffer idetical in size to the current framebuffer. Then draws the fb's texture to the current framebuffer with identity transform. 264 // Used for layers with children and transparency/mask that preserve 3D or don't mask to bounds. 265 if ((hasReplica && hasDescendantsWithContent) || (hasReplica && hasTransparency) || (hasTransparency && m_state.descendantsWithContent > 1)) 266 m_layerType = TransparencyLayer; 267} 268 269void TextureMapperNode::initializeTextureMapper(TextureMapper* textureMapper) 270{ 271 if (m_texture) 272 return; 273 m_surface = textureMapper->createTexture(); 274 m_replicaSurface = textureMapper->createTexture(); 275 m_texture = textureMapper->createTexture(); 276 cache()->mark(m_texture.get()); 277} 278 279TextureMapperNode::TextureMapperNode() 280 : m_layerType(DefaultLayer) 281 , m_surface(0) 282 , m_parent(0) 283 , m_effectTarget(0) 284 , m_platformClient(0) 285 , m_cache(0) 286{ 287} 288 289TextureMapperNode* TextureMapperNode::rootLayer() 290{ 291 if (m_effectTarget) 292 return m_effectTarget->rootLayer(); 293 if (m_parent) 294 return m_parent->rootLayer(); 295 return this; 296} 297 298void TextureMapperNode::invalidateTransform() 299{ 300 m_transforms.dirty = true; 301 if (m_layerType != ClipLayer) 302 m_state.dirty = true; 303 if (m_state.replicaLayer) 304 m_state.replicaLayer->invalidateTransform(); 305 const int size = m_children.size(); 306 for (int i = 0; i < size; ++i) { 307 if (TextureMapperNode* layer = m_children[i]) 308 layer->invalidateTransform(); 309 } 310} 311 312void TextureMapperNode::computeLocalTransform() 313{ 314 if (!m_transforms.localDirty) 315 return; 316 const float originX = m_state.anchorPoint.x() * m_size.width(); 317 const float originY = m_state.anchorPoint.y() * m_size.height(); 318 m_transforms.local = 319 TransformationMatrix() 320 .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z()) 321 .multiply(m_state.transform) 322 .translate3d(-originX, -originY, -m_state.anchorPoint.z()); 323 m_transforms.localDirty = false; 324} 325 326void TextureMapperNode::flattenTo2DSpaceIfNecessary() 327{ 328 if (m_state.preserves3D) 329 return; 330 331 m_transforms.forDescendants.setM13(0); 332 m_transforms.forDescendants.setM23(0); 333 m_transforms.forDescendants.setM31(0); 334 m_transforms.forDescendants.setM32(0); 335 m_transforms.forDescendants.setM33(1); 336 m_transforms.forDescendants.setM34(0); 337 m_transforms.forDescendants.setM43(0); 338} 339 340IntSize TextureMapperNode::nearestSurfaceSize() const 341{ 342 if (m_layerType == ClipLayer || m_layerType == RootLayer) 343 return m_surface && !m_surface->size().isEmpty() ? m_surface->size() : m_size; 344 return m_parent->nearestSurfaceSize(); 345} 346 347void TextureMapperNode::computeReplicaTransform() 348{ 349 if (!m_state.replicaLayer) 350 return; 351 352 m_nearestSurfaceSize = nearestSurfaceSize(); 353 354 if (m_layerType != TransparencyLayer) { 355 m_transforms.replica = TransformationMatrix(m_transforms.target).multiply(m_state.replicaLayer->m_transforms.local); 356 return; 357 } 358 359 const float originX = m_transforms.target.m41(); 360 const float originY = m_transforms.target.m42(); 361 m_transforms.replica = 362 TransformationMatrix() 363 .translate(originX, originY) 364 .multiply(m_state.replicaLayer->m_transforms.local) 365 .translate(-originX, -originY); 366} 367 368void TextureMapperNode::computeTransformations() 369{ 370 if (!m_transforms.dirty) 371 return; 372 373 m_transforms.dirty = false; 374 if ((m_size.isEmpty() && m_state.masksToBounds)) 375 return; 376 377 TextureMapperNode* parent = m_parent; 378 computeLocalTransform(); 379 380 m_transforms.target = TransformationMatrix(parent ? parent->m_transforms.forDescendants : TransformationMatrix()).multiply(m_transforms.local); 381 m_transforms.forDescendants = (m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target); 382 383 if (m_effectTarget) 384 return; 385 386 m_transforms.targetBoundingRect = IntRect(m_transforms.target.mapRect(entireRect())); 387 if (m_state.replicaLayer) 388 m_state.replicaLayer->computeTransformations(); 389 390 flattenTo2DSpaceIfNecessary(); 391 392 if (!m_state.backfaceVisibility && m_transforms.target.inverse().m33() < 0) { 393 m_state.visible = false; 394 return; 395 } 396 m_state.visible = true; 397 398 if (parent && parent->m_state.preserves3D) 399 m_transforms.centerZ = m_transforms.target.mapPoint(FloatPoint3D(m_size.width() / 2, m_size.height() / 2, 0)).z(); 400 401 if (!m_children.size()) 402 return; 403 404 if (m_state.childrenTransform.isIdentity()) 405 return; 406 407 const FloatPoint centerPoint = FloatPoint(m_size.width() / 2, m_size.height() / 2); 408 if (m_transforms.perspectiveDirty) 409 m_transforms.perspective = TransformationMatrix() 410 .translate(centerPoint.x(), centerPoint.y()) 411 .multiply(m_state.childrenTransform) 412 .translate(-centerPoint.x(), -centerPoint.y()); 413 m_transforms.perspectiveDirty = false; 414 m_transforms.forDescendants.multiply(m_transforms.perspective); 415} 416 417void TextureMapperNode::uploadTextureFromContent(TextureMapper* textureMapper, const IntRect& visibleRect, GraphicsLayer* layer) 418{ 419 if (m_size.isEmpty() || !layer) { 420 m_texture->destroy(); 421 return; 422 } 423 424 if (m_currentContent.contentType == DirectImageContentType) { 425 if (m_currentContent.image) 426 m_texture->setContentsToImage(m_currentContent.image.get()); 427 return; 428 } 429 430 if (m_currentContent.contentType == MediaContentType) { 431 if (!m_currentContent.media) 432 return; 433 m_texture->reset(m_size, true); 434 PlatformGraphicsContext* platformContext = m_texture->beginPaintMedia(); 435 GraphicsContext context(platformContext); 436 m_currentContent.media->paint(&context); 437 m_texture->endPaint(); 438 return; 439 } 440 441 const bool needsReset = (m_texture->contentSize() != m_size) || !m_texture->isValid(); 442 if ((m_currentContent.contentType != HTMLContentType) 443 || (!m_currentContent.needsDisplay && m_currentContent.needsDisplayRect.isEmpty() && !needsReset)) 444 return; 445 446 IntRect dirtyRect = IntRect(0, 0, m_size.width(), m_size.height()); 447 if (!needsReset && !m_currentContent.needsDisplay) 448 dirtyRect.intersect(m_currentContent.needsDisplayRect); 449 450 if (needsReset) 451 m_texture->reset(m_size, m_state.contentsOpaque); 452 453 { 454 GraphicsContext context(m_texture->beginPaint(dirtyRect)); 455 if (textureMapper) { 456 context.setImageInterpolationQuality(textureMapper->imageInterpolationQuality()); 457 context.setTextDrawingMode(textureMapper->textDrawingMode()); 458 } 459 layer->paintGraphicsLayerContents(context, dirtyRect); 460 } 461 m_texture->endPaint(); 462 m_currentContent.needsDisplay = false; 463} 464 465 466void TextureMapperNode::paint(TextureMapper* textureMapper, const TextureMapperContentLayer::PaintOptions& options) 467{ 468 ASSERT(m_layerType == RootLayer); 469 if (m_size.isEmpty()) 470 return; 471 472 TexmapPaintOptions opt; 473 opt.opacity = 1; 474 opt.rootLayer = this; 475 opt.scissorRect = options.targetRect; 476 opt.visibleRect = options.visibleRect; 477 opt.textureMapper = textureMapper; 478 opt.surface = 0; 479 opt.cache = m_cache; 480 paintRecursive(opt); 481 482 if (textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) { 483 textureMapper->bindSurface(0); 484 textureMapper->paintToTarget(*m_surface.get(), options.viewportSize, options.transform, options.opacity * m_state.opacity, options.targetRect); 485 } 486 m_cache->purge(); 487} 488 489void TextureMapperNode::paintSelf(const TexmapPaintOptions& options) 490{ 491 if (m_size.isEmpty() || (!m_state.drawsContent && m_currentContent.contentType == HTMLContentType)) 492 return; 493 494 RefPtr<BitmapTexture> replicaMaskTexture; 495 m_texture->unpack(); 496 497 RefPtr<BitmapTexture> maskTexture = m_state.maskLayer ? m_state.maskLayer->m_texture : 0; 498 if (m_state.replicaLayer && m_state.replicaLayer->m_state.maskLayer) 499 replicaMaskTexture = m_state.replicaLayer->m_state.maskLayer->m_texture; 500 501 if (maskTexture) 502 maskTexture->unpack(); 503 504 if (replicaMaskTexture) 505 replicaMaskTexture->unpack(); 506 507 const float opacity = options.isSurface ? 1 : options.opacity; 508 509 if (m_state.replicaLayer && !options.isSurface) 510 options.textureMapper->drawTexture(*m_texture.get(), replicaRect(), m_transforms.replica, 511 opacity * m_state.replicaLayer->m_state.opacity, 512 replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get()); 513 514 const IntRect rect = m_layerType == ClipLayer ? entireRect() : targetRect(); 515 const TransformationMatrix transform = m_layerType == ClipLayer ? TransformationMatrix() : m_transforms.target; 516 options.textureMapper->drawTexture(*m_texture.get(), rect, transform, opacity, options.isSurface ? 0 : maskTexture.get()); 517 options.cache->mark(m_texture.get()); 518} 519 520bool TextureMapperNode::paintReplica(const TexmapPaintOptions& options) 521{ 522 BitmapTexture& texture = *m_surface.get(); 523 TextureMapperNode* replica = m_state.replicaLayer; 524 RefPtr<BitmapTexture> maskTexture; 525 if (TextureMapperNode* mask = m_state.maskLayer) 526 maskTexture = mask->m_texture; 527 RefPtr<BitmapTexture> replicaMaskTexture; 528 if (!replica) 529 return false; 530 531 if (replica && replica->m_state.maskLayer) 532 replicaMaskTexture = replica->m_state.maskLayer->m_texture; 533 534 if (replicaMaskTexture) 535 replicaMaskTexture->unpack(); 536 ASSERT(m_replicaSurface); 537 m_replicaSurface->reset(options.surface->size()); 538 m_replicaSurface->setOffset(options.surface->offset()); 539 options.cache->mark(m_replicaSurface.get()); 540 options.textureMapper->bindSurface(m_replicaSurface.get()); 541 options.textureMapper->drawTexture(texture, replicaRect(), m_transforms.replica, replica->m_state.opacity, replicaMaskTexture ? replicaMaskTexture.get() : maskTexture.get()); 542 options.textureMapper->drawTexture(texture, IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), 1.0f, maskTexture.get()); 543 options.textureMapper->bindSurface(options.surface); 544 options.cache->mark(options.surface); 545 options.textureMapper->drawTexture(*m_replicaSurface.get(), IntRect(IntPoint(0, 0), options.surface->size()), TransformationMatrix(), options.opacity, 0); 546 return true; 547} 548 549void TextureMapperNode::paintSurface(const TexmapPaintOptions& options) 550{ 551 if (m_layerType == RootLayer || m_layerType == DefaultLayer || m_layerType == ScissorLayer) 552 return; 553 554 RefPtr<BitmapTexture> maskTexture; 555 if (TextureMapperNode* mask = m_state.maskLayer) 556 maskTexture = mask->m_texture; 557 558 ASSERT(m_surface); 559 BitmapTexture& texture = *m_surface.get(); 560 if (maskTexture) 561 maskTexture->unpack(); 562 texture.unpack(); 563 564 if (paintReplica(options)) 565 return; 566 567 options.textureMapper->bindSurface(options.surface); 568 options.textureMapper->drawTexture(texture, 569 m_layerType == TransparencyLayer ? IntRect(IntPoint(0, 0), options.surface->size()) : 570 targetRect(), 571 m_layerType == TransparencyLayer ? TransformationMatrix() : m_transforms.target, 572 options.opacity, maskTexture.get()); 573 options.cache->mark(&texture); 574} 575 576void TextureMapperNode::paintSelfAndChildren(const TexmapPaintOptions& options, TexmapPaintOptions& optionsForDescendants) 577{ 578 bool didPaintSelf = false; 579 if (!m_state.preserves3D || m_children.isEmpty()) { 580 paintSelf(options); 581 didPaintSelf = true; 582 } 583 584 if (m_children.isEmpty() && !options.isSurface) 585 return; 586 587 if (m_layerType == ScissorLayer) 588 optionsForDescendants.scissorRect.intersect(m_transforms.target.mapRect(IntRect(0, 0, m_size.width(), m_size.height()))); 589 590 for (int i = 0; i < m_children.size(); ++i) { 591 TextureMapperNode* layer = m_children[i]; 592 if (!layer) 593 continue; 594 595 if (!didPaintSelf && layer->m_transforms.centerZ >= 0) { 596 paintSelf(options); 597 didPaintSelf = true; 598 } 599 layer->paintRecursive(optionsForDescendants); 600 if (options.isSurface) { 601 ASSERT(m_surface); 602 options.cache->mark(m_surface.get()); 603 options.textureMapper->bindSurface(m_surface.get()); 604 } 605 } 606 if (!didPaintSelf) { 607 paintSelf(options); 608 didPaintSelf = true; 609 } 610} 611 612void TextureMapperNode::paintRecursive(TexmapPaintOptions options) 613{ 614 bool isDirty = m_state.dirty; 615 m_state.dirty = false; 616 617 if ((m_size.isEmpty() && (m_state.masksToBounds 618 || m_children.isEmpty())) || !m_state.visible || options.opacity < 0.01 || m_state.opacity < 0.01) 619 return; 620 621 computeReplicaTransform(); 622 623 if (m_state.maskLayer) 624 m_state.maskLayer->m_state.dirty = false; 625 626 if (m_state.replicaLayer) { 627 m_state.replicaLayer->m_state.dirty = false; 628 if (m_state.replicaLayer->m_state.maskLayer) 629 m_state.replicaLayer->m_state.maskLayer->m_state.dirty = false; 630 } 631 632 const bool isSurface = (m_layerType == ClipLayer 633 || m_layerType == TransparencyLayer 634 || (m_layerType == RootLayer 635 && (options.textureMapper->allowSurfaceForRoot() || m_state.hasSurfaceDescendants) 636 )); 637 638 const IntRect boundingRectfromNearestSurface = m_transforms.targetBoundingRect; 639 640 options.opacity *= m_state.opacity; 641 642 TexmapPaintOptions optionsForDescendants(options); 643 optionsForDescendants.opacity = isSurface ? 1 : options.opacity; 644 options.isSurface = isSurface; 645 646 if (m_layerType == ClipLayer) { 647 optionsForDescendants.visibleRect = TransformationMatrix().translate(-boundingRectfromNearestSurface.x(), -boundingRectfromNearestSurface.y()).mapRect(options.visibleRect); 648 optionsForDescendants.scissorRect = IntRect(0, 0, m_size.width(), m_size.height()); 649 } 650 651 if (m_layerType == ScissorLayer) 652 optionsForDescendants.scissorRect.intersect(m_transforms.targetBoundingRect); 653 options.textureMapper->setClip(optionsForDescendants.scissorRect); 654 655 TextureMapperCacheLock(m_texture.get()); 656 TextureMapperCacheLock(m_surface.get()); 657 TextureMapperCacheLock(m_replicaSurface.get()); 658 659 options.cache->purge(); 660 661 if (isSurface) { 662 ASSERT(m_surface); 663 if (!m_surface->isValid()) 664 isDirty = true; 665 if (m_state.tiled) { 666 m_surface->reset(options.visibleRect.size()); 667 m_surface->setOffset(options.visibleRect.location()); 668 } else if (isDirty) 669 m_surface->reset(m_layerType == TransparencyLayer ? options.surface->size() : m_size); 670 options.cache->mark(m_surface.get()); 671 options.textureMapper->bindSurface(m_surface.get()); 672 optionsForDescendants.surface = m_surface.get(); 673 } else if (m_surface) 674 m_surface->destroy(); 675 676 if (isDirty || !isSurface || m_state.tiled || !m_surface->isValid()) 677 paintSelfAndChildren(options, optionsForDescendants); 678 679 paintSurface(options); 680} 681 682TextureMapperNode::~TextureMapperNode() 683{ 684 setNeedsDisplay(); 685 { 686 const int childrenSize = m_children.size(); 687 for (int i = childrenSize-1; i >= 0; --i) { 688 ASSERT(m_children[i]->m_parent == this); 689 m_children[i]->m_parent = 0; 690 } 691 } 692 if (m_parent) 693 m_parent->m_children.remove(m_parent->m_children.find(this)); 694 if (m_cache) 695 delete m_cache; 696} 697 698void TextureMapperNode::performPostSyncOperations() 699{ 700 const LayerType prevLayerType = m_layerType; 701 computeLayerType(); 702 if (prevLayerType != m_layerType) 703 m_state.dirty = true; 704 if (m_transforms.dirty) 705 setNeedsDisplay(); 706 707 computeTransformations(); 708 if (m_state.maskLayer && !m_state.dirty) 709 m_state.dirty = m_state.maskLayer->m_state.dirty; 710 if (m_state.replicaLayer && !m_state.dirty) 711 m_state.dirty = m_state.replicaLayer->m_state.dirty; 712 713 const int size = m_children.size(); 714 715 for (int i = size - 1; i >= 0; --i) { 716 TextureMapperNode* layer = m_children[i]; 717 718 layer->performPostSyncOperations(); 719 if (!m_state.dirty) 720 m_state.dirty = layer->m_state.dirty; 721 } 722 m_state.hasSurfaceDescendants = hasSurfaceDescendants(); 723 if (m_state.dirty) 724 m_state.descendantsWithContent = countDescendantsWithContent(); 725 726 if (m_state.preserves3D) 727 sortByZOrder(m_children, 0, size); 728 if (m_state.dirty) 729 setNeedsDisplay(); 730} 731 732void TextureMapperNode::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, bool recurse) 733{ 734 TextureMapper* textureMapper = rootLayer()->m_platformClient->textureMapper(); 735 syncCompositingStateInternal(graphicsLayer, recurse, textureMapper); 736 performPostSyncOperations(); 737} 738 739void TextureMapperNode::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper) 740{ 741 const int changeMask = graphicsLayer->changeMask(); 742 initializeTextureMapper(textureMapper); 743 const TextureMapperNode::ContentData& pendingContent = graphicsLayer->pendingContent(); 744 if (changeMask == NoChanges && pendingContent.needsDisplayRect.isEmpty() && !pendingContent.needsDisplay) 745 return; 746 747 setNeedsDisplay(); 748 if (m_parent) 749 m_parent->m_state.dirty = true; 750 751 if (m_currentContent.contentType == HTMLContentType && (changeMask & ParentChange)) { 752 // The WebCore compositor manages item ownership. We have to make sure graphicsview doesn't 753 // try to snatch that ownership. 754 755 if (!graphicsLayer->parent()) 756 m_parent = 0; 757 else 758 m_parent = toTextureMapperNode(graphicsLayer->parent()); 759 760 if (!graphicsLayer->parent() && m_parent) { 761 size_t index = m_parent->m_children.find(this); 762 m_parent->m_children.remove(index); 763 } 764 } 765 766 if (changeMask & ChildrenChange) { 767 m_children.clear(); 768 for (size_t i = 0; i < graphicsLayer->children().size(); ++i) { 769 if (TextureMapperNode* child = toTextureMapperNode(graphicsLayer->children()[i])) { 770 if (!child) 771 continue; 772 m_children.append(child); 773 child->m_parent = this; 774 } 775 } 776 m_state.dirty = true; 777 } 778 779 if (changeMask & (SizeChange | ContentsRectChange)) { 780 IntSize wantedSize = IntSize(graphicsLayer->size().width(), graphicsLayer->size().height()); 781 if (wantedSize.isEmpty() && pendingContent.contentType == HTMLContentType) 782 wantedSize = IntSize(graphicsLayer->contentsRect().width(), graphicsLayer->contentsRect().height()); 783 784 if (wantedSize != m_size) { 785 m_size = IntSize(wantedSize.width(), wantedSize.height()); 786 if (m_platformClient) 787 m_platformClient->setSizeChanged(m_size); 788 const bool needsTiling = m_size.width() > 2000 || m_size.height() > 2000; 789 if (m_state.tiled != needsTiling) 790 m_state.tiled = needsTiling; 791 m_state.dirty = true; 792 } 793 } 794 795 if (changeMask & MaskLayerChange) { 796 if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->maskLayer())) 797 layer->m_effectTarget = this; 798 } 799 800 if (changeMask & ReplicaLayerChange) { 801 if (TextureMapperNode* layer = toTextureMapperNode(graphicsLayer->replicaLayer())) 802 layer->m_effectTarget = this; 803 } 804 805 if (changeMask & (TransformChange | SizeChange | AnchorPointChange | PositionChange)) 806 m_transforms.localDirty = true; 807 808 if (changeMask & (ChildrenTransformChange | SizeChange)) 809 m_transforms.perspectiveDirty = true; 810 811 if (changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | ContentsRectChange | BackfaceVisibilityChange | PositionChange | MaskLayerChange | DrawsContentChange | ContentChange | ReplicaLayerChange)) { 812 // Due to the differences between the way WebCore handles transforms and the way Qt handles transforms, 813 // all these elements affect the transforms of all the descendants. 814 invalidateTransform(); 815 } 816 817 if (changeMask & DisplayChange) 818 m_state.dirty = true; 819 820 m_state.maskLayer = toTextureMapperNode(graphicsLayer->maskLayer()); 821 m_state.replicaLayer = toTextureMapperNode(graphicsLayer->replicaLayer()); 822 m_state.pos = graphicsLayer->position(); 823 m_state.anchorPoint = graphicsLayer->anchorPoint(); 824 m_state.size = graphicsLayer->size(); 825 m_state.transform = graphicsLayer->transform(); 826 m_state.contentsRect = graphicsLayer->contentsRect(); 827 m_state.opacity = graphicsLayer->opacity(); 828 m_state.contentsRect = graphicsLayer->contentsRect(); 829 m_state.preserves3D = graphicsLayer->preserves3D(); 830 m_state.masksToBounds = graphicsLayer->masksToBounds(); 831 m_state.drawsContent = graphicsLayer->drawsContent(); 832 m_state.contentsOpaque = graphicsLayer->contentsOpaque(); 833 m_state.backfaceVisibility = graphicsLayer->backfaceVisibility(); 834 m_state.childrenTransform = graphicsLayer->childrenTransform(); 835 m_currentContent.contentType = pendingContent.contentType; 836 m_currentContent.image = pendingContent.image; 837 m_currentContent.media = pendingContent.media; 838 m_currentContent.backgroundColor = pendingContent.backgroundColor; 839 m_currentContent.needsDisplay = m_currentContent.needsDisplay || pendingContent.needsDisplay; 840 m_currentContent.needsDisplayRect.unite(pendingContent.needsDisplayRect); 841 842} 843 844void TextureMapperNode::syncCompositingStateInternal(GraphicsLayerTextureMapper* graphicsLayer, bool recurse, TextureMapper* textureMapper) 845{ 846 syncCompositingStateSelf(graphicsLayer, textureMapper); 847 848 graphicsLayer->didSynchronize(); 849 850 if (m_state.maskLayer) { 851 m_state.maskLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), false, textureMapper); 852 if (m_state.maskLayer->m_size.isEmpty()) 853 m_state.maskLayer->m_size = m_size; 854 } 855 856 if (m_state.replicaLayer) 857 m_state.replicaLayer->syncCompositingStateInternal(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), false, textureMapper); 858 859 if (m_state.dirty) 860 uploadTextureFromContent(textureMapper, m_state.visibleRect, graphicsLayer); 861 862 m_currentContent.needsDisplayRect = IntRect(); 863 m_currentContent.needsDisplay = false; 864 865 if (!recurse) 866 return; 867 868 Vector<GraphicsLayer*> children = graphicsLayer->children(); 869 for (int i = children.size() - 1; i >= 0; --i) { 870 TextureMapperNode* node = toTextureMapperNode(children[i]); 871 if (!node) 872 continue; 873 node->syncCompositingStateInternal(toGraphicsLayerTextureMapper(children[i]), true, textureMapper); 874 } 875} 876 877} 878