| 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 can_require_tiles_for_activation_(false), | 48 can_require_tiles_for_activation_(false), |
| 78 current_content_to_screen_scale_(0.f), | 49 current_content_to_screen_scale_(0.f), |
| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 } | 103 } |
| 135 } | 104 } |
| 136 | 105 |
| 137 // Create a new tile because our twin didn't have a valid one. | 106 // Create a new tile because our twin didn't have a valid one. |
| 138 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); | 107 scoped_refptr<Tile> tile = client_->CreateTile(this, tile_rect); |
| 139 if (tile.get()) { | 108 if (tile.get()) { |
| 140 DCHECK(!tile->is_shared()); | 109 DCHECK(!tile->is_shared()); |
| 141 tile->set_tiling_index(i, j); | 110 tile->set_tiling_index(i, j); |
| 142 tiles_[key] = tile; | 111 tiles_[key] = tile; |
| 143 } | 112 } |
| 144 eviction_tiles_cache_valid_ = false; | |
| 145 return tile.get(); | 113 return tile.get(); |
| 146 } | 114 } |
| 147 | 115 |
| 148 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { | 116 void PictureLayerTiling::CreateMissingTilesInLiveTilesRect() { |
| 149 const PictureLayerTiling* twin_tiling = | 117 const PictureLayerTiling* twin_tiling = |
| 150 client_->GetPendingOrActiveTwinTiling(this); | 118 client_->GetPendingOrActiveTwinTiling(this); |
| 151 bool include_borders = false; | 119 bool include_borders = false; |
| 152 for (TilingData::Iterator iter( | 120 for (TilingData::Iterator iter( |
| 153 &tiling_data_, live_tiles_rect_, include_borders); | 121 &tiling_data_, live_tiles_rect_, include_borders); |
| 154 iter; | 122 iter; |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 } | 470 } |
| 503 | 471 |
| 504 bool PictureLayerTiling::RemoveTileAt(int i, | 472 bool PictureLayerTiling::RemoveTileAt(int i, |
| 505 int j, | 473 int j, |
| 506 PictureLayerTiling* recycled_twin) { | 474 PictureLayerTiling* recycled_twin) { |
| 507 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); | 475 TileMap::iterator found = tiles_.find(TileMapKey(i, j)); |
| 508 if (found == tiles_.end()) | 476 if (found == tiles_.end()) |
| 509 return false; | 477 return false; |
| 510 found->second->set_shared(false); | 478 found->second->set_shared(false); |
| 511 tiles_.erase(found); | 479 tiles_.erase(found); |
| 512 eviction_tiles_cache_valid_ = false; | |
| 513 if (recycled_twin) { | 480 if (recycled_twin) { |
| 514 // Recycled twin does not also have a recycled twin, so pass NULL. | 481 // Recycled twin does not also have a recycled twin, so pass NULL. |
| 515 recycled_twin->RemoveTileAt(i, j, NULL); | 482 recycled_twin->RemoveTileAt(i, j, NULL); |
| 516 } | 483 } |
| 517 return true; | 484 return true; |
| 518 } | 485 } |
| 519 | 486 |
| 520 void PictureLayerTiling::Reset() { | 487 void PictureLayerTiling::Reset() { |
| 521 live_tiles_rect_ = gfx::Rect(); | 488 live_tiles_rect_ = gfx::Rect(); |
| 522 PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); | 489 PictureLayerTiling* recycled_twin = client_->GetRecycledTwinTiling(this); |
| 523 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 490 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 524 it->second->set_shared(false); | 491 it->second->set_shared(false); |
| 525 if (recycled_twin) | 492 if (recycled_twin) |
| 526 recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); | 493 recycled_twin->RemoveTileAt(it->first.first, it->first.second, NULL); |
| 527 } | 494 } |
| 528 tiles_.clear(); | 495 tiles_.clear(); |
| 529 eviction_tiles_cache_valid_ = false; | |
| 530 } | 496 } |
| 531 | 497 |
| 532 gfx::Rect PictureLayerTiling::ComputeSkewport( | 498 gfx::Rect PictureLayerTiling::ComputeSkewport( |
| 533 double current_frame_time_in_seconds, | 499 double current_frame_time_in_seconds, |
| 534 const gfx::Rect& visible_rect_in_content_space) const { | 500 const gfx::Rect& visible_rect_in_content_space) const { |
| 535 gfx::Rect skewport = visible_rect_in_content_space; | 501 gfx::Rect skewport = visible_rect_in_content_space; |
| 536 if (last_impl_frame_time_in_seconds_ == 0.0) | 502 if (last_impl_frame_time_in_seconds_ == 0.0) |
| 537 return skewport; | 503 return skewport; |
| 538 | 504 |
| 539 double time_delta = | 505 double time_delta = |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 current_eventually_rect_ = eventually_rect; | 617 current_eventually_rect_ = eventually_rect; |
| 652 current_occlusion_in_layer_space_ = occlusion_in_layer_space; | 618 current_occlusion_in_layer_space_ = occlusion_in_layer_space; |
| 653 current_content_to_screen_scale_ = content_to_screen_scale; | 619 current_content_to_screen_scale_ = content_to_screen_scale; |
| 654 | 620 |
| 655 gfx::Rect tiling_rect(tiling_size()); | 621 gfx::Rect tiling_rect(tiling_size()); |
| 656 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); | 622 has_visible_rect_tiles_ = tiling_rect.Intersects(current_visible_rect_); |
| 657 has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_); | 623 has_skewport_rect_tiles_ = tiling_rect.Intersects(current_skewport_rect_); |
| 658 has_soon_border_rect_tiles_ = | 624 has_soon_border_rect_tiles_ = |
| 659 tiling_rect.Intersects(current_soon_border_rect_); | 625 tiling_rect.Intersects(current_soon_border_rect_); |
| 660 has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_); | 626 has_eventually_rect_tiles_ = tiling_rect.Intersects(current_eventually_rect_); |
| 661 | |
| 662 eviction_tiles_cache_valid_ = false; | |
| 663 } | 627 } |
| 664 | 628 |
| 665 void PictureLayerTiling::SetLiveTilesRect( | 629 void PictureLayerTiling::SetLiveTilesRect( |
| 666 const gfx::Rect& new_live_tiles_rect) { | 630 const gfx::Rect& new_live_tiles_rect) { |
| 667 DCHECK(new_live_tiles_rect.IsEmpty() || | 631 DCHECK(new_live_tiles_rect.IsEmpty() || |
| 668 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) | 632 gfx::Rect(tiling_size()).Contains(new_live_tiles_rect)) |
| 669 << "tiling_size: " << tiling_size().ToString() | 633 << "tiling_size: " << tiling_size().ToString() |
| 670 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); | 634 << " new_live_tiles_rect: " << new_live_tiles_rect.ToString(); |
| 671 if (live_tiles_rect_ == new_live_tiles_rect) | 635 if (live_tiles_rect_ == new_live_tiles_rect) |
| 672 return; | 636 return; |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1041 if (delta < event.distance) | 1005 if (delta < event.distance) |
| 1042 break; | 1006 break; |
| 1043 } | 1007 } |
| 1044 | 1008 |
| 1045 gfx::Rect result(origin_x, origin_y, width, height); | 1009 gfx::Rect result(origin_x, origin_y, width, height); |
| 1046 if (cache) | 1010 if (cache) |
| 1047 cache->previous_result = result; | 1011 cache->previous_result = result; |
| 1048 return result; | 1012 return result; |
| 1049 } | 1013 } |
| 1050 | 1014 |
| 1051 void PictureLayerTiling::UpdateEvictionCacheIfNeeded( | |
| 1052 TreePriority tree_priority) { | |
| 1053 if (eviction_tiles_cache_valid_ && | |
| 1054 eviction_cache_tree_priority_ == tree_priority) | |
| 1055 return; | |
| 1056 | |
| 1057 eviction_tiles_now_.clear(); | |
| 1058 eviction_tiles_now_and_required_for_activation_.clear(); | |
| 1059 eviction_tiles_soon_.clear(); | |
| 1060 eviction_tiles_soon_and_required_for_activation_.clear(); | |
| 1061 eviction_tiles_eventually_.clear(); | |
| 1062 eviction_tiles_eventually_and_required_for_activation_.clear(); | |
| 1063 | |
| 1064 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | |
| 1065 Tile* tile = it->second.get(); | |
| 1066 UpdateTileAndTwinPriority(tile); | |
| 1067 const TilePriority& priority = | |
| 1068 tile->priority_for_tree_priority(tree_priority); | |
| 1069 switch (priority.priority_bin) { | |
| 1070 case TilePriority::EVENTUALLY: | |
| 1071 if (tile->required_for_activation()) | |
| 1072 eviction_tiles_eventually_and_required_for_activation_.push_back( | |
| 1073 tile); | |
| 1074 else | |
| 1075 eviction_tiles_eventually_.push_back(tile); | |
| 1076 break; | |
| 1077 case TilePriority::SOON: | |
| 1078 if (tile->required_for_activation()) | |
| 1079 eviction_tiles_soon_and_required_for_activation_.push_back(tile); | |
| 1080 else | |
| 1081 eviction_tiles_soon_.push_back(tile); | |
| 1082 break; | |
| 1083 case TilePriority::NOW: | |
| 1084 if (tile->required_for_activation()) | |
| 1085 eviction_tiles_now_and_required_for_activation_.push_back(tile); | |
| 1086 else | |
| 1087 eviction_tiles_now_.push_back(tile); | |
| 1088 break; | |
| 1089 } | |
| 1090 } | |
| 1091 | |
| 1092 // TODO(vmpstr): Do this lazily. One option is to have a "sorted" flag that | |
| 1093 // can be updated for each of the queues. | |
| 1094 TileEvictionOrder sort_order(tree_priority); | |
| 1095 std::sort(eviction_tiles_now_.begin(), eviction_tiles_now_.end(), sort_order); | |
| 1096 std::sort(eviction_tiles_now_and_required_for_activation_.begin(), | |
| 1097 eviction_tiles_now_and_required_for_activation_.end(), | |
| 1098 sort_order); | |
| 1099 std::sort( | |
| 1100 eviction_tiles_soon_.begin(), eviction_tiles_soon_.end(), sort_order); | |
| 1101 std::sort(eviction_tiles_soon_and_required_for_activation_.begin(), | |
| 1102 eviction_tiles_soon_and_required_for_activation_.end(), | |
| 1103 sort_order); | |
| 1104 std::sort(eviction_tiles_eventually_.begin(), | |
| 1105 eviction_tiles_eventually_.end(), | |
| 1106 sort_order); | |
| 1107 std::sort(eviction_tiles_eventually_and_required_for_activation_.begin(), | |
| 1108 eviction_tiles_eventually_and_required_for_activation_.end(), | |
| 1109 sort_order); | |
| 1110 | |
| 1111 eviction_tiles_cache_valid_ = true; | |
| 1112 eviction_cache_tree_priority_ = tree_priority; | |
| 1113 } | |
| 1114 | |
| 1115 const std::vector<Tile*>* PictureLayerTiling::GetEvictionTiles( | |
| 1116 TreePriority tree_priority, | |
| 1117 EvictionCategory category) { | |
| 1118 UpdateEvictionCacheIfNeeded(tree_priority); | |
| 1119 switch (category) { | |
| 1120 case EVENTUALLY: | |
| 1121 return &eviction_tiles_eventually_; | |
| 1122 case EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: | |
| 1123 return &eviction_tiles_eventually_and_required_for_activation_; | |
| 1124 case SOON: | |
| 1125 return &eviction_tiles_soon_; | |
| 1126 case SOON_AND_REQUIRED_FOR_ACTIVATION: | |
| 1127 return &eviction_tiles_soon_and_required_for_activation_; | |
| 1128 case NOW: | |
| 1129 return &eviction_tiles_now_; | |
| 1130 case NOW_AND_REQUIRED_FOR_ACTIVATION: | |
| 1131 return &eviction_tiles_now_and_required_for_activation_; | |
| 1132 } | |
| 1133 NOTREACHED(); | |
| 1134 return &eviction_tiles_eventually_; | |
| 1135 } | |
| 1136 | |
| 1137 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() | 1015 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator() |
| 1138 : tiling_(NULL), current_tile_(NULL) {} | 1016 : tiling_(NULL), current_tile_(NULL) {} |
| 1139 | 1017 |
| 1140 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( | 1018 PictureLayerTiling::TilingRasterTileIterator::TilingRasterTileIterator( |
| 1141 PictureLayerTiling* tiling) | 1019 PictureLayerTiling* tiling) |
| 1142 : tiling_(tiling), phase_(VISIBLE_RECT), current_tile_(NULL) { | 1020 : tiling_(tiling), phase_(VISIBLE_RECT), current_tile_(NULL) { |
| 1143 if (!tiling_->has_visible_rect_tiles_) { | 1021 if (!tiling_->has_visible_rect_tiles_) { |
| 1144 AdvancePhase(); | 1022 AdvancePhase(); |
| 1145 return; | 1023 return; |
| 1146 } | 1024 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 } | 1138 } |
| 1261 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); | 1139 current_tile_ = tiling_->TileAt(next_index.first, next_index.second); |
| 1262 } | 1140 } |
| 1263 | 1141 |
| 1264 if (current_tile_) | 1142 if (current_tile_) |
| 1265 tiling_->UpdateTileAndTwinPriority(current_tile_); | 1143 tiling_->UpdateTileAndTwinPriority(current_tile_); |
| 1266 return *this; | 1144 return *this; |
| 1267 } | 1145 } |
| 1268 | 1146 |
| 1269 } // namespace cc | 1147 } // namespace cc |
| OLD | NEW |