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/tiles/picture_layer_tiling.h" | 5 #include "cc/tiles/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/containers/hash_tables.h" | |
13 #include "base/containers/small_map.h" | |
12 #include "base/logging.h" | 14 #include "base/logging.h" |
13 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
14 #include "base/trace_event/trace_event_argument.h" | 16 #include "base/trace_event/trace_event_argument.h" |
15 #include "cc/base/math_util.h" | 17 #include "cc/base/math_util.h" |
16 #include "cc/playback/raster_source.h" | 18 #include "cc/playback/raster_source.h" |
17 #include "cc/tiles/prioritized_tile.h" | 19 #include "cc/tiles/prioritized_tile.h" |
18 #include "cc/tiles/tile.h" | 20 #include "cc/tiles/tile.h" |
19 #include "cc/tiles/tile_priority.h" | 21 #include "cc/tiles/tile_priority.h" |
20 #include "ui/gfx/geometry/point_conversions.h" | 22 #include "ui/gfx/geometry/point_conversions.h" |
21 #include "ui/gfx/geometry/rect_conversions.h" | 23 #include "ui/gfx/geometry/rect_conversions.h" |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
223 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); | 225 tiling_data_.TileXIndexFromSrcCoord(live_tiles_rect_.right() - 1); |
224 after_bottom = | 226 after_bottom = |
225 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); | 227 tiling_data_.TileYIndexFromSrcCoord(live_tiles_rect_.bottom() - 1); |
226 } | 228 } |
227 | 229 |
228 // There is no recycled twin since this is run on the pending tiling | 230 // There is no recycled twin since this is run on the pending tiling |
229 // during commit, and on the active tree during activate. | 231 // during commit, and on the active tree during activate. |
230 // Drop tiles outside the new layer bounds if the layer shrank. | 232 // Drop tiles outside the new layer bounds if the layer shrank. |
231 for (int i = after_right + 1; i <= before_right; ++i) { | 233 for (int i = after_right + 1; i <= before_right; ++i) { |
232 for (int j = before_top; j <= before_bottom; ++j) | 234 for (int j = before_top; j <= before_bottom; ++j) |
233 RemoveTileAt(i, j); | 235 RemoveTileAt(i, j, nullptr); |
234 } | 236 } |
235 for (int i = before_left; i <= after_right; ++i) { | 237 for (int i = before_left; i <= after_right; ++i) { |
236 for (int j = after_bottom + 1; j <= before_bottom; ++j) | 238 for (int j = after_bottom + 1; j <= before_bottom; ++j) |
237 RemoveTileAt(i, j); | 239 RemoveTileAt(i, j, nullptr); |
238 } | 240 } |
239 | 241 |
240 if (after_right > before_right) { | 242 if (after_right > before_right) { |
241 DCHECK_EQ(after_right, before_right + 1); | 243 DCHECK_EQ(after_right, before_right + 1); |
242 for (int j = before_top; j <= after_bottom; ++j) { | 244 for (int j = before_top; j <= after_bottom; ++j) { |
243 if (ShouldCreateTileAt(after_right, j)) | 245 if (ShouldCreateTileAt(after_right, j)) |
244 CreateTile(after_right, j); | 246 CreateTile(after_right, j); |
245 } | 247 } |
246 } | 248 } |
247 if (after_bottom > before_bottom) { | 249 if (after_bottom > before_bottom) { |
(...skipping 10 matching lines...) Expand all Loading... | |
258 !client_->GetPendingOrActiveTwinTiling(this)); | 260 !client_->GetPendingOrActiveTwinTiling(this)); |
259 RemoveTilesInRegion(layer_invalidation, true /* recreate tiles */); | 261 RemoveTilesInRegion(layer_invalidation, true /* recreate tiles */); |
260 } | 262 } |
261 | 263 |
262 void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation, | 264 void PictureLayerTiling::RemoveTilesInRegion(const Region& layer_invalidation, |
263 bool recreate_tiles) { | 265 bool recreate_tiles) { |
264 // We only invalidate the active tiling when it's orphaned: it has no pending | 266 // We only invalidate the active tiling when it's orphaned: it has no pending |
265 // twin, so it's slated for removal in the future. | 267 // twin, so it's slated for removal in the future. |
266 if (live_tiles_rect_.IsEmpty()) | 268 if (live_tiles_rect_.IsEmpty()) |
267 return; | 269 return; |
268 std::vector<TileMapKey> new_tile_keys; | 270 base::SmallMap<base::hash_map<TileMapKey, gfx::Rect>, 16> remove_tiles; |
reveman
2015/05/28 05:07:25
why 16? can we remove this magic value or add a co
danakj
2015/05/28 18:54:47
Done.
| |
269 gfx::Rect expanded_live_tiles_rect = | 271 gfx::Rect expanded_live_tiles_rect = |
270 tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); | 272 tiling_data_.ExpandRectIgnoringBordersToTileBounds(live_tiles_rect_); |
271 for (Region::Iterator iter(layer_invalidation); iter.has_rect(); | 273 for (Region::Iterator iter(layer_invalidation); iter.has_rect(); |
272 iter.next()) { | 274 iter.next()) { |
273 gfx::Rect layer_rect = iter.rect(); | 275 gfx::Rect layer_rect = iter.rect(); |
274 gfx::Rect content_rect = | 276 // The pixels which are invalid in content space. |
277 gfx::Rect invalid_content_rect = | |
275 gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); | 278 gfx::ScaleToEnclosingRect(layer_rect, contents_scale_); |
276 // Consider tiles inside the live tiles rect even if only their border | 279 // Consider tiles inside the live tiles rect even if only their border |
277 // pixels intersect the invalidation. But don't consider tiles outside | 280 // pixels intersect the invalidation. But don't consider tiles outside |
278 // the live tiles rect with the same conditions, as they won't exist. | 281 // the live tiles rect with the same conditions, as they won't exist. |
282 gfx::Rect coverage_content_rect = invalid_content_rect; | |
279 int border_pixels = tiling_data_.border_texels(); | 283 int border_pixels = tiling_data_.border_texels(); |
280 content_rect.Inset(-border_pixels, -border_pixels); | 284 coverage_content_rect.Inset(-border_pixels, -border_pixels); |
281 // Avoid needless work by not bothering to invalidate where there aren't | 285 // Avoid needless work by not bothering to invalidate where there aren't |
282 // tiles. | 286 // tiles. |
283 content_rect.Intersect(expanded_live_tiles_rect); | 287 coverage_content_rect.Intersect(expanded_live_tiles_rect); |
284 if (content_rect.IsEmpty()) | 288 if (coverage_content_rect.IsEmpty()) |
285 continue; | 289 continue; |
286 // Since the content_rect includes border pixels already, don't include | 290 // Since the content_rect includes border pixels already, don't include |
287 // borders when iterating to avoid double counting them. | 291 // borders when iterating to avoid double counting them. |
288 bool include_borders = false; | 292 bool include_borders = false; |
289 for ( | 293 for (TilingData::Iterator iter(&tiling_data_, coverage_content_rect, |
290 TilingData::Iterator iter(&tiling_data_, content_rect, include_borders); | 294 include_borders); |
291 iter; ++iter) { | 295 iter; ++iter) { |
292 if (RemoveTileAt(iter.index_x(), iter.index_y())) { | 296 // This also adds the TileMapKey to the map. |
293 if (recreate_tiles) | 297 remove_tiles[TileMapKey(iter.index())].Union(invalid_content_rect); |
294 new_tile_keys.push_back(TileMapKey(iter.index())); | |
295 } | |
296 } | 298 } |
297 } | 299 } |
298 | 300 |
299 for (const auto& key : new_tile_keys) | 301 for (const auto& pair : remove_tiles) { |
300 CreateTile(key.index_x, key.index_y); | 302 const TileMapKey& key = pair.first; |
303 const gfx::Rect& invalid_content_rect = pair.second; | |
304 Tile::Id old_id(0); | |
305 // TODO(danakj): This |old_id| will be empty if we are committing to a | |
306 // pending tree since there is no tile there to remove. crbug.com/490847 | |
307 if (RemoveTileAt(key.index_x, key.index_y, &old_id) && recreate_tiles) { | |
308 if (Tile* tile = CreateTile(key.index_x, key.index_y)) | |
309 tile->SetInvalidated(invalid_content_rect, old_id); | |
310 } | |
311 } | |
301 } | 312 } |
302 | 313 |
303 bool PictureLayerTiling::ShouldCreateTileAt(int i, int j) const { | 314 bool PictureLayerTiling::ShouldCreateTileAt(int i, int j) const { |
304 // Active tree should always create a tile. The reason for this is that active | 315 // Active tree should always create a tile. The reason for this is that active |
305 // tree represents content that we draw on screen, which means that whenever | 316 // tree represents content that we draw on screen, which means that whenever |
306 // we check whether a tile should exist somewhere, the answer is yes. This | 317 // we check whether a tile should exist somewhere, the answer is yes. This |
307 // doesn't mean it will actually be created (if raster source doesn't cover | 318 // doesn't mean it will actually be created (if raster source doesn't cover |
308 // the tile for instance). Pending tree, on the other hand, should only be | 319 // the tile for instance). Pending tree, on the other hand, should only be |
309 // creating tiles that are different from the current active tree, which is | 320 // creating tiles that are different from the current active tree, which is |
310 // represented by the logic in the rest of the function. | 321 // represented by the logic in the rest of the function. |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 texture_rect.Scale(dest_to_content_scale_, | 499 texture_rect.Scale(dest_to_content_scale_, |
489 dest_to_content_scale_); | 500 dest_to_content_scale_); |
490 texture_rect.Intersect(gfx::Rect(tiling_->tiling_size())); | 501 texture_rect.Intersect(gfx::Rect(tiling_->tiling_size())); |
491 if (texture_rect.IsEmpty()) | 502 if (texture_rect.IsEmpty()) |
492 return texture_rect; | 503 return texture_rect; |
493 texture_rect.Offset(-tex_origin.OffsetFromOrigin()); | 504 texture_rect.Offset(-tex_origin.OffsetFromOrigin()); |
494 | 505 |
495 return texture_rect; | 506 return texture_rect; |
496 } | 507 } |
497 | 508 |
498 bool PictureLayerTiling::RemoveTileAt(int i, int j) { | 509 bool PictureLayerTiling::RemoveTileAt(int i, int j, Tile::Id* id) { |
499 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); | 510 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); |
500 if (found == tiles_.end()) | 511 if (found == tiles_.end()) |
501 return false; | 512 return false; |
513 if (id) | |
514 *id = found->second->id(); | |
502 tiles_.erase(found); | 515 tiles_.erase(found); |
503 return true; | 516 return true; |
504 } | 517 } |
505 | 518 |
506 void PictureLayerTiling::Reset() { | 519 void PictureLayerTiling::Reset() { |
507 live_tiles_rect_ = gfx::Rect(); | 520 live_tiles_rect_ = gfx::Rect(); |
508 tiles_.clear(); | 521 tiles_.clear(); |
509 all_tiles_done_ = true; | 522 all_tiles_done_ = true; |
510 } | 523 } |
511 | 524 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
656 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) | 669 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) |
657 << "tiling_size: " << tiling_size().ToString() | 670 << "tiling_size: " << tiling_size().ToString() |
658 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); | 671 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); |
659 if (live_tiles_rect_ == new_live_tiles_rect) | 672 if (live_tiles_rect_ == new_live_tiles_rect) |
660 return; | 673 return; |
661 | 674 |
662 // Iterate to delete all tiles outside of our new live_tiles rect. | 675 // Iterate to delete all tiles outside of our new live_tiles rect. |
663 for (TilingData::DifferenceIterator iter(&tiling_data_, live_tiles_rect_, | 676 for (TilingData::DifferenceIterator iter(&tiling_data_, live_tiles_rect_, |
664 new_live_tiles_rect); | 677 new_live_tiles_rect); |
665 iter; ++iter) { | 678 iter; ++iter) { |
666 RemoveTileAt(iter.index_x(), iter.index_y()); | 679 RemoveTileAt(iter.index_x(), iter.index_y(), nullptr); |
667 } | 680 } |
668 | 681 |
669 // Iterate to allocate new tiles for all regions with newly exposed area. | 682 // Iterate to allocate new tiles for all regions with newly exposed area. |
670 for (TilingData::DifferenceIterator iter(&tiling_data_, new_live_tiles_rect, | 683 for (TilingData::DifferenceIterator iter(&tiling_data_, new_live_tiles_rect, |
671 live_tiles_rect_); | 684 live_tiles_rect_); |
672 iter; ++iter) { | 685 iter; ++iter) { |
673 TileMapKey key(iter.index()); | 686 TileMapKey key(iter.index()); |
674 if (ShouldCreateTileAt(key.index_x, key.index_y)) | 687 if (ShouldCreateTileAt(key.index_x, key.index_y)) |
675 CreateTile(key.index_x, key.index_y); | 688 CreateTile(key.index_x, key.index_y); |
676 } | 689 } |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1080 break; | 1093 break; |
1081 } | 1094 } |
1082 | 1095 |
1083 gfx::Rect result(origin_x, origin_y, width, height); | 1096 gfx::Rect result(origin_x, origin_y, width, height); |
1084 if (cache) | 1097 if (cache) |
1085 cache->previous_result = result; | 1098 cache->previous_result = result; |
1086 return result; | 1099 return result; |
1087 } | 1100 } |
1088 | 1101 |
1089 } // namespace cc | 1102 } // namespace cc |
OLD | NEW |