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