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