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/layers/picture_layer_impl.h" 6 7 #include <algorithm> 8 #include <limits> 9 #include <set> 10 11 #include "base/debug/trace_event_argument.h" 12 #include "base/time/time.h" 13 #include "cc/base/math_util.h" 14 #include "cc/base/util.h" 15 #include "cc/debug/debug_colors.h" 16 #include "cc/debug/micro_benchmark_impl.h" 17 #include "cc/debug/traced_value.h" 18 #include "cc/layers/append_quads_data.h" 19 #include "cc/layers/solid_color_layer_impl.h" 20 #include "cc/output/begin_frame_args.h" 21 #include "cc/quads/checkerboard_draw_quad.h" 22 #include "cc/quads/debug_border_draw_quad.h" 23 #include "cc/quads/picture_draw_quad.h" 24 #include "cc/quads/solid_color_draw_quad.h" 25 #include "cc/quads/tile_draw_quad.h" 26 #include "cc/resources/tile_manager.h" 27 #include "cc/trees/layer_tree_impl.h" 28 #include "cc/trees/occlusion_tracker.h" 29 #include "ui/gfx/quad_f.h" 30 #include "ui/gfx/rect_conversions.h" 31 #include "ui/gfx/size_conversions.h" 32 33 namespace { 34 const float kMaxScaleRatioDuringPinch = 2.0f; 35 36 // When creating a new tiling during pinch, snap to an existing 37 // tiling's scale if the desired scale is within this ratio. 38 const float kSnapToExistingTilingRatio = 1.2f; 39 40 // Estimate skewport 60 frames ahead for pre-rasterization on the CPU. 41 const float kCpuSkewportTargetTimeInFrames = 60.0f; 42 43 // Don't pre-rasterize on the GPU (except for kBackflingGuardDistancePixels in 44 // TileManager::BinFromTilePriority). 45 const float kGpuSkewportTargetTimeInFrames = 0.0f; 46 47 } // namespace 48 49 namespace cc { 50 51 PictureLayerImpl::Pair::Pair() : active(NULL), pending(NULL) { 52 } 53 54 PictureLayerImpl::Pair::Pair(PictureLayerImpl* active_layer, 55 PictureLayerImpl* pending_layer) 56 : active(active_layer), pending(pending_layer) { 57 } 58 59 PictureLayerImpl::Pair::~Pair() { 60 } 61 62 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) 63 : LayerImpl(tree_impl, id), 64 twin_layer_(NULL), 65 pile_(PicturePileImpl::Create()), 66 ideal_page_scale_(0.f), 67 ideal_device_scale_(0.f), 68 ideal_source_scale_(0.f), 69 ideal_contents_scale_(0.f), 70 raster_page_scale_(0.f), 71 raster_device_scale_(0.f), 72 raster_source_scale_(0.f), 73 raster_contents_scale_(0.f), 74 low_res_raster_contents_scale_(0.f), 75 raster_source_scale_is_fixed_(false), 76 was_screen_space_transform_animating_(false), 77 needs_post_commit_initialization_(true), 78 should_update_tile_priorities_(false) { 79 layer_tree_impl()->RegisterPictureLayerImpl(this); 80 } 81 82 PictureLayerImpl::~PictureLayerImpl() { 83 layer_tree_impl()->UnregisterPictureLayerImpl(this); 84 } 85 86 const char* PictureLayerImpl::LayerTypeAsString() const { 87 return "cc::PictureLayerImpl"; 88 } 89 90 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( 91 LayerTreeImpl* tree_impl) { 92 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 93 } 94 95 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { 96 // It's possible this layer was never drawn or updated (e.g. because it was 97 // a descendant of an opacity 0 layer). 98 DoPostCommitInitializationIfNeeded(); 99 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); 100 101 // We have already synced the important bits from the the active layer, and 102 // we will soon swap out its tilings and use them for recycling. However, 103 // there are now tiles in this layer's tilings that were unref'd and replaced 104 // with new tiles (due to invalidation). This resets all active priorities on 105 // the to-be-recycled tiling to ensure replaced tiles don't linger and take 106 // memory (due to a stale 'active' priority). 107 if (layer_impl->tilings_) 108 layer_impl->tilings_->DidBecomeRecycled(); 109 110 LayerImpl::PushPropertiesTo(base_layer); 111 112 // When the pending tree pushes to the active tree, the pending twin 113 // becomes recycled. 114 layer_impl->twin_layer_ = NULL; 115 twin_layer_ = NULL; 116 117 layer_impl->UpdatePile(pile_); 118 119 DCHECK(!pile_->is_solid_color() || !tilings_->num_tilings()); 120 // Tilings would be expensive to push, so we swap. 121 layer_impl->tilings_.swap(tilings_); 122 layer_impl->tilings_->SetClient(layer_impl); 123 if (tilings_) 124 tilings_->SetClient(this); 125 126 // Ensure that the recycle tree doesn't have any unshared tiles. 127 if (tilings_ && pile_->is_solid_color()) 128 tilings_->RemoveAllTilings(); 129 130 // Remove invalidated tiles from what will become a recycle tree. 131 if (tilings_) 132 tilings_->RemoveTilesInRegion(invalidation_); 133 134 layer_impl->raster_page_scale_ = raster_page_scale_; 135 layer_impl->raster_device_scale_ = raster_device_scale_; 136 layer_impl->raster_source_scale_ = raster_source_scale_; 137 layer_impl->raster_contents_scale_ = raster_contents_scale_; 138 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; 139 layer_impl->needs_post_commit_initialization_ = false; 140 141 // The invalidation on this soon-to-be-recycled layer must be cleared to 142 // mirror clearing the invalidation in PictureLayer's version of this function 143 // in case push properties is skipped. 144 layer_impl->invalidation_.Swap(&invalidation_); 145 invalidation_.Clear(); 146 needs_post_commit_initialization_ = true; 147 148 // We always need to push properties. 149 // See http://crbug.com/303943 150 needs_push_properties_ = true; 151 } 152 153 void PictureLayerImpl::UpdatePile(scoped_refptr<PicturePileImpl> pile) { 154 bool could_have_tilings = CanHaveTilings(); 155 pile_.swap(pile); 156 157 // Need to call UpdateTiles again if CanHaveTilings changed. 158 if (could_have_tilings != CanHaveTilings()) { 159 layer_tree_impl()->set_needs_update_draw_properties(); 160 } 161 } 162 163 void PictureLayerImpl::AppendQuads( 164 RenderPass* render_pass, 165 const OcclusionTracker<LayerImpl>& occlusion_tracker, 166 AppendQuadsData* append_quads_data) { 167 DCHECK(!needs_post_commit_initialization_); 168 169 SharedQuadState* shared_quad_state = 170 render_pass->CreateAndAppendSharedQuadState(); 171 172 if (pile_->is_solid_color()) { 173 PopulateSharedQuadState(shared_quad_state); 174 175 AppendDebugBorderQuad( 176 render_pass, content_bounds(), shared_quad_state, append_quads_data); 177 178 SolidColorLayerImpl::AppendSolidQuads( 179 render_pass, 180 occlusion_tracker, 181 shared_quad_state, 182 visible_content_rect(), 183 draw_properties().target_space_transform, 184 pile_->solid_color()); 185 return; 186 } 187 188 float max_contents_scale = MaximumTilingContentsScale(); 189 gfx::Transform scaled_draw_transform = draw_transform(); 190 scaled_draw_transform.Scale(SK_MScalar1 / max_contents_scale, 191 SK_MScalar1 / max_contents_scale); 192 gfx::Size scaled_content_bounds = 193 gfx::ToCeiledSize(gfx::ScaleSize(content_bounds(), max_contents_scale)); 194 195 gfx::Rect scaled_visible_content_rect = 196 gfx::ScaleToEnclosingRect(visible_content_rect(), max_contents_scale); 197 scaled_visible_content_rect.Intersect(gfx::Rect(scaled_content_bounds)); 198 199 Occlusion occlusion = 200 occlusion_tracker.GetCurrentOcclusionForLayer(scaled_draw_transform); 201 202 shared_quad_state->SetAll(scaled_draw_transform, 203 scaled_content_bounds, 204 scaled_visible_content_rect, 205 draw_properties().clip_rect, 206 draw_properties().is_clipped, 207 draw_properties().opacity, 208 blend_mode(), 209 sorting_context_id_); 210 211 if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) { 212 AppendDebugBorderQuad( 213 render_pass, 214 scaled_content_bounds, 215 shared_quad_state, 216 append_quads_data, 217 DebugColors::DirectPictureBorderColor(), 218 DebugColors::DirectPictureBorderWidth(layer_tree_impl())); 219 220 gfx::Rect geometry_rect = scaled_visible_content_rect; 221 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); 222 gfx::Rect visible_geometry_rect = 223 occlusion.GetUnoccludedContentRect(geometry_rect); 224 if (visible_geometry_rect.IsEmpty()) 225 return; 226 227 gfx::Size texture_size = scaled_visible_content_rect.size(); 228 gfx::RectF texture_rect = gfx::RectF(texture_size); 229 gfx::Rect quad_content_rect = scaled_visible_content_rect; 230 231 PictureDrawQuad* quad = 232 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); 233 quad->SetNew(shared_quad_state, 234 geometry_rect, 235 opaque_rect, 236 visible_geometry_rect, 237 texture_rect, 238 texture_size, 239 RGBA_8888, 240 quad_content_rect, 241 max_contents_scale, 242 pile_); 243 return; 244 } 245 246 AppendDebugBorderQuad( 247 render_pass, scaled_content_bounds, shared_quad_state, append_quads_data); 248 249 if (ShowDebugBorders()) { 250 for (PictureLayerTilingSet::CoverageIterator iter( 251 tilings_.get(), 252 max_contents_scale, 253 scaled_visible_content_rect, 254 ideal_contents_scale_); 255 iter; 256 ++iter) { 257 SkColor color; 258 float width; 259 if (*iter && iter->IsReadyToDraw()) { 260 ManagedTileState::TileVersion::Mode mode = 261 iter->GetTileVersionForDrawing().mode(); 262 if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) { 263 color = DebugColors::SolidColorTileBorderColor(); 264 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl()); 265 } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) { 266 color = DebugColors::PictureTileBorderColor(); 267 width = DebugColors::PictureTileBorderWidth(layer_tree_impl()); 268 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) { 269 color = DebugColors::HighResTileBorderColor(); 270 width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); 271 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) { 272 color = DebugColors::LowResTileBorderColor(); 273 width = DebugColors::LowResTileBorderWidth(layer_tree_impl()); 274 } else if (iter->contents_scale() > max_contents_scale) { 275 color = DebugColors::ExtraHighResTileBorderColor(); 276 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl()); 277 } else { 278 color = DebugColors::ExtraLowResTileBorderColor(); 279 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl()); 280 } 281 } else { 282 color = DebugColors::MissingTileBorderColor(); 283 width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); 284 } 285 286 DebugBorderDrawQuad* debug_border_quad = 287 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); 288 gfx::Rect geometry_rect = iter.geometry_rect(); 289 gfx::Rect visible_geometry_rect = geometry_rect; 290 debug_border_quad->SetNew(shared_quad_state, 291 geometry_rect, 292 visible_geometry_rect, 293 color, 294 width); 295 } 296 } 297 298 // Keep track of the tilings that were used so that tilings that are 299 // unused can be considered for removal. 300 std::vector<PictureLayerTiling*> seen_tilings; 301 302 // Ignore missing tiles outside of viewport for tile priority. This is 303 // normally the same as draw viewport but can be independently overridden by 304 // embedders like Android WebView with SetExternalDrawConstraints. 305 gfx::Rect scaled_viewport_for_tile_priority = gfx::ScaleToEnclosingRect( 306 GetViewportForTilePriorityInContentSpace(), max_contents_scale); 307 308 size_t missing_tile_count = 0u; 309 size_t on_demand_missing_tile_count = 0u; 310 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(), 311 max_contents_scale, 312 scaled_visible_content_rect, 313 ideal_contents_scale_); 314 iter; 315 ++iter) { 316 gfx::Rect geometry_rect = iter.geometry_rect(); 317 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); 318 gfx::Rect visible_geometry_rect = 319 occlusion.GetUnoccludedContentRect(geometry_rect); 320 if (visible_geometry_rect.IsEmpty()) 321 continue; 322 323 append_quads_data->visible_content_area += 324 visible_geometry_rect.width() * visible_geometry_rect.height(); 325 326 bool has_draw_quad = false; 327 if (*iter && iter->IsReadyToDraw()) { 328 const ManagedTileState::TileVersion& tile_version = 329 iter->GetTileVersionForDrawing(); 330 switch (tile_version.mode()) { 331 case ManagedTileState::TileVersion::RESOURCE_MODE: { 332 gfx::RectF texture_rect = iter.texture_rect(); 333 334 // The raster_contents_scale_ is the best scale that the layer is 335 // trying to produce, even though it may not be ideal. Since that's 336 // the best the layer can promise in the future, consider those as 337 // complete. But if a tile is ideal scale, we don't want to consider 338 // it incomplete and trying to replace it with a tile at a worse 339 // scale. 340 if (iter->contents_scale() != raster_contents_scale_ && 341 iter->contents_scale() != ideal_contents_scale_ && 342 geometry_rect.Intersects(scaled_viewport_for_tile_priority)) { 343 append_quads_data->num_incomplete_tiles++; 344 } 345 346 TileDrawQuad* quad = 347 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); 348 quad->SetNew(shared_quad_state, 349 geometry_rect, 350 opaque_rect, 351 visible_geometry_rect, 352 tile_version.get_resource_id(), 353 texture_rect, 354 iter.texture_size(), 355 tile_version.contents_swizzled()); 356 has_draw_quad = true; 357 break; 358 } 359 case ManagedTileState::TileVersion::PICTURE_PILE_MODE: { 360 if (!layer_tree_impl() 361 ->GetRendererCapabilities() 362 .allow_rasterize_on_demand) { 363 ++on_demand_missing_tile_count; 364 break; 365 } 366 367 gfx::RectF texture_rect = iter.texture_rect(); 368 369 ResourceProvider* resource_provider = 370 layer_tree_impl()->resource_provider(); 371 ResourceFormat format = 372 resource_provider->memory_efficient_texture_format(); 373 PictureDrawQuad* quad = 374 render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>(); 375 quad->SetNew(shared_quad_state, 376 geometry_rect, 377 opaque_rect, 378 visible_geometry_rect, 379 texture_rect, 380 iter.texture_size(), 381 format, 382 iter->content_rect(), 383 iter->contents_scale(), 384 pile_); 385 has_draw_quad = true; 386 break; 387 } 388 case ManagedTileState::TileVersion::SOLID_COLOR_MODE: { 389 SolidColorDrawQuad* quad = 390 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); 391 quad->SetNew(shared_quad_state, 392 geometry_rect, 393 visible_geometry_rect, 394 tile_version.get_solid_color(), 395 false); 396 has_draw_quad = true; 397 break; 398 } 399 } 400 } 401 402 if (!has_draw_quad) { 403 if (draw_checkerboard_for_missing_tiles()) { 404 CheckerboardDrawQuad* quad = 405 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>(); 406 SkColor color = DebugColors::DefaultCheckerboardColor(); 407 quad->SetNew( 408 shared_quad_state, geometry_rect, visible_geometry_rect, color); 409 } else { 410 SkColor color = SafeOpaqueBackgroundColor(); 411 SolidColorDrawQuad* quad = 412 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); 413 quad->SetNew(shared_quad_state, 414 geometry_rect, 415 visible_geometry_rect, 416 color, 417 false); 418 } 419 420 if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) { 421 append_quads_data->num_missing_tiles++; 422 ++missing_tile_count; 423 } 424 append_quads_data->approximated_visible_content_area += 425 visible_geometry_rect.width() * visible_geometry_rect.height(); 426 continue; 427 } 428 429 if (iter->priority(ACTIVE_TREE).resolution != HIGH_RESOLUTION) { 430 append_quads_data->approximated_visible_content_area += 431 visible_geometry_rect.width() * visible_geometry_rect.height(); 432 } 433 434 if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling()) 435 seen_tilings.push_back(iter.CurrentTiling()); 436 } 437 438 if (missing_tile_count) { 439 TRACE_EVENT_INSTANT2("cc", 440 "PictureLayerImpl::AppendQuads checkerboard", 441 TRACE_EVENT_SCOPE_THREAD, 442 "missing_tile_count", 443 missing_tile_count, 444 "on_demand_missing_tile_count", 445 on_demand_missing_tile_count); 446 } 447 448 // Aggressively remove any tilings that are not seen to save memory. Note 449 // that this is at the expense of doing cause more frequent re-painting. A 450 // better scheme would be to maintain a tighter visible_content_rect for the 451 // finer tilings. 452 CleanUpTilingsOnActiveLayer(seen_tilings); 453 } 454 455 void PictureLayerImpl::UpdateTiles(const Occlusion& occlusion_in_content_space, 456 bool resourceless_software_draw) { 457 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles"); 458 DCHECK_EQ(1.f, contents_scale_x()); 459 DCHECK_EQ(1.f, contents_scale_y()); 460 461 DoPostCommitInitializationIfNeeded(); 462 463 // Any draw properties derived from |transform|, |viewport|, and |clip| 464 // parameters in LayerTreeHostImpl::SetExternalDrawConstraints are not valid 465 // for prioritizing tiles during resourceless software draws. This is because 466 // resourceless software draws can have wildly different transforms/viewports 467 // from regular draws. 468 if (!resourceless_software_draw) { 469 visible_rect_for_tile_priority_ = visible_content_rect(); 470 } 471 viewport_rect_for_tile_priority_ = 472 layer_tree_impl()->ViewportRectForTilePriority(); 473 screen_space_transform_for_tile_priority_ = screen_space_transform(); 474 475 if (!CanHaveTilings()) { 476 ideal_page_scale_ = 0.f; 477 ideal_device_scale_ = 0.f; 478 ideal_contents_scale_ = 0.f; 479 ideal_source_scale_ = 0.f; 480 SanityCheckTilingState(); 481 return; 482 } 483 484 UpdateIdealScales(); 485 486 DCHECK(tilings_->num_tilings() > 0 || raster_contents_scale_ == 0.f) 487 << "A layer with no tilings shouldn't have valid raster scales"; 488 if (!raster_contents_scale_ || ShouldAdjustRasterScale()) { 489 RecalculateRasterScales(); 490 AddTilingsForRasterScale(); 491 } 492 493 DCHECK(raster_page_scale_); 494 DCHECK(raster_device_scale_); 495 DCHECK(raster_source_scale_); 496 DCHECK(raster_contents_scale_); 497 DCHECK(low_res_raster_contents_scale_); 498 499 was_screen_space_transform_animating_ = 500 draw_properties().screen_space_transform_is_animating; 501 502 should_update_tile_priorities_ = true; 503 504 UpdateTilePriorities(occlusion_in_content_space); 505 506 if (layer_tree_impl()->IsPendingTree()) 507 MarkVisibleResourcesAsRequired(); 508 } 509 510 void PictureLayerImpl::UpdateTilePriorities( 511 const Occlusion& occlusion_in_content_space) { 512 DCHECK(!pile_->is_solid_color() || !tilings_->num_tilings()); 513 514 TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities"); 515 516 double current_frame_time_in_seconds = 517 (layer_tree_impl()->CurrentBeginFrameArgs().frame_time - 518 base::TimeTicks()).InSecondsF(); 519 520 gfx::Rect viewport_rect_in_layer_space = 521 GetViewportForTilePriorityInContentSpace(); 522 bool tiling_needs_update = false; 523 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 524 if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTimeAndViewport( 525 current_frame_time_in_seconds, viewport_rect_in_layer_space)) { 526 tiling_needs_update = true; 527 break; 528 } 529 } 530 if (!tiling_needs_update) 531 return; 532 533 WhichTree tree = 534 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; 535 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 536 // Pass |occlusion_in_content_space| for |occlusion_in_layer_space| since 537 // they are the same space in picture lbayer, as contents scale is always 1. 538 tilings_->tiling_at(i)->UpdateTilePriorities(tree, 539 viewport_rect_in_layer_space, 540 ideal_contents_scale_, 541 current_frame_time_in_seconds, 542 occlusion_in_content_space); 543 } 544 545 // Tile priorities were modified. 546 layer_tree_impl()->DidModifyTilePriorities(); 547 } 548 549 gfx::Rect PictureLayerImpl::GetViewportForTilePriorityInContentSpace() const { 550 // If visible_rect_for_tile_priority_ is empty or 551 // viewport_rect_for_tile_priority_ is set to be different from the device 552 // viewport, try to inverse project the viewport into layer space and use 553 // that. Otherwise just use visible_rect_for_tile_priority_ 554 gfx::Rect visible_rect_in_content_space = visible_rect_for_tile_priority_; 555 556 if (visible_rect_in_content_space.IsEmpty() || 557 layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority_) { 558 gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization); 559 560 if (screen_space_transform_for_tile_priority_.GetInverse(&view_to_layer)) { 561 // Transform from view space to content space. 562 visible_rect_in_content_space = 563 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( 564 view_to_layer, viewport_rect_for_tile_priority_)); 565 } 566 } 567 return visible_rect_in_content_space; 568 } 569 570 PictureLayerImpl* PictureLayerImpl::GetRecycledTwinLayer() { 571 // TODO(vmpstr): Maintain recycled twin as a member. crbug.com/407418 572 return static_cast<PictureLayerImpl*>( 573 layer_tree_impl()->FindRecycleTreeLayerById(id())); 574 } 575 576 void PictureLayerImpl::NotifyTileStateChanged(const Tile* tile) { 577 if (layer_tree_impl()->IsActiveTree()) { 578 gfx::RectF layer_damage_rect = 579 gfx::ScaleRect(tile->content_rect(), 1.f / tile->contents_scale()); 580 AddDamageRect(layer_damage_rect); 581 } 582 } 583 584 void PictureLayerImpl::DidBecomeActive() { 585 LayerImpl::DidBecomeActive(); 586 tilings_->DidBecomeActive(); 587 layer_tree_impl()->DidModifyTilePriorities(); 588 } 589 590 void PictureLayerImpl::DidBeginTracing() { 591 pile_->DidBeginTracing(); 592 } 593 594 void PictureLayerImpl::ReleaseResources() { 595 if (tilings_) 596 RemoveAllTilings(); 597 598 ResetRasterScale(); 599 600 // To avoid an edge case after lost context where the tree is up to date but 601 // the tilings have not been managed, request an update draw properties 602 // to force tilings to get managed. 603 layer_tree_impl()->set_needs_update_draw_properties(); 604 } 605 606 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() { 607 return pile_->GetFlattenedPicture(); 608 } 609 610 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling, 611 const gfx::Rect& content_rect) { 612 DCHECK(!pile_->is_solid_color()); 613 if (!pile_->CanRaster(tiling->contents_scale(), content_rect)) 614 return scoped_refptr<Tile>(); 615 616 int flags = 0; 617 618 // TODO(vmpstr): Revisit this. For now, enabling analysis means that we get as 619 // much savings on memory as we can. However, for some cases like ganesh or 620 // small layers, the amount of time we spend analyzing might not justify 621 // memory savings that we can get. Note that we don't handle solid color 622 // masks, so we shouldn't bother analyzing those. 623 // Bugs: crbug.com/397198, crbug.com/396908 624 if (!pile_->is_mask()) 625 flags = Tile::USE_PICTURE_ANALYSIS; 626 627 return layer_tree_impl()->tile_manager()->CreateTile( 628 pile_.get(), 629 content_rect.size(), 630 content_rect, 631 tiling->contents_scale(), 632 id(), 633 layer_tree_impl()->source_frame_number(), 634 flags); 635 } 636 637 PicturePileImpl* PictureLayerImpl::GetPile() { 638 return pile_.get(); 639 } 640 641 const Region* PictureLayerImpl::GetInvalidation() { 642 return &invalidation_; 643 } 644 645 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling( 646 const PictureLayerTiling* tiling) const { 647 if (!twin_layer_) 648 return NULL; 649 return twin_layer_->tilings_->TilingAtScale(tiling->contents_scale()); 650 } 651 652 PictureLayerTiling* PictureLayerImpl::GetRecycledTwinTiling( 653 const PictureLayerTiling* tiling) { 654 PictureLayerImpl* recycled_twin = GetRecycledTwinLayer(); 655 if (!recycled_twin || !recycled_twin->tilings_) 656 return NULL; 657 return recycled_twin->tilings_->TilingAtScale(tiling->contents_scale()); 658 } 659 660 size_t PictureLayerImpl::GetMaxTilesForInterestArea() const { 661 return layer_tree_impl()->settings().max_tiles_for_interest_area; 662 } 663 664 float PictureLayerImpl::GetSkewportTargetTimeInSeconds() const { 665 float skewport_target_time_in_frames = 666 layer_tree_impl()->use_gpu_rasterization() 667 ? kGpuSkewportTargetTimeInFrames 668 : kCpuSkewportTargetTimeInFrames; 669 return skewport_target_time_in_frames * 670 layer_tree_impl()->begin_impl_frame_interval().InSecondsF() * 671 layer_tree_impl()->settings().skewport_target_time_multiplier; 672 } 673 674 int PictureLayerImpl::GetSkewportExtrapolationLimitInContentPixels() const { 675 return layer_tree_impl() 676 ->settings() 677 .skewport_extrapolation_limit_in_content_pixels; 678 } 679 680 gfx::Size PictureLayerImpl::CalculateTileSize( 681 const gfx::Size& content_bounds) const { 682 int max_texture_size = 683 layer_tree_impl()->resource_provider()->max_texture_size(); 684 685 if (pile_->is_mask()) { 686 // Masks are not tiled, so if we can't cover the whole mask with one tile, 687 // don't make any tiles at all. Returning an empty size signals this. 688 if (content_bounds.width() > max_texture_size || 689 content_bounds.height() > max_texture_size) 690 return gfx::Size(); 691 return content_bounds; 692 } 693 694 gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size; 695 if (layer_tree_impl()->use_gpu_rasterization()) { 696 // TODO(ernstm) crbug.com/365877: We need a unified way to override the 697 // default-tile-size. 698 default_tile_size = 699 gfx::Size(layer_tree_impl()->device_viewport_size().width(), 700 layer_tree_impl()->device_viewport_size().height() / 4); 701 } 702 default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size)); 703 704 gfx::Size max_untiled_content_size = 705 layer_tree_impl()->settings().max_untiled_layer_size; 706 max_untiled_content_size.SetToMin( 707 gfx::Size(max_texture_size, max_texture_size)); 708 709 bool any_dimension_too_large = 710 content_bounds.width() > max_untiled_content_size.width() || 711 content_bounds.height() > max_untiled_content_size.height(); 712 713 bool any_dimension_one_tile = 714 content_bounds.width() <= default_tile_size.width() || 715 content_bounds.height() <= default_tile_size.height(); 716 717 // If long and skinny, tile at the max untiled content size, and clamp 718 // the smaller dimension to the content size, e.g. 1000x12 layer with 719 // 500x500 max untiled size would get 500x12 tiles. Also do this 720 // if the layer is small. 721 if (any_dimension_one_tile || !any_dimension_too_large) { 722 int width = std::min( 723 std::max(max_untiled_content_size.width(), default_tile_size.width()), 724 content_bounds.width()); 725 int height = std::min( 726 std::max(max_untiled_content_size.height(), default_tile_size.height()), 727 content_bounds.height()); 728 // Round up to the closest multiple of 64. This improves recycling and 729 // avoids odd texture sizes. 730 width = RoundUp(width, 64); 731 height = RoundUp(height, 64); 732 return gfx::Size(width, height); 733 } 734 735 return default_tile_size; 736 } 737 738 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { 739 TRACE_EVENT0("cc", "SyncFromActiveLayer"); 740 DCHECK(!other->needs_post_commit_initialization_); 741 DCHECK(other->tilings_); 742 743 if (!DrawsContent()) { 744 RemoveAllTilings(); 745 return; 746 } 747 748 raster_page_scale_ = other->raster_page_scale_; 749 raster_device_scale_ = other->raster_device_scale_; 750 raster_source_scale_ = other->raster_source_scale_; 751 raster_contents_scale_ = other->raster_contents_scale_; 752 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_; 753 754 bool synced_high_res_tiling = false; 755 if (CanHaveTilings()) { 756 synced_high_res_tiling = tilings_->SyncTilings( 757 *other->tilings_, bounds(), invalidation_, MinimumContentsScale()); 758 } else { 759 RemoveAllTilings(); 760 } 761 762 // If our MinimumContentsScale has changed to prevent the twin's high res 763 // tiling from being synced, we should reset the raster scale and let it be 764 // recalculated (1) again. This can happen if our bounds shrink to the point 765 // where min contents scale grows. 766 // (1) - TODO(vmpstr) Instead of hoping that this will be recalculated, we 767 // should refactor this code a little bit and actually recalculate this. 768 // However, this is a larger undertaking, so this will work for now. 769 if (!synced_high_res_tiling) 770 ResetRasterScale(); 771 else 772 SanityCheckTilingState(); 773 } 774 775 void PictureLayerImpl::SyncTiling( 776 const PictureLayerTiling* tiling) { 777 if (!CanHaveTilingWithScale(tiling->contents_scale())) 778 return; 779 tilings_->AddTiling(tiling->contents_scale()); 780 781 // If this tree needs update draw properties, then the tiling will 782 // get updated prior to drawing or activation. If this tree does not 783 // need update draw properties, then its transforms are up to date and 784 // we can create tiles for this tiling immediately. 785 if (!layer_tree_impl()->needs_update_draw_properties() && 786 should_update_tile_priorities_) { 787 // TODO(danakj): Add a DCHECK() that we are not using occlusion tracking 788 // when we stop using the pending tree in the browser compositor. If we want 789 // to support occlusion tracking here, we need to dirty the draw properties 790 // or save occlusion as a draw property. 791 UpdateTilePriorities(Occlusion()); 792 } 793 } 794 795 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const { 796 gfx::Rect content_rect(content_bounds()); 797 PictureLayerTilingSet::CoverageIterator iter( 798 tilings_.get(), 1.f, content_rect, ideal_contents_scale_); 799 800 // Mask resource not ready yet. 801 if (!iter || !*iter) 802 return 0; 803 804 // Masks only supported if they fit on exactly one tile. 805 DCHECK(iter.geometry_rect() == content_rect) 806 << "iter rect " << iter.geometry_rect().ToString() << " content rect " 807 << content_rect.ToString(); 808 809 const ManagedTileState::TileVersion& tile_version = 810 iter->GetTileVersionForDrawing(); 811 if (!tile_version.IsReadyToDraw() || 812 tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE) 813 return 0; 814 815 return tile_version.get_resource_id(); 816 } 817 818 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const { 819 DCHECK(layer_tree_impl()->IsPendingTree()); 820 DCHECK(ideal_contents_scale_); 821 DCHECK_GT(tilings_->num_tilings(), 0u); 822 823 // The goal of this function is to find the minimum set of tiles that need to 824 // be ready to draw in order to activate without flashing content from a 825 // higher res on the active tree to a lower res on the pending tree. 826 827 // First, early out for layers with no visible content. 828 if (visible_rect_for_tile_priority_.IsEmpty()) 829 return; 830 831 // Only mark tiles inside the viewport for tile priority as required for 832 // activation. This viewport is normally the same as the draw viewport but 833 // can be independently overridden by embedders like Android WebView with 834 // SetExternalDrawConstraints. 835 gfx::Rect rect = GetViewportForTilePriorityInContentSpace(); 836 rect.Intersect(visible_rect_for_tile_priority_); 837 838 float min_acceptable_scale = 839 std::min(raster_contents_scale_, ideal_contents_scale_); 840 841 if (PictureLayerImpl* twin = twin_layer_) { 842 float twin_min_acceptable_scale = 843 std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_); 844 // Ignore 0 scale in case CalculateContentsScale() has never been 845 // called for active twin. 846 if (twin_min_acceptable_scale != 0.0f) { 847 min_acceptable_scale = 848 std::min(min_acceptable_scale, twin_min_acceptable_scale); 849 } 850 } 851 852 PictureLayerTiling* high_res = NULL; 853 PictureLayerTiling* low_res = NULL; 854 855 // First pass: ready to draw tiles in acceptable but non-ideal tilings are 856 // marked as required for activation so that their textures are not thrown 857 // away; any non-ready tiles are not marked as required. 858 Region missing_region = rect; 859 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 860 PictureLayerTiling* tiling = tilings_->tiling_at(i); 861 DCHECK(tiling->has_ever_been_updated()); 862 863 if (tiling->resolution() == LOW_RESOLUTION) { 864 DCHECK(!low_res) << "There can only be one low res tiling"; 865 low_res = tiling; 866 } 867 if (tiling->contents_scale() < min_acceptable_scale) 868 continue; 869 if (tiling->resolution() == HIGH_RESOLUTION) { 870 DCHECK(!high_res) << "There can only be one high res tiling"; 871 high_res = tiling; 872 continue; 873 } 874 for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, rect); iter; 875 ++iter) { 876 if (!*iter || !iter->IsReadyToDraw()) 877 continue; 878 879 missing_region.Subtract(iter.geometry_rect()); 880 iter->MarkRequiredForActivation(); 881 } 882 } 883 DCHECK(high_res) << "There must be one high res tiling"; 884 885 // If these pointers are null (because no twin, no matching tiling, or the 886 // simpification just below), then high res tiles will be required to fill any 887 // holes left by the first pass above. If the pointers are valid, then this 888 // layer is allowed to skip any tiles that are not ready on its twin. 889 const PictureLayerTiling* twin_high_res = NULL; 890 const PictureLayerTiling* twin_low_res = NULL; 891 892 if (twin_layer_) { 893 // As a simplification, only allow activating to skip twin tiles that the 894 // active layer is also missing when both this layer and its twin have 895 // "simple" sets of tilings: only 2 tilings (high and low) or only 1 high 896 // res tiling. This avoids having to iterate/track coverage of non-ideal 897 // tilings during the last draw call on the active layer. 898 if (tilings_->num_tilings() <= 2 && 899 twin_layer_->tilings_->num_tilings() <= tilings_->num_tilings()) { 900 twin_low_res = low_res ? GetTwinTiling(low_res) : NULL; 901 twin_high_res = high_res ? GetTwinTiling(high_res) : NULL; 902 } 903 904 // If this layer and its twin have different transforms, then don't compare 905 // them and only allow activating to high res tiles, since tiles on each 906 // layer will be in different places on screen. 907 if (twin_layer_->layer_tree_impl()->RequiresHighResToDraw() || 908 bounds() != twin_layer_->bounds() || 909 draw_properties().screen_space_transform != 910 twin_layer_->draw_properties().screen_space_transform) { 911 twin_high_res = NULL; 912 twin_low_res = NULL; 913 } 914 } 915 916 // As a second pass, mark as required any visible high res tiles not filled in 917 // by acceptable non-ideal tiles from the first pass. 918 if (MarkVisibleTilesAsRequired( 919 high_res, twin_high_res, rect, missing_region)) { 920 // As an optional third pass, if a high res tile was skipped because its 921 // twin was also missing, then fall back to mark low res tiles as required 922 // in case the active twin is substituting those for missing high res 923 // content. Only suitable, when low res is enabled. 924 if (low_res) { 925 MarkVisibleTilesAsRequired(low_res, twin_low_res, rect, missing_region); 926 } 927 } 928 } 929 930 bool PictureLayerImpl::MarkVisibleTilesAsRequired( 931 PictureLayerTiling* tiling, 932 const PictureLayerTiling* optional_twin_tiling, 933 const gfx::Rect& rect, 934 const Region& missing_region) const { 935 bool twin_had_missing_tile = false; 936 for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, rect); iter; 937 ++iter) { 938 Tile* tile = *iter; 939 // A null tile (i.e. missing recording) can just be skipped. 940 if (!tile) 941 continue; 942 943 // If the tile is occluded, don't mark it as required for activation. 944 if (tile->is_occluded(PENDING_TREE)) 945 continue; 946 947 // If the missing region doesn't cover it, this tile is fully 948 // covered by acceptable tiles at other scales. 949 if (!missing_region.Intersects(iter.geometry_rect())) 950 continue; 951 952 // If the twin tile doesn't exist (i.e. missing recording or so far away 953 // that it is outside the visible tile rect) or this tile is shared between 954 // with the twin, then this tile isn't required to prevent flashing. 955 if (optional_twin_tiling) { 956 Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j()); 957 if (!twin_tile || twin_tile == tile) { 958 // However if the shared tile is being used on the active tree, then 959 // there's no missing content in this place, and low res is not needed. 960 if (!twin_tile || !twin_tile->IsReadyToDraw()) 961 twin_had_missing_tile = true; 962 continue; 963 } 964 } 965 966 tile->MarkRequiredForActivation(); 967 } 968 return twin_had_missing_tile; 969 } 970 971 void PictureLayerImpl::DoPostCommitInitialization() { 972 DCHECK(needs_post_commit_initialization_); 973 DCHECK(layer_tree_impl()->IsPendingTree()); 974 975 if (!tilings_) 976 tilings_.reset(new PictureLayerTilingSet(this, bounds())); 977 978 DCHECK(!twin_layer_); 979 twin_layer_ = static_cast<PictureLayerImpl*>( 980 layer_tree_impl()->FindActiveTreeLayerById(id())); 981 if (twin_layer_) { 982 DCHECK(!twin_layer_->twin_layer_); 983 twin_layer_->twin_layer_ = this; 984 // If the twin has never been pushed to, do not sync from it. 985 // This can happen if this function is called during activation. 986 if (!twin_layer_->needs_post_commit_initialization_) 987 SyncFromActiveLayer(twin_layer_); 988 } 989 990 needs_post_commit_initialization_ = false; 991 } 992 993 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { 994 DCHECK(CanHaveTilingWithScale(contents_scale)) << 995 "contents_scale: " << contents_scale; 996 997 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale); 998 999 DCHECK(pile_->HasRecordings()); 1000 1001 if (twin_layer_) 1002 twin_layer_->SyncTiling(tiling); 1003 1004 return tiling; 1005 } 1006 1007 void PictureLayerImpl::RemoveTiling(float contents_scale) { 1008 if (!tilings_ || tilings_->num_tilings() == 0) 1009 return; 1010 1011 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1012 PictureLayerTiling* tiling = tilings_->tiling_at(i); 1013 if (tiling->contents_scale() == contents_scale) { 1014 tilings_->Remove(tiling); 1015 break; 1016 } 1017 } 1018 if (tilings_->num_tilings() == 0) 1019 ResetRasterScale(); 1020 SanityCheckTilingState(); 1021 } 1022 1023 void PictureLayerImpl::RemoveAllTilings() { 1024 if (tilings_) 1025 tilings_->RemoveAllTilings(); 1026 // If there are no tilings, then raster scales are no longer meaningful. 1027 ResetRasterScale(); 1028 } 1029 1030 namespace { 1031 1032 inline float PositiveRatio(float float1, float float2) { 1033 DCHECK_GT(float1, 0); 1034 DCHECK_GT(float2, 0); 1035 return float1 > float2 ? float1 / float2 : float2 / float1; 1036 } 1037 1038 } // namespace 1039 1040 void PictureLayerImpl::AddTilingsForRasterScale() { 1041 PictureLayerTiling* high_res = NULL; 1042 PictureLayerTiling* low_res = NULL; 1043 1044 PictureLayerTiling* previous_low_res = NULL; 1045 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1046 PictureLayerTiling* tiling = tilings_->tiling_at(i); 1047 if (tiling->contents_scale() == raster_contents_scale_) 1048 high_res = tiling; 1049 if (tiling->contents_scale() == low_res_raster_contents_scale_) 1050 low_res = tiling; 1051 if (tiling->resolution() == LOW_RESOLUTION) 1052 previous_low_res = tiling; 1053 1054 // Reset all tilings to non-ideal until the end of this function. 1055 tiling->set_resolution(NON_IDEAL_RESOLUTION); 1056 } 1057 1058 if (!high_res) { 1059 high_res = AddTiling(raster_contents_scale_); 1060 if (raster_contents_scale_ == low_res_raster_contents_scale_) 1061 low_res = high_res; 1062 } 1063 1064 // Only create new low res tilings when the transform is static. This 1065 // prevents wastefully creating a paired low res tiling for every new high res 1066 // tiling during a pinch or a CSS animation. 1067 bool is_pinching = layer_tree_impl()->PinchGestureActive(); 1068 if (layer_tree_impl()->create_low_res_tiling() && !is_pinching && 1069 !draw_properties().screen_space_transform_is_animating && !low_res && 1070 low_res != high_res) 1071 low_res = AddTiling(low_res_raster_contents_scale_); 1072 1073 // Set low-res if we have one. 1074 if (!low_res) 1075 low_res = previous_low_res; 1076 if (low_res && low_res != high_res) 1077 low_res->set_resolution(LOW_RESOLUTION); 1078 1079 // Make sure we always have one high-res (even if high == low). 1080 high_res->set_resolution(HIGH_RESOLUTION); 1081 1082 SanityCheckTilingState(); 1083 } 1084 1085 bool PictureLayerImpl::ShouldAdjustRasterScale() const { 1086 if (was_screen_space_transform_animating_ != 1087 draw_properties().screen_space_transform_is_animating) 1088 return true; 1089 1090 if (draw_properties().screen_space_transform_is_animating && 1091 raster_contents_scale_ != ideal_contents_scale_ && 1092 ShouldAdjustRasterScaleDuringScaleAnimations()) 1093 return true; 1094 1095 bool is_pinching = layer_tree_impl()->PinchGestureActive(); 1096 if (is_pinching && raster_page_scale_) { 1097 // We change our raster scale when it is: 1098 // - Higher than ideal (need a lower-res tiling available) 1099 // - Too far from ideal (need a higher-res tiling available) 1100 float ratio = ideal_page_scale_ / raster_page_scale_; 1101 if (raster_page_scale_ > ideal_page_scale_ || 1102 ratio > kMaxScaleRatioDuringPinch) 1103 return true; 1104 } 1105 1106 if (!is_pinching) { 1107 // When not pinching, match the ideal page scale factor. 1108 if (raster_page_scale_ != ideal_page_scale_) 1109 return true; 1110 } 1111 1112 // Always match the ideal device scale factor. 1113 if (raster_device_scale_ != ideal_device_scale_) 1114 return true; 1115 1116 // When the source scale changes we want to match it, but not when animating 1117 // or when we've fixed the scale in place. 1118 if (!draw_properties().screen_space_transform_is_animating && 1119 !raster_source_scale_is_fixed_ && 1120 raster_source_scale_ != ideal_source_scale_) 1121 return true; 1122 1123 return false; 1124 } 1125 1126 float PictureLayerImpl::SnappedContentsScale(float scale) { 1127 // If a tiling exists within the max snapping ratio, snap to its scale. 1128 float snapped_contents_scale = scale; 1129 float snapped_ratio = kSnapToExistingTilingRatio; 1130 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1131 float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale(); 1132 float ratio = PositiveRatio(tiling_contents_scale, scale); 1133 if (ratio < snapped_ratio) { 1134 snapped_contents_scale = tiling_contents_scale; 1135 snapped_ratio = ratio; 1136 } 1137 } 1138 return snapped_contents_scale; 1139 } 1140 1141 void PictureLayerImpl::RecalculateRasterScales() { 1142 float old_raster_contents_scale = raster_contents_scale_; 1143 float old_raster_page_scale = raster_page_scale_; 1144 float old_raster_source_scale = raster_source_scale_; 1145 1146 raster_device_scale_ = ideal_device_scale_; 1147 raster_page_scale_ = ideal_page_scale_; 1148 raster_source_scale_ = ideal_source_scale_; 1149 raster_contents_scale_ = ideal_contents_scale_; 1150 1151 // If we're not animating, or leaving an animation, and the 1152 // ideal_source_scale_ changes, then things are unpredictable, and we fix 1153 // the raster_source_scale_ in place. 1154 if (old_raster_source_scale && 1155 !draw_properties().screen_space_transform_is_animating && 1156 !was_screen_space_transform_animating_ && 1157 old_raster_source_scale != ideal_source_scale_) 1158 raster_source_scale_is_fixed_ = true; 1159 1160 // TODO(danakj): Adjust raster source scale closer to ideal source scale at 1161 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending 1162 // tree. This will allow CSS scale changes to get re-rastered at an 1163 // appropriate rate. (crbug.com/413636) 1164 if (raster_source_scale_is_fixed_) { 1165 raster_contents_scale_ /= raster_source_scale_; 1166 raster_source_scale_ = 1.f; 1167 } 1168 1169 // During pinch we completely ignore the current ideal scale, and just use 1170 // a multiple of the previous scale. 1171 // TODO(danakj): This seems crazy, we should use the current ideal, no? 1172 bool is_pinching = layer_tree_impl()->PinchGestureActive(); 1173 if (is_pinching && old_raster_contents_scale) { 1174 // See ShouldAdjustRasterScale: 1175 // - When zooming out, preemptively create new tiling at lower resolution. 1176 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio. 1177 bool zooming_out = old_raster_page_scale > ideal_page_scale_; 1178 float desired_contents_scale = 1179 zooming_out ? old_raster_contents_scale / kMaxScaleRatioDuringPinch 1180 : old_raster_contents_scale * kMaxScaleRatioDuringPinch; 1181 raster_contents_scale_ = SnappedContentsScale(desired_contents_scale); 1182 raster_page_scale_ = 1183 raster_contents_scale_ / raster_device_scale_ / raster_source_scale_; 1184 } 1185 1186 raster_contents_scale_ = 1187 std::max(raster_contents_scale_, MinimumContentsScale()); 1188 1189 // If we're not re-rasterizing during animation, rasterize at the maximum 1190 // scale that will occur during the animation, if the maximum scale is 1191 // known. However we want to avoid excessive memory use. If the scale is 1192 // smaller than what we would choose otherwise, then it's always better off 1193 // for us memory-wise. But otherwise, we don't choose a scale at which this 1194 // layer's rastered content would become larger than the viewport. 1195 if (draw_properties().screen_space_transform_is_animating && 1196 !ShouldAdjustRasterScaleDuringScaleAnimations()) { 1197 bool can_raster_at_maximum_scale = false; 1198 // TODO(ajuma): If we need to deal with scale-down animations starting right 1199 // as a layer gets promoted, then we'd want to have the 1200 // |starting_animation_contents_scale| passed in here as a separate draw 1201 // property so we could try use that when the max is too large. 1202 // See crbug.com/422341. 1203 float maximum_scale = draw_properties().maximum_animation_contents_scale; 1204 if (maximum_scale) { 1205 gfx::Size bounds_at_maximum_scale = 1206 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), maximum_scale)); 1207 if (bounds_at_maximum_scale.GetArea() <= 1208 layer_tree_impl()->device_viewport_size().GetArea()) 1209 can_raster_at_maximum_scale = true; 1210 } 1211 // Use the computed scales for the raster scale directly, do not try to use 1212 // the ideal scale here. The current ideal scale may be way too large in the 1213 // case of an animation with scale, and will be constantly changing. 1214 if (can_raster_at_maximum_scale) 1215 raster_contents_scale_ = maximum_scale; 1216 else 1217 raster_contents_scale_ = 1.f * ideal_page_scale_ * ideal_device_scale_; 1218 } 1219 1220 // If this layer would create zero or one tiles at this content scale, 1221 // don't create a low res tiling. 1222 gfx::Size content_bounds = 1223 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_)); 1224 gfx::Size tile_size = CalculateTileSize(content_bounds); 1225 bool tile_covers_bounds = tile_size.width() >= content_bounds.width() && 1226 tile_size.height() >= content_bounds.height(); 1227 if (tile_size.IsEmpty() || tile_covers_bounds) { 1228 low_res_raster_contents_scale_ = raster_contents_scale_; 1229 return; 1230 } 1231 1232 float low_res_factor = 1233 layer_tree_impl()->settings().low_res_contents_scale_factor; 1234 low_res_raster_contents_scale_ = std::max( 1235 raster_contents_scale_ * low_res_factor, 1236 MinimumContentsScale()); 1237 } 1238 1239 void PictureLayerImpl::CleanUpTilingsOnActiveLayer( 1240 std::vector<PictureLayerTiling*> used_tilings) { 1241 DCHECK(layer_tree_impl()->IsActiveTree()); 1242 if (tilings_->num_tilings() == 0) 1243 return; 1244 1245 float min_acceptable_high_res_scale = std::min( 1246 raster_contents_scale_, ideal_contents_scale_); 1247 float max_acceptable_high_res_scale = std::max( 1248 raster_contents_scale_, ideal_contents_scale_); 1249 float twin_low_res_scale = 0.f; 1250 1251 PictureLayerImpl* twin = twin_layer_; 1252 if (twin && twin->CanHaveTilings()) { 1253 min_acceptable_high_res_scale = std::min( 1254 min_acceptable_high_res_scale, 1255 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_)); 1256 max_acceptable_high_res_scale = std::max( 1257 max_acceptable_high_res_scale, 1258 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_)); 1259 1260 for (size_t i = 0; i < twin->tilings_->num_tilings(); ++i) { 1261 PictureLayerTiling* tiling = twin->tilings_->tiling_at(i); 1262 if (tiling->resolution() == LOW_RESOLUTION) 1263 twin_low_res_scale = tiling->contents_scale(); 1264 } 1265 } 1266 1267 std::vector<PictureLayerTiling*> to_remove; 1268 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1269 PictureLayerTiling* tiling = tilings_->tiling_at(i); 1270 1271 // Keep multiple high resolution tilings even if not used to help 1272 // activate earlier at non-ideal resolutions. 1273 if (tiling->contents_scale() >= min_acceptable_high_res_scale && 1274 tiling->contents_scale() <= max_acceptable_high_res_scale) 1275 continue; 1276 1277 // Keep low resolution tilings, if the layer should have them. 1278 if (layer_tree_impl()->create_low_res_tiling()) { 1279 if (tiling->resolution() == LOW_RESOLUTION || 1280 tiling->contents_scale() == twin_low_res_scale) 1281 continue; 1282 } 1283 1284 // Don't remove tilings that are being used (and thus would cause a flash.) 1285 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) != 1286 used_tilings.end()) 1287 continue; 1288 1289 to_remove.push_back(tiling); 1290 } 1291 1292 if (to_remove.empty()) 1293 return; 1294 1295 PictureLayerImpl* recycled_twin = GetRecycledTwinLayer(); 1296 // Remove tilings on this tree and the twin tree. 1297 for (size_t i = 0; i < to_remove.size(); ++i) { 1298 const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]); 1299 // Only remove tilings from the twin layer if they have 1300 // NON_IDEAL_RESOLUTION. 1301 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION) 1302 twin->RemoveTiling(to_remove[i]->contents_scale()); 1303 // Remove the tiling from the recycle tree. Note that we ignore resolution, 1304 // since we don't need to maintain high/low res on the recycle tree. 1305 if (recycled_twin) 1306 recycled_twin->RemoveTiling(to_remove[i]->contents_scale()); 1307 // TODO(enne): temporary sanity CHECK for http://crbug.com/358350 1308 CHECK_NE(HIGH_RESOLUTION, to_remove[i]->resolution()); 1309 tilings_->Remove(to_remove[i]); 1310 } 1311 1312 DCHECK_GT(tilings_->num_tilings(), 0u); 1313 SanityCheckTilingState(); 1314 } 1315 1316 float PictureLayerImpl::MinimumContentsScale() const { 1317 float setting_min = layer_tree_impl()->settings().minimum_contents_scale; 1318 1319 // If the contents scale is less than 1 / width (also for height), 1320 // then it will end up having less than one pixel of content in that 1321 // dimension. Bump the minimum contents scale up in this case to prevent 1322 // this from happening. 1323 int min_dimension = std::min(bounds().width(), bounds().height()); 1324 if (!min_dimension) 1325 return setting_min; 1326 1327 return std::max(1.f / min_dimension, setting_min); 1328 } 1329 1330 void PictureLayerImpl::ResetRasterScale() { 1331 raster_page_scale_ = 0.f; 1332 raster_device_scale_ = 0.f; 1333 raster_source_scale_ = 0.f; 1334 raster_contents_scale_ = 0.f; 1335 low_res_raster_contents_scale_ = 0.f; 1336 raster_source_scale_is_fixed_ = false; 1337 1338 // When raster scales aren't valid, don't update tile priorities until 1339 // this layer has been updated via UpdateDrawProperties. 1340 should_update_tile_priorities_ = false; 1341 } 1342 1343 bool PictureLayerImpl::CanHaveTilings() const { 1344 if (pile_->is_solid_color()) 1345 return false; 1346 if (!DrawsContent()) 1347 return false; 1348 if (!pile_->HasRecordings()) 1349 return false; 1350 return true; 1351 } 1352 1353 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const { 1354 if (!CanHaveTilings()) 1355 return false; 1356 if (contents_scale < MinimumContentsScale()) 1357 return false; 1358 return true; 1359 } 1360 1361 void PictureLayerImpl::SanityCheckTilingState() const { 1362 #if DCHECK_IS_ON 1363 // Recycle tree doesn't have any restrictions. 1364 if (layer_tree_impl()->IsRecycleTree()) 1365 return; 1366 1367 if (!CanHaveTilings()) { 1368 DCHECK_EQ(0u, tilings_->num_tilings()); 1369 return; 1370 } 1371 if (tilings_->num_tilings() == 0) 1372 return; 1373 1374 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res 1375 // tiling to mark its tiles as being required for activation. 1376 DCHECK_EQ(1, tilings_->NumHighResTilings()); 1377 #endif 1378 } 1379 1380 bool PictureLayerImpl::ShouldAdjustRasterScaleDuringScaleAnimations() const { 1381 if (!layer_tree_impl()->use_gpu_rasterization()) 1382 return false; 1383 1384 // Re-rastering text at different scales using GPU rasterization causes 1385 // texture uploads for glyphs at each scale (see crbug.com/366225). To 1386 // workaround this performance issue, we don't re-rasterize layers with 1387 // text during scale animations. 1388 // TODO(ajuma): Remove this workaround once text can be efficiently 1389 // re-rastered at different scales (e.g. by using distance-field fonts). 1390 if (pile_->has_text()) 1391 return false; 1392 1393 return true; 1394 } 1395 1396 float PictureLayerImpl::MaximumTilingContentsScale() const { 1397 float max_contents_scale = MinimumContentsScale(); 1398 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1399 const PictureLayerTiling* tiling = tilings_->tiling_at(i); 1400 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale()); 1401 } 1402 return max_contents_scale; 1403 } 1404 1405 void PictureLayerImpl::UpdateIdealScales() { 1406 DCHECK(CanHaveTilings()); 1407 1408 float min_contents_scale = MinimumContentsScale(); 1409 DCHECK_GT(min_contents_scale, 0.f); 1410 float min_page_scale = layer_tree_impl()->min_page_scale_factor(); 1411 DCHECK_GT(min_page_scale, 0.f); 1412 float min_device_scale = 1.f; 1413 float min_source_scale = 1414 min_contents_scale / min_page_scale / min_device_scale; 1415 1416 float ideal_page_scale = draw_properties().page_scale_factor; 1417 float ideal_device_scale = draw_properties().device_scale_factor; 1418 float ideal_source_scale = draw_properties().ideal_contents_scale / 1419 ideal_page_scale / ideal_device_scale; 1420 ideal_contents_scale_ = 1421 std::max(draw_properties().ideal_contents_scale, min_contents_scale); 1422 ideal_page_scale_ = draw_properties().page_scale_factor; 1423 ideal_device_scale_ = draw_properties().device_scale_factor; 1424 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale); 1425 } 1426 1427 void PictureLayerImpl::GetDebugBorderProperties( 1428 SkColor* color, 1429 float* width) const { 1430 *color = DebugColors::TiledContentLayerBorderColor(); 1431 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); 1432 } 1433 1434 void PictureLayerImpl::GetAllTilesForTracing( 1435 std::set<const Tile*>* tiles) const { 1436 if (!tilings_) 1437 return; 1438 1439 for (size_t i = 0; i < tilings_->num_tilings(); ++i) 1440 tilings_->tiling_at(i)->GetAllTilesForTracing(tiles); 1441 } 1442 1443 void PictureLayerImpl::AsValueInto(base::debug::TracedValue* state) const { 1444 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded(); 1445 LayerImpl::AsValueInto(state); 1446 state->SetDouble("ideal_contents_scale", ideal_contents_scale_); 1447 state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale()); 1448 state->BeginArray("tilings"); 1449 tilings_->AsValueInto(state); 1450 state->EndArray(); 1451 1452 state->BeginArray("tile_priority_rect"); 1453 MathUtil::AddToTracedValue(GetViewportForTilePriorityInContentSpace(), state); 1454 state->EndArray(); 1455 1456 state->BeginArray("visible_rect"); 1457 MathUtil::AddToTracedValue(visible_content_rect(), state); 1458 state->EndArray(); 1459 1460 state->BeginArray("pictures"); 1461 pile_->AsValueInto(state); 1462 state->EndArray(); 1463 1464 state->BeginArray("invalidation"); 1465 invalidation_.AsValueInto(state); 1466 state->EndArray(); 1467 1468 state->BeginArray("coverage_tiles"); 1469 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(), 1470 1.f, 1471 gfx::Rect(content_bounds()), 1472 ideal_contents_scale_); 1473 iter; 1474 ++iter) { 1475 state->BeginDictionary(); 1476 1477 state->BeginArray("geometry_rect"); 1478 MathUtil::AddToTracedValue(iter.geometry_rect(), state); 1479 state->EndArray(); 1480 1481 if (*iter) 1482 TracedValue::SetIDRef(*iter, state, "tile"); 1483 1484 state->EndDictionary(); 1485 } 1486 state->EndArray(); 1487 } 1488 1489 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const { 1490 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded(); 1491 return tilings_->GPUMemoryUsageInBytes(); 1492 } 1493 1494 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) { 1495 benchmark->RunOnLayer(this); 1496 } 1497 1498 WhichTree PictureLayerImpl::GetTree() const { 1499 return layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; 1500 } 1501 1502 bool PictureLayerImpl::IsOnActiveOrPendingTree() const { 1503 return !layer_tree_impl()->IsRecycleTree(); 1504 } 1505 1506 bool PictureLayerImpl::HasValidTilePriorities() const { 1507 return IsOnActiveOrPendingTree() && IsDrawnRenderSurfaceLayerListMember(); 1508 } 1509 1510 bool PictureLayerImpl::AllTilesRequiredForActivationAreReadyToDraw() const { 1511 if (!layer_tree_impl()->IsPendingTree()) 1512 return true; 1513 1514 if (!HasValidTilePriorities()) 1515 return true; 1516 1517 if (!tilings_) 1518 return true; 1519 1520 if (visible_rect_for_tile_priority_.IsEmpty()) 1521 return true; 1522 1523 gfx::Rect rect = GetViewportForTilePriorityInContentSpace(); 1524 rect.Intersect(visible_rect_for_tile_priority_); 1525 1526 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1527 PictureLayerTiling* tiling = tilings_->tiling_at(i); 1528 if (tiling->resolution() != HIGH_RESOLUTION && 1529 tiling->resolution() != LOW_RESOLUTION) 1530 continue; 1531 1532 for (PictureLayerTiling::CoverageIterator iter(tiling, 1.f, rect); iter; 1533 ++iter) { 1534 const Tile* tile = *iter; 1535 // A null tile (i.e. missing recording) can just be skipped. 1536 if (!tile) 1537 continue; 1538 1539 if (tile->required_for_activation() && !tile->IsReadyToDraw()) 1540 return false; 1541 } 1542 } 1543 1544 return true; 1545 } 1546 1547 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator() 1548 : layer_(NULL), current_stage_(arraysize(stages_)) { 1549 } 1550 1551 PictureLayerImpl::LayerRasterTileIterator::LayerRasterTileIterator( 1552 PictureLayerImpl* layer, 1553 bool prioritize_low_res) 1554 : layer_(layer), current_stage_(0) { 1555 DCHECK(layer_); 1556 1557 // Early out if the layer has no tilings. 1558 if (!layer_->tilings_ || !layer_->tilings_->num_tilings()) { 1559 current_stage_ = arraysize(stages_); 1560 return; 1561 } 1562 1563 // Tiles without valid priority are treated as having lowest priority and 1564 // never considered for raster. 1565 if (!layer_->HasValidTilePriorities()) { 1566 current_stage_ = arraysize(stages_); 1567 return; 1568 } 1569 1570 WhichTree tree = layer_->GetTree(); 1571 1572 // Find high and low res tilings and initialize the iterators. 1573 for (size_t i = 0; i < layer_->tilings_->num_tilings(); ++i) { 1574 PictureLayerTiling* tiling = layer_->tilings_->tiling_at(i); 1575 if (tiling->resolution() == HIGH_RESOLUTION) { 1576 iterators_[HIGH_RES] = 1577 PictureLayerTiling::TilingRasterTileIterator(tiling, tree); 1578 } 1579 1580 if (tiling->resolution() == LOW_RESOLUTION) { 1581 iterators_[LOW_RES] = 1582 PictureLayerTiling::TilingRasterTileIterator(tiling, tree); 1583 } 1584 } 1585 1586 if (prioritize_low_res) { 1587 stages_[0].iterator_type = LOW_RES; 1588 stages_[0].tile_type = TilePriority::NOW; 1589 1590 stages_[1].iterator_type = HIGH_RES; 1591 stages_[1].tile_type = TilePriority::NOW; 1592 } else { 1593 stages_[0].iterator_type = HIGH_RES; 1594 stages_[0].tile_type = TilePriority::NOW; 1595 1596 stages_[1].iterator_type = LOW_RES; 1597 stages_[1].tile_type = TilePriority::NOW; 1598 } 1599 1600 stages_[2].iterator_type = HIGH_RES; 1601 stages_[2].tile_type = TilePriority::SOON; 1602 1603 stages_[3].iterator_type = HIGH_RES; 1604 stages_[3].tile_type = TilePriority::EVENTUALLY; 1605 1606 IteratorType index = stages_[current_stage_].iterator_type; 1607 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type; 1608 if (!iterators_[index] || iterators_[index].get_type() != tile_type) 1609 AdvanceToNextStage(); 1610 } 1611 1612 PictureLayerImpl::LayerRasterTileIterator::~LayerRasterTileIterator() {} 1613 1614 PictureLayerImpl::LayerRasterTileIterator::operator bool() const { 1615 return current_stage_ < arraysize(stages_); 1616 } 1617 1618 PictureLayerImpl::LayerRasterTileIterator& 1619 PictureLayerImpl::LayerRasterTileIterator:: 1620 operator++() { 1621 IteratorType index = stages_[current_stage_].iterator_type; 1622 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type; 1623 1624 // First advance the iterator. 1625 DCHECK(iterators_[index]); 1626 DCHECK(iterators_[index].get_type() == tile_type); 1627 ++iterators_[index]; 1628 1629 if (!iterators_[index] || iterators_[index].get_type() != tile_type) 1630 AdvanceToNextStage(); 1631 1632 return *this; 1633 } 1634 1635 Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() { 1636 DCHECK(*this); 1637 1638 IteratorType index = stages_[current_stage_].iterator_type; 1639 DCHECK(iterators_[index]); 1640 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type); 1641 1642 return *iterators_[index]; 1643 } 1644 1645 const Tile* PictureLayerImpl::LayerRasterTileIterator::operator*() const { 1646 DCHECK(*this); 1647 1648 IteratorType index = stages_[current_stage_].iterator_type; 1649 DCHECK(iterators_[index]); 1650 DCHECK(iterators_[index].get_type() == stages_[current_stage_].tile_type); 1651 1652 return *iterators_[index]; 1653 } 1654 1655 void PictureLayerImpl::LayerRasterTileIterator::AdvanceToNextStage() { 1656 DCHECK_LT(current_stage_, arraysize(stages_)); 1657 ++current_stage_; 1658 while (current_stage_ < arraysize(stages_)) { 1659 IteratorType index = stages_[current_stage_].iterator_type; 1660 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type; 1661 1662 if (iterators_[index] && iterators_[index].get_type() == tile_type) 1663 break; 1664 ++current_stage_; 1665 } 1666 } 1667 1668 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator() 1669 : layer_(NULL), 1670 tree_priority_(SAME_PRIORITY_FOR_BOTH_TREES), 1671 current_category_(PictureLayerTiling::EVENTUALLY), 1672 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES), 1673 current_tiling_(0u) { 1674 } 1675 1676 PictureLayerImpl::LayerEvictionTileIterator::LayerEvictionTileIterator( 1677 PictureLayerImpl* layer, 1678 TreePriority tree_priority) 1679 : layer_(layer), 1680 tree_priority_(tree_priority), 1681 current_category_(PictureLayerTiling::EVENTUALLY), 1682 current_tiling_range_type_(PictureLayerTilingSet::HIGHER_THAN_HIGH_RES), 1683 current_tiling_(CurrentTilingRange().start - 1u) { 1684 // TODO(vmpstr): Once tile priorities are determined by the iterators, ensure 1685 // that layers that don't have valid tile priorities have lowest priorities so 1686 // they evict their tiles first (crbug.com/381704) 1687 DCHECK(layer_->tilings_); 1688 do { 1689 if (!AdvanceToNextTiling()) 1690 break; 1691 1692 current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator( 1693 layer_->tilings_->tiling_at(CurrentTilingIndex()), 1694 tree_priority, 1695 current_category_); 1696 } while (!current_iterator_); 1697 } 1698 1699 PictureLayerImpl::LayerEvictionTileIterator::~LayerEvictionTileIterator() { 1700 } 1701 1702 Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() { 1703 DCHECK(*this); 1704 return *current_iterator_; 1705 } 1706 1707 const Tile* PictureLayerImpl::LayerEvictionTileIterator::operator*() const { 1708 DCHECK(*this); 1709 return *current_iterator_; 1710 } 1711 1712 PictureLayerImpl::LayerEvictionTileIterator& 1713 PictureLayerImpl::LayerEvictionTileIterator:: 1714 operator++() { 1715 DCHECK(*this); 1716 ++current_iterator_; 1717 while (!current_iterator_) { 1718 if (!AdvanceToNextTiling()) 1719 break; 1720 1721 current_iterator_ = PictureLayerTiling::TilingEvictionTileIterator( 1722 layer_->tilings_->tiling_at(CurrentTilingIndex()), 1723 tree_priority_, 1724 current_category_); 1725 } 1726 return *this; 1727 } 1728 1729 PictureLayerImpl::LayerEvictionTileIterator::operator bool() const { 1730 return !!current_iterator_; 1731 } 1732 1733 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextCategory() { 1734 switch (current_category_) { 1735 case PictureLayerTiling::EVENTUALLY: 1736 current_category_ = 1737 PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION; 1738 return true; 1739 case PictureLayerTiling::EVENTUALLY_AND_REQUIRED_FOR_ACTIVATION: 1740 current_category_ = PictureLayerTiling::SOON; 1741 return true; 1742 case PictureLayerTiling::SOON: 1743 current_category_ = PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION; 1744 return true; 1745 case PictureLayerTiling::SOON_AND_REQUIRED_FOR_ACTIVATION: 1746 current_category_ = PictureLayerTiling::NOW; 1747 return true; 1748 case PictureLayerTiling::NOW: 1749 current_category_ = PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION; 1750 return true; 1751 case PictureLayerTiling::NOW_AND_REQUIRED_FOR_ACTIVATION: 1752 return false; 1753 } 1754 NOTREACHED(); 1755 return false; 1756 } 1757 1758 bool 1759 PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTilingRangeType() { 1760 switch (current_tiling_range_type_) { 1761 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES: 1762 current_tiling_range_type_ = PictureLayerTilingSet::LOWER_THAN_LOW_RES; 1763 return true; 1764 case PictureLayerTilingSet::LOWER_THAN_LOW_RES: 1765 current_tiling_range_type_ = 1766 PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES; 1767 return true; 1768 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES: 1769 current_tiling_range_type_ = PictureLayerTilingSet::LOW_RES; 1770 return true; 1771 case PictureLayerTilingSet::LOW_RES: 1772 current_tiling_range_type_ = PictureLayerTilingSet::HIGH_RES; 1773 return true; 1774 case PictureLayerTilingSet::HIGH_RES: 1775 if (!AdvanceToNextCategory()) 1776 return false; 1777 1778 current_tiling_range_type_ = PictureLayerTilingSet::HIGHER_THAN_HIGH_RES; 1779 return true; 1780 } 1781 NOTREACHED(); 1782 return false; 1783 } 1784 1785 bool PictureLayerImpl::LayerEvictionTileIterator::AdvanceToNextTiling() { 1786 DCHECK_NE(current_tiling_, CurrentTilingRange().end); 1787 ++current_tiling_; 1788 while (current_tiling_ == CurrentTilingRange().end) { 1789 if (!AdvanceToNextTilingRangeType()) 1790 return false; 1791 1792 current_tiling_ = CurrentTilingRange().start; 1793 } 1794 return true; 1795 } 1796 1797 PictureLayerTilingSet::TilingRange 1798 PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingRange() const { 1799 return layer_->tilings_->GetTilingRange(current_tiling_range_type_); 1800 } 1801 1802 size_t PictureLayerImpl::LayerEvictionTileIterator::CurrentTilingIndex() const { 1803 DCHECK_NE(current_tiling_, CurrentTilingRange().end); 1804 switch (current_tiling_range_type_) { 1805 case PictureLayerTilingSet::HIGHER_THAN_HIGH_RES: 1806 case PictureLayerTilingSet::LOW_RES: 1807 case PictureLayerTilingSet::HIGH_RES: 1808 return current_tiling_; 1809 // Tilings in the following ranges are accessed in reverse order. 1810 case PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES: 1811 case PictureLayerTilingSet::LOWER_THAN_LOW_RES: { 1812 PictureLayerTilingSet::TilingRange tiling_range = CurrentTilingRange(); 1813 size_t current_tiling_range_offset = current_tiling_ - tiling_range.start; 1814 return tiling_range.end - 1 - current_tiling_range_offset; 1815 } 1816 } 1817 NOTREACHED(); 1818 return 0; 1819 } 1820 1821 } // namespace cc 1822