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 113PictureLayerTiling* 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 121void PictureLayerTilingSet::RemoveAllTilings() { 122 tilings_.clear(); 123} 124 125void 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 133void PictureLayerTilingSet::RemoveAllTiles() { 134 for (size_t i = 0; i < tilings_.size(); ++i) 135 tilings_[i]->Reset(); 136} 137 138PictureLayerTilingSet::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 170PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { 171} 172 173gfx::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 182gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { 183 if (!tiling_iter_) 184 return gfx::RectF(); 185 return tiling_iter_.texture_rect(); 186} 187 188gfx::Size PictureLayerTilingSet::CoverageIterator::texture_size() const { 189 if (!tiling_iter_) 190 return gfx::Size(); 191 return tiling_iter_.texture_size(); 192} 193 194Tile* PictureLayerTilingSet::CoverageIterator::operator->() const { 195 if (!tiling_iter_) 196 return NULL; 197 return *tiling_iter_; 198} 199 200Tile* PictureLayerTilingSet::CoverageIterator::operator*() const { 201 if (!tiling_iter_) 202 return NULL; 203 return *tiling_iter_; 204} 205 206PictureLayerTiling* 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 214int 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 230PictureLayerTilingSet::CoverageIterator& 231PictureLayerTilingSet::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 290PictureLayerTilingSet::CoverageIterator::operator bool() const { 291 return current_tiling_ < static_cast<int>(set_->tilings_.size()) || 292 region_iter_.has_rect(); 293} 294 295void 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 332void PictureLayerTilingSet::DidBecomeActive() { 333 for (size_t i = 0; i < tilings_.size(); ++i) 334 tilings_[i]->DidBecomeActive(); 335} 336 337scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const { 338 scoped_ptr<base::ListValue> state(new base::ListValue()); 339 for (size_t i = 0; i < tilings_.size(); ++i) 340 state->Append(tilings_[i]->AsValue().release()); 341 return state.PassAs<base::Value>(); 342} 343 344size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const { 345 size_t amount = 0; 346 for (size_t i = 0; i < tilings_.size(); ++i) 347 amount += tilings_[i]->GPUMemoryUsageInBytes(); 348 return amount; 349} 350 351} // namespace cc 352