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 "cc/base/math_util.h" | 15 #include "cc/base/math_util.h" |
15 #include "cc/resources/tile.h" | 16 #include "cc/resources/tile.h" |
16 #include "cc/resources/tile_priority.h" | 17 #include "cc/resources/tile_priority.h" |
17 #include "cc/trees/occlusion_tracker.h" | 18 #include "cc/trees/occlusion_tracker.h" |
18 #include "ui/gfx/point_conversions.h" | 19 #include "ui/gfx/point_conversions.h" |
19 #include "ui/gfx/rect_conversions.h" | 20 #include "ui/gfx/rect_conversions.h" |
20 #include "ui/gfx/safe_integer_conversions.h" | 21 #include "ui/gfx/safe_integer_conversions.h" |
21 #include "ui/gfx/size_conversions.h" | 22 #include "ui/gfx/size_conversions.h" |
22 | 23 |
23 namespace cc { | 24 namespace cc { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); | 141 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); |
141 if (tile.get()) { | 142 if (tile.get()) { |
142 DCHECK(!tile->is_shared()); | 143 DCHECK(!tile->is_shared()); |
143 tiles_[key] = tile; | 144 tiles_[key] = tile; |
144 } | 145 } |
145 return tile.get(); | 146 return tile.get(); |
146 } | 147 } |
147 | 148 |
148 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { | 149 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
149 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); | 150 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
150 bool include_borders = true; | 151 bool include_borders = false; |
151 for (TilingData::Iterator iter( | 152 for (TilingData::Iterator iter( |
152 &tiling_data_, live_tiles_rect_, include_borders); | 153 &tiling_data_, live_tiles_rect_, include_borders); |
153 iter; | 154 iter; |
154 ++iter) { | 155 ++iter) { |
155 TileMapKey key = iter.index(); | 156 TileMapKey key = iter.index(); |
156 TileMap::iterator find = tiles_.find(key); | 157 TileMap::iterator find = tiles_.find(key); |
157 if (find != tiles_.end()) | 158 if (find != tiles_.end()) |
158 continue; | 159 continue; |
159 CreateTile(key.first, key.second, twin_tiling); | 160 CreateTile(key.first, key.second, twin_tiling); |
160 } | 161 } |
| 162 |
| 163 VerifyLiveTilesRect(); |
161 } | 164 } |
162 | 165 |
163 void PictureLayerTiling::UpdateTilesToCurrentPile( | 166 void PictureLayerTiling::UpdateTilesToCurrentPile( |
164 const Region& layer_invalidation, | 167 const Region& layer_invalidation, |
165 const gfx::Size& new_layer_bounds) { | 168 const gfx::Size& new_layer_bounds) { |
166 DCHECK(!new_layer_bounds.IsEmpty()); | 169 DCHECK(!new_layer_bounds.IsEmpty()); |
167 | 170 |
168 gfx::Size old_layer_bounds = layer_bounds_; | 171 gfx::Size old_layer_bounds = layer_bounds_; |
169 layer_bounds_ = new_layer_bounds; | 172 layer_bounds_ = new_layer_bounds; |
170 | 173 |
171 gfx::Size content_bounds = | 174 gfx::Size content_bounds = |
172 gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_)); | 175 gfx::ToCeiledSize(gfx::ScaleSize(layer_bounds_, contents_scale_)); |
173 gfx::Size tile_size = tiling_data_.max_texture_size(); | 176 gfx::Size tile_size = tiling_data_.max_texture_size(); |
174 | 177 |
175 if (layer_bounds_ != old_layer_bounds) { | 178 if (layer_bounds_ != old_layer_bounds) { |
| 179 // The SetLiveTilesRect() method would drop tiles outside the new bounds, |
| 180 // but may do so incorrectly if resizing the tiling causes the number of |
| 181 // tiles in the tiling_data_ to change. |
| 182 gfx::Rect content_rect(content_bounds); |
| 183 int before_left = tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.x()); |
| 184 int before_top = tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.y()); |
| 185 int before_right = |
| 186 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
| 187 int before_bottom = |
| 188 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
| 189 |
| 190 // The live_tiles_rect_ is clamped to stay within the tiling size as we |
| 191 // change it. |
| 192 live_tiles_rect_.Intersect(content_rect); |
| 193 tiling_data_.SetTilingSize(content_bounds); |
| 194 |
| 195 int after_right = -1; |
| 196 int after_bottom = -1; |
| 197 if (!live_tiles_rect_.IsEmpty()) { |
| 198 after_right = |
| 199 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
| 200 after_bottom = |
| 201 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
| 202 } |
| 203 |
| 204 // There is no recycled twin since this is run on the pending tiling. |
| 205 PictureLayerTiling* recycled_twin = NULL; |
| 206 DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); |
| 207 DCHECK_EQ(PENDING_TREE, client_->GetTree()); |
| 208 |
176 // Drop tiles outside the new layer bounds if the layer shrank. | 209 // Drop tiles outside the new layer bounds if the layer shrank. |
177 SetLiveTilesRect( | 210 for (int i = after_right + 1; i <= before_right; ++i) { |
178 gfx::IntersectRects(live_tiles_rect_, gfx::Rect(content_bounds))); | 211 for (int j = before_top; j <= before_bottom; ++j) |
179 tiling_data_.SetTilingSize(content_bounds); | 212 RemoveTileAt(i, j, recycled_twin); |
| 213 } |
| 214 for (int i = before_left; i <= after_right; ++i) { |
| 215 for (int j = after_bottom + 1; j <= before_bottom; ++j) |
| 216 RemoveTileAt(i, j, recycled_twin); |
| 217 } |
| 218 |
| 219 // If the layer grew, the live_tiles_rect_ is not changed, but a new row |
| 220 // and/or column of tiles may now exist inside the same live_tiles_rect_. |
| 221 const PictureLayerTiling* twin_tiling = client_->GetTwinTiling(this); |
| 222 if (after_right > before_right) { |
| 223 DCHECK_EQ(after_right, before_right + 1); |
| 224 for (int j = before_top; j <= after_bottom; ++j) |
| 225 CreateTile(after_right, j, twin_tiling); |
| 226 } |
| 227 if (after_bottom > before_bottom) { |
| 228 DCHECK_EQ(after_bottom, before_bottom + 1); |
| 229 for (int i = before_left; i <= before_right; ++i) |
| 230 CreateTile(i, after_bottom, twin_tiling); |
| 231 } |
| 232 |
180 tile_size = client_->CalculateTileSize(content_bounds); | 233 tile_size = client_->CalculateTileSize(content_bounds); |
181 } | 234 } |
182 | 235 |
183 if (tile_size != tiling_data_.max_texture_size()) { | 236 if (tile_size != tiling_data_.max_texture_size()) { |
184 tiling_data_.SetMaxTextureSize(tile_size); | 237 tiling_data_.SetMaxTextureSize(tile_size); |
185 // When the tile size changes, the TilingData positions no longer work | 238 // When the tile size changes, the TilingData positions no longer work |
186 // as valid keys to the TileMap, so just drop all tiles. | 239 // as valid keys to the TileMap, so just drop all tiles. |
187 Reset(); | 240 Reset(); |
188 } else { | 241 } else { |
189 Invalidate(layer_invalidation); | 242 Invalidate(layer_invalidation); |
190 } | 243 } |
191 | 244 |
192 PicturePileImpl* pile = client_->GetPile(); | 245 PicturePileImpl* pile = client_->GetPile(); |
193 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) | 246 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) |
194 it->second->set_picture_pile(pile); | 247 it->second->set_picture_pile(pile); |
| 248 VerifyLiveTilesRect(); |
195 } | 249 } |
196 | 250 |
197 void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) { | 251 void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_region) { |
198 bool recreate_invalidated_tiles = false; | 252 bool recreate_invalidated_tiles = false; |
199 DoInvalidate(layer_region, recreate_invalidated_tiles); | 253 DoInvalidate(layer_region, recreate_invalidated_tiles); |
200 } | 254 } |
201 | 255 |
202 void PictureLayerTiling::Invalidate(const Region& layer_region) { | 256 void PictureLayerTiling::Invalidate(const Region& layer_region) { |
203 bool recreate_invalidated_tiles = true; | 257 bool recreate_invalidated_tiles = true; |
204 DoInvalidate(layer_region, recreate_invalidated_tiles); | 258 DoInvalidate(layer_region, recreate_invalidated_tiles); |
205 } | 259 } |
206 | 260 |
207 void PictureLayerTiling::DoInvalidate(const Region& layer_region, | 261 void PictureLayerTiling::DoInvalidate(const Region& layer_region, |
208 bool recreate_invalidated_tiles) { | 262 bool recreate_invalidated_tiles) { |
209 std::vector<TileMapKey> new_tile_keys; | 263 std::vector<TileMapKey> new_tile_keys; |
210 gfx::Rect expanded_live_tiles_rect = | 264 gfx::Rect expanded_live_tiles_rect = |
211 tiling_data_.ExpandRectIgnoringBordersToTileBoundsWithBorders( | 265 tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); |
212 live_tiles_rect_); | |
213 for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { | 266 for (Region::Iterator iter(layer_region); iter.has_rect(); iter.next()) { |
214 gfx::Rect layer_rect = iter.rect(); | 267 gfx::Rect layer_rect = iter.rect(); |
215 gfx::Rect content_rect = | 268 gfx::Rect content_rect = |
216 gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); | 269 gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); |
| 270 // Consider tiles inside the live tiles rect even if only their border |
| 271 // pixels intersect the invalidation. But don't consider tiles outside |
| 272 // the live tiles rect with the same conditions, as they won't exist. |
| 273 int border_pixels = tiling_data_.border_texels(); |
| 274 content_rect.Inset(-border_pixels, -border_pixels); |
217 // Avoid needless work by not bothering to invalidate where there aren't | 275 // Avoid needless work by not bothering to invalidate where there aren't |
218 // tiles. | 276 // tiles. |
219 content_rect.Intersect(expanded_live_tiles_rect); | 277 content_rect.Intersect(expanded_live_tiles_rect); |
220 if (content_rect.IsEmpty()) | 278 if (content_rect.IsEmpty()) |
221 continue; | 279 continue; |
222 bool include_borders = true; | 280 // Since the content_rect includes border pixels already, don't include |
| 281 // borders when iterating to avoid double counting them. |
| 282 bool include_borders = false; |
223 for (TilingData::Iterator iter( | 283 for (TilingData::Iterator iter( |
224 &tiling_data_, content_rect, include_borders); | 284 &tiling_data_, content_rect, include_borders); |
225 iter; | 285 iter; |
226 ++iter) { | 286 ++iter) { |
227 // There is no recycled twin since this is run on the pending tiling. | 287 // There is no recycled twin since this is run on the pending tiling. |
228 PictureLayerTiling* recycled_twin = NULL; | 288 PictureLayerTiling* recycled_twin = NULL; |
229 DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); | 289 DCHECK_EQ(recycled_twin, client_->GetRecycledTwinTiling(this)); |
230 DCHECK_EQ(PENDING_TREE, client_->GetTree()); | 290 DCHECK_EQ(PENDING_TREE, client_->GetTree()); |
231 if (RemoveTileAt(iter.index_x(), iter.index_y(), recycled_twin)) | 291 if (RemoveTileAt(iter.index_x(), iter.index_y(), recycled_twin)) |
232 new_tile_keys.push_back(iter.index()); | 292 new_tile_keys.push_back(iter.index()); |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 | 575 |
516 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; | 576 last_impl_frame_time_in_seconds_ = current_frame_time_in_seconds; |
517 last_visible_rect_in_content_space_ = visible_rect_in_content_space; | 577 last_visible_rect_in_content_space_ = visible_rect_in_content_space; |
518 | 578 |
519 eviction_tiles_cache_valid_ = false; | 579 eviction_tiles_cache_valid_ = false; |
520 | 580 |
521 TilePriority now_priority(resolution_, TilePriority::NOW, 0); | 581 TilePriority now_priority(resolution_, TilePriority::NOW, 0); |
522 float content_to_screen_scale = ideal_contents_scale / contents_scale_; | 582 float content_to_screen_scale = ideal_contents_scale / contents_scale_; |
523 | 583 |
524 // Assign now priority to all visible tiles. | 584 // Assign now priority to all visible tiles. |
525 bool include_borders = true; | 585 bool include_borders = false; |
526 has_visible_rect_tiles_ = false; | 586 has_visible_rect_tiles_ = false; |
527 for (TilingData::Iterator iter( | 587 for (TilingData::Iterator iter( |
528 &tiling_data_, visible_rect_in_content_space, include_borders); | 588 &tiling_data_, visible_rect_in_content_space, include_borders); |
529 iter; | 589 iter; |
530 ++iter) { | 590 ++iter) { |
531 TileMap::iterator find = tiles_.find(iter.index()); | 591 TileMap::iterator find = tiles_.find(iter.index()); |
532 if (find == tiles_.end()) | 592 if (find == tiles_.end()) |
533 continue; | 593 continue; |
534 has_visible_rect_tiles_ = true; | 594 has_visible_rect_tiles_ = true; |
535 Tile* tile = find->second.get(); | 595 Tile* tile = find->second.get(); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 for (TilingData::DifferenceIterator iter(&tiling_data_, | 709 for (TilingData::DifferenceIterator iter(&tiling_data_, |
650 new_live_tiles_rect, | 710 new_live_tiles_rect, |
651 live_tiles_rect_); | 711 live_tiles_rect_); |
652 iter; | 712 iter; |
653 ++iter) { | 713 ++iter) { |
654 TileMapKey key(iter.index()); | 714 TileMapKey key(iter.index()); |
655 CreateTile(key.first, key.second, twin_tiling); | 715 CreateTile(key.first, key.second, twin_tiling); |
656 } | 716 } |
657 | 717 |
658 live_tiles_rect_ = new_live_tiles_rect; | 718 live_tiles_rect_ = new_live_tiles_rect; |
| 719 VerifyLiveTilesRect(); |
| 720 } |
| 721 |
| 722 void PictureLayerTiling::VerifyLiveTilesRect() { |
| 723 #if DCHECK_IS_ON |
| 724 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 725 if (!it->second.get()) |
| 726 continue; |
| 727 DCHECK(it->first.first < tiling_data_.num_tiles_x()) |
| 728 << this << " " << it->first.first << "," << it->first.second |
| 729 << " num_tiles_x " << tiling_data_.num_tiles_x() << " live_tiles_rect " |
| 730 << live_tiles_rect_.ToString(); |
| 731 DCHECK(it->first.second < tiling_data_.num_tiles_y()) |
| 732 << this << " " << it->first.first << "," << it->first.second |
| 733 << " num_tiles_y " << tiling_data_.num_tiles_y() << " live_tiles_rect " |
| 734 << live_tiles_rect_.ToString(); |
| 735 DCHECK(tiling_data_.TileBounds(it->first.first, it->first.second) |
| 736 .Intersects(live_tiles_rect_)) |
| 737 << this << " " << it->first.first << "," << it->first.second |
| 738 << " tile bounds " |
| 739 << tiling_data_.TileBounds(it->first.first, it->first.second).ToString() |
| 740 << " live_tiles_rect " << live_tiles_rect_.ToString(); |
| 741 } |
| 742 #endif |
659 } | 743 } |
660 | 744 |
661 void PictureLayerTiling::DidBecomeRecycled() { | 745 void PictureLayerTiling::DidBecomeRecycled() { |
662 // DidBecomeActive below will set the active priority for tiles that are | 746 // DidBecomeActive below will set the active priority for tiles that are |
663 // still in the tree. Calling this first on an active tiling that is becoming | 747 // still in the tree. Calling this first on an active tiling that is becoming |
664 // recycled takes care of tiles that are no longer in the active tree (eg. | 748 // recycled takes care of tiles that are no longer in the active tree (eg. |
665 // due to a pending invalidation). | 749 // due to a pending invalidation). |
666 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 750 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
667 it->second->SetPriority(ACTIVE_TREE, TilePriority()); | 751 it->second->SetPriority(ACTIVE_TREE, TilePriority()); |
668 } | 752 } |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 PictureLayerTiling* tiling, | 1033 PictureLayerTiling* tiling, |
950 WhichTree tree) | 1034 WhichTree tree) |
951 : tiling_(tiling), phase_(VISIBLE_RECT), tree_(tree), current_tile_(NULL) { | 1035 : tiling_(tiling), phase_(VISIBLE_RECT), tree_(tree), current_tile_(NULL) { |
952 if (!tiling_->has_visible_rect_tiles_) { | 1036 if (!tiling_->has_visible_rect_tiles_) { |
953 AdvancePhase(); | 1037 AdvancePhase(); |
954 return; | 1038 return; |
955 } | 1039 } |
956 | 1040 |
957 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, | 1041 visible_iterator_ = TilingData::Iterator(&tiling_->tiling_data_, |
958 tiling_->current_visible_rect_, | 1042 tiling_->current_visible_rect_, |
959 true /* include_borders */); | 1043 false /* include_borders */); |
960 if (!visible_iterator_) { | 1044 if (!visible_iterator_) { |
961 AdvancePhase(); | 1045 AdvancePhase(); |
962 return; | 1046 return; |
963 } | 1047 } |
964 | 1048 |
965 current_tile_ = | 1049 current_tile_ = |
966 tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); | 1050 tiling_->TileAt(visible_iterator_.index_x(), visible_iterator_.index_y()); |
967 if (!current_tile_ || !TileNeedsRaster(current_tile_)) | 1051 if (!current_tile_ || !TileNeedsRaster(current_tile_)) |
968 ++(*this); | 1052 ++(*this); |
969 } | 1053 } |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 DCHECK(*this); | 1190 DCHECK(*this); |
1107 do { | 1191 do { |
1108 ++current_eviction_tiles_index_; | 1192 ++current_eviction_tiles_index_; |
1109 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && | 1193 } while (current_eviction_tiles_index_ != eviction_tiles_->size() && |
1110 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); | 1194 !(*eviction_tiles_)[current_eviction_tiles_index_]->HasResources()); |
1111 | 1195 |
1112 return *this; | 1196 return *this; |
1113 } | 1197 } |
1114 | 1198 |
1115 } // namespace cc | 1199 } // namespace cc |
OLD | NEW |