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 9namespace cc { 10 11namespace { 12 13class 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 23PictureLayerTilingSet::PictureLayerTilingSet( 24 PictureLayerTilingClient* client, 25 gfx::Size layer_bounds) 26 : client_(client), 27 layer_bounds_(layer_bounds) { 28} 29 30PictureLayerTilingSet::~PictureLayerTilingSet() { 31} 32 33void PictureLayerTilingSet::SetClient(PictureLayerTilingClient* client) { 34 client_ = client; 35 for (size_t i = 0; i < tilings_.size(); ++i) 36 tilings_[i]->SetClient(client_); 37} 38 39void 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 95void 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 100PictureLayerTiling* 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 113int PictureLayerTilingSet::NumHighResTilings() const { 114 int num_high_res = 0; 115 for (size_t i = 0; i < tilings_.size(); ++i) { 116 if (tilings_[i]->resolution() == HIGH_RESOLUTION) 117 num_high_res++; 118 } 119 return num_high_res; 120} 121 122PictureLayerTiling* PictureLayerTilingSet::TilingAtScale(float scale) const { 123 for (size_t i = 0; i < tilings_.size(); ++i) { 124 if (tilings_[i]->contents_scale() == scale) 125 return tilings_[i]; 126 } 127 return NULL; 128} 129 130void PictureLayerTilingSet::RemoveAllTilings() { 131 tilings_.clear(); 132} 133 134void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) { 135 ScopedPtrVector<PictureLayerTiling>::iterator iter = 136 std::find(tilings_.begin(), tilings_.end(), tiling); 137 if (iter == tilings_.end()) 138 return; 139 tilings_.erase(iter); 140} 141 142void PictureLayerTilingSet::RemoveAllTiles() { 143 for (size_t i = 0; i < tilings_.size(); ++i) 144 tilings_[i]->Reset(); 145} 146 147PictureLayerTilingSet::CoverageIterator::CoverageIterator( 148 const PictureLayerTilingSet* set, 149 float contents_scale, 150 gfx::Rect content_rect, 151 float ideal_contents_scale) 152 : set_(set), 153 contents_scale_(contents_scale), 154 ideal_contents_scale_(ideal_contents_scale), 155 current_tiling_(-1) { 156 missing_region_.Union(content_rect); 157 158 for (ideal_tiling_ = 0; 159 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size(); 160 ++ideal_tiling_) { 161 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_]; 162 if (tiling->contents_scale() < ideal_contents_scale_) { 163 if (ideal_tiling_ > 0) 164 ideal_tiling_--; 165 break; 166 } 167 } 168 169 DCHECK_LE(set_->tilings_.size(), 170 static_cast<size_t>(std::numeric_limits<int>::max())); 171 172 int num_tilings = set_->tilings_.size(); 173 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0) 174 ideal_tiling_--; 175 176 ++(*this); 177} 178 179PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { 180} 181 182gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const { 183 if (!tiling_iter_) { 184 if (!region_iter_.has_rect()) 185 return gfx::Rect(); 186 return region_iter_.rect(); 187 } 188 return tiling_iter_.geometry_rect(); 189} 190 191gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { 192 if (!tiling_iter_) 193 return gfx::RectF(); 194 return tiling_iter_.texture_rect(); 195} 196 197gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const { 198 if (!tiling_iter_) 199 return gfx::Size(); 200 return tiling_iter_.texture_size(); 201} 202 203Tile* PictureLayerTilingSet::CoverageIterator::operator->() const { 204 if (!tiling_iter_) 205 return NULL; 206 return *tiling_iter_; 207} 208 209Tile* PictureLayerTilingSet::CoverageIterator::operator*() const { 210 if (!tiling_iter_) 211 return NULL; 212 return *tiling_iter_; 213} 214 215PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() { 216 if (current_tiling_ < 0) 217 return NULL; 218 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size()) 219 return NULL; 220 return set_->tilings_[current_tiling_]; 221} 222 223int PictureLayerTilingSet::CoverageIterator::NextTiling() const { 224 // Order returned by this method is: 225 // 1. Ideal tiling index 226 // 2. Tiling index < Ideal in decreasing order (higher res than ideal) 227 // 3. Tiling index > Ideal in increasing order (lower res than ideal) 228 // 4. Tiling index > tilings.size() (invalid index) 229 if (current_tiling_ < 0) 230 return ideal_tiling_; 231 else if (current_tiling_ > ideal_tiling_) 232 return current_tiling_ + 1; 233 else if (current_tiling_) 234 return current_tiling_ - 1; 235 else 236 return ideal_tiling_ + 1; 237} 238 239PictureLayerTilingSet::CoverageIterator& 240PictureLayerTilingSet::CoverageIterator::operator++() { 241 bool first_time = current_tiling_ < 0; 242 243 if (!*this && !first_time) 244 return *this; 245 246 if (tiling_iter_) 247 ++tiling_iter_; 248 249 // Loop until we find a valid place to stop. 250 while (true) { 251 while (tiling_iter_ && 252 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) { 253 missing_region_.Union(tiling_iter_.geometry_rect()); 254 ++tiling_iter_; 255 } 256 if (tiling_iter_) 257 return *this; 258 259 // If the set of current rects for this tiling is done, go to the next 260 // tiling and set up to iterate through all of the remaining holes. 261 // This will also happen the first time through the loop. 262 if (!region_iter_.has_rect()) { 263 current_tiling_ = NextTiling(); 264 current_region_.Swap(&missing_region_); 265 missing_region_.Clear(); 266 region_iter_ = Region::Iterator(current_region_); 267 268 // All done and all filled. 269 if (!region_iter_.has_rect()) { 270 current_tiling_ = set_->tilings_.size(); 271 return *this; 272 } 273 274 // No more valid tiles, return this checkerboard rect. 275 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) 276 return *this; 277 } 278 279 // Pop a rect off. If there are no more tilings, then these will be 280 // treated as geometry with null tiles that the caller can checkerboard. 281 gfx::Rect last_rect = region_iter_.rect(); 282 region_iter_.next(); 283 284 // Done, found next checkerboard rect to return. 285 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) 286 return *this; 287 288 // Construct a new iterator for the next tiling, but we need to loop 289 // again until we get to a valid one. 290 tiling_iter_ = PictureLayerTiling::CoverageIterator( 291 set_->tilings_[current_tiling_], 292 contents_scale_, 293 last_rect); 294 } 295 296 return *this; 297} 298 299PictureLayerTilingSet::CoverageIterator::operator bool() const { 300 return current_tiling_ < static_cast<int>(set_->tilings_.size()) || 301 region_iter_.has_rect(); 302} 303 304void PictureLayerTilingSet::UpdateTilePriorities( 305 WhichTree tree, 306 gfx::Size device_viewport, 307 gfx::Rect viewport_in_content_space, 308 gfx::Rect visible_content_rect, 309 gfx::Size last_layer_bounds, 310 gfx::Size current_layer_bounds, 311 float last_layer_contents_scale, 312 float current_layer_contents_scale, 313 const gfx::Transform& last_screen_transform, 314 const gfx::Transform& current_screen_transform, 315 double current_frame_time_in_seconds, 316 size_t max_tiles_for_interest_area) { 317 gfx::Rect viewport_in_layer_space = gfx::ScaleToEnclosingRect( 318 viewport_in_content_space, 319 1.f / current_layer_contents_scale); 320 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect( 321 visible_content_rect, 322 1.f / current_layer_contents_scale); 323 324 for (size_t i = 0; i < tilings_.size(); ++i) { 325 tilings_[i]->UpdateTilePriorities( 326 tree, 327 device_viewport, 328 viewport_in_layer_space, 329 visible_layer_rect, 330 last_layer_bounds, 331 current_layer_bounds, 332 last_layer_contents_scale, 333 current_layer_contents_scale, 334 last_screen_transform, 335 current_screen_transform, 336 current_frame_time_in_seconds, 337 max_tiles_for_interest_area); 338 } 339} 340 341void PictureLayerTilingSet::DidBecomeActive() { 342 for (size_t i = 0; i < tilings_.size(); ++i) 343 tilings_[i]->DidBecomeActive(); 344} 345 346void PictureLayerTilingSet::DidBecomeRecycled() { 347 for (size_t i = 0; i < tilings_.size(); ++i) 348 tilings_[i]->DidBecomeRecycled(); 349} 350 351scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const { 352 scoped_ptr<base::ListValue> state(new base::ListValue()); 353 for (size_t i = 0; i < tilings_.size(); ++i) 354 state->Append(tilings_[i]->AsValue().release()); 355 return state.PassAs<base::Value>(); 356} 357 358size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const { 359 size_t amount = 0; 360 for (size_t i = 0; i < tilings_.size(); ++i) 361 amount += tilings_[i]->GPUMemoryUsageInBytes(); 362 return amount; 363} 364 365} // namespace cc 366