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 3 // found in the LICENSE file. 4 5 #include "cc/resources/picture_layer_tiling_set.h" 6 7 #include <limits> 8 9 namespace cc { 10 11 namespace { 12 13 class LargestToSmallestScaleFunctor { 14 public: 15 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) { 16 return left->contents_scale() > right->contents_scale(); 17 } 18 }; 19 20 } // namespace 21 22 23 PictureLayerTilingSet::PictureLayerTilingSet( 24 PictureLayerTilingClient* client, 25 gfx::Size layer_bounds) 26 : client_(client), 27 layer_bounds_(layer_bounds) { 28 } 29 30 PictureLayerTilingSet::~PictureLayerTilingSet() { 31 } 32 33 void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) { 34 client_ = client; 35 for (size_t i = 0; i < tilings_.size(); ++i) 36 tilings_[i]->SetClient(client_); 37 } 38 39 void PictureLayerTilingSet::SyncTilings( 40 const PictureLayerTilingSet& other, 41 gfx::Size new_layer_bounds, 42 const Region& layer_invalidation, 43 float minimum_contents_scale) { 44 if (new_layer_bounds.IsEmpty()) { 45 RemoveAllTilings(); 46 layer_bounds_ = new_layer_bounds; 47 return; 48 } 49 50 tilings_.reserve(other.tilings_.size()); 51 52 // Remove any tilings that aren't in |other| or don't meet the minimum. 53 for (size_t i = 0; i < tilings_.size(); ++i) { 54 float scale = tilings_[i]->contents_scale(); 55 if (scale >= minimum_contents_scale && !!other.TilingAtScale(scale)) 56 continue; 57 // Swap with the last element and remove it. 58 tilings_.swap(tilings_.begin() + i, tilings_.end() - 1); 59 tilings_.pop_back(); 60 --i; 61 } 62 63 // Add any missing tilings from |other| that meet the minimum. 64 for (size_t i = 0; i < other.tilings_.size(); ++i) { 65 float contents_scale = other.tilings_[i]->contents_scale(); 66 if (contents_scale < minimum_contents_scale) 67 continue; 68 if (PictureLayerTiling* this_tiling = TilingAtScale(contents_scale)) { 69 this_tiling->set_resolution(other.tilings_[i]->resolution()); 70 71 // These two calls must come before updating the pile, because they may 72 // destroy tiles that the new pile cannot raster. 73 this_tiling->SetLayerBounds(new_layer_bounds); 74 this_tiling->Invalidate(layer_invalidation); 75 76 this_tiling->UpdateTilesToCurrentPile(); 77 this_tiling->CreateMissingTilesInLiveTilesRect(); 78 79 DCHECK(this_tiling->tile_size() == 80 client_->CalculateTileSize(this_tiling->ContentRect().size())); 81 continue; 82 } 83 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create( 84 contents_scale, 85 new_layer_bounds, 86 client_); 87 new_tiling->set_resolution(other.tilings_[i]->resolution()); 88 tilings_.push_back(new_tiling.Pass()); 89 } 90 tilings_.sort(LargestToSmallestScaleFunctor()); 91 92 layer_bounds_ = new_layer_bounds; 93 } 94 95 void PictureLayerTilingSet::SetCanUseLCDText(bool can_use_lcd_text) { 96 for (size_t i = 0; i < tilings_.size(); ++i) 97 tilings_[i]->SetCanUseLCDText(can_use_lcd_text); 98 } 99 100 PictureLayerTiling* PictureLayerTilingSet::AddTiling(float contents_scale) { 101 for (size_t i = 0; i < tilings_.size(); ++i) 102 DCHECK_NE(tilings_[i]->contents_scale(), contents_scale); 103 104 tilings_.push_back(PictureLayerTiling::Create(contents_scale, 105 layer_bounds_, 106 client_)); 107 PictureLayerTiling* appended = tilings_.back(); 108 109 tilings_.sort(LargestToSmallestScaleFunctor()); 110 return appended; 111 } 112 113 PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const { 114 for (size_t i = 0; i < tilings_.size(); ++i) { 115 if (tilings_[i]->contents_scale() == scale) 116 return tilings_[i]; 117 } 118 return NULL; 119 } 120 121 void PictureLayerTilingSet::RemoveAllTilings() { 122 tilings_.clear(); 123 } 124 125 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) { 126 ScopedPtrVector<PictureLayerTiling>::iterator iter = 127 std::find(tilings_.begin(), tilings_.end(), tiling); 128 if (iter == tilings_.end()) 129 return; 130 tilings_.erase(iter); 131 } 132 133 void PictureLayerTilingSet::RemoveAllTiles() { 134 for (size_t i = 0; i < tilings_.size(); ++i) 135 tilings_[i]->Reset(); 136 } 137 138 PictureLayerTilingSet::CoverageIterator::CoverageIterator( 139 const PictureLayerTilingSet* set, 140 float contents_scale, 141 gfx::Rect content_rect, 142 float ideal_contents_scale) 143 : set_(set), 144 contents_scale_(contents_scale), 145 ideal_contents_scale_(ideal_contents_scale), 146 current_tiling_(-1) { 147 missing_region_.Union(content_rect); 148 149 for (ideal_tiling_ = 0; 150 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size(); 151 ++ideal_tiling_) { 152 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_]; 153 if (tiling->contents_scale() < ideal_contents_scale_) { 154 if (ideal_tiling_ > 0) 155 ideal_tiling_--; 156 break; 157 } 158 } 159 160 DCHECK_LE(set_->tilings_.size(), 161 static_cast<size_t>(std::numeric_limits<int>::max())); 162 163 int num_tilings = set_->tilings_.size(); 164 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0) 165 ideal_tiling_--; 166 167 ++(*this); 168 } 169 170 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { 171 } 172 173 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const { 174 if (!tiling_iter_) { 175 if (!region_iter_.has_rect()) 176 return gfx::Rect(); 177 return region_iter_.rect(); 178 } 179 return tiling_iter_.geometry_rect(); 180 } 181 182 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { 183 if (!tiling_iter_) 184 return gfx::RectF(); 185 return tiling_iter_.texture_rect(); 186 } 187 188 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const { 189 if (!tiling_iter_) 190 return gfx::Size(); 191 return tiling_iter_.texture_size(); 192 } 193 194 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const { 195 if (!tiling_iter_) 196 return NULL; 197 return *tiling_iter_; 198 } 199 200 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const { 201 if (!tiling_iter_) 202 return NULL; 203 return *tiling_iter_; 204 } 205 206 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() { 207 if (current_tiling_ < 0) 208 return NULL; 209 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size()) 210 return NULL; 211 return set_->tilings_[current_tiling_]; 212 } 213 214 int PictureLayerTilingSet::CoverageIterator::NextTiling() const { 215 // Order returned by this method is: 216 // 1. Ideal tiling index 217 // 2. Tiling index < Ideal in decreasing order (higher res than ideal) 218 // 3. Tiling index > Ideal in increasing order (lower res than ideal) 219 // 4. Tiling index > tilings.size() (invalid index) 220 if (current_tiling_ < 0) 221 return ideal_tiling_; 222 else if (current_tiling_ > ideal_tiling_) 223 return current_tiling_ + 1; 224 else if (current_tiling_) 225 return current_tiling_ - 1; 226 else 227 return ideal_tiling_ + 1; 228 } 229 230 PictureLayerTilingSet::CoverageIterator& 231 PictureLayerTilingSet::CoverageIterator::operator++() { 232 bool first_time = current_tiling_ < 0; 233 234 if (!*this && !first_time) 235 return *this; 236 237 if (tiling_iter_) 238 ++tiling_iter_; 239 240 // Loop until we find a valid place to stop. 241 while (true) { 242 while (tiling_iter_ && 243 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) { 244 missing_region_.Union(tiling_iter_.geometry_rect()); 245 ++tiling_iter_; 246 } 247 if (tiling_iter_) 248 return *this; 249 250 // If the set of current rects for this tiling is done, go to the next 251 // tiling and set up to iterate through all of the remaining holes. 252 // This will also happen the first time through the loop. 253 if (!region_iter_.has_rect()) { 254 current_tiling_ = NextTiling(); 255 current_region_.Swap(&missing_region_); 256 missing_region_.Clear(); 257 region_iter_ = Region::Iterator(current_region_); 258 259 // All done and all filled. 260 if (!region_iter_.has_rect()) { 261 current_tiling_ = set_->tilings_.size(); 262 return *this; 263 } 264 265 // No more valid tiles, return this checkerboard rect. 266 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) 267 return *this; 268 } 269 270 // Pop a rect off. If there are no more tilings, then these will be 271 // treated as geometry with null tiles that the caller can checkerboard. 272 gfx::Rect last_rect = region_iter_.rect(); 273 region_iter_.next(); 274 275 // Done, found next checkerboard rect to return. 276 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) 277 return *this; 278 279 // Construct a new iterator for the next tiling, but we need to loop 280 // again until we get to a valid one. 281 tiling_iter_ = PictureLayerTiling::CoverageIterator( 282 set_->tilings_[current_tiling_], 283 contents_scale_, 284 last_rect); 285 } 286 287 return *this; 288 } 289 290 PictureLayerTilingSet::CoverageIterator::operator bool() const { 291 return current_tiling_ < static_cast<int>(set_->tilings_.size()) || 292 region_iter_.has_rect(); 293 } 294 295 void PictureLayerTilingSet::UpdateTilePriorities( 296 WhichTree tree, 297 gfx::Size device_viewport, 298 gfx::Rect viewport_in_content_space, 299 gfx::Rect visible_content_rect, 300 gfx::Size last_layer_bounds, 301 gfx::Size current_layer_bounds, 302 float last_layer_contents_scale, 303 float current_layer_contents_scale, 304 const gfx::Transform& last_screen_transform, 305 const gfx::Transform& current_screen_transform, 306 double current_frame_time_in_seconds, 307 size_t max_tiles_for_interest_area) { 308 gfx::Rect viewport_in_layer_space = gfx::ScaleToEnclosingRect( 309 viewport_in_content_space, 310 1.f / current_layer_contents_scale); 311 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect( 312 visible_content_rect, 313 1.f / current_layer_contents_scale); 314 315 for (size_t i = 0; i < tilings_.size(); ++i) { 316 tilings_[i]->UpdateTilePriorities( 317 tree, 318 device_viewport, 319 viewport_in_layer_space, 320 visible_layer_rect, 321 last_layer_bounds, 322 current_layer_bounds, 323 last_layer_contents_scale, 324 current_layer_contents_scale, 325 last_screen_transform, 326 current_screen_transform, 327 current_frame_time_in_seconds, 328 max_tiles_for_interest_area); 329 } 330 } 331 332 void PictureLayerTilingSet::DidBecomeActive() { 333 for (size_t i = 0; i < tilings_.size(); ++i) 334 tilings_[i]->DidBecomeActive(); 335 } 336 337 void PictureLayerTilingSet::DidBecomeRecycled() { 338 for (size_t i = 0; i < tilings_.size(); ++i) 339 tilings_[i]->DidBecomeRecycled(); 340 } 341 342 scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const { 343 scoped_ptr<base::ListValue> state(new base::ListValue()); 344 for (size_t i = 0; i < tilings_.size(); ++i) 345 state->Append(tilings_[i]->AsValue().release()); 346 return state.PassAs<base::Value>(); 347 } 348 349 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const { 350 size_t amount = 0; 351 for (size_t i = 0; i < tilings_.size(); ++i) 352 amount += tilings_[i]->GPUMemoryUsageInBytes(); 353 return amount; 354 } 355 356 } // namespace cc 357