Chromium Code Reviews| 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 "CCLayerImpl.h" | 9 #include "CCLayerImpl.h" |
| 10 #include "CCLayerTreeHost.h" | 10 #include "CCLayerTreeHost.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 validForFrame = true; | 51 validForFrame = true; |
| 52 updateRect = dirtyRect; | 52 updateRect = dirtyRect; |
| 53 dirtyRect = IntRect(); | 53 dirtyRect = IntRect(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 IntRect dirtyRect; | 56 IntRect dirtyRect; |
| 57 IntRect updateRect; | 57 IntRect updateRect; |
| 58 bool partialUpdate; | 58 bool partialUpdate; |
| 59 bool validForFrame; | 59 bool validForFrame; |
| 60 bool occluded; | 60 bool occluded; |
| 61 bool isInUseOnImpl; | |
| 62 | 61 |
| 63 private: | 62 private: |
| 64 explicit UpdatableTile(scoped_ptr<LayerTextureUpdater::Texture> texture) | 63 explicit UpdatableTile(scoped_ptr<LayerTextureUpdater::Texture> texture) |
| 65 : partialUpdate(false) | 64 : partialUpdate(false) |
| 66 , validForFrame(false) | 65 , validForFrame(false) |
| 67 , occluded(false) | 66 , occluded(false) |
| 68 , isInUseOnImpl(false) | |
| 69 , m_texture(texture.Pass()) | 67 , m_texture(texture.Pass()) |
| 70 { | 68 { |
| 71 } | 69 } |
| 72 | 70 |
| 73 scoped_ptr<LayerTextureUpdater::Texture> m_texture; | 71 scoped_ptr<LayerTextureUpdater::Texture> m_texture; |
| 74 | 72 |
| 75 DISALLOW_COPY_AND_ASSIGN(UpdatableTile); | 73 DISALLOW_COPY_AND_ASSIGN(UpdatableTile); |
| 76 }; | 74 }; |
| 77 | 75 |
| 78 TiledLayerChromium::TiledLayerChromium() | 76 TiledLayerChromium::TiledLayerChromium() |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 Vector<UpdatableTile*> invalidTiles; | 199 Vector<UpdatableTile*> invalidTiles; |
| 202 | 200 |
| 203 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) { | 201 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) { |
| 204 int i = iter->first.first; | 202 int i = iter->first.first; |
| 205 int j = iter->first.second; | 203 int j = iter->first.second; |
| 206 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 204 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
| 207 // FIXME: This should not ever be null. | 205 // FIXME: This should not ever be null. |
| 208 if (!tile) | 206 if (!tile) |
| 209 continue; | 207 continue; |
| 210 | 208 |
| 211 tile->isInUseOnImpl = false; | |
| 212 | |
| 213 if (!tile->managedTexture()->haveBackingTexture()) { | 209 if (!tile->managedTexture()->haveBackingTexture()) { |
| 214 // Evicted tiles get deleted from both layers | 210 // Evicted tiles get deleted from both layers |
| 215 invalidTiles.append(tile); | 211 invalidTiles.append(tile); |
| 216 continue; | 212 continue; |
| 217 } | 213 } |
| 218 | 214 |
| 219 if (!tile->validForFrame) { | 215 if (!tile->validForFrame) { |
| 220 // Invalidated tiles are set so they can get different debug colors. | 216 // Invalidated tiles are set so they can get different debug colors. |
| 221 tiledLayer->pushInvalidTile(i, j); | 217 tiledLayer->pushInvalidTile(i, j); |
| 222 continue; | 218 continue; |
| 223 } | 219 } |
| 224 | 220 |
| 225 tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId( ), tile->opaqueRect()); | 221 tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId( ), tile->opaqueRect()); |
| 226 tile->isInUseOnImpl = true; | |
| 227 } | 222 } |
| 228 for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); ite r != invalidTiles.end(); ++iter) | 223 for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); ite r != invalidTiles.end(); ++iter) |
| 229 m_tiler->takeTile((*iter)->i(), (*iter)->j()); | 224 m_tiler->takeTile((*iter)->i(), (*iter)->j()); |
| 230 } | 225 } |
| 231 | 226 |
| 232 CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const | 227 CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const |
| 233 { | 228 { |
| 234 if (!layerTreeHost()) | 229 if (!layerTreeHost()) |
| 235 return 0; | 230 return 0; |
| 236 return layerTreeHost()->contentsTextureManager(); | 231 return layerTreeHost()->contentsTextureManager(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 continue; | 310 continue; |
| 316 IntRect bound = m_tiler->tileRect(tile); | 311 IntRect bound = m_tiler->tileRect(tile); |
| 317 bound.intersect(contentRect); | 312 bound.intersect(contentRect); |
| 318 tile->dirtyRect.unite(bound); | 313 tile->dirtyRect.unite(bound); |
| 319 } | 314 } |
| 320 } | 315 } |
| 321 | 316 |
| 322 // Returns true if tile is dirty and only part of it needs to be updated. | 317 // Returns true if tile is dirty and only part of it needs to be updated. |
| 323 bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) | 318 bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) |
| 324 { | 319 { |
| 325 return !tile->dirtyRect.contains(m_tiler->tileRect(tile)); | 320 return !tile->updateRect.contains(m_tiler->tileRect(tile)) && tile->managedT exture()->haveBackingTexture(); |
| 326 } | 321 } |
| 327 | 322 |
| 328 // Dirty tiles with valid textures needs buffered update to guarantee that | |
| 329 // we don't modify textures currently used for drawing by the impl thread. | |
| 330 bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile) | |
| 331 { | |
| 332 if (!tile->managedTexture()->haveBackingTexture()) | |
| 333 return false; | |
| 334 | |
| 335 if (!tile->isDirty()) | |
| 336 return false; | |
| 337 | |
| 338 if (!tile->isInUseOnImpl) | |
| 339 return false; | |
| 340 | |
| 341 return true; | |
| 342 } | |
| 343 | |
| 344 | |
| 345 bool TiledLayerChromium::updateTiles(int left, int top, int right, int bottom, C CTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStat s& stats, bool& didPaint) | 323 bool TiledLayerChromium::updateTiles(int left, int top, int right, int bottom, C CTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStat s& stats, bool& didPaint) |
| 346 { | 324 { |
| 347 didPaint = false; | 325 didPaint = false; |
| 348 createTextureUpdaterIfNeeded(); | 326 createTextureUpdaterIfNeeded(); |
| 349 | 327 |
| 350 bool ignoreOcclusions = !occlusion; | 328 bool ignoreOcclusions = !occlusion; |
| 351 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { | 329 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { |
|
danakj
2012/10/17 23:39:44
I see. This will make it dirty now.
| |
| 352 m_failedUpdate = true; | 330 m_failedUpdate = true; |
| 353 return false; | 331 return false; |
| 354 } | 332 } |
| 355 | 333 |
| 356 IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclu sions); | 334 IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclu sions); |
| 357 | 335 |
| 358 if (occlusion) | 336 if (occlusion) |
| 359 occlusion->overdrawMetrics().didPaint(paintRect); | 337 occlusion->overdrawMetrics().didPaint(paintRect); |
| 360 | 338 |
| 361 if (paintRect.isEmpty()) | 339 if (paintRect.isEmpty()) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 if (!tile) | 449 if (!tile) |
| 472 continue; | 450 continue; |
| 473 | 451 |
| 474 IntRect tileRect = m_tiler->tileBounds(i, j); | 452 IntRect tileRect = m_tiler->tileBounds(i, j); |
| 475 | 453 |
| 476 // Use updateRect as the above loop copied the dirty rect for this f rame to updateRect. | 454 // Use updateRect as the above loop copied the dirty rect for this f rame to updateRect. |
| 477 const IntRect& dirtyRect = tile->updateRect; | 455 const IntRect& dirtyRect = tile->updateRect; |
| 478 if (dirtyRect.isEmpty()) | 456 if (dirtyRect.isEmpty()) |
| 479 continue; | 457 continue; |
| 480 | 458 |
| 459 // FIXME: Decide if partial update should be allowed based on cost | |
| 460 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 | |
| 461 if (layerTreeHost() && layerTreeHost()->bufferedUpdates()) { | |
| 462 // If we get a partial update, we use the same texture, otherwis e return | |
| 463 // the current texture backing, so we don't update visible textu res non-atomically. | |
| 464 // If the current backing is in-use, it won't be deleted until a fter the commit | |
| 465 // as the texture manager will not allow deletion or recycling | |
| 466 // of in-use textures. | |
| 467 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request PartialTextureUpdate()) | |
| 468 tile->partialUpdate = true; | |
| 469 else | |
| 470 tile->managedTexture()->returnBackingTexture(); | |
| 471 } | |
| 472 | |
| 481 // Save what was painted opaque in the tile. Keep the old area if th e paint didn't touch it, and didn't paint some | 473 // Save what was painted opaque in the tile. Keep the old area if th e paint didn't touch it, and didn't paint some |
| 482 // other part of the tile opaque. | 474 // other part of the tile opaque. |
| 483 IntRect tilePaintedRect = intersection(tileRect, paintRect); | 475 IntRect tilePaintedRect = intersection(tileRect, paintRect); |
| 484 IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaque Rect); | 476 IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaque Rect); |
| 485 if (!tilePaintedRect.isEmpty()) { | 477 if (!tilePaintedRect.isEmpty()) { |
| 486 IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRec t(), tilePaintedRect); | 478 IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRec t(), tilePaintedRect); |
| 487 bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRe ct.contains(paintInsideTileOpaqueRect); | 479 bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRe ct.contains(paintInsideTileOpaqueRect); |
| 488 bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect .isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); | 480 bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect .isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); |
| 489 | 481 |
| 490 if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInside TileOpaqueRect) | 482 if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInside TileOpaqueRect) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 resetUpdateState(); | 562 resetUpdateState(); |
| 571 | 563 |
| 572 if (m_tiler->hasEmptyBounds()) | 564 if (m_tiler->hasEmptyBounds()) |
| 573 return; | 565 return; |
| 574 | 566 |
| 575 bool drawsToRoot = !renderTarget()->parent(); | 567 bool drawsToRoot = !renderTarget()->parent(); |
| 576 bool smallAnimatedLayer = isSmallAnimatedLayer(this); | 568 bool smallAnimatedLayer = isSmallAnimatedLayer(this); |
| 577 | 569 |
| 578 // Minimally create the tiles in the desired pre-paint rect. | 570 // Minimally create the tiles in the desired pre-paint rect. |
| 579 IntRect createTilesRect = idlePaintRect(); | 571 IntRect createTilesRect = idlePaintRect(); |
| 572 if (smallAnimatedLayer) | |
| 573 createTilesRect = IntRect(IntPoint::zero(), contentBounds()); | |
| 580 if (!createTilesRect.isEmpty()) { | 574 if (!createTilesRect.isEmpty()) { |
| 581 int left, top, right, bottom; | 575 int left, top, right, bottom; |
| 582 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot tom); | 576 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot tom); |
| 583 for (int j = top; j <= bottom; ++j) { | 577 for (int j = top; j <= bottom; ++j) { |
| 584 for (int i = left; i <= right; ++i) { | 578 for (int i = left; i <= right; ++i) { |
| 585 if (!tileAt(i, j)) | 579 if (!tileAt(i, j)) |
| 586 createTile(i, j); | 580 createTile(i, j); |
| 587 } | 581 } |
| 588 } | 582 } |
| 589 } | 583 } |
| 590 | 584 |
| 591 // Also, minimally create all tiles for small animated layers and also | |
| 592 // double-buffer them since we have limited their size to be reasonable. | |
| 593 IntRect doubleBufferedRect = visibleContentRect(); | |
| 594 if (smallAnimatedLayer) | |
| 595 doubleBufferedRect = IntRect(IntPoint::zero(), contentBounds()); | |
| 596 | |
| 597 // Create additional textures for double-buffered updates when needed. | |
| 598 // These textures must stay alive while the updated textures are incremental ly | |
| 599 // uploaded, swapped atomically via pushProperties, and finally deleted | |
| 600 // after the commit is complete, after which they can be recycled. | |
| 601 if (!doubleBufferedRect.isEmpty()) { | |
| 602 int left, top, right, bottom; | |
| 603 m_tiler->contentRectToTileIndices(doubleBufferedRect, left, top, right, bottom); | |
| 604 for (int j = top; j <= bottom; ++j) { | |
| 605 for (int i = left; i <= right; ++i) { | |
| 606 UpdatableTile* tile = tileAt(i, j); | |
| 607 if (!tile) | |
| 608 tile = createTile(i, j); | |
| 609 // We need an additional texture if the tile needs a buffered-up date and it's not a partial update. | |
| 610 // FIXME: Decide if partial update should be allowed based on co st | |
| 611 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 | |
| 612 if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || ! tileNeedsBufferedUpdate(tile)) | |
| 613 continue; | |
| 614 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request PartialTextureUpdate()) { | |
| 615 tile->partialUpdate = true; | |
| 616 continue; | |
| 617 } | |
| 618 | |
| 619 IntRect tileRect = m_tiler->tileRect(tile); | |
| 620 tile->dirtyRect = tileRect; | |
|
danakj
2012/10/17 23:19:37
who's doing this now?
epenner
2012/10/17 23:33:14
Throwing the texture away will make it dirty.... B
| |
| 621 LayerTextureUpdater::Texture* backBuffer = tile->texture(); | |
| 622 setPriorityForTexture(visibleContentRect(), tile->dirtyRect, dra wsToRoot, smallAnimatedLayer, backBuffer->texture()); | |
| 623 scoped_ptr<CCPrioritizedTexture> frontBuffer = CCPrioritizedText ure::create(backBuffer->texture()->textureManager(), | |
| 624 backBuffer->texture()->size(), | |
| 625 backBuffer->texture()->format()); | |
| 626 // Swap backBuffer into frontBuffer and add it to delete after c ommit queue. | |
| 627 backBuffer->swapTextureWith(frontBuffer); | |
| 628 layerTreeHost()->deleteTextureAfterCommit(frontBuffer.Pass()); | |
| 629 } | |
| 630 } | |
| 631 } | |
| 632 | |
| 633 // Now update priorities on all tiles we have in the layer, no matter where they are. | 585 // Now update priorities on all tiles we have in the layer, no matter where they are. |
| 634 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) { | 586 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) { |
| 635 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); | 587 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); |
| 636 // FIXME: This should not ever be null. | 588 // FIXME: This should not ever be null. |
| 637 if (!tile) | 589 if (!tile) |
| 638 continue; | 590 continue; |
| 639 IntRect tileRect = m_tiler->tileRect(tile); | 591 IntRect tileRect = m_tiler->tileRect(tile); |
| 640 setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, small AnimatedLayer, tile->managedTexture()); | 592 setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, small AnimatedLayer, tile->managedTexture()); |
| 641 } | 593 } |
| 642 } | 594 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 IntRect prepaintRect = visibleContentRect(); | 731 IntRect prepaintRect = visibleContentRect(); |
| 780 prepaintRect.inflateX(m_tiler->tileSize().width()); | 732 prepaintRect.inflateX(m_tiler->tileSize().width()); |
| 781 prepaintRect.inflateY(m_tiler->tileSize().height() * 2); | 733 prepaintRect.inflateY(m_tiler->tileSize().height() * 2); |
| 782 IntRect contentRect(IntPoint::zero(), contentBounds()); | 734 IntRect contentRect(IntPoint::zero(), contentBounds()); |
| 783 prepaintRect.intersect(contentRect); | 735 prepaintRect.intersect(contentRect); |
| 784 | 736 |
| 785 return prepaintRect; | 737 return prepaintRect; |
| 786 } | 738 } |
| 787 | 739 |
| 788 } | 740 } |
| OLD | NEW |