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 int 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 122 PictureLayerTiling* 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 130 void PictureLayerTilingSet::RemoveAllTilings() { 131 tilings_.clear(); 132 } 133 134 void 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 142 void PictureLayerTilingSet::RemoveAllTiles() { 143 for (size_t i = 0; i < tilings_.size(); ++i) 144 tilings_[i]->Reset(); 145 } 146 147 PictureLayerTilingSet::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 179 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { 180 } 181 182 gfx::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 191 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { 192 if (!tiling_iter_) 193 return gfx::RectF(); 194 return tiling_iter_.texture_rect(); 195 } 196 197 gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const { 198 if (!tiling_iter_) 199 return gfx::Size(); 200 return tiling_iter_.texture_size(); 201 } 202 203 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const { 204 if (!tiling_iter_) 205 return NULL; 206 return *tiling_iter_; 207 } 208 209 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const { 210 if (!tiling_iter_) 211 return NULL; 212 return *tiling_iter_; 213 } 214 215 PictureLayerTiling* 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 223 int 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 239 PictureLayerTilingSet::CoverageIterator& 240 PictureLayerTilingSet::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 299 PictureLayerTilingSet::CoverageIterator::operator bool() const { 300 return current_tiling_ < static_cast<int>(set_->tilings_.size()) || 301 region_iter_.has_rect(); 302 } 303 304 void 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 341 void PictureLayerTilingSet::DidBecomeActive() { 342 for (size_t i = 0; i < tilings_.size(); ++i) 343 tilings_[i]->DidBecomeActive(); 344 } 345 346 void PictureLayerTilingSet::DidBecomeRecycled() { 347 for (size_t i = 0; i < tilings_.size(); ++i) 348 tilings_[i]->DidBecomeRecycled(); 349 } 350 351 scoped_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 358 size_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