Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "cc/resources/picture_layer_tiling.h" | 5 #include "cc/resources/picture_layer_tiling.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <limits> | 9 #include <limits> |
| 10 | 10 |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "cc/base/math_util.h" | 12 #include "cc/base/math_util.h" |
| 13 #include "cc/resources/tile.h" | |
| 14 #include "cc/resources/tile_priority.h" | |
| 13 #include "ui/gfx/point_conversions.h" | 15 #include "ui/gfx/point_conversions.h" |
| 14 #include "ui/gfx/rect_conversions.h" | 16 #include "ui/gfx/rect_conversions.h" |
| 15 #include "ui/gfx/safe_integer_conversions.h" | 17 #include "ui/gfx/safe_integer_conversions.h" |
| 16 #include "ui/gfx/size_conversions.h" | 18 #include "ui/gfx/size_conversions.h" |
| 17 | 19 |
| 18 namespace cc { | 20 namespace cc { |
| 21 namespace { | |
| 22 | |
| 23 class HighPriorityFirstOrder { | |
| 24 public: | |
| 25 explicit HighPriorityFirstOrder(WhichTree tree) : tree_(tree) {} | |
| 26 ~HighPriorityFirstOrder() {} | |
| 27 | |
| 28 bool operator()(const Tile* a, const Tile* b) const { | |
| 29 const TilePriority& a_priority = a->priority(tree_); | |
| 30 const TilePriority& b_priority = b->priority(tree_); | |
| 31 | |
| 32 return (a_priority.priority_bin < b_priority.priority_bin) || | |
| 33 (a_priority.priority_bin == b_priority.priority_bin && | |
| 34 a_priority.distance_to_visible < b_priority.distance_to_visible); | |
| 35 } | |
| 36 | |
| 37 private: | |
| 38 WhichTree tree_; | |
| 39 }; | |
| 40 | |
| 41 class LowPriorityFirstOrder { | |
| 42 public: | |
| 43 explicit LowPriorityFirstOrder(WhichTree tree) : tree_(tree) {} | |
| 44 ~LowPriorityFirstOrder() {} | |
| 45 | |
| 46 bool operator()(const Tile* a, const Tile* b) const { | |
| 47 const TilePriority& a_priority = a->priority(tree_); | |
| 48 const TilePriority& b_priority = b->priority(tree_); | |
| 49 | |
| 50 return (a_priority.priority_bin > b_priority.priority_bin) || | |
| 51 (a_priority.priority_bin == b_priority.priority_bin && | |
| 52 a_priority.distance_to_visible > b_priority.distance_to_visible); | |
| 53 } | |
| 54 | |
| 55 private: | |
| 56 WhichTree tree_; | |
| 57 }; | |
| 58 | |
| 59 } // namespace | |
| 19 | 60 |
| 20 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( | 61 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
| 21 float contents_scale, | 62 float contents_scale, |
| 22 const gfx::Size& layer_bounds, | 63 const gfx::Size& layer_bounds, |
| 23 PictureLayerTilingClient* client) { | 64 PictureLayerTilingClient* client) { |
| 24 return make_scoped_ptr(new PictureLayerTiling(contents_scale, | 65 return make_scoped_ptr(new PictureLayerTiling(contents_scale, |
| 25 layer_bounds, | 66 layer_bounds, |
| 26 client)); | 67 client)); |
| 27 } | 68 } |
| 28 | 69 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 57 } | 98 } |
| 58 | 99 |
| 59 gfx::Rect PictureLayerTiling::ContentRect() const { | 100 gfx::Rect PictureLayerTiling::ContentRect() const { |
| 60 return gfx::Rect(tiling_data_.total_size()); | 101 return gfx::Rect(tiling_data_.total_size()); |
| 61 } | 102 } |
| 62 | 103 |
| 63 gfx::SizeF PictureLayerTiling::ContentSizeF() const { | 104 gfx::SizeF PictureLayerTiling::ContentSizeF() const { |
| 64 return gfx::ScaleSize(layer_bounds_, contents_scale_); | 105 return gfx::ScaleSize(layer_bounds_, contents_scale_); |
| 65 } | 106 } |
| 66 | 107 |
| 108 bool PictureLayerTiling::HasVisibleTilesAtOrAfterPriority(size_t priority_index) | |
| 109 const { | |
| 110 return priority_index < visible_tiles_.size(); | |
| 111 } | |
| 112 | |
| 113 Tile* PictureLayerTiling::RasterTileForPriority(size_t priority_index) { | |
| 114 // First, return visible tiles. | |
| 115 if (priority_index < visible_tiles_.size()) | |
| 116 return visible_tiles_[priority_index]; | |
| 117 priority_index -= visible_tiles_.size(); | |
| 118 | |
| 119 // Next, return skewport tiles. | |
| 120 if (priority_index < skewport_tiles_.size()) { | |
| 121 if (!skewport_tiles_sorted_) { | |
| 122 std::sort(skewport_tiles_.begin(), | |
| 123 skewport_tiles_.end(), | |
| 124 HighPriorityFirstOrder(last_update_tree_)); | |
| 125 skewport_tiles_sorted_ = true; | |
| 126 } | |
| 127 return skewport_tiles_[priority_index]; | |
| 128 } | |
| 129 priority_index -= skewport_tiles_.size(); | |
| 130 | |
| 131 // Next, return eventually tiles. | |
| 132 if (priority_index < eventually_tiles_.size()) { | |
| 133 if (!eventually_tiles_sorted_) { | |
| 134 std::sort(eventually_tiles_.begin(), | |
| 135 eventually_tiles_.end(), | |
| 136 HighPriorityFirstOrder(last_update_tree_)); | |
| 137 eventually_tiles_sorted_ = true; | |
| 138 } | |
| 139 return eventually_tiles_[priority_index]; | |
| 140 } | |
| 141 | |
| 142 // If we got here, that means we're out of tiles that need raster. | |
| 143 return NULL; | |
| 144 } | |
| 145 | |
| 146 Tile* PictureLayerTiling::EvictionTileForPriority(size_t priority_index) { | |
| 147 if (priority_index < eviction_tiles_.size()) { | |
| 148 if (!eviction_tiles_sorted_) { | |
| 149 std::sort(eviction_tiles_.begin(), | |
| 150 eviction_tiles_.end(), | |
| 151 LowPriorityFirstOrder(last_update_tree_)); | |
| 152 eviction_tiles_sorted_ = true; | |
| 153 } | |
| 154 return eviction_tiles_[priority_index]; | |
| 155 } | |
| 156 | |
| 157 // No more eviction tiles present. | |
| 158 return NULL; | |
| 159 } | |
| 160 | |
| 67 Tile* PictureLayerTiling::TileAt(int i, int j) const { | 161 Tile* PictureLayerTiling::TileAt(int i, int j) const { |
| 68 TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j)); | 162 TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j)); |
| 69 if (iter == tiles_.end()) | 163 if (iter == tiles_.end()) |
| 70 return NULL; | 164 return NULL; |
| 71 return iter->second.get(); | 165 return iter->second.get(); |
| 72 } | 166 } |
| 73 | 167 |
| 74 void PictureLayerTiling::CreateTile(int i, | 168 void PictureLayerTiling::CreateTile(int i, |
| 75 int j, | 169 int j, |
| 76 const PictureLayerTiling* twin_tiling) { | 170 const PictureLayerTiling* twin_tiling) { |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 ContentRect(), | 517 ContentRect(), |
| 424 &expansion_cache_); | 518 &expansion_cache_); |
| 425 | 519 |
| 426 DCHECK(eventually_rect.IsEmpty() || ContentRect().Contains(eventually_rect)); | 520 DCHECK(eventually_rect.IsEmpty() || ContentRect().Contains(eventually_rect)); |
| 427 | 521 |
| 428 SetLiveTilesRect(eventually_rect); | 522 SetLiveTilesRect(eventually_rect); |
| 429 | 523 |
| 430 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; | 524 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
| 431 last_visible_rect_in_content_space_ = visible_rect_in_content_space; | 525 last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
| 432 | 526 |
| 527 visible_tiles_.clear(); | |
| 528 skewport_tiles_.clear(); | |
| 529 skewport_tiles_sorted_ = false; | |
| 530 eventually_tiles_.clear(); | |
| 531 eventually_tiles_sorted_ = false; | |
| 532 eviction_tiles_.clear(); | |
| 533 eviction_tiles_sorted_ = false; | |
| 534 | |
| 433 // Assign now priority to all visible tiles. | 535 // Assign now priority to all visible tiles. |
| 434 TilePriority now_priority(resolution_, TilePriority::NOW, 0); | 536 TilePriority now_priority(resolution_, TilePriority::NOW, 0); |
| 435 for (TilingData::Iterator iter(&tiling_data_, visible_rect_in_content_space); | 537 for (TilingData::Iterator iter(&tiling_data_, visible_rect_in_content_space); |
| 436 iter; | 538 iter; |
| 437 ++iter) { | 539 ++iter) { |
| 438 TileMap::iterator find = tiles_.find(iter.index()); | 540 TileMap::iterator find = tiles_.find(iter.index()); |
| 439 if (find == tiles_.end()) | 541 if (find == tiles_.end()) |
| 440 continue; | 542 continue; |
| 441 Tile* tile = find->second.get(); | 543 Tile* tile = find->second.get(); |
| 442 | 544 |
| 443 tile->SetPriority(tree, now_priority); | 545 tile->SetPriority(tree, now_priority); |
| 546 visible_tiles_.push_back(tile); | |
|
vmpstr
2014/02/27 21:18:34
Doing conditional pushes here (if it actually need
| |
| 547 eviction_tiles_.push_back(tile); | |
| 444 } | 548 } |
| 445 | 549 |
| 446 // Assign soon priority to all tiles in the skewport that are not visible. | 550 // Assign soon priority to all tiles in the skewport that are not visible. |
| 447 float content_to_screen_scale = | 551 float content_to_screen_scale = |
| 448 1.0f / (contents_scale_ * layer_contents_scale); | 552 1.0f / (contents_scale_ * layer_contents_scale); |
| 553 | |
| 449 for (TilingData::DifferenceIterator iter( | 554 for (TilingData::DifferenceIterator iter( |
| 450 &tiling_data_, skewport, visible_rect_in_content_space); | 555 &tiling_data_, skewport, visible_rect_in_content_space); |
| 451 iter; | 556 iter; |
| 452 ++iter) { | 557 ++iter) { |
| 453 TileMap::iterator find = tiles_.find(iter.index()); | 558 TileMap::iterator find = tiles_.find(iter.index()); |
| 454 if (find == tiles_.end()) | 559 if (find == tiles_.end()) |
| 455 continue; | 560 continue; |
| 456 Tile* tile = find->second.get(); | 561 Tile* tile = find->second.get(); |
| 457 | 562 |
| 458 gfx::Rect tile_bounds = | 563 gfx::Rect tile_bounds = |
| 459 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); | 564 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
| 460 | 565 |
| 461 float distance_to_visible = | 566 float distance_to_visible = |
| 462 visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * | 567 visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * |
| 463 content_to_screen_scale; | 568 content_to_screen_scale; |
| 464 | 569 |
| 465 TilePriority priority(resolution_, TilePriority::SOON, distance_to_visible); | 570 TilePriority priority(resolution_, TilePriority::SOON, distance_to_visible); |
| 466 tile->SetPriority(tree, priority); | 571 tile->SetPriority(tree, priority); |
| 572 skewport_tiles_.push_back(tile); | |
| 573 eviction_tiles_.push_back(tile); | |
| 467 } | 574 } |
| 468 | 575 |
| 469 // Assign eventually priority to all tiles in the eventually rect that are not | 576 // Assign eventually priority to all tiles in the eventually rect that are not |
| 470 // in the skewport. | 577 // in the skewport. |
| 471 for (TilingData::DifferenceIterator iter( | 578 for (TilingData::DifferenceIterator iter( |
| 472 &tiling_data_, eventually_rect, skewport); | 579 &tiling_data_, eventually_rect, skewport); |
| 473 iter; | 580 iter; |
| 474 ++iter) { | 581 ++iter) { |
| 475 TileMap::iterator find = tiles_.find(iter.index()); | 582 TileMap::iterator find = tiles_.find(iter.index()); |
| 476 if (find == tiles_.end()) | 583 if (find == tiles_.end()) |
| 477 continue; | 584 continue; |
| 478 Tile* tile = find->second.get(); | 585 Tile* tile = find->second.get(); |
| 479 | 586 |
| 480 gfx::Rect tile_bounds = | 587 gfx::Rect tile_bounds = |
| 481 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); | 588 tiling_data_.TileBounds(iter.index_x(), iter.index_y()); |
| 482 | 589 |
| 483 float distance_to_visible = | 590 float distance_to_visible = |
| 484 visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * | 591 visible_rect_in_content_space.ManhattanInternalDistance(tile_bounds) * |
| 485 content_to_screen_scale; | 592 content_to_screen_scale; |
| 486 TilePriority priority( | 593 TilePriority priority( |
| 487 resolution_, TilePriority::EVENTUALLY, distance_to_visible); | 594 resolution_, TilePriority::EVENTUALLY, distance_to_visible); |
| 488 tile->SetPriority(tree, priority); | 595 tile->SetPriority(tree, priority); |
| 596 eventually_tiles_.push_back(tile); | |
| 597 eviction_tiles_.push_back(tile); | |
| 489 } | 598 } |
| 599 | |
| 600 last_update_tree_ = tree; | |
| 490 } | 601 } |
| 491 | 602 |
| 492 void PictureLayerTiling::SetLiveTilesRect( | 603 void PictureLayerTiling::SetLiveTilesRect( |
| 493 const gfx::Rect& new_live_tiles_rect) { | 604 const gfx::Rect& new_live_tiles_rect) { |
| 494 DCHECK(new_live_tiles_rect.IsEmpty() || | 605 DCHECK(new_live_tiles_rect.IsEmpty() || |
| 495 ContentRect().Contains(new_live_tiles_rect)); | 606 ContentRect().Contains(new_live_tiles_rect)); |
| 496 if (live_tiles_rect_ == new_live_tiles_rect) | 607 if (live_tiles_rect_ == new_live_tiles_rect) |
| 497 return; | 608 return; |
| 498 | 609 |
| 499 // Iterate to delete all tiles outside of our new live_tiles rect. | 610 // Iterate to delete all tiles outside of our new live_tiles rect. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 client_->UpdatePile(it->second.get()); | 660 client_->UpdatePile(it->second.get()); |
| 550 } | 661 } |
| 551 } | 662 } |
| 552 | 663 |
| 553 void PictureLayerTiling::UpdateTilesToCurrentPile() { | 664 void PictureLayerTiling::UpdateTilesToCurrentPile() { |
| 554 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 665 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 555 client_->UpdatePile(it->second.get()); | 666 client_->UpdatePile(it->second.get()); |
| 556 } | 667 } |
| 557 } | 668 } |
| 558 | 669 |
| 670 size_t PictureLayerTiling::RequiredGPUMemoryInBytes() const { | |
| 671 size_t amount = 0; | |
| 672 for (TilingData::Iterator iter(&tiling_data_, | |
| 673 last_visible_rect_in_content_space_); | |
| 674 iter; | |
| 675 ++iter) { | |
| 676 TileMap::const_iterator find = tiles_.find(iter.index()); | |
| 677 if (find == tiles_.end()) | |
| 678 continue; | |
| 679 Tile* tile = find->second.get(); | |
| 680 amount += tile->GPUMemoryUsageInBytes(); | |
| 681 } | |
| 682 return amount; | |
| 683 } | |
| 684 | |
| 559 scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { | 685 scoped_ptr<base::Value> PictureLayerTiling::AsValue() const { |
| 560 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | 686 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); |
| 561 state->SetInteger("num_tiles", tiles_.size()); | 687 state->SetInteger("num_tiles", tiles_.size()); |
| 562 state->SetDouble("content_scale", contents_scale_); | 688 state->SetDouble("content_scale", contents_scale_); |
| 563 state->Set("content_bounds", | 689 state->Set("content_bounds", |
| 564 MathUtil::AsValue(ContentRect().size()).release()); | 690 MathUtil::AsValue(ContentRect().size()).release()); |
| 565 return state.PassAs<base::Value>(); | 691 return state.PassAs<base::Value>(); |
| 566 } | 692 } |
| 567 | 693 |
| 568 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { | 694 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 if (delta < event.distance) | 842 if (delta < event.distance) |
| 717 break; | 843 break; |
| 718 } | 844 } |
| 719 | 845 |
| 720 gfx::Rect result(origin_x, origin_y, width, height); | 846 gfx::Rect result(origin_x, origin_y, width, height); |
| 721 if (cache) | 847 if (cache) |
| 722 cache->previous_result = result; | 848 cache->previous_result = result; |
| 723 return result; | 849 return result; |
| 724 } | 850 } |
| 725 | 851 |
| 852 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() | |
| 853 : tiling_(NULL), current_index_(0) {} | |
| 854 | |
| 855 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( | |
| 856 PictureLayerTiling* tiling) | |
| 857 : tiling_(tiling), current_index_(0) { | |
| 858 Tile* tile = tiling_->RasterTileForPriority(current_index_); | |
| 859 if (!tile) | |
| 860 return; | |
| 861 | |
| 862 RasterMode raster_mode = | |
| 863 tile->DetermineRasterModeForTree(tiling_->last_update_tree_); | |
| 864 if (!tile->NeedsRasterForMode(raster_mode)) | |
| 865 ++(*this); | |
| 866 } | |
| 867 | |
| 868 PictureLayerTiling::TilingRasterTileIterator::~TilingRasterTileIterator() {} | |
| 869 | |
| 870 void PictureLayerTiling::TilingRasterTileIterator::operator++() { | |
| 871 DCHECK(*this); | |
| 872 while (true) { | |
| 873 ++current_index_; | |
| 874 | |
| 875 Tile* tile = tiling_->RasterTileForPriority(current_index_); | |
| 876 if (!tile) | |
| 877 break; | |
| 878 | |
| 879 RasterMode raster_mode = | |
| 880 tile->DetermineRasterModeForTree(tiling_->last_update_tree_); | |
| 881 if (tile->NeedsRasterForMode(raster_mode)) | |
| 882 break; | |
| 883 } | |
| 884 } | |
| 885 | |
| 886 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() | |
| 887 : tiling_(NULL), current_index_(0) {} | |
| 888 | |
| 889 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( | |
| 890 PictureLayerTiling* tiling) | |
| 891 : tiling_(tiling), current_index_(0) { | |
| 892 Tile* tile = tiling_->EvictionTileForPriority(current_index_); | |
| 893 if (!tile) | |
| 894 return; | |
| 895 | |
| 896 if (!tile->HasResources()) | |
| 897 ++(*this); | |
| 898 } | |
| 899 | |
| 900 PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() {} | |
| 901 | |
| 902 void PictureLayerTiling::TilingEvictionTileIterator::operator++() { | |
| 903 DCHECK(*this); | |
| 904 while (true) { | |
| 905 ++current_index_; | |
| 906 | |
| 907 Tile* tile = tiling_->EvictionTileForPriority(current_index_); | |
| 908 if (!tile || tile->HasResources()) | |
| 909 break; | |
| 910 } | |
| 911 } | |
| 912 | |
| 726 } // namespace cc | 913 } // namespace cc |
| OLD | NEW |