| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 | 6 |
| 7 #include "cc/tiled_layer.h" | 7 #include "cc/tiled_layer.h" |
| 8 | 8 |
| 9 #include "Region.h" | 9 #include "Region.h" |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 validForFrame = true; | 61 validForFrame = true; |
| 62 updateRect = dirtyRect; | 62 updateRect = dirtyRect; |
| 63 dirtyRect = IntRect(); | 63 dirtyRect = IntRect(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 IntRect dirtyRect; | 66 IntRect dirtyRect; |
| 67 IntRect updateRect; | 67 IntRect updateRect; |
| 68 bool partialUpdate; | 68 bool partialUpdate; |
| 69 bool validForFrame; | 69 bool validForFrame; |
| 70 bool occluded; | 70 bool occluded; |
| 71 bool isInUseOnImpl; | |
| 72 | 71 |
| 73 private: | 72 private: |
| 74 explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updaterResource) | 73 explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updaterResource) |
| 75 : partialUpdate(false) | 74 : partialUpdate(false) |
| 76 , validForFrame(false) | 75 , validForFrame(false) |
| 77 , occluded(false) | 76 , occluded(false) |
| 78 , isInUseOnImpl(false) | |
| 79 , m_updaterResource(updaterResource.Pass()) | 77 , m_updaterResource(updaterResource.Pass()) |
| 80 { | 78 { |
| 81 } | 79 } |
| 82 | 80 |
| 83 scoped_ptr<LayerUpdater::Resource> m_updaterResource; | 81 scoped_ptr<LayerUpdater::Resource> m_updaterResource; |
| 84 | 82 |
| 85 DISALLOW_COPY_AND_ASSIGN(UpdatableTile); | 83 DISALLOW_COPY_AND_ASSIGN(UpdatableTile); |
| 86 }; | 84 }; |
| 87 | 85 |
| 88 TiledLayer::TiledLayer() | 86 TiledLayer::TiledLayer() |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 Vector<UpdatableTile*> invalidTiles; | 207 Vector<UpdatableTile*> invalidTiles; |
| 210 | 208 |
| 211 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { | 209 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { |
| 212 int i = iter->first.first; | 210 int i = iter->first.first; |
| 213 int j = iter->first.second; | 211 int j = iter->first.second; |
| 214 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 212 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
| 215 // FIXME: This should not ever be null. | 213 // FIXME: This should not ever be null. |
| 216 if (!tile) | 214 if (!tile) |
| 217 continue; | 215 continue; |
| 218 | 216 |
| 219 tile->isInUseOnImpl = false; | |
| 220 | |
| 221 if (!tile->managedTexture()->haveBackingTexture()) { | 217 if (!tile->managedTexture()->haveBackingTexture()) { |
| 222 // Evicted tiles get deleted from both layers | 218 // Evicted tiles get deleted from both layers |
| 223 invalidTiles.append(tile); | 219 invalidTiles.append(tile); |
| 224 continue; | 220 continue; |
| 225 } | 221 } |
| 226 | 222 |
| 227 if (!tile->validForFrame) { | 223 if (!tile->validForFrame) { |
| 228 // Invalidated tiles are set so they can get different debug colors. | 224 // Invalidated tiles are set so they can get different debug colors. |
| 229 tiledLayer->pushInvalidTile(i, j); | 225 tiledLayer->pushInvalidTile(i, j); |
| 230 continue; | 226 continue; |
| 231 } | 227 } |
| 232 | 228 |
| 233 tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId(
), tile->opaqueRect(), tile->managedTexture()->contentsSwizzled()); | 229 tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId(
), tile->opaqueRect(), tile->managedTexture()->contentsSwizzled()); |
| 234 tile->isInUseOnImpl = true; | |
| 235 } | 230 } |
| 236 for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); ite
r != invalidTiles.end(); ++iter) | 231 for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); ite
r != invalidTiles.end(); ++iter) |
| 237 m_tiler->takeTile((*iter)->i(), (*iter)->j()); | 232 m_tiler->takeTile((*iter)->i(), (*iter)->j()); |
| 238 } | 233 } |
| 239 | 234 |
| 240 PrioritizedTextureManager* TiledLayer::textureManager() const | 235 PrioritizedTextureManager* TiledLayer::textureManager() const |
| 241 { | 236 { |
| 242 if (!layerTreeHost()) | 237 if (!layerTreeHost()) |
| 243 return 0; | 238 return 0; |
| 244 return layerTreeHost()->contentsTextureManager(); | 239 return layerTreeHost()->contentsTextureManager(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 continue; | 318 continue; |
| 324 IntRect bound = m_tiler->tileRect(tile); | 319 IntRect bound = m_tiler->tileRect(tile); |
| 325 bound.intersect(contentRect); | 320 bound.intersect(contentRect); |
| 326 tile->dirtyRect.unite(bound); | 321 tile->dirtyRect.unite(bound); |
| 327 } | 322 } |
| 328 } | 323 } |
| 329 | 324 |
| 330 // Returns true if tile is dirty and only part of it needs to be updated. | 325 // Returns true if tile is dirty and only part of it needs to be updated. |
| 331 bool TiledLayer::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) | 326 bool TiledLayer::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) |
| 332 { | 327 { |
| 333 return !tile->dirtyRect.contains(m_tiler->tileRect(tile)); | 328 return !tile->dirtyRect.contains(m_tiler->tileRect(tile)) && tile->managedTe
xture()->haveBackingTexture(); |
| 334 } | 329 } |
| 335 | 330 |
| 336 // Dirty tiles with valid textures needs buffered update to guarantee that | |
| 337 // we don't modify textures currently used for drawing by the impl thread. | |
| 338 bool TiledLayer::tileNeedsBufferedUpdate(UpdatableTile* tile) | |
| 339 { | |
| 340 if (!tile->managedTexture()->haveBackingTexture()) | |
| 341 return false; | |
| 342 | |
| 343 if (!tile->isDirty()) | |
| 344 return false; | |
| 345 | |
| 346 if (!tile->isInUseOnImpl) | |
| 347 return false; | |
| 348 | |
| 349 return true; | |
| 350 } | |
| 351 | |
| 352 | |
| 353 bool TiledLayer::updateTiles(int left, int top, int right, int bottom, TextureUp
dateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats, bool
& didPaint) | 331 bool TiledLayer::updateTiles(int left, int top, int right, int bottom, TextureUp
dateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats, bool
& didPaint) |
| 354 { | 332 { |
| 355 didPaint = false; | 333 didPaint = false; |
| 356 createUpdaterIfNeeded(); | 334 createUpdaterIfNeeded(); |
| 357 | 335 |
| 358 bool ignoreOcclusions = !occlusion; | 336 bool ignoreOcclusions = !occlusion; |
| 359 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { | 337 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { |
| 360 m_failedUpdate = true; | 338 m_failedUpdate = true; |
| 361 return false; | 339 return false; |
| 362 } | 340 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 tile->occluded = true; | 375 tile->occluded = true; |
| 398 occludedTileCount++; | 376 occludedTileCount++; |
| 399 } else { | 377 } else { |
| 400 succeeded &= tile->managedTexture()->requestLate(); | 378 succeeded &= tile->managedTexture()->requestLate(); |
| 401 } | 379 } |
| 402 } | 380 } |
| 403 } | 381 } |
| 404 | 382 |
| 405 if (!succeeded) | 383 if (!succeeded) |
| 406 return; | 384 return; |
| 407 | 385 if (occlusion) |
| 408 // FIXME: Remove the loop and just pass the count! | 386 occlusion->overdrawMetrics().didCullTilesForUpload(occludedTileCount); |
| 409 for (int i = 0; i < occludedTileCount; i++) | |
| 410 occlusion->overdrawMetrics().didCullTileForUpload(); | |
| 411 } | 387 } |
| 412 | 388 |
| 413 bool TiledLayer::haveTexturesForTiles(int left, int top, int right, int bottom,
bool ignoreOcclusions) | 389 bool TiledLayer::haveTexturesForTiles(int left, int top, int right, int bottom,
bool ignoreOcclusions) |
| 414 { | 390 { |
| 415 for (int j = top; j <= bottom; ++j) { | 391 for (int j = top; j <= bottom; ++j) { |
| 416 for (int i = left; i <= right; ++i) { | 392 for (int i = left; i <= right; ++i) { |
| 417 UpdatableTile* tile = tileAt(i, j); | 393 UpdatableTile* tile = tileAt(i, j); |
| 418 DCHECK(tile); // Did setTexturePriorites get skipped? | 394 DCHECK(tile); // Did setTexturePriorites get skipped? |
| 419 // FIXME: This should not ever be null. | 395 // FIXME: This should not ever be null. |
| 420 if (!tile) | 396 if (!tile) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 441 IntRect paintRect; | 417 IntRect paintRect; |
| 442 for (int j = top; j <= bottom; ++j) { | 418 for (int j = top; j <= bottom; ++j) { |
| 443 for (int i = left; i <= right; ++i) { | 419 for (int i = left; i <= right; ++i) { |
| 444 UpdatableTile* tile = tileAt(i, j); | 420 UpdatableTile* tile = tileAt(i, j); |
| 445 DCHECK(tile); // Did setTexturePriorites get skipped? | 421 DCHECK(tile); // Did setTexturePriorites get skipped? |
| 446 // FIXME: This should not ever be null. | 422 // FIXME: This should not ever be null. |
| 447 if (!tile) | 423 if (!tile) |
| 448 continue; | 424 continue; |
| 449 if (tile->occluded && !ignoreOcclusions) | 425 if (tile->occluded && !ignoreOcclusions) |
| 450 continue; | 426 continue; |
| 427 // FIXME: Decide if partial update should be allowed based on cost |
| 428 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 |
| 429 if (tile->isDirty() && layerTreeHost() && layerTreeHost()->bufferedU
pdates()) { |
| 430 // If we get a partial update, we use the same texture, otherwis
e return the |
| 431 // current texture backing, so we don't update visible textures
non-atomically. |
| 432 // If the current backing is in-use, it won't be deleted until a
fter the commit |
| 433 // as the texture manager will not allow deletion or recycling o
f in-use textures. |
| 434 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request
PartialTextureUpdate()) |
| 435 tile->partialUpdate = true; |
| 436 else { |
| 437 tile->dirtyRect = m_tiler->tileRect(tile); |
| 438 tile->managedTexture()->returnBackingTexture(); |
| 439 } |
| 440 } |
| 441 |
| 451 paintRect.unite(tile->dirtyRect); | 442 paintRect.unite(tile->dirtyRect); |
| 452 tile->markForUpdate(); | 443 tile->markForUpdate(); |
| 453 } | 444 } |
| 454 } | 445 } |
| 455 return paintRect; | 446 return paintRect; |
| 456 } | 447 } |
| 457 | 448 |
| 458 void TiledLayer::updateTileTextures(const IntRect& paintRect, int left, int top,
int right, int bottom, TextureUpdateQueue& queue, const OcclusionTracker* occlu
sion, RenderingStats& stats) | 449 void TiledLayer::updateTileTextures(const IntRect& paintRect, int left, int top,
int right, int bottom, TextureUpdateQueue& queue, const OcclusionTracker* occlu
sion, RenderingStats& stats) |
| 459 { | 450 { |
| 460 // The updateRect should be in layer space. So we have to convert the paintR
ect from content space to layer space. | 451 // The updateRect should be in layer space. So we have to convert the paintR
ect from content space to layer space. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 updateScrollPrediction(); | 570 updateScrollPrediction(); |
| 580 | 571 |
| 581 if (m_tiler->hasEmptyBounds()) | 572 if (m_tiler->hasEmptyBounds()) |
| 582 return; | 573 return; |
| 583 | 574 |
| 584 bool drawsToRoot = !renderTarget()->parent(); | 575 bool drawsToRoot = !renderTarget()->parent(); |
| 585 bool smallAnimatedLayer = isSmallAnimatedLayer(this); | 576 bool smallAnimatedLayer = isSmallAnimatedLayer(this); |
| 586 | 577 |
| 587 // Minimally create the tiles in the desired pre-paint rect. | 578 // Minimally create the tiles in the desired pre-paint rect. |
| 588 IntRect createTilesRect = idlePaintRect(); | 579 IntRect createTilesRect = idlePaintRect(); |
| 580 if (smallAnimatedLayer) |
| 581 createTilesRect = IntRect(IntPoint::zero(), contentBounds()); |
| 589 if (!createTilesRect.isEmpty()) { | 582 if (!createTilesRect.isEmpty()) { |
| 590 int left, top, right, bottom; | 583 int left, top, right, bottom; |
| 591 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot
tom); | 584 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot
tom); |
| 592 for (int j = top; j <= bottom; ++j) { | 585 for (int j = top; j <= bottom; ++j) { |
| 593 for (int i = left; i <= right; ++i) { | 586 for (int i = left; i <= right; ++i) { |
| 594 if (!tileAt(i, j)) | 587 if (!tileAt(i, j)) |
| 595 createTile(i, j); | 588 createTile(i, j); |
| 596 } | 589 } |
| 597 } | 590 } |
| 598 } | 591 } |
| 599 | 592 |
| 600 // Also, minimally create all tiles for small animated layers and also | |
| 601 // double-buffer them since we have limited their size to be reasonable. | |
| 602 IntRect doubleBufferedRect = visibleContentRect(); | |
| 603 if (smallAnimatedLayer) | |
| 604 doubleBufferedRect = IntRect(IntPoint::zero(), contentBounds()); | |
| 605 | |
| 606 // Create additional textures for double-buffered updates when needed. | |
| 607 // These textures must stay alive while the updated textures are incremental
ly | |
| 608 // uploaded, swapped atomically via pushProperties, and finally deleted | |
| 609 // after the commit is complete, after which they can be recycled. | |
| 610 if (!doubleBufferedRect.isEmpty()) { | |
| 611 int left, top, right, bottom; | |
| 612 m_tiler->contentRectToTileIndices(doubleBufferedRect, left, top, right,
bottom); | |
| 613 for (int j = top; j <= bottom; ++j) { | |
| 614 for (int i = left; i <= right; ++i) { | |
| 615 UpdatableTile* tile = tileAt(i, j); | |
| 616 if (!tile) | |
| 617 tile = createTile(i, j); | |
| 618 // We need an additional texture if the tile needs a buffered-up
date and it's not a partial update. | |
| 619 // FIXME: Decide if partial update should be allowed based on co
st | |
| 620 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 | |
| 621 if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || !
tileNeedsBufferedUpdate(tile)) | |
| 622 continue; | |
| 623 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request
PartialTextureUpdate()) { | |
| 624 tile->partialUpdate = true; | |
| 625 continue; | |
| 626 } | |
| 627 | |
| 628 IntRect tileRect = m_tiler->tileRect(tile); | |
| 629 tile->dirtyRect = tileRect; | |
| 630 LayerUpdater::Resource* backBuffer = tile->updaterResource(); | |
| 631 setPriorityForTexture(visibleContentRect(), tile->dirtyRect, dra
wsToRoot, smallAnimatedLayer, backBuffer->texture()); | |
| 632 scoped_ptr<PrioritizedTexture> frontBuffer = PrioritizedTexture:
:create(backBuffer->texture()->textureManager(), | |
| 633
backBuffer->texture()->size(), | |
| 634
backBuffer->texture()->format()); | |
| 635 // Swap backBuffer into frontBuffer and add it to delete after c
ommit queue. | |
| 636 backBuffer->swapTextureWith(frontBuffer); | |
| 637 layerTreeHost()->deleteTextureAfterCommit(frontBuffer.Pass()); | |
| 638 } | |
| 639 } | |
| 640 } | |
| 641 | |
| 642 // Now update priorities on all tiles we have in the layer, no matter where
they are. | 593 // Now update priorities on all tiles we have in the layer, no matter where
they are. |
| 643 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { | 594 for (LayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(
); iter != m_tiler->tiles().end(); ++iter) { |
| 644 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 595 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
| 645 // FIXME: This should not ever be null. | 596 // FIXME: This should not ever be null. |
| 646 if (!tile) | 597 if (!tile) |
| 647 continue; | 598 continue; |
| 648 IntRect tileRect = m_tiler->tileRect(tile); | 599 IntRect tileRect = m_tiler->tileRect(tile); |
| 649 setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, sma
llAnimatedLayer, tile->managedTexture()); | 600 setPriorityForTexture(m_predictedVisibleRect, tileRect, drawsToRoot, sma
llAnimatedLayer, tile->managedTexture()); |
| 650 } | 601 } |
| 651 } | 602 } |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 IntRect prepaintRect = visibleContentRect(); | 792 IntRect prepaintRect = visibleContentRect(); |
| 842 prepaintRect.inflateX(m_tiler->tileSize().width() * prepaintColumns); | 793 prepaintRect.inflateX(m_tiler->tileSize().width() * prepaintColumns); |
| 843 prepaintRect.inflateY(m_tiler->tileSize().height() * prepaintRows); | 794 prepaintRect.inflateY(m_tiler->tileSize().height() * prepaintRows); |
| 844 IntRect contentRect(IntPoint::zero(), contentBounds()); | 795 IntRect contentRect(IntPoint::zero(), contentBounds()); |
| 845 prepaintRect.intersect(contentRect); | 796 prepaintRect.intersect(contentRect); |
| 846 | 797 |
| 847 return prepaintRect; | 798 return prepaintRect; |
| 848 } | 799 } |
| 849 | 800 |
| 850 } | 801 } |
| OLD | NEW |