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 10 #include "base/time/time.h" 11 #include "cc/base/math_util.h" 12 #include "cc/base/util.h" 13 #include "cc/debug/debug_colors.h" 14 #include "cc/debug/micro_benchmark_impl.h" 15 #include "cc/debug/traced_value.h" 16 #include "cc/layers/append_quads_data.h" 17 #include "cc/layers/quad_sink.h" 18 #include "cc/quads/checkerboard_draw_quad.h" 19 #include "cc/quads/debug_border_draw_quad.h" 20 #include "cc/quads/picture_draw_quad.h" 21 #include "cc/quads/solid_color_draw_quad.h" 22 #include "cc/quads/tile_draw_quad.h" 23 #include "cc/resources/tile_manager.h" 24 #include "cc/trees/layer_tree_impl.h" 25 #include "ui/gfx/quad_f.h" 26 #include "ui/gfx/rect_conversions.h" 27 #include "ui/gfx/size_conversions.h" 28 29 namespace { 30 const float kMaxScaleRatioDuringPinch = 2.0f; 31 32 // When creating a new tiling during pinch, snap to an existing 33 // tiling's scale if the desired scale is within this ratio. 34 const float kSnapToExistingTilingRatio = 0.2f; 35 } 36 37 namespace cc { 38 39 PictureLayerImpl::PictureLayerImpl(LayerTreeImpl* tree_impl, int id) 40 : LayerImpl(tree_impl, id), 41 twin_layer_(NULL), 42 pile_(PicturePileImpl::Create()), 43 last_content_scale_(0), 44 is_mask_(false), 45 ideal_page_scale_(0.f), 46 ideal_device_scale_(0.f), 47 ideal_source_scale_(0.f), 48 ideal_contents_scale_(0.f), 49 raster_page_scale_(0.f), 50 raster_device_scale_(0.f), 51 raster_source_scale_(0.f), 52 raster_contents_scale_(0.f), 53 low_res_raster_contents_scale_(0.f), 54 raster_source_scale_was_animating_(false), 55 is_using_lcd_text_(tree_impl->settings().can_use_lcd_text), 56 needs_post_commit_initialization_(true), 57 should_update_tile_priorities_(false) {} 58 59 PictureLayerImpl::~PictureLayerImpl() {} 60 61 const char* PictureLayerImpl::LayerTypeAsString() const { 62 return "cc::PictureLayerImpl"; 63 } 64 65 scoped_ptr<LayerImpl> PictureLayerImpl::CreateLayerImpl( 66 LayerTreeImpl* tree_impl) { 67 return PictureLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 68 } 69 70 void PictureLayerImpl::PushPropertiesTo(LayerImpl* base_layer) { 71 // It's possible this layer was never drawn or updated (e.g. because it was 72 // a descendant of an opacity 0 layer). 73 DoPostCommitInitializationIfNeeded(); 74 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); 75 76 // We have already synced the important bits from the the active layer, and 77 // we will soon swap out its tilings and use them for recycling. However, 78 // there are now tiles in this layer's tilings that were unref'd and replaced 79 // with new tiles (due to invalidation). This resets all active priorities on 80 // the to-be-recycled tiling to ensure replaced tiles don't linger and take 81 // memory (due to a stale 'active' priority). 82 if (layer_impl->tilings_) 83 layer_impl->tilings_->DidBecomeRecycled(); 84 85 LayerImpl::PushPropertiesTo(base_layer); 86 87 // When the pending tree pushes to the active tree, the pending twin 88 // disappears. 89 layer_impl->twin_layer_ = NULL; 90 twin_layer_ = NULL; 91 92 layer_impl->SetIsMask(is_mask_); 93 layer_impl->pile_ = pile_; 94 95 // Tilings would be expensive to push, so we swap. This optimization requires 96 // an extra invalidation in SyncFromActiveLayer. 97 layer_impl->tilings_.swap(tilings_); 98 layer_impl->tilings_->SetClient(layer_impl); 99 if (tilings_) 100 tilings_->SetClient(this); 101 102 layer_impl->raster_page_scale_ = raster_page_scale_; 103 layer_impl->raster_device_scale_ = raster_device_scale_; 104 layer_impl->raster_source_scale_ = raster_source_scale_; 105 layer_impl->raster_contents_scale_ = raster_contents_scale_; 106 layer_impl->low_res_raster_contents_scale_ = low_res_raster_contents_scale_; 107 108 layer_impl->UpdateLCDTextStatus(is_using_lcd_text_); 109 layer_impl->needs_post_commit_initialization_ = false; 110 111 // The invalidation on this soon-to-be-recycled layer must be cleared to 112 // mirror clearing the invalidation in PictureLayer's version of this function 113 // in case push properties is skipped. 114 layer_impl->invalidation_.Swap(&invalidation_); 115 invalidation_.Clear(); 116 needs_post_commit_initialization_ = true; 117 } 118 119 void PictureLayerImpl::AppendQuads(QuadSink* quad_sink, 120 AppendQuadsData* append_quads_data) { 121 DCHECK(!needs_post_commit_initialization_); 122 gfx::Rect rect(visible_content_rect()); 123 gfx::Rect content_rect(content_bounds()); 124 125 SharedQuadState* shared_quad_state = 126 quad_sink->UseSharedQuadState(CreateSharedQuadState()); 127 128 if (current_draw_mode_ == DRAW_MODE_RESOURCELESS_SOFTWARE) { 129 AppendDebugBorderQuad( 130 quad_sink, 131 shared_quad_state, 132 append_quads_data, 133 DebugColors::DirectPictureBorderColor(), 134 DebugColors::DirectPictureBorderWidth(layer_tree_impl())); 135 136 gfx::Rect geometry_rect = rect; 137 gfx::Rect opaque_rect = contents_opaque() ? geometry_rect : gfx::Rect(); 138 gfx::Size texture_size = rect.size(); 139 gfx::RectF texture_rect = gfx::RectF(texture_size); 140 gfx::Rect quad_content_rect = rect; 141 float contents_scale = contents_scale_x(); 142 143 scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); 144 quad->SetNew(shared_quad_state, 145 geometry_rect, 146 opaque_rect, 147 texture_rect, 148 texture_size, 149 RGBA_8888, 150 quad_content_rect, 151 contents_scale, 152 pile_); 153 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) 154 append_quads_data->num_missing_tiles++; 155 return; 156 } 157 158 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); 159 160 if (ShowDebugBorders()) { 161 for (PictureLayerTilingSet::CoverageIterator iter( 162 tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_); 163 iter; 164 ++iter) { 165 SkColor color; 166 float width; 167 if (*iter && iter->IsReadyToDraw()) { 168 ManagedTileState::TileVersion::Mode mode = 169 iter->GetTileVersionForDrawing().mode(); 170 if (mode == ManagedTileState::TileVersion::SOLID_COLOR_MODE) { 171 color = DebugColors::SolidColorTileBorderColor(); 172 width = DebugColors::SolidColorTileBorderWidth(layer_tree_impl()); 173 } else if (mode == ManagedTileState::TileVersion::PICTURE_PILE_MODE) { 174 color = DebugColors::PictureTileBorderColor(); 175 width = DebugColors::PictureTileBorderWidth(layer_tree_impl()); 176 } else if (iter->priority(ACTIVE_TREE).resolution == HIGH_RESOLUTION) { 177 color = DebugColors::HighResTileBorderColor(); 178 width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); 179 } else if (iter->priority(ACTIVE_TREE).resolution == LOW_RESOLUTION) { 180 color = DebugColors::LowResTileBorderColor(); 181 width = DebugColors::LowResTileBorderWidth(layer_tree_impl()); 182 } else if (iter->contents_scale() > contents_scale_x()) { 183 color = DebugColors::ExtraHighResTileBorderColor(); 184 width = DebugColors::ExtraHighResTileBorderWidth(layer_tree_impl()); 185 } else { 186 color = DebugColors::ExtraLowResTileBorderColor(); 187 width = DebugColors::ExtraLowResTileBorderWidth(layer_tree_impl()); 188 } 189 } else { 190 color = DebugColors::MissingTileBorderColor(); 191 width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); 192 } 193 194 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = 195 DebugBorderDrawQuad::Create(); 196 gfx::Rect geometry_rect = iter.geometry_rect(); 197 debug_border_quad->SetNew(shared_quad_state, geometry_rect, color, width); 198 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), 199 append_quads_data); 200 } 201 } 202 203 // Keep track of the tilings that were used so that tilings that are 204 // unused can be considered for removal. 205 std::vector<PictureLayerTiling*> seen_tilings; 206 207 for (PictureLayerTilingSet::CoverageIterator iter( 208 tilings_.get(), contents_scale_x(), rect, ideal_contents_scale_); 209 iter; 210 ++iter) { 211 gfx::Rect geometry_rect = iter.geometry_rect(); 212 if (!*iter || !iter->IsReadyToDraw()) { 213 if (DrawCheckerboardForMissingTiles()) { 214 // TODO(enne): Figure out how to show debug "invalidated checker" color 215 scoped_ptr<CheckerboardDrawQuad> quad = CheckerboardDrawQuad::Create(); 216 SkColor color = DebugColors::DefaultCheckerboardColor(); 217 quad->SetNew(shared_quad_state, geometry_rect, color); 218 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) 219 append_quads_data->num_missing_tiles++; 220 } else { 221 SkColor color = SafeOpaqueBackgroundColor(); 222 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); 223 quad->SetNew(shared_quad_state, geometry_rect, color, false); 224 if (quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data)) 225 append_quads_data->num_missing_tiles++; 226 } 227 228 append_quads_data->had_incomplete_tile = true; 229 continue; 230 } 231 232 const ManagedTileState::TileVersion& tile_version = 233 iter->GetTileVersionForDrawing(); 234 scoped_ptr<DrawQuad> draw_quad; 235 switch (tile_version.mode()) { 236 case ManagedTileState::TileVersion::RESOURCE_MODE: { 237 gfx::RectF texture_rect = iter.texture_rect(); 238 gfx::Rect opaque_rect = iter->opaque_rect(); 239 opaque_rect.Intersect(geometry_rect); 240 241 if (iter->contents_scale() != ideal_contents_scale_) 242 append_quads_data->had_incomplete_tile = true; 243 244 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); 245 quad->SetNew(shared_quad_state, 246 geometry_rect, 247 opaque_rect, 248 tile_version.get_resource_id(), 249 texture_rect, 250 iter.texture_size(), 251 tile_version.contents_swizzled()); 252 draw_quad = quad.PassAs<DrawQuad>(); 253 break; 254 } 255 case ManagedTileState::TileVersion::PICTURE_PILE_MODE: { 256 gfx::RectF texture_rect = iter.texture_rect(); 257 gfx::Rect opaque_rect = iter->opaque_rect(); 258 opaque_rect.Intersect(geometry_rect); 259 260 ResourceProvider* resource_provider = 261 layer_tree_impl()->resource_provider(); 262 ResourceFormat format = 263 resource_provider->memory_efficient_texture_format(); 264 scoped_ptr<PictureDrawQuad> quad = PictureDrawQuad::Create(); 265 quad->SetNew(shared_quad_state, 266 geometry_rect, 267 opaque_rect, 268 texture_rect, 269 iter.texture_size(), 270 format, 271 iter->content_rect(), 272 iter->contents_scale(), 273 pile_); 274 draw_quad = quad.PassAs<DrawQuad>(); 275 break; 276 } 277 case ManagedTileState::TileVersion::SOLID_COLOR_MODE: { 278 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); 279 quad->SetNew(shared_quad_state, 280 geometry_rect, 281 tile_version.get_solid_color(), 282 false); 283 draw_quad = quad.PassAs<DrawQuad>(); 284 break; 285 } 286 } 287 288 DCHECK(draw_quad); 289 quad_sink->Append(draw_quad.Pass(), append_quads_data); 290 291 if (seen_tilings.empty() || seen_tilings.back() != iter.CurrentTiling()) 292 seen_tilings.push_back(iter.CurrentTiling()); 293 } 294 295 // Aggressively remove any tilings that are not seen to save memory. Note 296 // that this is at the expense of doing cause more frequent re-painting. A 297 // better scheme would be to maintain a tighter visible_content_rect for the 298 // finer tilings. 299 CleanUpTilingsOnActiveLayer(seen_tilings); 300 } 301 302 void PictureLayerImpl::UpdateTilePriorities() { 303 DCHECK(!needs_post_commit_initialization_); 304 CHECK(should_update_tile_priorities_); 305 306 if (!layer_tree_impl()->device_viewport_valid_for_tile_management()) { 307 for (size_t i = 0; i < tilings_->num_tilings(); ++i) 308 DCHECK(tilings_->tiling_at(i)->has_ever_been_updated()); 309 return; 310 } 311 312 if (!tilings_->num_tilings()) 313 return; 314 315 double current_frame_time_in_seconds = 316 (layer_tree_impl()->CurrentFrameTimeTicks() - 317 base::TimeTicks()).InSecondsF(); 318 319 bool tiling_needs_update = false; 320 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 321 if (tilings_->tiling_at(i)->NeedsUpdateForFrameAtTime( 322 current_frame_time_in_seconds)) { 323 tiling_needs_update = true; 324 break; 325 } 326 } 327 if (!tiling_needs_update) 328 return; 329 330 UpdateLCDTextStatus(can_use_lcd_text()); 331 332 gfx::Transform current_screen_space_transform = screen_space_transform(); 333 334 gfx::Size viewport_size = layer_tree_impl()->DrawViewportSize(); 335 gfx::Rect viewport_in_content_space; 336 gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization); 337 if (screen_space_transform().GetInverse(&screen_to_layer)) { 338 viewport_in_content_space = 339 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect( 340 screen_to_layer, gfx::Rect(viewport_size))); 341 } 342 343 WhichTree tree = 344 layer_tree_impl()->IsActiveTree() ? ACTIVE_TREE : PENDING_TREE; 345 size_t max_tiles_for_interest_area = 346 layer_tree_impl()->settings().max_tiles_for_interest_area; 347 tilings_->UpdateTilePriorities( 348 tree, 349 viewport_size, 350 viewport_in_content_space, 351 visible_content_rect(), 352 last_bounds_, 353 bounds(), 354 last_content_scale_, 355 contents_scale_x(), 356 last_screen_space_transform_, 357 current_screen_space_transform, 358 current_frame_time_in_seconds, 359 max_tiles_for_interest_area); 360 361 if (layer_tree_impl()->IsPendingTree()) 362 MarkVisibleResourcesAsRequired(); 363 364 last_screen_space_transform_ = current_screen_space_transform; 365 last_bounds_ = bounds(); 366 last_content_scale_ = contents_scale_x(); 367 368 // Tile priorities were modified. 369 layer_tree_impl()->DidModifyTilePriorities(); 370 } 371 372 void PictureLayerImpl::DidBecomeActive() { 373 LayerImpl::DidBecomeActive(); 374 tilings_->DidBecomeActive(); 375 layer_tree_impl()->DidModifyTilePriorities(); 376 } 377 378 void PictureLayerImpl::DidBeginTracing() { 379 pile_->DidBeginTracing(); 380 } 381 382 void PictureLayerImpl::DidLoseOutputSurface() { 383 if (tilings_) 384 RemoveAllTilings(); 385 386 ResetRasterScale(); 387 } 388 389 void PictureLayerImpl::CalculateContentsScale( 390 float ideal_contents_scale, 391 float device_scale_factor, 392 float page_scale_factor, 393 bool animating_transform_to_screen, 394 float* contents_scale_x, 395 float* contents_scale_y, 396 gfx::Size* content_bounds) { 397 DoPostCommitInitializationIfNeeded(); 398 399 // This function sets valid raster scales and manages tilings, so tile 400 // priorities can now be updated. 401 should_update_tile_priorities_ = true; 402 403 if (!CanHaveTilings()) { 404 ideal_page_scale_ = page_scale_factor; 405 ideal_device_scale_ = device_scale_factor; 406 ideal_contents_scale_ = ideal_contents_scale; 407 ideal_source_scale_ = 408 ideal_contents_scale_ / ideal_page_scale_ / ideal_device_scale_; 409 *contents_scale_x = ideal_contents_scale_; 410 *contents_scale_y = ideal_contents_scale_; 411 *content_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), 412 ideal_contents_scale_, 413 ideal_contents_scale_)); 414 return; 415 } 416 417 float min_contents_scale = MinimumContentsScale(); 418 DCHECK_GT(min_contents_scale, 0.f); 419 float min_page_scale = layer_tree_impl()->min_page_scale_factor(); 420 DCHECK_GT(min_page_scale, 0.f); 421 float min_device_scale = 1.f; 422 float min_source_scale = 423 min_contents_scale / min_page_scale / min_device_scale; 424 425 float ideal_page_scale = page_scale_factor; 426 float ideal_device_scale = device_scale_factor; 427 float ideal_source_scale = 428 ideal_contents_scale / ideal_page_scale / ideal_device_scale; 429 430 ideal_contents_scale_ = std::max(ideal_contents_scale, min_contents_scale); 431 ideal_page_scale_ = ideal_page_scale; 432 ideal_device_scale_ = ideal_device_scale; 433 ideal_source_scale_ = std::max(ideal_source_scale, min_source_scale); 434 435 ManageTilings(animating_transform_to_screen); 436 437 // The content scale and bounds for a PictureLayerImpl is somewhat fictitious. 438 // There are (usually) several tilings at different scales. However, the 439 // content bounds is the (integer!) space in which quads are generated. 440 // In order to guarantee that we can fill this integer space with any set of 441 // tilings (and then map back to floating point texture coordinates), the 442 // contents scale must be at least as large as the largest of the tilings. 443 float max_contents_scale = min_contents_scale; 444 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 445 const PictureLayerTiling* tiling = tilings_->tiling_at(i); 446 max_contents_scale = std::max(max_contents_scale, tiling->contents_scale()); 447 } 448 449 *contents_scale_x = max_contents_scale; 450 *contents_scale_y = max_contents_scale; 451 *content_bounds = gfx::ToCeiledSize( 452 gfx::ScaleSize(bounds(), max_contents_scale, max_contents_scale)); 453 } 454 455 skia::RefPtr<SkPicture> PictureLayerImpl::GetPicture() { 456 return pile_->GetFlattenedPicture(); 457 } 458 459 bool PictureLayerImpl::ShouldUseGPURasterization() const { 460 // TODO(skaslev): Add a proper heuristic for hybrid (software or GPU) 461 // tile rasterization. Currently, when --enable-gpu-rasterization is 462 // set all tiles get GPU rasterized. 463 return layer_tree_impl()->settings().gpu_rasterization; 464 } 465 466 scoped_refptr<Tile> PictureLayerImpl::CreateTile(PictureLayerTiling* tiling, 467 gfx::Rect content_rect) { 468 if (!pile_->CanRaster(tiling->contents_scale(), content_rect)) 469 return scoped_refptr<Tile>(); 470 471 int flags = 0; 472 if (is_using_lcd_text_) 473 flags |= Tile::USE_LCD_TEXT; 474 if (ShouldUseGPURasterization()) 475 flags |= Tile::USE_GPU_RASTERIZATION; 476 return layer_tree_impl()->tile_manager()->CreateTile( 477 pile_.get(), 478 content_rect.size(), 479 content_rect, 480 contents_opaque() ? content_rect : gfx::Rect(), 481 tiling->contents_scale(), 482 id(), 483 layer_tree_impl()->source_frame_number(), 484 flags); 485 } 486 487 void PictureLayerImpl::UpdatePile(Tile* tile) { 488 tile->set_picture_pile(pile_); 489 } 490 491 const Region* PictureLayerImpl::GetInvalidation() { 492 return &invalidation_; 493 } 494 495 const PictureLayerTiling* PictureLayerImpl::GetTwinTiling( 496 const PictureLayerTiling* tiling) const { 497 498 if (!twin_layer_) 499 return NULL; 500 for (size_t i = 0; i < twin_layer_->tilings_->num_tilings(); ++i) 501 if (twin_layer_->tilings_->tiling_at(i)->contents_scale() == 502 tiling->contents_scale()) 503 return twin_layer_->tilings_->tiling_at(i); 504 return NULL; 505 } 506 507 gfx::Size PictureLayerImpl::CalculateTileSize( 508 gfx::Size content_bounds) const { 509 if (is_mask_) { 510 int max_size = layer_tree_impl()->MaxTextureSize(); 511 return gfx::Size( 512 std::min(max_size, content_bounds.width()), 513 std::min(max_size, content_bounds.height())); 514 } 515 516 int max_texture_size = 517 layer_tree_impl()->resource_provider()->max_texture_size(); 518 519 gfx::Size default_tile_size = layer_tree_impl()->settings().default_tile_size; 520 default_tile_size.SetToMin(gfx::Size(max_texture_size, max_texture_size)); 521 522 gfx::Size max_untiled_content_size = 523 layer_tree_impl()->settings().max_untiled_layer_size; 524 max_untiled_content_size.SetToMin( 525 gfx::Size(max_texture_size, max_texture_size)); 526 527 bool any_dimension_too_large = 528 content_bounds.width() > max_untiled_content_size.width() || 529 content_bounds.height() > max_untiled_content_size.height(); 530 531 bool any_dimension_one_tile = 532 content_bounds.width() <= default_tile_size.width() || 533 content_bounds.height() <= default_tile_size.height(); 534 535 // If long and skinny, tile at the max untiled content size, and clamp 536 // the smaller dimension to the content size, e.g. 1000x12 layer with 537 // 500x500 max untiled size would get 500x12 tiles. Also do this 538 // if the layer is small. 539 if (any_dimension_one_tile || !any_dimension_too_large) { 540 int width = 541 std::min(max_untiled_content_size.width(), content_bounds.width()); 542 int height = 543 std::min(max_untiled_content_size.height(), content_bounds.height()); 544 // Round width and height up to the closest multiple of 64, or 56 if 545 // we should avoid power-of-two textures. This helps reduce the number 546 // of different textures sizes to help recycling, and also keeps all 547 // textures multiple-of-eight, which is preferred on some drivers (IMG). 548 bool avoid_pow2 = 549 layer_tree_impl()->GetRendererCapabilities().avoid_pow2_textures; 550 int round_up_to = avoid_pow2 ? 56 : 64; 551 width = RoundUp(width, round_up_to); 552 height = RoundUp(height, round_up_to); 553 return gfx::Size(width, height); 554 } 555 556 return default_tile_size; 557 } 558 559 void PictureLayerImpl::SyncFromActiveLayer(const PictureLayerImpl* other) { 560 DCHECK(!other->needs_post_commit_initialization_); 561 DCHECK(other->tilings_); 562 563 UpdateLCDTextStatus(other->is_using_lcd_text_); 564 565 if (!DrawsContent()) { 566 RemoveAllTilings(); 567 return; 568 } 569 570 raster_page_scale_ = other->raster_page_scale_; 571 raster_device_scale_ = other->raster_device_scale_; 572 raster_source_scale_ = other->raster_source_scale_; 573 raster_contents_scale_ = other->raster_contents_scale_; 574 low_res_raster_contents_scale_ = other->low_res_raster_contents_scale_; 575 576 // Add synthetic invalidations for any recordings that were dropped. As 577 // tiles are updated to point to this new pile, this will force the dropping 578 // of tiles that can no longer be rastered. This is not ideal, but is a 579 // trade-off for memory (use the same pile as much as possible, by switching 580 // during DidBecomeActive) and for time (don't bother checking every tile 581 // during activation to see if the new pile can still raster it). 582 for (int x = 0; x < pile_->num_tiles_x(); ++x) { 583 for (int y = 0; y < pile_->num_tiles_y(); ++y) { 584 bool previously_had = other->pile_->HasRecordingAt(x, y); 585 bool now_has = pile_->HasRecordingAt(x, y); 586 if (now_has || !previously_had) 587 continue; 588 gfx::Rect layer_rect = pile_->tile_bounds(x, y); 589 invalidation_.Union(layer_rect); 590 } 591 } 592 593 // Union in the other newly exposed regions as invalid. 594 Region difference_region = Region(gfx::Rect(bounds())); 595 difference_region.Subtract(gfx::Rect(other->bounds())); 596 invalidation_.Union(difference_region); 597 598 if (CanHaveTilings()) { 599 // The recycle tree's tiling set is two frames out of date, so it needs to 600 // have both this frame's invalidation and the previous frame's invalidation 601 // (stored on the active layer). 602 Region tiling_invalidation = other->invalidation_; 603 tiling_invalidation.Union(invalidation_); 604 tilings_->SyncTilings(*other->tilings_, 605 bounds(), 606 tiling_invalidation, 607 MinimumContentsScale()); 608 } else { 609 RemoveAllTilings(); 610 } 611 612 SanityCheckTilingState(); 613 } 614 615 void PictureLayerImpl::SyncTiling( 616 const PictureLayerTiling* tiling) { 617 if (!CanHaveTilingWithScale(tiling->contents_scale())) 618 return; 619 tilings_->AddTiling(tiling->contents_scale()); 620 621 // If this tree needs update draw properties, then the tiling will 622 // get updated prior to drawing or activation. If this tree does not 623 // need update draw properties, then its transforms are up to date and 624 // we can create tiles for this tiling immediately. 625 if (!layer_tree_impl()->needs_update_draw_properties() && 626 should_update_tile_priorities_) 627 UpdateTilePriorities(); 628 } 629 630 void PictureLayerImpl::SetIsMask(bool is_mask) { 631 if (is_mask_ == is_mask) 632 return; 633 is_mask_ = is_mask; 634 if (tilings_) 635 tilings_->RemoveAllTiles(); 636 } 637 638 ResourceProvider::ResourceId PictureLayerImpl::ContentsResourceId() const { 639 gfx::Rect content_rect(content_bounds()); 640 float scale = contents_scale_x(); 641 PictureLayerTilingSet::CoverageIterator iter( 642 tilings_.get(), scale, content_rect, ideal_contents_scale_); 643 644 // Mask resource not ready yet. 645 if (!iter || !*iter) 646 return 0; 647 648 // Masks only supported if they fit on exactly one tile. 649 if (iter.geometry_rect() != content_rect) 650 return 0; 651 652 const ManagedTileState::TileVersion& tile_version = 653 iter->GetTileVersionForDrawing(); 654 if (!tile_version.IsReadyToDraw() || 655 tile_version.mode() != ManagedTileState::TileVersion::RESOURCE_MODE) 656 return 0; 657 658 return tile_version.get_resource_id(); 659 } 660 661 void PictureLayerImpl::MarkVisibleResourcesAsRequired() const { 662 DCHECK(layer_tree_impl()->IsPendingTree()); 663 DCHECK(!layer_tree_impl()->needs_update_draw_properties()); 664 DCHECK(ideal_contents_scale_); 665 DCHECK_GT(tilings_->num_tilings(), 0u); 666 667 // The goal of this function is to find the minimum set of tiles that need to 668 // be ready to draw in order to activate without flashing content from a 669 // higher res on the active tree to a lower res on the pending tree. 670 671 gfx::Rect rect(visible_content_rect()); 672 673 float min_acceptable_scale = 674 std::min(raster_contents_scale_, ideal_contents_scale_); 675 676 if (PictureLayerImpl* twin = twin_layer_) { 677 float twin_min_acceptable_scale = 678 std::min(twin->ideal_contents_scale_, twin->raster_contents_scale_); 679 // Ignore 0 scale in case CalculateContentsScale() has never been 680 // called for active twin. 681 if (twin_min_acceptable_scale != 0.0f) { 682 min_acceptable_scale = 683 std::min(min_acceptable_scale, twin_min_acceptable_scale); 684 } 685 } 686 687 PictureLayerTiling* high_res = NULL; 688 PictureLayerTiling* low_res = NULL; 689 690 // First pass: ready to draw tiles in acceptable but non-ideal tilings are 691 // marked as required for activation so that their textures are not thrown 692 // away; any non-ready tiles are not marked as required. 693 Region missing_region = rect; 694 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 695 PictureLayerTiling* tiling = tilings_->tiling_at(i); 696 DCHECK(tiling->has_ever_been_updated()); 697 698 if (tiling->resolution() == LOW_RESOLUTION) { 699 DCHECK(!low_res) << "There can only be one low res tiling"; 700 low_res = tiling; 701 } 702 if (tiling->contents_scale() < min_acceptable_scale) 703 continue; 704 if (tiling->resolution() == HIGH_RESOLUTION) { 705 DCHECK(!high_res) << "There can only be one high res tiling"; 706 high_res = tiling; 707 continue; 708 } 709 for (PictureLayerTiling::CoverageIterator iter(tiling, 710 contents_scale_x(), 711 rect); 712 iter; 713 ++iter) { 714 if (!*iter || !iter->IsReadyToDraw()) 715 continue; 716 717 // This iteration is over the visible content rect which is potentially 718 // less conservative than projecting the viewport into the layer. 719 // Ignore tiles that are know to be outside the viewport. 720 if (iter->priority(PENDING_TREE).distance_to_visible_in_pixels != 0) 721 continue; 722 723 missing_region.Subtract(iter.geometry_rect()); 724 iter->MarkRequiredForActivation(); 725 } 726 } 727 DCHECK(high_res) << "There must be one high res tiling"; 728 729 // If these pointers are null (because no twin, no matching tiling, or the 730 // simpification just below), then high res tiles will be required to fill any 731 // holes left by the first pass above. If the pointers are valid, then this 732 // layer is allowed to skip any tiles that are not ready on its twin. 733 const PictureLayerTiling* twin_high_res = NULL; 734 const PictureLayerTiling* twin_low_res = NULL; 735 736 // As a simplification, only allow activating to skip twin tiles that the 737 // active layer is also missing when both this layer and its twin have 2 738 // tilings (high and low). This avoids having to iterate/track coverage of 739 // non-ideal tilings during the last draw call on the active layer. 740 if (high_res && low_res && tilings_->num_tilings() == 2 && 741 twin_layer_ && twin_layer_->tilings_->num_tilings() == 2) { 742 twin_low_res = GetTwinTiling(low_res); 743 if (twin_low_res) 744 twin_high_res = GetTwinTiling(high_res); 745 } 746 // If this layer and its twin have different transforms, then don't compare 747 // them and only allow activating to high res tiles, since tiles on each layer 748 // will be in different places on screen. 749 if (!twin_high_res || !twin_low_res || 750 draw_properties().screen_space_transform != 751 twin_layer_->draw_properties().screen_space_transform) { 752 twin_high_res = NULL; 753 twin_low_res = NULL; 754 } 755 756 // TODO(enne): temporarily disable this optimization: http://crbug.com/335289 757 twin_high_res = NULL; 758 twin_low_res = NULL; 759 760 // As a second pass, mark as required any visible high res tiles not filled in 761 // by acceptable non-ideal tiles from the first pass. 762 if (MarkVisibleTilesAsRequired( 763 high_res, twin_high_res, contents_scale_x(), rect, missing_region)) { 764 // As an optional third pass, if a high res tile was skipped because its 765 // twin was also missing, then fall back to mark low res tiles as required 766 // in case the active twin is substituting those for missing high res 767 // content. 768 MarkVisibleTilesAsRequired( 769 low_res, twin_low_res, contents_scale_x(), rect, missing_region); 770 } 771 } 772 773 bool PictureLayerImpl::MarkVisibleTilesAsRequired( 774 PictureLayerTiling* tiling, 775 const PictureLayerTiling* optional_twin_tiling, 776 float contents_scale, 777 gfx::Rect rect, 778 const Region& missing_region) const { 779 bool twin_had_missing_tile = false; 780 for (PictureLayerTiling::CoverageIterator iter(tiling, 781 contents_scale, 782 rect); 783 iter; 784 ++iter) { 785 Tile* tile = *iter; 786 // A null tile (i.e. missing recording) can just be skipped. 787 if (!tile) 788 continue; 789 790 // This iteration is over the visible content rect which is potentially 791 // less conservative than projecting the viewport into the layer. 792 // Ignore tiles that are know to be outside the viewport. 793 if (tile->priority(PENDING_TREE).distance_to_visible_in_pixels != 0) 794 continue; 795 796 // If the missing region doesn't cover it, this tile is fully 797 // covered by acceptable tiles at other scales. 798 if (!missing_region.Intersects(iter.geometry_rect())) 799 continue; 800 801 // If the twin tile doesn't exist (i.e. missing recording or so far away 802 // that it is outside the visible tile rect) or this tile is shared between 803 // with the twin, then this tile isn't required to prevent flashing. 804 if (optional_twin_tiling) { 805 Tile* twin_tile = optional_twin_tiling->TileAt(iter.i(), iter.j()); 806 if (!twin_tile || twin_tile == tile) { 807 twin_had_missing_tile = true; 808 continue; 809 } 810 } 811 812 tile->MarkRequiredForActivation(); 813 } 814 return twin_had_missing_tile; 815 } 816 817 void PictureLayerImpl::DoPostCommitInitialization() { 818 DCHECK(needs_post_commit_initialization_); 819 DCHECK(layer_tree_impl()->IsPendingTree()); 820 821 if (!tilings_) 822 tilings_.reset(new PictureLayerTilingSet(this, bounds())); 823 824 DCHECK(!twin_layer_); 825 twin_layer_ = static_cast<PictureLayerImpl*>( 826 layer_tree_impl()->FindActiveTreeLayerById(id())); 827 if (twin_layer_) { 828 DCHECK(!twin_layer_->twin_layer_); 829 twin_layer_->twin_layer_ = this; 830 // If the twin has never been pushed to, do not sync from it. 831 // This can happen if this function is called during activation. 832 if (!twin_layer_->needs_post_commit_initialization_) 833 SyncFromActiveLayer(twin_layer_); 834 } 835 836 needs_post_commit_initialization_ = false; 837 } 838 839 PictureLayerTiling* PictureLayerImpl::AddTiling(float contents_scale) { 840 DCHECK(CanHaveTilingWithScale(contents_scale)) << 841 "contents_scale: " << contents_scale; 842 843 PictureLayerTiling* tiling = tilings_->AddTiling(contents_scale); 844 845 DCHECK(pile_->HasRecordings()); 846 847 if (twin_layer_) 848 twin_layer_->SyncTiling(tiling); 849 850 return tiling; 851 } 852 853 void PictureLayerImpl::RemoveTiling(float contents_scale) { 854 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 855 PictureLayerTiling* tiling = tilings_->tiling_at(i); 856 if (tiling->contents_scale() == contents_scale) { 857 tilings_->Remove(tiling); 858 break; 859 } 860 } 861 if (tilings_->num_tilings() == 0) 862 ResetRasterScale(); 863 SanityCheckTilingState(); 864 } 865 866 void PictureLayerImpl::RemoveAllTilings() { 867 tilings_->RemoveAllTilings(); 868 // If there are no tilings, then raster scales are no longer meaningful. 869 ResetRasterScale(); 870 } 871 872 namespace { 873 874 inline float PositiveRatio(float float1, float float2) { 875 DCHECK_GT(float1, 0); 876 DCHECK_GT(float2, 0); 877 return float1 > float2 ? float1 / float2 : float2 / float1; 878 } 879 880 } // namespace 881 882 void PictureLayerImpl::ManageTilings(bool animating_transform_to_screen) { 883 DCHECK(ideal_contents_scale_); 884 DCHECK(ideal_page_scale_); 885 DCHECK(ideal_device_scale_); 886 DCHECK(ideal_source_scale_); 887 DCHECK(CanHaveTilings()); 888 DCHECK(!needs_post_commit_initialization_); 889 890 bool change_target_tiling = 891 raster_page_scale_ == 0.f || 892 raster_device_scale_ == 0.f || 893 raster_source_scale_ == 0.f || 894 raster_contents_scale_ == 0.f || 895 low_res_raster_contents_scale_ == 0.f || 896 ShouldAdjustRasterScale(animating_transform_to_screen); 897 898 if (tilings_->num_tilings() == 0) { 899 DCHECK(change_target_tiling) 900 << "A layer with no tilings shouldn't have valid raster scales"; 901 } 902 903 // Store the value for the next time ShouldAdjustRasterScale is called. 904 raster_source_scale_was_animating_ = animating_transform_to_screen; 905 906 if (!change_target_tiling) 907 return; 908 909 if (!layer_tree_impl()->device_viewport_valid_for_tile_management()) 910 return; 911 912 RecalculateRasterScales(animating_transform_to_screen); 913 914 PictureLayerTiling* high_res = NULL; 915 PictureLayerTiling* low_res = NULL; 916 917 PictureLayerTiling* previous_low_res = NULL; 918 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 919 PictureLayerTiling* tiling = tilings_->tiling_at(i); 920 if (tiling->contents_scale() == raster_contents_scale_) 921 high_res = tiling; 922 if (tiling->contents_scale() == low_res_raster_contents_scale_) 923 low_res = tiling; 924 if (tiling->resolution() == LOW_RESOLUTION) 925 previous_low_res = tiling; 926 927 // Reset all tilings to non-ideal until the end of this function. 928 tiling->set_resolution(NON_IDEAL_RESOLUTION); 929 } 930 931 if (!high_res) { 932 high_res = AddTiling(raster_contents_scale_); 933 if (raster_contents_scale_ == low_res_raster_contents_scale_) 934 low_res = high_res; 935 } 936 937 // Only create new low res tilings when the transform is static. This 938 // prevents wastefully creating a paired low res tiling for every new high res 939 // tiling during a pinch or a CSS animation. 940 bool is_pinching = layer_tree_impl()->PinchGestureActive(); 941 if (!is_pinching && !animating_transform_to_screen && !low_res && 942 low_res != high_res) 943 low_res = AddTiling(low_res_raster_contents_scale_); 944 945 // Set low-res if we have one. 946 if (!low_res) 947 low_res = previous_low_res; 948 if (low_res && low_res != high_res) 949 low_res->set_resolution(LOW_RESOLUTION); 950 951 // Make sure we always have one high-res (even if high == low). 952 high_res->set_resolution(HIGH_RESOLUTION); 953 954 SanityCheckTilingState(); 955 } 956 957 bool PictureLayerImpl::ShouldAdjustRasterScale( 958 bool animating_transform_to_screen) const { 959 // TODO(danakj): Adjust raster source scale closer to ideal source scale at 960 // a throttled rate. Possibly make use of invalidation_.IsEmpty() on pending 961 // tree. This will allow CSS scale changes to get re-rastered at an 962 // appropriate rate. 963 964 if (raster_source_scale_was_animating_ && !animating_transform_to_screen) 965 return true; 966 967 bool is_pinching = layer_tree_impl()->PinchGestureActive(); 968 if (is_pinching && raster_page_scale_) { 969 // We change our raster scale when it is: 970 // - Higher than ideal (need a lower-res tiling available) 971 // - Too far from ideal (need a higher-res tiling available) 972 float ratio = ideal_page_scale_ / raster_page_scale_; 973 if (raster_page_scale_ > ideal_page_scale_ || 974 ratio > kMaxScaleRatioDuringPinch) 975 return true; 976 } 977 978 if (!is_pinching) { 979 // When not pinching, match the ideal page scale factor. 980 if (raster_page_scale_ != ideal_page_scale_) 981 return true; 982 } 983 984 // Always match the ideal device scale factor. 985 if (raster_device_scale_ != ideal_device_scale_) 986 return true; 987 988 return false; 989 } 990 991 float PictureLayerImpl::SnappedContentsScale(float scale) { 992 // If a tiling exists within the max snapping ratio, snap to its scale. 993 float snapped_contents_scale = scale; 994 float snapped_ratio = kSnapToExistingTilingRatio; 995 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 996 float tiling_contents_scale = tilings_->tiling_at(i)->contents_scale(); 997 float ratio = PositiveRatio(tiling_contents_scale, scale); 998 if (ratio < snapped_ratio) { 999 snapped_contents_scale = tiling_contents_scale; 1000 snapped_ratio = ratio; 1001 } 1002 } 1003 return snapped_contents_scale; 1004 } 1005 1006 void PictureLayerImpl::RecalculateRasterScales( 1007 bool animating_transform_to_screen) { 1008 raster_device_scale_ = ideal_device_scale_; 1009 raster_source_scale_ = ideal_source_scale_; 1010 1011 bool is_pinching = layer_tree_impl()->PinchGestureActive(); 1012 if (!is_pinching || raster_contents_scale_ == 0.f) { 1013 // When not pinching or when we have no previous scale, we use ideal scale: 1014 raster_page_scale_ = ideal_page_scale_; 1015 raster_contents_scale_ = ideal_contents_scale_; 1016 } else { 1017 // See ShouldAdjustRasterScale: 1018 // - When zooming out, preemptively create new tiling at lower resolution. 1019 // - When zooming in, approximate ideal using multiple of kMaxScaleRatio. 1020 bool zooming_out = raster_page_scale_ > ideal_page_scale_; 1021 float desired_contents_scale = 1022 zooming_out ? raster_contents_scale_ / kMaxScaleRatioDuringPinch 1023 : raster_contents_scale_ * kMaxScaleRatioDuringPinch; 1024 raster_contents_scale_ = SnappedContentsScale(desired_contents_scale); 1025 raster_page_scale_ = raster_contents_scale_ / raster_device_scale_; 1026 } 1027 1028 raster_contents_scale_ = 1029 std::max(raster_contents_scale_, MinimumContentsScale()); 1030 1031 // Don't allow animating CSS scales to drop below 1. This is needed because 1032 // changes in raster source scale aren't handled. See the comment in 1033 // ShouldAdjustRasterScale. 1034 if (animating_transform_to_screen) { 1035 raster_contents_scale_ = std::max( 1036 raster_contents_scale_, 1.f * ideal_page_scale_ * ideal_device_scale_); 1037 } 1038 1039 // If this layer would only create one tile at this content scale, 1040 // don't create a low res tiling. 1041 gfx::Size content_bounds = 1042 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), raster_contents_scale_)); 1043 gfx::Size tile_size = CalculateTileSize(content_bounds); 1044 if (tile_size.width() >= content_bounds.width() && 1045 tile_size.height() >= content_bounds.height()) { 1046 low_res_raster_contents_scale_ = raster_contents_scale_; 1047 return; 1048 } 1049 1050 float low_res_factor = 1051 layer_tree_impl()->settings().low_res_contents_scale_factor; 1052 low_res_raster_contents_scale_ = std::max( 1053 raster_contents_scale_ * low_res_factor, 1054 MinimumContentsScale()); 1055 } 1056 1057 void PictureLayerImpl::CleanUpTilingsOnActiveLayer( 1058 std::vector<PictureLayerTiling*> used_tilings) { 1059 DCHECK(layer_tree_impl()->IsActiveTree()); 1060 if (tilings_->num_tilings() == 0) 1061 return; 1062 1063 float min_acceptable_high_res_scale = std::min( 1064 raster_contents_scale_, ideal_contents_scale_); 1065 float max_acceptable_high_res_scale = std::max( 1066 raster_contents_scale_, ideal_contents_scale_); 1067 1068 PictureLayerImpl* twin = twin_layer_; 1069 if (twin) { 1070 min_acceptable_high_res_scale = std::min( 1071 min_acceptable_high_res_scale, 1072 std::min(twin->raster_contents_scale_, twin->ideal_contents_scale_)); 1073 max_acceptable_high_res_scale = std::max( 1074 max_acceptable_high_res_scale, 1075 std::max(twin->raster_contents_scale_, twin->ideal_contents_scale_)); 1076 } 1077 1078 std::vector<PictureLayerTiling*> to_remove; 1079 for (size_t i = 0; i < tilings_->num_tilings(); ++i) { 1080 PictureLayerTiling* tiling = tilings_->tiling_at(i); 1081 1082 // Keep multiple high resolution tilings even if not used to help 1083 // activate earlier at non-ideal resolutions. 1084 if (tiling->contents_scale() >= min_acceptable_high_res_scale && 1085 tiling->contents_scale() <= max_acceptable_high_res_scale) 1086 continue; 1087 1088 // Low resolution can't activate, so only keep one around. 1089 if (tiling->resolution() == LOW_RESOLUTION) 1090 continue; 1091 1092 // Don't remove tilings that are being used (and thus would cause a flash.) 1093 if (std::find(used_tilings.begin(), used_tilings.end(), tiling) != 1094 used_tilings.end()) 1095 continue; 1096 1097 to_remove.push_back(tiling); 1098 } 1099 1100 for (size_t i = 0; i < to_remove.size(); ++i) { 1101 const PictureLayerTiling* twin_tiling = GetTwinTiling(to_remove[i]); 1102 // Only remove tilings from the twin layer if they have 1103 // NON_IDEAL_RESOLUTION. 1104 if (twin_tiling && twin_tiling->resolution() == NON_IDEAL_RESOLUTION) 1105 twin->RemoveTiling(to_remove[i]->contents_scale()); 1106 tilings_->Remove(to_remove[i]); 1107 } 1108 DCHECK_GT(tilings_->num_tilings(), 0u); 1109 1110 SanityCheckTilingState(); 1111 } 1112 1113 float PictureLayerImpl::MinimumContentsScale() const { 1114 float setting_min = layer_tree_impl()->settings().minimum_contents_scale; 1115 1116 // If the contents scale is less than 1 / width (also for height), 1117 // then it will end up having less than one pixel of content in that 1118 // dimension. Bump the minimum contents scale up in this case to prevent 1119 // this from happening. 1120 int min_dimension = std::min(bounds().width(), bounds().height()); 1121 if (!min_dimension) 1122 return setting_min; 1123 1124 return std::max(1.f / min_dimension, setting_min); 1125 } 1126 1127 void PictureLayerImpl::UpdateLCDTextStatus(bool new_status) { 1128 // Once this layer is not using lcd text, don't switch back. 1129 if (!is_using_lcd_text_) 1130 return; 1131 1132 if (is_using_lcd_text_ == new_status) 1133 return; 1134 1135 is_using_lcd_text_ = new_status; 1136 tilings_->SetCanUseLCDText(is_using_lcd_text_); 1137 } 1138 1139 void PictureLayerImpl::ResetRasterScale() { 1140 raster_page_scale_ = 0.f; 1141 raster_device_scale_ = 0.f; 1142 raster_source_scale_ = 0.f; 1143 raster_contents_scale_ = 0.f; 1144 low_res_raster_contents_scale_ = 0.f; 1145 1146 // When raster scales aren't valid, don't update tile priorities until 1147 // this layer has been updated via UpdateDrawProperties. 1148 should_update_tile_priorities_ = false; 1149 } 1150 1151 bool PictureLayerImpl::CanHaveTilings() const { 1152 if (!DrawsContent()) 1153 return false; 1154 if (!pile_->HasRecordings()) 1155 return false; 1156 return true; 1157 } 1158 1159 bool PictureLayerImpl::CanHaveTilingWithScale(float contents_scale) const { 1160 if (!CanHaveTilings()) 1161 return false; 1162 if (contents_scale < MinimumContentsScale()) 1163 return false; 1164 return true; 1165 } 1166 1167 void PictureLayerImpl::SanityCheckTilingState() const { 1168 if (!DCHECK_IS_ON()) 1169 return; 1170 1171 if (!CanHaveTilings()) { 1172 DCHECK_EQ(0u, tilings_->num_tilings()); 1173 return; 1174 } 1175 if (tilings_->num_tilings() == 0) 1176 return; 1177 1178 // MarkVisibleResourcesAsRequired depends on having exactly 1 high res 1179 // tiling to mark its tiles as being required for activation. 1180 DCHECK_EQ(1, tilings_->NumHighResTilings()); 1181 } 1182 1183 void PictureLayerImpl::GetDebugBorderProperties( 1184 SkColor* color, 1185 float* width) const { 1186 *color = DebugColors::TiledContentLayerBorderColor(); 1187 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); 1188 } 1189 1190 void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const { 1191 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded(); 1192 LayerImpl::AsValueInto(state); 1193 state->SetDouble("ideal_contents_scale", ideal_contents_scale_); 1194 state->SetDouble("geometry_contents_scale", contents_scale_x()); 1195 state->Set("tilings", tilings_->AsValue().release()); 1196 state->Set("pictures", pile_->AsValue().release()); 1197 state->Set("invalidation", invalidation_.AsValue().release()); 1198 1199 scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue); 1200 for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(), 1201 contents_scale_x(), 1202 gfx::Rect(content_bounds()), 1203 ideal_contents_scale_); 1204 iter; 1205 ++iter) { 1206 scoped_ptr<base::DictionaryValue> tile_data(new base::DictionaryValue); 1207 tile_data->Set("geometry_rect", 1208 MathUtil::AsValue(iter.geometry_rect()).release()); 1209 if (*iter) 1210 tile_data->Set("tile", TracedValue::CreateIDRef(*iter).release()); 1211 1212 coverage_tiles->Append(tile_data.release()); 1213 } 1214 state->Set("coverage_tiles", coverage_tiles.release()); 1215 state->SetBoolean("is_using_lcd_text", is_using_lcd_text_); 1216 } 1217 1218 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const { 1219 const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded(); 1220 return tilings_->GPUMemoryUsageInBytes(); 1221 } 1222 1223 void PictureLayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) { 1224 benchmark->RunOnLayer(this); 1225 } 1226 1227 } // namespace cc 1228