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