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 #include <set> | 10 #include <set> |
11 | 11 |
12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
13 #include "base/debug/trace_event_argument.h" | 13 #include "base/debug/trace_event_argument.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "cc/base/math_util.h" | 15 #include "cc/base/math_util.h" |
16 #include "cc/resources/tile.h" | 16 #include "cc/resources/tile.h" |
17 #include "cc/resources/tile_priority.h" | 17 #include "cc/resources/tile_priority.h" |
18 #include "ui/gfx/geometry/point_conversions.h" | 18 #include "ui/gfx/geometry/point_conversions.h" |
19 #include "ui/gfx/geometry/rect_conversions.h" | 19 #include "ui/gfx/geometry/rect_conversions.h" |
20 #include "ui/gfx/geometry/safe_integer_conversions.h" | 20 #include "ui/gfx/geometry/safe_integer_conversions.h" |
21 #include "ui/gfx/geometry/size_conversions.h" | 21 #include "ui/gfx/geometry/size_conversions.h" |
22 | 22 |
23 namespace cc { | 23 namespace cc { |
24 namespace { | 24 namespace { |
25 | 25 |
26 const float kSoonBorderDistanceInScreenPixels = 312.f; | 26 const float kSoonBorderDistanceInScreenPixels = 312.f; |
27 | 27 |
28 class TileEvictionOrder { | |
29 public: | |
30 explicit TileEvictionOrder(TreePriority tree_priority) | |
31 : tree_priority_(tree_priority) {} | |
32 ~TileEvictionOrder() {} | |
33 | |
34 bool operator()(const Tile* a, const Tile* b) { | |
35 const TilePriority& a_priority = | |
36 a->priority_for_tree_priority(tree_priority_); | |
37 const TilePriority& b_priority = | |
38 b->priority_for_tree_priority(tree_priority_); | |
39 | |
40 DCHECK(a_priority.priority_bin == b_priority.priority_bin); | |
41 DCHECK(a->required_for_activation() == b->required_for_activation()); | |
42 | |
43 // Or if a is occluded and b is unoccluded. | |
44 bool a_is_occluded = a->is_occluded_for_tree_priority(tree_priority_); | |
45 bool b_is_occluded = b->is_occluded_for_tree_priority(tree_priority_); | |
46 if (a_is_occluded != b_is_occluded) | |
47 return a_is_occluded; | |
48 | |
49 // Or if a is farther away from visible. | |
50 return a_priority.distance_to_visible > b_priority.distance_to_visible; | |
51 } | |
52 | |
53 private: | |
54 TreePriority tree_priority_; | |
55 }; | |
56 | |
57 } // namespace | 28 } // namespace |
58 | 29 |
59 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( | 30 scoped_ptr<PictureLayerTiling> PictureLayerTiling::Create( |
60 float contents_scale, | 31 float contents_scale, |
61 const gfx::Size& layer_bounds, | 32 const gfx::Size& layer_bounds, |
62 PictureLayerTilingClient* client) { | 33 PictureLayerTilingClient* client) { |
63 return make_scoped_ptr(new PictureLayerTiling(contents_scale, | 34 return make_scoped_ptr(new PictureLayerTiling(contents_scale, |
64 layer_bounds, | 35 layer_bounds, |
65 client)); | 36 client)); |
66 } | 37 } |
67 | 38 |
68 PictureLayerTiling::PictureLayerTiling(float contents_scale, | 39 PictureLayerTiling::PictureLayerTiling(float contents_scale, |
69 const gfx::Size& layer_bounds, | 40 const gfx::Size& layer_bounds, |
70 PictureLayerTilingClient* client) | 41 PictureLayerTilingClient* client) |
71 : contents_scale_(contents_scale), | 42 : contents_scale_(contents_scale), |
72 layer_bounds_(layer_bounds), | 43 layer_bounds_(layer_bounds), |
73 resolution_(NON_IDEAL_RESOLUTION), | 44 resolution_(NON_IDEAL_RESOLUTION), |
74 client_(client), | 45 client_(client), |
75 tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), | 46 tiling_data_(gfx::Size(), gfx::Size(), kBorderTexels), |
76 last_impl_frame_time_in_seconds_(0.0), | 47 last_impl_frame_time_in_seconds_(0.0), |
77 content_to_screen_scale_(0.f), | 48 content_to_screen_scale_(0.f), |
78 can_require_tiles_for_activation_(false), | 49 can_require_tiles_for_activation_(false), |
79 has_visible_rect_tiles_(false), | 50 has_visible_rect_tiles_(false), |
80 has_skewport_rect_tiles_(false), | 51 has_skewport_rect_tiles_(false), |
81 has_soon_border_rect_tiles_(false), | 52 has_soon_border_rect_tiles_(false), |
82 has_eventually_rect_tiles_(false), | 53 has_eventually_rect_tiles_(false) { |
83 eviction_tiles_cache_valid_(false), | |
84 eviction_cache_tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES) { | |
85 gfx::Size content_bounds = | 54 gfx::Size content_bounds = |
86 gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); | 55 gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds, contents_scale)); |
87 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); | 56 gfx::Size tile_size = client_->CalculateTileSize(content_bounds); |
88 if (tile_size.IsEmpty()) { | 57 if (tile_size.IsEmpty()) { |
89 layer_bounds_ = gfx::Size(); | 58 layer_bounds_ = gfx::Size(); |
90 content_bounds = gfx::Size(); | 59 content_bounds = gfx::Size(); |
91 } | 60 } |
92 | 61 |
93 DCHECK(!gfx::ToFlooredSize( | 62 DCHECK(!gfx::ToFlooredSize( |
94 gfx::ScaleSize(layer_bounds, contents_scale)).IsEmpty()) << | 63 gfx::ScaleSize(layer_bounds, contents_scale)).IsEmpty()) << |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 } | 107 } |
139 } | 108 } |
140 | 109 |
141 // Create a new tile because our twin didn't have a valid one. | 110 // Create a new tile because our twin didn't have a valid one. |
142 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); | 111 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); |
143 if (tile.get()) { | 112 if (tile.get()) { |
144 DCHECK(!tile->is_shared()); | 113 DCHECK(!tile->is_shared()); |
145 tile->set_tiling_index(i, j); | 114 tile->set_tiling_index(i, j); |
146 tiles_[key] = tile; | 115 tiles_[key] = tile; |
147 } | 116 } |
148 eviction_tiles_cache_valid_ = false; | |
149 return tile.get(); | 117 return tile.get(); |
150 } | 118 } |
151 | 119 |
152 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { | 120 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
153 const PictureLayerTiling* twin_tiling = | 121 const PictureLayerTiling* twin_tiling = |
154 client_->GetPendingOrActiveTwinTiling(this); | 122 client_->GetPendingOrActiveTwinTiling(this); |
155 bool include_borders = false; | 123 bool include_borders = false; |
156 for (TilingData::Iterator iter( | 124 for (TilingData::Iterator iter( |
157 &tiling_data_, live_tiles_rect_, include_borders); | 125 &tiling_data_, live_tiles_rect_, include_borders); |
158 iter; | 126 iter; |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 } | 429 } |
462 | 430 |
463 bool PictureLayerTiling::RemoveTileAt(int i, | 431 bool PictureLayerTiling::RemoveTileAt(int i, |
464 int j, | 432 int j, |
465 PictureLayerTiling* recycled_twin) { | 433 PictureLayerTiling* recycled_twin) { |
466 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); | 434 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); |
467 if (found == tiles_.end()) | 435 if (found == tiles_.end()) |
468 return false; | 436 return false; |
469 found->second->set_shared(false); | 437 found->second->set_shared(false); |
470 tiles_.erase(found); | 438 tiles_.erase(found); |
471 eviction_tiles_cache_valid_ = false; | |
472 if (recycled_twin) { | 439 if (recycled_twin) { |
473 // Recycled twin does not also have a recycled twin, so pass NULL. | 440 // Recycled twin does not also have a recycled twin, so pass NULL. |
474 recycled_twin->RemoveTileAt(i, j, NULL); | 441 recycled_twin->RemoveTileAt(i, j, NULL); |
475 } | 442 } |
476 return true; | 443 return true; |
477 } | 444 } |
478 | 445 |
479 void PictureLayerTiling::Reset() { | 446 void PictureLayerTiling::Reset() { |
480 live_tiles_rect_ = gfx::Rect(); | 447 live_tiles_rect_ = gfx::Rect(); |
481 PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); | 448 PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); |
482 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 449 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
483 it->second->set_shared(false); | 450 it->second->set_shared(false); |
484 if (recycled_twin) | 451 if (recycled_twin) |
485 recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); | 452 recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); |
486 } | 453 } |
487 tiles_.clear(); | 454 tiles_.clear(); |
488 eviction_tiles_cache_valid_ = false; | |
489 } | 455 } |
490 | 456 |
491 gfx::Rect PictureLayerTiling::ComputeSkewport( | 457 gfx::Rect PictureLayerTiling::ComputeSkewport( |
492 double current_frame_time_in_seconds, | 458 double current_frame_time_in_seconds, |
493 const gfx::Rect& visible_rect_in_content_space) const { | 459 const gfx::Rect& visible_rect_in_content_space) const { |
494 gfx::Rect skewport = visible_rect_in_content_space; | 460 gfx::Rect skewport = visible_rect_in_content_space; |
495 if (last_impl_frame_time_in_seconds_ == 0.0) | 461 if (last_impl_frame_time_in_seconds_ == 0.0) |
496 return skewport; | 462 return skewport; |
497 | 463 |
498 double time_delta = | 464 double time_delta = |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale_; | 554 float border = kSoonBorderDistanceInScreenPixels / content_to_screen_scale_; |
589 soon_border_rect.Inset(-border, -border, -border, -border); | 555 soon_border_rect.Inset(-border, -border, -border, -border); |
590 | 556 |
591 // Update the tiling state. | 557 // Update the tiling state. |
592 SetLiveTilesRect(eventually_rect); | 558 SetLiveTilesRect(eventually_rect); |
593 | 559 |
594 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; | 560 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
595 last_viewport_in_layer_space_ = viewport_in_layer_space; | 561 last_viewport_in_layer_space_ = viewport_in_layer_space; |
596 last_visible_rect_in_content_space_ = visible_rect_in_content_space; | 562 last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
597 | 563 |
598 eviction_tiles_cache_valid_ = false; | |
599 | |
600 current_visible_rect_ = visible_rect_in_content_space; | 564 current_visible_rect_ = visible_rect_in_content_space; |
601 current_skewport_rect_ = skewport; | 565 current_skewport_rect_ = skewport; |
602 current_soon_border_rect_ = soon_border_rect; | 566 current_soon_border_rect_ = soon_border_rect; |
603 current_eventually_rect_ = eventually_rect; | 567 current_eventually_rect_ = eventually_rect; |
604 current_occlusion_in_layer_space_ = occlusion_in_layer_space; | 568 current_occlusion_in_layer_space_ = occlusion_in_layer_space; |
605 | 569 |
606 // Update has_*_tiles state. | 570 // Update has_*_tiles state. |
607 gfx::Rect tiling_rect(tiling_size()); | 571 gfx::Rect tiling_rect(tiling_size()); |
608 | 572 |
609 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); | 573 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 if (delta < event.distance) | 956 if (delta < event.distance) |
993 break; | 957 break; |
994 } | 958 } |
995 | 959 |
996 gfx::Rect result(origin_x, origin_y, width, height); | 960 gfx::Rect result(origin_x, origin_y, width, height); |
997 if (cache) | 961 if (cache) |
998 cache->previous_result = result; | 962 cache->previous_result = result; |
999 return result; | 963 return result; |
1000 } | 964 } |
1001 | 965 |
1002 void PictureLayerTiling::UpdateEvictionCacheIfNeeded( | |
1003 TreePriority tree_priority) { | |
1004 if (eviction_tiles_cache_valid_ && | |
1005 eviction_cache_tree_priority_ == tree_priority) | |
1006 return; | |
1007 | |
1008 eviction_tiles_now_.clear(); | |
1009 eviction_tiles_now_and_required_for_activation_.clear(); | |
1010 eviction_tiles_soon_.clear(); | |
1011 eviction_tiles_soon_and_required_for_activation_.clear(); | |
1012 eviction_tiles_eventually_.clear(); | |
1013 eviction_tiles_eventually_and_required_for_activation_.clear(); | |
1014 | |
1015 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | |
1016 Tile* tile = it->second.get(); | |
1017 UpdateTileAndTwinPriority(tile); | |
1018 const TilePriority& priority = | |
1019 tile->priority_for_tree_priority(tree_priority); | |
1020 switch (priority.priority_bin) { | |
1021 case TilePriority::EVENTUALLY: | |
1022 if (tile->required_for_activation()) | |
1023 eviction_tiles_eventually_and_required_for_activation_.push_back( | |
1024 tile); | |
1025 else | |
1026 eviction_tiles_eventually_.push_back(tile); | |
1027 break; | |
1028 case TilePriority::SOON: | |
1029 if (tile->required_for_activation()) | |
1030 eviction_tiles_soon_and_required_for_activation_.push_back(tile); | |
1031 else | |
1032 eviction_tiles_soon_.push_back(tile); | |
1033 break; | |
1034 case TilePriority::NOW: | |
1035 if (tile->required_for_activation()) | |
1036 eviction_tiles_now_and_required_for_activation_.push_back(tile); | |
1037 else | |
1038 eviction_tiles_now_.push_back(tile); | |
1039 break; | |
1040 } | |
1041 } | |
1042 | |
1043 // TODO(vmpstr): Do this lazily. One option is to have a "sorted" flag that | |
1044 // can be updated for each of the queues. | |
1045 TileEvictionOrder sort_order(tree_priority); | |
1046 std::sort(eviction_tiles_now_.begin(), eviction_tiles_now_.end(), sort_order); | |
1047 std::sort(eviction_tiles_now_and_required_for_activation_.begin(), | |
1048 eviction_tiles_now_and_required_for_activation_.end(), | |
1049 sort_order); | |
1050 std::sort( | |
1051 eviction_tiles_soon_.begin(), eviction_tiles_soon_.end(), sort_order); | |
1052 std::sort(eviction_tiles_soon_and_required_for_activation_.begin(), | |
1053 eviction_tiles_soon_and_required_for_activation_.end(), | |
1054 sort_order); | |
1055 std::sort(eviction_tiles_eventually_.begin(), | |
1056 eviction_tiles_eventually_.end(), | |
1057 sort_order); | |
1058 std::sort(eviction_tiles_eventually_and_required_for_activation_.begin(), | |
1059 eviction_tiles_eventually_and_required_for_activation_.end(), | |
1060 sort_order); | |
1061 | |
1062 eviction_tiles_cache_valid_ = true; | |
1063 eviction_cache_tree_priority_ = tree_priority; | |
1064 } | |
1065 | |
1066 const std::vector<Tile*>* PictureLayerTiling::GetEvictionTiles( | |
1067 TreePriority tree_priority, | |
1068 EvictionCategory category) { | |
1069 UpdateEvictionCacheIfNeeded(tree_priority); | |
1070 switch (category) { | |
1071 case EVENTUALLY: | |
1072 return &eviction_tiles_eventually_; | |
1073 case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: | |
1074 return &eviction_tiles_eventually_and_required_for_activation_; | |
1075 case SOON: | |
1076 return &eviction_tiles_soon_; | |
1077 case SOON_AND_REQUIRED_FOR_ACTIVATION: | |
1078 return &eviction_tiles_soon_and_required_for_activation_; | |
1079 case NOW: | |
1080 return &eviction_tiles_now_; | |
1081 case NOW_AND_REQUIRED_FOR_ACTIVATION: | |
1082 return &eviction_tiles_now_and_required_for_activation_; | |
1083 } | |
1084 NOTREACHED(); | |
1085 return &eviction_tiles_eventually_; | |
1086 } | |
1087 | |
1088 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() | 966 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() |
1089 : tiling_(NULL), current_tile_(NULL) {} | 967 : tiling_(NULL), current_tile_(NULL) {} |
1090 | 968 |
1091 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( | 969 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( |
1092 PictureLayerTiling* tiling) | 970 PictureLayerTiling* tiling) |
1093 : tiling_(tiling), phase_(VISIBLE_RECT), current_tile_(NULL) { | 971 : tiling_(tiling), phase_(VISIBLE_RECT), current_tile_(NULL) { |
1094 if (!tiling_->has_visible_rect_tiles_) { | 972 if (!tiling_->has_visible_rect_tiles_) { |
1095 AdvancePhase(); | 973 AdvancePhase(); |
1096 return; | 974 return; |
1097 } | 975 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 } | 1089 } |
1212 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); | 1090 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); |
1213 } | 1091 } |
1214 | 1092 |
1215 if (current_tile_) | 1093 if (current_tile_) |
1216 tiling_->UpdateTileAndTwinPriority(current_tile_); | 1094 tiling_->UpdateTileAndTwinPriority(current_tile_); |
1217 return *this; | 1095 return *this; |
1218 } | 1096 } |
1219 | 1097 |
1220 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() | 1098 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator() |
1221 : eviction_tiles_(NULL), current_eviction_tiles_index_(0u) { | 1099 : tiling_(nullptr), |
| 1100 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES), |
| 1101 eviction_category_(EVENTUALLY), |
| 1102 processing_soon_border_rect_(false), |
| 1103 skip_shared_high_priority_tiles_(false), |
| 1104 unoccluded_now_tiles_index_(0u), |
| 1105 current_tile_(nullptr) { |
1222 } | 1106 } |
1223 | 1107 |
1224 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( | 1108 PictureLayerTiling::TilingEvictionTileIterator::TilingEvictionTileIterator( |
1225 PictureLayerTiling* tiling, | 1109 PictureLayerTiling* tiling, |
1226 TreePriority tree_priority, | 1110 TreePriority tree_priority, |
1227 EvictionCategory category) | 1111 EvictionCategory category, |
1228 : eviction_tiles_(tiling->GetEvictionTiles(tree_priority, category)), | 1112 bool skip_shared_high_priority_tiles) |
1229 // Note: initializing to "0 - 1" works as overflow is well defined for | 1113 : tiling_(tiling), |
1230 // unsigned integers. | 1114 tree_priority_(tree_priority), |
1231 current_eviction_tiles_index_(static_cast<size_t>(0) - 1) { | 1115 eviction_category_(category), |
1232 DCHECK(eviction_tiles_); | 1116 processing_soon_border_rect_(true), |
1233 ++(*this); | 1117 skip_shared_high_priority_tiles_(skip_shared_high_priority_tiles), |
| 1118 unoccluded_now_tiles_index_(0), |
| 1119 current_tile_(nullptr) { |
| 1120 WhichTree tree = tiling_->client_->GetTree(); |
| 1121 if (tree == PENDING_TREE) { |
| 1122 switch (eviction_category_) { |
| 1123 case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: |
| 1124 case SOON_AND_REQUIRED_FOR_ACTIVATION: |
| 1125 // Pending EVENTUALLY and SOON tiles are never required for activation. |
| 1126 return; |
| 1127 default: |
| 1128 break; |
| 1129 } |
| 1130 } else { |
| 1131 switch (eviction_category_) { |
| 1132 case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: |
| 1133 case SOON_AND_REQUIRED_FOR_ACTIVATION: |
| 1134 case NOW_AND_REQUIRED_FOR_ACTIVATION: { |
| 1135 // Early out if there is no pending twin tiling. |
| 1136 if (!skip_shared_high_priority_tiles_) |
| 1137 return; |
| 1138 const PictureLayerTiling* twin_tiling = |
| 1139 tiling_->client_->GetPendingOrActiveTwinTiling(tiling_); |
| 1140 if (!twin_tiling) |
| 1141 return; |
| 1142 // Early out if the pending twin tiling does not have NOW tiles. |
| 1143 TilePriority::PriorityBin max_twin_tile_priority_bin = |
| 1144 twin_tiling->client_->GetMaxTilePriorityBin(); |
| 1145 if (max_twin_tile_priority_bin > TilePriority::NOW) |
| 1146 return; |
| 1147 break; |
| 1148 } |
| 1149 default: |
| 1150 break; |
| 1151 } |
| 1152 } |
| 1153 TilePriority::PriorityBin max_tile_priority_bin = |
| 1154 tiling_->client_->GetMaxTilePriorityBin(); |
| 1155 switch (eviction_category_) { |
| 1156 case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: |
| 1157 case EVENTUALLY: |
| 1158 if (tiling_->has_eventually_rect_tiles_) { |
| 1159 if (max_tile_priority_bin < TilePriority::EVENTUALLY) |
| 1160 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( |
| 1161 &tiling_->tiling_data_, tiling_->current_eventually_rect_, |
| 1162 tiling_->current_skewport_rect_, |
| 1163 tiling_->current_soon_border_rect_); |
| 1164 else |
| 1165 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( |
| 1166 &tiling_->tiling_data_, tiling_->current_eventually_rect_, |
| 1167 gfx::Rect(), gfx::Rect()); |
| 1168 bool skipped_tiles = false; |
| 1169 AdvanceEventually(&skipped_tiles); |
| 1170 if (!current_tile_ && !skipped_tiles && |
| 1171 max_tile_priority_bin == TilePriority::EVENTUALLY) |
| 1172 tiling_->has_eventually_rect_tiles_ = false; |
| 1173 } |
| 1174 break; |
| 1175 case SOON_AND_REQUIRED_FOR_ACTIVATION: |
| 1176 case SOON: |
| 1177 if (max_tile_priority_bin <= TilePriority::SOON && |
| 1178 (tiling_->has_skewport_rect_tiles_ || |
| 1179 tiling_->has_soon_border_rect_tiles_)) { |
| 1180 if (tiling_->has_soon_border_rect_tiles_) |
| 1181 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( |
| 1182 &tiling_->tiling_data_, tiling_->current_soon_border_rect_, |
| 1183 tiling_->current_skewport_rect_, tiling_->current_visible_rect_); |
| 1184 AdvanceSoon(); |
| 1185 } |
| 1186 break; |
| 1187 case NOW_AND_REQUIRED_FOR_ACTIVATION: |
| 1188 case NOW: |
| 1189 if (max_tile_priority_bin <= TilePriority::NOW && |
| 1190 tiling_->has_visible_rect_tiles_) { |
| 1191 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, |
| 1192 tiling_->current_visible_rect_, |
| 1193 false /* include_borders */); |
| 1194 AdvanceNow(); |
| 1195 } |
| 1196 break; |
| 1197 } |
| 1198 } |
| 1199 |
| 1200 void PictureLayerTiling::TilingEvictionTileIterator::AdvanceEventually( |
| 1201 bool* skipped_tiles) { |
| 1202 bool required_for_activation = |
| 1203 eviction_category_ == EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION; |
| 1204 while (spiral_iterator_) { |
| 1205 std::pair<int, int> next_index = spiral_iterator_.index(); |
| 1206 Tile* tile = tiling_->TileAt(next_index.first, next_index.second); |
| 1207 ++spiral_iterator_; |
| 1208 if (!tile || !tile->HasResources()) |
| 1209 continue; |
| 1210 if (PrepareTileUnlessReturnedByTwin(tile) && |
| 1211 tile->required_for_activation() == required_for_activation) { |
| 1212 current_tile_ = tile; |
| 1213 return; |
| 1214 } |
| 1215 if (skipped_tiles) |
| 1216 *skipped_tiles = true; |
| 1217 } |
| 1218 |
| 1219 current_tile_ = nullptr; |
| 1220 } |
| 1221 |
| 1222 void PictureLayerTiling::TilingEvictionTileIterator::AdvanceSoon() { |
| 1223 bool required_for_activation = |
| 1224 eviction_category_ == SOON_AND_REQUIRED_FOR_ACTIVATION; |
| 1225 while (spiral_iterator_) { |
| 1226 std::pair<int, int> next_index = spiral_iterator_.index(); |
| 1227 Tile* tile = tiling_->TileAt(next_index.first, next_index.second); |
| 1228 ++spiral_iterator_; |
| 1229 if (tile && tile->HasResources() && PrepareTileUnlessReturnedByTwin(tile) && |
| 1230 tile->required_for_activation() == required_for_activation) { |
| 1231 current_tile_ = tile; |
| 1232 return; |
| 1233 } |
| 1234 if (!spiral_iterator_ && processing_soon_border_rect_) { |
| 1235 if (tiling_->has_skewport_rect_tiles_) { |
| 1236 // Max tile priority bin should never be SOON so there is no need to |
| 1237 // create a special case for the inclusion of the visible rect. |
| 1238 DCHECK_EQ(tiling_->client_->GetMaxTilePriorityBin(), TilePriority::NOW); |
| 1239 DCHECK_LT(tiling_->client_->GetMaxTilePriorityBin(), |
| 1240 TilePriority::SOON); |
| 1241 spiral_iterator_ = TilingData::ReverseSpiralDifferenceIterator( |
| 1242 &tiling_->tiling_data_, tiling_->current_skewport_rect_, |
| 1243 tiling_->current_visible_rect_, tiling_->current_visible_rect_); |
| 1244 } |
| 1245 processing_soon_border_rect_ = false; |
| 1246 } |
| 1247 } |
| 1248 |
| 1249 current_tile_ = nullptr; |
| 1250 } |
| 1251 |
| 1252 void PictureLayerTiling::TilingEvictionTileIterator::AdvanceNow() { |
| 1253 bool required_for_activation = |
| 1254 eviction_category_ == NOW_AND_REQUIRED_FOR_ACTIVATION; |
| 1255 if (visible_iterator_) { |
| 1256 WhichTree tree = tiling_->client_->GetTree(); |
| 1257 bool skip_all_shared_tiles = |
| 1258 skip_shared_high_priority_tiles_ && |
| 1259 tree_priority_ == (tree == ACTIVE_TREE ? NEW_CONTENT_TAKES_PRIORITY |
| 1260 : SMOOTHNESS_TAKES_PRIORITY); |
| 1261 while (visible_iterator_) { |
| 1262 std::pair<int, int> next_index = visible_iterator_.index(); |
| 1263 Tile* tile = tiling_->TileAt(next_index.first, next_index.second); |
| 1264 ++visible_iterator_; |
| 1265 if (!tile || !tile->HasResources()) |
| 1266 continue; |
| 1267 if (skip_all_shared_tiles && tile->is_shared()) |
| 1268 continue; |
| 1269 if (tree == PENDING_TREE && |
| 1270 tiling_->IsTileRequiredForActivationIfVisible(tile) != |
| 1271 required_for_activation) |
| 1272 continue; |
| 1273 if (!tiling_->IsTileOccluded(tile)) { |
| 1274 unoccluded_now_tiles_.push_back(tile); |
| 1275 continue; |
| 1276 } |
| 1277 if (PrepareTileUnlessReturnedByTwin(tile) && |
| 1278 tile->required_for_activation() == required_for_activation) { |
| 1279 current_tile_ = tile; |
| 1280 return; |
| 1281 } |
| 1282 } |
| 1283 } |
| 1284 |
| 1285 while (unoccluded_now_tiles_index_ < unoccluded_now_tiles_.size()) { |
| 1286 Tile* tile = unoccluded_now_tiles_[unoccluded_now_tiles_index_]; |
| 1287 ++unoccluded_now_tiles_index_; |
| 1288 DCHECK(tile); |
| 1289 if (!tile->HasResources()) |
| 1290 continue; |
| 1291 if (PrepareTileUnlessReturnedByTwin(tile) && |
| 1292 tile->required_for_activation() == required_for_activation) { |
| 1293 current_tile_ = tile; |
| 1294 return; |
| 1295 } |
| 1296 } |
| 1297 |
| 1298 current_tile_ = nullptr; |
| 1299 } |
| 1300 |
| 1301 bool PictureLayerTiling::TilingEvictionTileIterator:: |
| 1302 PrepareTileUnlessReturnedByTwin(Tile* tile) const { |
| 1303 if (skip_shared_high_priority_tiles_ && tile->is_shared()) { |
| 1304 WhichTree tree = tiling_->client_->GetTree(); |
| 1305 switch (tree_priority_) { |
| 1306 case SMOOTHNESS_TAKES_PRIORITY: |
| 1307 // The priority for tile priority of a shared tile will be the active |
| 1308 // priority thus return shared tiles from the active tree. |
| 1309 if (tree != ACTIVE_TREE) |
| 1310 return false; |
| 1311 break; |
| 1312 case NEW_CONTENT_TAKES_PRIORITY: |
| 1313 // The priority for tile priority of a shared tile will be the pending |
| 1314 // priority thus return shared tiles from the pending tree. |
| 1315 if (tree != PENDING_TREE) |
| 1316 return false; |
| 1317 break; |
| 1318 case SAME_PRIORITY_FOR_BOTH_TREES: { |
| 1319 // The priority for tile priority of a shared tile will be a combined |
| 1320 // priority thus return shared tiles from a higher priority tree. |
| 1321 tiling_->UpdateTileAndTwinPriority(tile); |
| 1322 WhichTree other_tree = tree == ACTIVE_TREE ? PENDING_TREE : ACTIVE_TREE; |
| 1323 const TilePriority& priority = tile->priority(tree); |
| 1324 const TilePriority& other_priority = tile->priority(other_tree); |
| 1325 if (priority.priority_bin != other_priority.priority_bin) |
| 1326 return priority.priority_bin < other_priority.priority_bin; |
| 1327 const bool occluded = tile->is_occluded(tree); |
| 1328 const bool other_occluded = tile->is_occluded(other_tree); |
| 1329 if (occluded != other_occluded) |
| 1330 return !occluded; |
| 1331 if (priority.distance_to_visible != other_priority.distance_to_visible) |
| 1332 return priority.distance_to_visible < |
| 1333 other_priority.distance_to_visible; |
| 1334 return tree == ACTIVE_TREE; |
| 1335 } |
| 1336 default: |
| 1337 NOTREACHED(); |
| 1338 } |
| 1339 } |
| 1340 tiling_->UpdateTileAndTwinPriority(tile); |
| 1341 return true; |
1234 } | 1342 } |
1235 | 1343 |
1236 PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() { | 1344 PictureLayerTiling::TilingEvictionTileIterator::~TilingEvictionTileIterator() { |
1237 } | 1345 } |
1238 | 1346 |
1239 PictureLayerTiling::TilingEvictionTileIterator::operator bool() const { | 1347 PictureLayerTiling::TilingEvictionTileIterator::operator bool() const { |
1240 return eviction_tiles_ && | 1348 return !!current_tile_; |
1241 current_eviction_tiles_index_ != eviction_tiles_->size(); | |
1242 } | 1349 } |
1243 | 1350 |
1244 Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() { | 1351 Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() { |
1245 DCHECK(*this); | 1352 DCHECK(*this); |
1246 return (*eviction_tiles_)[current_eviction_tiles_index_]; | 1353 return current_tile_; |
1247 } | 1354 } |
1248 | 1355 |
1249 const Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() const { | 1356 const Tile* PictureLayerTiling::TilingEvictionTileIterator::operator*() const { |
1250 DCHECK(*this); | 1357 DCHECK(*this); |
1251 return (*eviction_tiles_)[current_eviction_tiles_index_]; | 1358 return current_tile_; |
1252 } | 1359 } |
1253 | 1360 |
1254 PictureLayerTiling::TilingEvictionTileIterator& | 1361 PictureLayerTiling::TilingEvictionTileIterator& |
1255 PictureLayerTiling::TilingEvictionTileIterator:: | 1362 PictureLayerTiling::TilingEvictionTileIterator:: |
1256 operator++() { | 1363 operator++() { |
1257 DCHECK(*this); | 1364 switch (eviction_category_) { |
1258 do { | 1365 case EVENTUALLY: |
1259 ++current_eviction_tiles_index_; | 1366 case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: |
1260 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && | 1367 AdvanceEventually(nullptr); |
1261 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); | 1368 break; |
1262 | 1369 case SOON: |
| 1370 case SOON_AND_REQUIRED_FOR_ACTIVATION: |
| 1371 AdvanceSoon(); |
| 1372 break; |
| 1373 case NOW: |
| 1374 case NOW_AND_REQUIRED_FOR_ACTIVATION: |
| 1375 AdvanceNow(); |
| 1376 break; |
| 1377 } |
1263 return *this; | 1378 return *this; |
1264 } | 1379 } |
1265 | 1380 |
1266 } // namespace cc | 1381 } // namespace cc |
OLD | NEW |