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 |