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