| OLD | NEW |
| (Empty) |
| 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 #include <set> | |
| 9 #include <vector> | |
| 10 | |
| 11 namespace cc { | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 class LargestToSmallestScaleFunctor { | |
| 16 public: | |
| 17 bool operator() (PictureLayerTiling* left, PictureLayerTiling* right) { | |
| 18 return left->contents_scale() > right->contents_scale(); | |
| 19 } | |
| 20 }; | |
| 21 | |
| 22 inline float LargerRatio(float float1, float float2) { | |
| 23 DCHECK_GT(float1, 0.f); | |
| 24 DCHECK_GT(float2, 0.f); | |
| 25 return float1 > float2 ? float1 / float2 : float2 / float1; | |
| 26 } | |
| 27 | |
| 28 } // namespace | |
| 29 | |
| 30 // static | |
| 31 scoped_ptr<PictureLayerTilingSet> PictureLayerTilingSet::Create( | |
| 32 PictureLayerTilingClient* client, | |
| 33 size_t max_tiles_for_interest_area, | |
| 34 float skewport_target_time_in_seconds, | |
| 35 int skewport_extrapolation_limit_in_content_pixels) { | |
| 36 return make_scoped_ptr(new PictureLayerTilingSet( | |
| 37 client, max_tiles_for_interest_area, skewport_target_time_in_seconds, | |
| 38 skewport_extrapolation_limit_in_content_pixels)); | |
| 39 } | |
| 40 | |
| 41 PictureLayerTilingSet::PictureLayerTilingSet( | |
| 42 PictureLayerTilingClient* client, | |
| 43 size_t max_tiles_for_interest_area, | |
| 44 float skewport_target_time_in_seconds, | |
| 45 int skewport_extrapolation_limit_in_content_pixels) | |
| 46 : max_tiles_for_interest_area_(max_tiles_for_interest_area), | |
| 47 skewport_target_time_in_seconds_(skewport_target_time_in_seconds), | |
| 48 skewport_extrapolation_limit_in_content_pixels_( | |
| 49 skewport_extrapolation_limit_in_content_pixels), | |
| 50 client_(client) { | |
| 51 } | |
| 52 | |
| 53 PictureLayerTilingSet::~PictureLayerTilingSet() { | |
| 54 } | |
| 55 | |
| 56 void PictureLayerTilingSet::CopyTilingsFromPendingTwin( | |
| 57 const PictureLayerTilingSet* pending_twin_set, | |
| 58 const scoped_refptr<RasterSource>& raster_source) { | |
| 59 if (pending_twin_set->tilings_.empty()) { | |
| 60 // If the twin (pending) tiling set is empty, it was not updated for the | |
| 61 // current frame. So we drop tilings from our set as well, instead of | |
| 62 // leaving behind unshared tilings that are all non-ideal. | |
| 63 RemoveAllTilings(); | |
| 64 } | |
| 65 | |
| 66 for (PictureLayerTiling* pending_twin_tiling : pending_twin_set->tilings_) { | |
| 67 float contents_scale = pending_twin_tiling->contents_scale(); | |
| 68 PictureLayerTiling* this_tiling = FindTilingWithScale(contents_scale); | |
| 69 if (!this_tiling) { | |
| 70 scoped_ptr<PictureLayerTiling> new_tiling = PictureLayerTiling::Create( | |
| 71 contents_scale, raster_source, client_, max_tiles_for_interest_area_, | |
| 72 skewport_target_time_in_seconds_, | |
| 73 skewport_extrapolation_limit_in_content_pixels_); | |
| 74 tilings_.push_back(new_tiling.Pass()); | |
| 75 this_tiling = tilings_.back(); | |
| 76 } | |
| 77 this_tiling->CloneTilesAndPropertiesFrom(*pending_twin_tiling); | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 void PictureLayerTilingSet::UpdateTilingsToCurrentRasterSource( | |
| 82 scoped_refptr<RasterSource> raster_source, | |
| 83 const PictureLayerTilingSet* pending_twin_set, | |
| 84 const Region& layer_invalidation, | |
| 85 float minimum_contents_scale, | |
| 86 float maximum_contents_scale) { | |
| 87 RemoveTilingsBelowScale(minimum_contents_scale); | |
| 88 RemoveTilingsAboveScale(maximum_contents_scale); | |
| 89 | |
| 90 // Copy over tilings that are shared with the |pending_twin_set| tiling set | |
| 91 // (if it exists). | |
| 92 if (pending_twin_set) | |
| 93 CopyTilingsFromPendingTwin(pending_twin_set, raster_source); | |
| 94 | |
| 95 // If the tiling is not shared (FindTilingWithScale returns nullptr) or if | |
| 96 // |this| is the sync set (pending_twin_set is nullptr), then invalidate | |
| 97 // tiles and update them to the new raster source. | |
| 98 for (PictureLayerTiling* tiling : tilings_) { | |
| 99 if (pending_twin_set && | |
| 100 pending_twin_set->FindTilingWithScale(tiling->contents_scale())) { | |
| 101 continue; | |
| 102 } | |
| 103 | |
| 104 tiling->SetRasterSourceAndResize(raster_source); | |
| 105 tiling->Invalidate(layer_invalidation); | |
| 106 tiling->SetRasterSourceOnTiles(); | |
| 107 // This is needed for cases where the live tiles rect didn't change but | |
| 108 // recordings exist in the raster source that did not exist on the last | |
| 109 // raster source. | |
| 110 tiling->CreateMissingTilesInLiveTilesRect(); | |
| 111 | |
| 112 // If |pending_twin_set| is present, then |this| is active and |tiling| is | |
| 113 // not in the pending set, which means it is now NON_IDEAL_RESOLUTION. | |
| 114 if (pending_twin_set) | |
| 115 tiling->set_resolution(NON_IDEAL_RESOLUTION); | |
| 116 } | |
| 117 | |
| 118 tilings_.sort(LargestToSmallestScaleFunctor()); | |
| 119 | |
| 120 #if DCHECK_IS_ON() | |
| 121 for (PictureLayerTiling* tiling : tilings_) { | |
| 122 DCHECK(tiling->tile_size() == | |
| 123 client_->CalculateTileSize(tiling->tiling_size())) | |
| 124 << "tile_size: " << tiling->tile_size().ToString() | |
| 125 << " tiling_size: " << tiling->tiling_size().ToString() | |
| 126 << " CalculateTileSize: " | |
| 127 << client_->CalculateTileSize(tiling->tiling_size()).ToString(); | |
| 128 } | |
| 129 | |
| 130 if (!tilings_.empty()) { | |
| 131 DCHECK_LE(NumHighResTilings(), 1); | |
| 132 // When commiting from the main thread the high res tiling may get dropped, | |
| 133 // but when cloning to the active tree, there should always be one. | |
| 134 if (pending_twin_set) { | |
| 135 DCHECK_EQ(1, NumHighResTilings()) | |
| 136 << " num tilings on active: " << tilings_.size() | |
| 137 << " num tilings on pending: " << pending_twin_set->tilings_.size() | |
| 138 << " num high res on pending: " | |
| 139 << pending_twin_set->NumHighResTilings() | |
| 140 << " are on active tree: " << (client_->GetTree() == ACTIVE_TREE); | |
| 141 } | |
| 142 } | |
| 143 #endif | |
| 144 } | |
| 145 | |
| 146 void PictureLayerTilingSet::CleanUpTilings( | |
| 147 float min_acceptable_high_res_scale, | |
| 148 float max_acceptable_high_res_scale, | |
| 149 const std::vector<PictureLayerTiling*>& needed_tilings, | |
| 150 bool should_have_low_res, | |
| 151 PictureLayerTilingSet* twin_set, | |
| 152 PictureLayerTilingSet* recycled_twin_set) { | |
| 153 float twin_low_res_scale = 0.f; | |
| 154 if (twin_set) { | |
| 155 PictureLayerTiling* tiling = | |
| 156 twin_set->FindTilingWithResolution(LOW_RESOLUTION); | |
| 157 if (tiling) | |
| 158 twin_low_res_scale = tiling->contents_scale(); | |
| 159 } | |
| 160 | |
| 161 std::vector<PictureLayerTiling*> to_remove; | |
| 162 for (auto* tiling : tilings_) { | |
| 163 // Keep all tilings within the min/max scales. | |
| 164 if (tiling->contents_scale() >= min_acceptable_high_res_scale && | |
| 165 tiling->contents_scale() <= max_acceptable_high_res_scale) { | |
| 166 continue; | |
| 167 } | |
| 168 | |
| 169 // Keep low resolution tilings, if the tiling set should have them. | |
| 170 if (should_have_low_res && | |
| 171 (tiling->resolution() == LOW_RESOLUTION || | |
| 172 tiling->contents_scale() == twin_low_res_scale)) { | |
| 173 continue; | |
| 174 } | |
| 175 | |
| 176 // Don't remove tilings that are required. | |
| 177 if (std::find(needed_tilings.begin(), needed_tilings.end(), tiling) != | |
| 178 needed_tilings.end()) { | |
| 179 continue; | |
| 180 } | |
| 181 | |
| 182 to_remove.push_back(tiling); | |
| 183 } | |
| 184 | |
| 185 for (auto* tiling : to_remove) { | |
| 186 PictureLayerTiling* recycled_twin_tiling = | |
| 187 recycled_twin_set | |
| 188 ? recycled_twin_set->FindTilingWithScale(tiling->contents_scale()) | |
| 189 : nullptr; | |
| 190 // Remove the tiling from the recycle tree. Note that we ignore resolution, | |
| 191 // since we don't need to maintain high/low res on the recycle set. | |
| 192 if (recycled_twin_tiling) | |
| 193 recycled_twin_set->Remove(recycled_twin_tiling); | |
| 194 | |
| 195 DCHECK_NE(HIGH_RESOLUTION, tiling->resolution()); | |
| 196 Remove(tiling); | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 void PictureLayerTilingSet::RemoveNonIdealTilings() { | |
| 201 auto to_remove = tilings_.remove_if([](PictureLayerTiling* t) { | |
| 202 return t->resolution() == NON_IDEAL_RESOLUTION; | |
| 203 }); | |
| 204 tilings_.erase(to_remove, tilings_.end()); | |
| 205 } | |
| 206 | |
| 207 void PictureLayerTilingSet::MarkAllTilingsNonIdeal() { | |
| 208 for (auto* tiling : tilings_) | |
| 209 tiling->set_resolution(NON_IDEAL_RESOLUTION); | |
| 210 } | |
| 211 | |
| 212 PictureLayerTiling* PictureLayerTilingSet::AddTiling( | |
| 213 float contents_scale, | |
| 214 scoped_refptr<RasterSource> raster_source) { | |
| 215 for (size_t i = 0; i < tilings_.size(); ++i) { | |
| 216 DCHECK_NE(tilings_[i]->contents_scale(), contents_scale); | |
| 217 DCHECK_EQ(tilings_[i]->raster_source(), raster_source.get()); | |
| 218 } | |
| 219 | |
| 220 tilings_.push_back(PictureLayerTiling::Create( | |
| 221 contents_scale, raster_source, client_, max_tiles_for_interest_area_, | |
| 222 skewport_target_time_in_seconds_, | |
| 223 skewport_extrapolation_limit_in_content_pixels_)); | |
| 224 PictureLayerTiling* appended = tilings_.back(); | |
| 225 | |
| 226 tilings_.sort(LargestToSmallestScaleFunctor()); | |
| 227 return appended; | |
| 228 } | |
| 229 | |
| 230 int PictureLayerTilingSet::NumHighResTilings() const { | |
| 231 return std::count_if(tilings_.begin(), tilings_.end(), | |
| 232 [](PictureLayerTiling* tiling) { | |
| 233 return tiling->resolution() == HIGH_RESOLUTION; | |
| 234 }); | |
| 235 } | |
| 236 | |
| 237 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithScale( | |
| 238 float scale) const { | |
| 239 for (size_t i = 0; i < tilings_.size(); ++i) { | |
| 240 if (tilings_[i]->contents_scale() == scale) | |
| 241 return tilings_[i]; | |
| 242 } | |
| 243 return NULL; | |
| 244 } | |
| 245 | |
| 246 PictureLayerTiling* PictureLayerTilingSet::FindTilingWithResolution( | |
| 247 TileResolution resolution) const { | |
| 248 auto iter = std::find_if(tilings_.begin(), tilings_.end(), | |
| 249 [resolution](const PictureLayerTiling* tiling) { | |
| 250 return tiling->resolution() == resolution; | |
| 251 }); | |
| 252 if (iter == tilings_.end()) | |
| 253 return NULL; | |
| 254 return *iter; | |
| 255 } | |
| 256 | |
| 257 void PictureLayerTilingSet::RemoveTilingsBelowScale(float minimum_scale) { | |
| 258 auto to_remove = | |
| 259 tilings_.remove_if([minimum_scale](PictureLayerTiling* tiling) { | |
| 260 return tiling->contents_scale() < minimum_scale; | |
| 261 }); | |
| 262 tilings_.erase(to_remove, tilings_.end()); | |
| 263 } | |
| 264 | |
| 265 void PictureLayerTilingSet::RemoveTilingsAboveScale(float maximum_scale) { | |
| 266 auto to_remove = | |
| 267 tilings_.remove_if([maximum_scale](PictureLayerTiling* tiling) { | |
| 268 return tiling->contents_scale() > maximum_scale; | |
| 269 }); | |
| 270 tilings_.erase(to_remove, tilings_.end()); | |
| 271 } | |
| 272 | |
| 273 void PictureLayerTilingSet::RemoveAllTilings() { | |
| 274 tilings_.clear(); | |
| 275 } | |
| 276 | |
| 277 void PictureLayerTilingSet::Remove(PictureLayerTiling* tiling) { | |
| 278 ScopedPtrVector<PictureLayerTiling>::iterator iter = | |
| 279 std::find(tilings_.begin(), tilings_.end(), tiling); | |
| 280 if (iter == tilings_.end()) | |
| 281 return; | |
| 282 tilings_.erase(iter); | |
| 283 } | |
| 284 | |
| 285 void PictureLayerTilingSet::RemoveAllTiles() { | |
| 286 for (size_t i = 0; i < tilings_.size(); ++i) | |
| 287 tilings_[i]->Reset(); | |
| 288 } | |
| 289 | |
| 290 float PictureLayerTilingSet::GetSnappedContentsScale( | |
| 291 float start_scale, | |
| 292 float snap_to_existing_tiling_ratio) const { | |
| 293 // If a tiling exists within the max snapping ratio, snap to its scale. | |
| 294 float snapped_contents_scale = start_scale; | |
| 295 float snapped_ratio = snap_to_existing_tiling_ratio; | |
| 296 for (const auto* tiling : tilings_) { | |
| 297 float tiling_contents_scale = tiling->contents_scale(); | |
| 298 float ratio = LargerRatio(tiling_contents_scale, start_scale); | |
| 299 if (ratio < snapped_ratio) { | |
| 300 snapped_contents_scale = tiling_contents_scale; | |
| 301 snapped_ratio = ratio; | |
| 302 } | |
| 303 } | |
| 304 return snapped_contents_scale; | |
| 305 } | |
| 306 | |
| 307 float PictureLayerTilingSet::GetMaximumContentsScale() const { | |
| 308 if (tilings_.empty()) | |
| 309 return 0.f; | |
| 310 // The first tiling has the largest contents scale. | |
| 311 return tilings_[0]->contents_scale(); | |
| 312 } | |
| 313 | |
| 314 bool PictureLayerTilingSet::UpdateTilePriorities( | |
| 315 const gfx::Rect& required_rect_in_layer_space, | |
| 316 float ideal_contents_scale, | |
| 317 double current_frame_time_in_seconds, | |
| 318 const Occlusion& occlusion_in_layer_space, | |
| 319 bool can_require_tiles_for_activation) { | |
| 320 bool updated = false; | |
| 321 for (auto* tiling : tilings_) { | |
| 322 tiling->set_can_require_tiles_for_activation( | |
| 323 can_require_tiles_for_activation); | |
| 324 updated |= tiling->ComputeTilePriorityRects( | |
| 325 required_rect_in_layer_space, ideal_contents_scale, | |
| 326 current_frame_time_in_seconds, occlusion_in_layer_space); | |
| 327 } | |
| 328 return updated; | |
| 329 } | |
| 330 | |
| 331 void PictureLayerTilingSet::GetAllTilesAndPrioritiesForTracing( | |
| 332 std::map<const Tile*, TilePriority>* tile_map) const { | |
| 333 for (auto* tiling : tilings_) | |
| 334 tiling->GetAllTilesAndPrioritiesForTracing(tile_map); | |
| 335 } | |
| 336 | |
| 337 PictureLayerTilingSet::CoverageIterator::CoverageIterator( | |
| 338 const PictureLayerTilingSet* set, | |
| 339 float contents_scale, | |
| 340 const gfx::Rect& content_rect, | |
| 341 float ideal_contents_scale) | |
| 342 : set_(set), | |
| 343 contents_scale_(contents_scale), | |
| 344 ideal_contents_scale_(ideal_contents_scale), | |
| 345 current_tiling_(-1) { | |
| 346 missing_region_.Union(content_rect); | |
| 347 | |
| 348 for (ideal_tiling_ = 0; | |
| 349 static_cast<size_t>(ideal_tiling_) < set_->tilings_.size(); | |
| 350 ++ideal_tiling_) { | |
| 351 PictureLayerTiling* tiling = set_->tilings_[ideal_tiling_]; | |
| 352 if (tiling->contents_scale() < ideal_contents_scale_) { | |
| 353 if (ideal_tiling_ > 0) | |
| 354 ideal_tiling_--; | |
| 355 break; | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 DCHECK_LE(set_->tilings_.size(), | |
| 360 static_cast<size_t>(std::numeric_limits<int>::max())); | |
| 361 | |
| 362 int num_tilings = set_->tilings_.size(); | |
| 363 if (ideal_tiling_ == num_tilings && ideal_tiling_ > 0) | |
| 364 ideal_tiling_--; | |
| 365 | |
| 366 ++(*this); | |
| 367 } | |
| 368 | |
| 369 PictureLayerTilingSet::CoverageIterator::~CoverageIterator() { | |
| 370 } | |
| 371 | |
| 372 gfx::Rect PictureLayerTilingSet::CoverageIterator::geometry_rect() const { | |
| 373 if (!tiling_iter_) { | |
| 374 if (!region_iter_.has_rect()) | |
| 375 return gfx::Rect(); | |
| 376 return region_iter_.rect(); | |
| 377 } | |
| 378 return tiling_iter_.geometry_rect(); | |
| 379 } | |
| 380 | |
| 381 gfx::RectF PictureLayerTilingSet::CoverageIterator::texture_rect() const { | |
| 382 if (!tiling_iter_) | |
| 383 return gfx::RectF(); | |
| 384 return tiling_iter_.texture_rect(); | |
| 385 } | |
| 386 | |
| 387 Tile* PictureLayerTilingSet::CoverageIterator::operator->() const { | |
| 388 if (!tiling_iter_) | |
| 389 return NULL; | |
| 390 return *tiling_iter_; | |
| 391 } | |
| 392 | |
| 393 Tile* PictureLayerTilingSet::CoverageIterator::operator*() const { | |
| 394 if (!tiling_iter_) | |
| 395 return NULL; | |
| 396 return *tiling_iter_; | |
| 397 } | |
| 398 | |
| 399 TileResolution PictureLayerTilingSet::CoverageIterator::resolution() const { | |
| 400 const PictureLayerTiling* tiling = CurrentTiling(); | |
| 401 DCHECK(tiling); | |
| 402 return tiling->resolution(); | |
| 403 } | |
| 404 | |
| 405 PictureLayerTiling* PictureLayerTilingSet::CoverageIterator::CurrentTiling() | |
| 406 const { | |
| 407 if (current_tiling_ < 0) | |
| 408 return NULL; | |
| 409 if (static_cast<size_t>(current_tiling_) >= set_->tilings_.size()) | |
| 410 return NULL; | |
| 411 return set_->tilings_[current_tiling_]; | |
| 412 } | |
| 413 | |
| 414 int PictureLayerTilingSet::CoverageIterator::NextTiling() const { | |
| 415 // Order returned by this method is: | |
| 416 // 1. Ideal tiling index | |
| 417 // 2. Tiling index < Ideal in decreasing order (higher res than ideal) | |
| 418 // 3. Tiling index > Ideal in increasing order (lower res than ideal) | |
| 419 // 4. Tiling index > tilings.size() (invalid index) | |
| 420 if (current_tiling_ < 0) | |
| 421 return ideal_tiling_; | |
| 422 else if (current_tiling_ > ideal_tiling_) | |
| 423 return current_tiling_ + 1; | |
| 424 else if (current_tiling_) | |
| 425 return current_tiling_ - 1; | |
| 426 else | |
| 427 return ideal_tiling_ + 1; | |
| 428 } | |
| 429 | |
| 430 PictureLayerTilingSet::CoverageIterator& | |
| 431 PictureLayerTilingSet::CoverageIterator::operator++() { | |
| 432 bool first_time = current_tiling_ < 0; | |
| 433 | |
| 434 if (!*this && !first_time) | |
| 435 return *this; | |
| 436 | |
| 437 if (tiling_iter_) | |
| 438 ++tiling_iter_; | |
| 439 | |
| 440 // Loop until we find a valid place to stop. | |
| 441 while (true) { | |
| 442 while (tiling_iter_ && | |
| 443 (!*tiling_iter_ || !tiling_iter_->IsReadyToDraw())) { | |
| 444 missing_region_.Union(tiling_iter_.geometry_rect()); | |
| 445 ++tiling_iter_; | |
| 446 } | |
| 447 if (tiling_iter_) | |
| 448 return *this; | |
| 449 | |
| 450 // If the set of current rects for this tiling is done, go to the next | |
| 451 // tiling and set up to iterate through all of the remaining holes. | |
| 452 // This will also happen the first time through the loop. | |
| 453 if (!region_iter_.has_rect()) { | |
| 454 current_tiling_ = NextTiling(); | |
| 455 current_region_.Swap(&missing_region_); | |
| 456 missing_region_.Clear(); | |
| 457 region_iter_ = Region::Iterator(current_region_); | |
| 458 | |
| 459 // All done and all filled. | |
| 460 if (!region_iter_.has_rect()) { | |
| 461 current_tiling_ = set_->tilings_.size(); | |
| 462 return *this; | |
| 463 } | |
| 464 | |
| 465 // No more valid tiles, return this checkerboard rect. | |
| 466 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) | |
| 467 return *this; | |
| 468 } | |
| 469 | |
| 470 // Pop a rect off. If there are no more tilings, then these will be | |
| 471 // treated as geometry with null tiles that the caller can checkerboard. | |
| 472 gfx::Rect last_rect = region_iter_.rect(); | |
| 473 region_iter_.next(); | |
| 474 | |
| 475 // Done, found next checkerboard rect to return. | |
| 476 if (current_tiling_ >= static_cast<int>(set_->tilings_.size())) | |
| 477 return *this; | |
| 478 | |
| 479 // Construct a new iterator for the next tiling, but we need to loop | |
| 480 // again until we get to a valid one. | |
| 481 tiling_iter_ = PictureLayerTiling::CoverageIterator( | |
| 482 set_->tilings_[current_tiling_], | |
| 483 contents_scale_, | |
| 484 last_rect); | |
| 485 } | |
| 486 | |
| 487 return *this; | |
| 488 } | |
| 489 | |
| 490 PictureLayerTilingSet::CoverageIterator::operator bool() const { | |
| 491 return current_tiling_ < static_cast<int>(set_->tilings_.size()) || | |
| 492 region_iter_.has_rect(); | |
| 493 } | |
| 494 | |
| 495 void PictureLayerTilingSet::AsValueInto( | |
| 496 base::trace_event::TracedValue* state) const { | |
| 497 for (size_t i = 0; i < tilings_.size(); ++i) { | |
| 498 state->BeginDictionary(); | |
| 499 tilings_[i]->AsValueInto(state); | |
| 500 state->EndDictionary(); | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const { | |
| 505 size_t amount = 0; | |
| 506 for (size_t i = 0; i < tilings_.size(); ++i) | |
| 507 amount += tilings_[i]->GPUMemoryUsageInBytes(); | |
| 508 return amount; | |
| 509 } | |
| 510 | |
| 511 PictureLayerTilingSet::TilingRange PictureLayerTilingSet::GetTilingRange( | |
| 512 TilingRangeType type) const { | |
| 513 // Doesn't seem to be the case right now but if it ever becomes a performance | |
| 514 // problem to compute these ranges each time this function is called, we can | |
| 515 // compute them only when the tiling set has changed instead. | |
| 516 TilingRange high_res_range(0, 0); | |
| 517 TilingRange low_res_range(tilings_.size(), tilings_.size()); | |
| 518 for (size_t i = 0; i < tilings_.size(); ++i) { | |
| 519 const PictureLayerTiling* tiling = tilings_[i]; | |
| 520 if (tiling->resolution() == HIGH_RESOLUTION) | |
| 521 high_res_range = TilingRange(i, i + 1); | |
| 522 if (tiling->resolution() == LOW_RESOLUTION) | |
| 523 low_res_range = TilingRange(i, i + 1); | |
| 524 } | |
| 525 | |
| 526 TilingRange range(0, 0); | |
| 527 switch (type) { | |
| 528 case HIGHER_THAN_HIGH_RES: | |
| 529 range = TilingRange(0, high_res_range.start); | |
| 530 break; | |
| 531 case HIGH_RES: | |
| 532 range = high_res_range; | |
| 533 break; | |
| 534 case BETWEEN_HIGH_AND_LOW_RES: | |
| 535 // TODO(vmpstr): This code assumes that high res tiling will come before | |
| 536 // low res tiling, however there are cases where this assumption is | |
| 537 // violated. As a result, it's better to be safe in these situations, | |
| 538 // since otherwise we can end up accessing a tiling that doesn't exist. | |
| 539 // See crbug.com/429397 for high res tiling appearing after low res | |
| 540 // tiling discussion/fixes. | |
| 541 if (high_res_range.start <= low_res_range.start) | |
| 542 range = TilingRange(high_res_range.end, low_res_range.start); | |
| 543 else | |
| 544 range = TilingRange(low_res_range.end, high_res_range.start); | |
| 545 break; | |
| 546 case LOW_RES: | |
| 547 range = low_res_range; | |
| 548 break; | |
| 549 case LOWER_THAN_LOW_RES: | |
| 550 range = TilingRange(low_res_range.end, tilings_.size()); | |
| 551 break; | |
| 552 } | |
| 553 | |
| 554 DCHECK_LE(range.start, range.end); | |
| 555 return range; | |
| 556 } | |
| 557 | |
| 558 } // namespace cc | |
| OLD | NEW |