1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "cc/resources/tile_manager.h" 6 7 #include <algorithm> 8 #include <limits> 9 #include <string> 10 11 #include "base/bind.h" 12 #include "base/debug/trace_event_argument.h" 13 #include "base/json/json_writer.h" 14 #include "base/logging.h" 15 #include "base/metrics/histogram.h" 16 #include "cc/debug/devtools_instrumentation.h" 17 #include "cc/debug/frame_viewer_instrumentation.h" 18 #include "cc/debug/traced_value.h" 19 #include "cc/layers/picture_layer_impl.h" 20 #include "cc/resources/raster_buffer.h" 21 #include "cc/resources/rasterizer.h" 22 #include "cc/resources/tile.h" 23 #include "skia/ext/paint_simplifier.h" 24 #include "third_party/skia/include/core/SkBitmap.h" 25 #include "third_party/skia/include/core/SkPixelRef.h" 26 #include "ui/gfx/rect_conversions.h" 27 28 namespace cc { 29 namespace { 30 31 // Flag to indicate whether we should try and detect that 32 // a tile is of solid color. 33 const bool kUseColorEstimator = true; 34 35 class RasterTaskImpl : public RasterTask { 36 public: 37 RasterTaskImpl( 38 const Resource* resource, 39 PicturePileImpl* picture_pile, 40 const gfx::Rect& content_rect, 41 float contents_scale, 42 RasterMode raster_mode, 43 TileResolution tile_resolution, 44 int layer_id, 45 const void* tile_id, 46 int source_frame_number, 47 bool analyze_picture, 48 RenderingStatsInstrumentation* rendering_stats, 49 const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply, 50 ImageDecodeTask::Vector* dependencies) 51 : RasterTask(resource, dependencies), 52 picture_pile_(picture_pile), 53 content_rect_(content_rect), 54 contents_scale_(contents_scale), 55 raster_mode_(raster_mode), 56 tile_resolution_(tile_resolution), 57 layer_id_(layer_id), 58 tile_id_(tile_id), 59 source_frame_number_(source_frame_number), 60 analyze_picture_(analyze_picture), 61 rendering_stats_(rendering_stats), 62 reply_(reply) {} 63 64 // Overridden from Task: 65 virtual void RunOnWorkerThread() OVERRIDE { 66 TRACE_EVENT0("cc", "RasterizerTaskImpl::RunOnWorkerThread"); 67 68 DCHECK(picture_pile_.get()); 69 DCHECK(raster_buffer_); 70 71 if (analyze_picture_) { 72 Analyze(picture_pile_.get()); 73 if (analysis_.is_solid_color) 74 return; 75 } 76 77 Raster(picture_pile_.get()); 78 } 79 80 // Overridden from RasterizerTask: 81 virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE { 82 DCHECK(!raster_buffer_); 83 raster_buffer_ = client->AcquireBufferForRaster(resource()); 84 } 85 virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE { 86 client->ReleaseBufferForRaster(raster_buffer_.Pass()); 87 } 88 virtual void RunReplyOnOriginThread() OVERRIDE { 89 DCHECK(!raster_buffer_); 90 reply_.Run(analysis_, !HasFinishedRunning()); 91 } 92 93 protected: 94 virtual ~RasterTaskImpl() { DCHECK(!raster_buffer_); } 95 96 private: 97 void Analyze(const PicturePileImpl* picture_pile) { 98 frame_viewer_instrumentation::ScopedAnalyzeTask analyze_task( 99 tile_id_, tile_resolution_, source_frame_number_, layer_id_); 100 101 DCHECK(picture_pile); 102 103 picture_pile->AnalyzeInRect( 104 content_rect_, contents_scale_, &analysis_, rendering_stats_); 105 106 // Record the solid color prediction. 107 UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed", 108 analysis_.is_solid_color); 109 110 // Clear the flag if we're not using the estimator. 111 analysis_.is_solid_color &= kUseColorEstimator; 112 } 113 114 void Raster(const PicturePileImpl* picture_pile) { 115 frame_viewer_instrumentation::ScopedRasterTask raster_task( 116 tile_id_, 117 tile_resolution_, 118 source_frame_number_, 119 layer_id_, 120 raster_mode_); 121 devtools_instrumentation::ScopedLayerTask layer_task( 122 devtools_instrumentation::kRasterTask, layer_id_); 123 124 skia::RefPtr<SkCanvas> canvas = raster_buffer_->AcquireSkCanvas(); 125 DCHECK(canvas); 126 127 skia::RefPtr<SkDrawFilter> draw_filter; 128 switch (raster_mode_) { 129 case LOW_QUALITY_RASTER_MODE: 130 draw_filter = skia::AdoptRef(new skia::PaintSimplifier); 131 break; 132 case HIGH_QUALITY_RASTER_MODE: 133 break; 134 case NUM_RASTER_MODES: 135 default: 136 NOTREACHED(); 137 } 138 canvas->setDrawFilter(draw_filter.get()); 139 140 base::TimeDelta prev_rasterize_time = 141 rendering_stats_->impl_thread_rendering_stats().rasterize_time; 142 143 // Only record rasterization time for highres tiles, because 144 // lowres tiles are not required for activation and therefore 145 // introduce noise in the measurement (sometimes they get rasterized 146 // before we draw and sometimes they aren't) 147 RenderingStatsInstrumentation* stats = 148 tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL; 149 DCHECK(picture_pile); 150 picture_pile->RasterToBitmap( 151 canvas.get(), content_rect_, contents_scale_, stats); 152 153 if (rendering_stats_->record_rendering_stats()) { 154 base::TimeDelta current_rasterize_time = 155 rendering_stats_->impl_thread_rendering_stats().rasterize_time; 156 LOCAL_HISTOGRAM_CUSTOM_COUNTS( 157 "Renderer4.PictureRasterTimeUS", 158 (current_rasterize_time - prev_rasterize_time).InMicroseconds(), 159 0, 160 100000, 161 100); 162 } 163 164 raster_buffer_->ReleaseSkCanvas(canvas); 165 } 166 167 PicturePileImpl::Analysis analysis_; 168 scoped_refptr<PicturePileImpl> picture_pile_; 169 gfx::Rect content_rect_; 170 float contents_scale_; 171 RasterMode raster_mode_; 172 TileResolution tile_resolution_; 173 int layer_id_; 174 const void* tile_id_; 175 int source_frame_number_; 176 bool analyze_picture_; 177 RenderingStatsInstrumentation* rendering_stats_; 178 const base::Callback<void(const PicturePileImpl::Analysis&, bool)> reply_; 179 scoped_ptr<RasterBuffer> raster_buffer_; 180 181 DISALLOW_COPY_AND_ASSIGN(RasterTaskImpl); 182 }; 183 184 class ImageDecodeTaskImpl : public ImageDecodeTask { 185 public: 186 ImageDecodeTaskImpl(SkPixelRef* pixel_ref, 187 int layer_id, 188 RenderingStatsInstrumentation* rendering_stats, 189 const base::Callback<void(bool was_canceled)>& reply) 190 : pixel_ref_(skia::SharePtr(pixel_ref)), 191 layer_id_(layer_id), 192 rendering_stats_(rendering_stats), 193 reply_(reply) {} 194 195 // Overridden from Task: 196 virtual void RunOnWorkerThread() OVERRIDE { 197 TRACE_EVENT0("cc", "ImageDecodeTaskImpl::RunOnWorkerThread"); 198 199 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( 200 pixel_ref_.get()); 201 // This will cause the image referred to by pixel ref to be decoded. 202 pixel_ref_->lockPixels(); 203 pixel_ref_->unlockPixels(); 204 } 205 206 // Overridden from RasterizerTask: 207 virtual void ScheduleOnOriginThread(RasterizerTaskClient* client) OVERRIDE {} 208 virtual void CompleteOnOriginThread(RasterizerTaskClient* client) OVERRIDE {} 209 virtual void RunReplyOnOriginThread() OVERRIDE { 210 reply_.Run(!HasFinishedRunning()); 211 } 212 213 protected: 214 virtual ~ImageDecodeTaskImpl() {} 215 216 private: 217 skia::RefPtr<SkPixelRef> pixel_ref_; 218 int layer_id_; 219 RenderingStatsInstrumentation* rendering_stats_; 220 const base::Callback<void(bool was_canceled)> reply_; 221 222 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); 223 }; 224 225 const size_t kScheduledRasterTasksLimit = 32u; 226 227 // Memory limit policy works by mapping some bin states to the NEVER bin. 228 const ManagedTileBin kBinPolicyMap[NUM_TILE_MEMORY_LIMIT_POLICIES][NUM_BINS] = { 229 // [ALLOW_NOTHING] 230 {NEVER_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 231 NEVER_BIN, // [NOW_BIN] 232 NEVER_BIN, // [SOON_BIN] 233 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 234 NEVER_BIN, // [EVENTUALLY_BIN] 235 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN] 236 NEVER_BIN, // [AT_LAST_BIN] 237 NEVER_BIN // [NEVER_BIN] 238 }, 239 // [ALLOW_ABSOLUTE_MINIMUM] 240 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 241 NOW_BIN, // [NOW_BIN] 242 NEVER_BIN, // [SOON_BIN] 243 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 244 NEVER_BIN, // [EVENTUALLY_BIN] 245 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN] 246 NEVER_BIN, // [AT_LAST_BIN] 247 NEVER_BIN // [NEVER_BIN] 248 }, 249 // [ALLOW_PREPAINT_ONLY] 250 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 251 NOW_BIN, // [NOW_BIN] 252 SOON_BIN, // [SOON_BIN] 253 NEVER_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 254 NEVER_BIN, // [EVENTUALLY_BIN] 255 NEVER_BIN, // [AT_LAST_AND_ACTIVE_BIN] 256 NEVER_BIN, // [AT_LAST_BIN] 257 NEVER_BIN // [NEVER_BIN] 258 }, 259 // [ALLOW_ANYTHING] 260 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 261 NOW_BIN, // [NOW_BIN] 262 SOON_BIN, // [SOON_BIN] 263 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 264 EVENTUALLY_BIN, // [EVENTUALLY_BIN] 265 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] 266 AT_LAST_BIN, // [AT_LAST_BIN] 267 NEVER_BIN // [NEVER_BIN] 268 }}; 269 270 // Ready to draw works by mapping NOW_BIN to NOW_AND_READY_TO_DRAW_BIN. 271 const ManagedTileBin kBinReadyToDrawMap[2][NUM_BINS] = { 272 // Not ready 273 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 274 NOW_BIN, // [NOW_BIN] 275 SOON_BIN, // [SOON_BIN] 276 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 277 EVENTUALLY_BIN, // [EVENTUALLY_BIN] 278 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] 279 AT_LAST_BIN, // [AT_LAST_BIN] 280 NEVER_BIN // [NEVER_BIN] 281 }, 282 // Ready 283 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 284 NOW_AND_READY_TO_DRAW_BIN, // [NOW_BIN] 285 SOON_BIN, // [SOON_BIN] 286 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 287 EVENTUALLY_BIN, // [EVENTUALLY_BIN] 288 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] 289 AT_LAST_BIN, // [AT_LAST_BIN] 290 NEVER_BIN // [NEVER_BIN] 291 }}; 292 293 // Active works by mapping some bin stats to equivalent _ACTIVE_BIN state. 294 const ManagedTileBin kBinIsActiveMap[2][NUM_BINS] = { 295 // Inactive 296 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 297 NOW_BIN, // [NOW_BIN] 298 SOON_BIN, // [SOON_BIN] 299 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 300 EVENTUALLY_BIN, // [EVENTUALLY_BIN] 301 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] 302 AT_LAST_BIN, // [AT_LAST_BIN] 303 NEVER_BIN // [NEVER_BIN] 304 }, 305 // Active 306 {NOW_AND_READY_TO_DRAW_BIN, // [NOW_AND_READY_TO_DRAW_BIN] 307 NOW_BIN, // [NOW_BIN] 308 SOON_BIN, // [SOON_BIN] 309 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_AND_ACTIVE_BIN] 310 EVENTUALLY_AND_ACTIVE_BIN, // [EVENTUALLY_BIN] 311 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_AND_ACTIVE_BIN] 312 AT_LAST_AND_ACTIVE_BIN, // [AT_LAST_BIN] 313 NEVER_BIN // [NEVER_BIN] 314 }}; 315 316 // Determine bin based on three categories of tiles: things we need now, 317 // things we need soon, and eventually. 318 inline ManagedTileBin BinFromTilePriority(const TilePriority& prio) { 319 if (prio.priority_bin == TilePriority::NOW) 320 return NOW_BIN; 321 322 if (prio.priority_bin == TilePriority::SOON) 323 return SOON_BIN; 324 325 if (prio.distance_to_visible == std::numeric_limits<float>::infinity()) 326 return NEVER_BIN; 327 328 return EVENTUALLY_BIN; 329 } 330 331 } // namespace 332 333 RasterTaskCompletionStats::RasterTaskCompletionStats() 334 : completed_count(0u), canceled_count(0u) {} 335 336 scoped_refptr<base::debug::ConvertableToTraceFormat> 337 RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) { 338 scoped_refptr<base::debug::TracedValue> state = 339 new base::debug::TracedValue(); 340 state->SetInteger("completed_count", stats.completed_count); 341 state->SetInteger("canceled_count", stats.canceled_count); 342 return state; 343 } 344 345 // static 346 scoped_ptr<TileManager> TileManager::Create( 347 TileManagerClient* client, 348 base::SequencedTaskRunner* task_runner, 349 ResourcePool* resource_pool, 350 Rasterizer* rasterizer, 351 RenderingStatsInstrumentation* rendering_stats_instrumentation) { 352 return make_scoped_ptr(new TileManager(client, 353 task_runner, 354 resource_pool, 355 rasterizer, 356 rendering_stats_instrumentation)); 357 } 358 359 TileManager::TileManager( 360 TileManagerClient* client, 361 const scoped_refptr<base::SequencedTaskRunner>& task_runner, 362 ResourcePool* resource_pool, 363 Rasterizer* rasterizer, 364 RenderingStatsInstrumentation* rendering_stats_instrumentation) 365 : client_(client), 366 task_runner_(task_runner), 367 resource_pool_(resource_pool), 368 rasterizer_(rasterizer), 369 prioritized_tiles_dirty_(false), 370 all_tiles_that_need_to_be_rasterized_have_memory_(true), 371 all_tiles_required_for_activation_have_memory_(true), 372 bytes_releasable_(0), 373 resources_releasable_(0), 374 ever_exceeded_memory_budget_(false), 375 rendering_stats_instrumentation_(rendering_stats_instrumentation), 376 did_initialize_visible_tile_(false), 377 did_check_for_completed_tasks_since_last_schedule_tasks_(true), 378 did_oom_on_last_assign_(false), 379 ready_to_activate_check_notifier_( 380 task_runner_.get(), 381 base::Bind(&TileManager::CheckIfReadyToActivate, 382 base::Unretained(this))) { 383 rasterizer_->SetClient(this); 384 } 385 386 TileManager::~TileManager() { 387 // Reset global state and manage. This should cause 388 // our memory usage to drop to zero. 389 global_state_ = GlobalStateThatImpactsTilePriority(); 390 391 RasterTaskQueue empty; 392 rasterizer_->ScheduleTasks(&empty); 393 orphan_raster_tasks_.clear(); 394 395 // This should finish all pending tasks and release any uninitialized 396 // resources. 397 rasterizer_->Shutdown(); 398 rasterizer_->CheckForCompletedTasks(); 399 400 prioritized_tiles_.Clear(); 401 402 FreeResourcesForReleasedTiles(); 403 CleanUpReleasedTiles(); 404 405 DCHECK_EQ(0u, bytes_releasable_); 406 DCHECK_EQ(0u, resources_releasable_); 407 } 408 409 void TileManager::Release(Tile* tile) { 410 DCHECK(TilePriority() == tile->combined_priority()); 411 412 prioritized_tiles_dirty_ = true; 413 released_tiles_.push_back(tile); 414 } 415 416 void TileManager::DidChangeTilePriority(Tile* tile) { 417 prioritized_tiles_dirty_ = true; 418 } 419 420 TaskSetCollection TileManager::TasksThatShouldBeForcedToComplete() const { 421 TaskSetCollection tasks_that_should_be_forced_to_complete; 422 if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY) 423 tasks_that_should_be_forced_to_complete[REQUIRED_FOR_ACTIVATION] = true; 424 return tasks_that_should_be_forced_to_complete; 425 } 426 427 void TileManager::FreeResourcesForReleasedTiles() { 428 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); 429 it != released_tiles_.end(); 430 ++it) { 431 Tile* tile = *it; 432 FreeResourcesForTile(tile); 433 } 434 } 435 436 void TileManager::CleanUpReleasedTiles() { 437 // Make sure |prioritized_tiles_| doesn't contain any of the tiles 438 // we're about to delete. 439 DCHECK(prioritized_tiles_.IsEmpty()); 440 441 std::vector<Tile*>::iterator it = released_tiles_.begin(); 442 while (it != released_tiles_.end()) { 443 Tile* tile = *it; 444 445 if (tile->HasRasterTask()) { 446 ++it; 447 continue; 448 } 449 450 DCHECK(!tile->HasResources()); 451 DCHECK(tiles_.find(tile->id()) != tiles_.end()); 452 tiles_.erase(tile->id()); 453 454 LayerCountMap::iterator layer_it = 455 used_layer_counts_.find(tile->layer_id()); 456 DCHECK_GT(layer_it->second, 0); 457 if (--layer_it->second == 0) { 458 used_layer_counts_.erase(layer_it); 459 image_decode_tasks_.erase(tile->layer_id()); 460 } 461 462 delete tile; 463 it = released_tiles_.erase(it); 464 } 465 } 466 467 void TileManager::UpdatePrioritizedTileSetIfNeeded() { 468 if (!prioritized_tiles_dirty_) 469 return; 470 471 prioritized_tiles_.Clear(); 472 473 FreeResourcesForReleasedTiles(); 474 CleanUpReleasedTiles(); 475 476 GetTilesWithAssignedBins(&prioritized_tiles_); 477 prioritized_tiles_dirty_ = false; 478 } 479 480 void TileManager::DidFinishRunningTasks(TaskSet task_set) { 481 if (task_set == ALL) { 482 TRACE_EVENT1("cc", "TileManager::DidFinishRunningTasks", "task_set", "ALL"); 483 484 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > 485 global_state_.soft_memory_limit_in_bytes; 486 487 // When OOM, keep re-assigning memory until we reach a steady state 488 // where top-priority tiles are initialized. 489 if (all_tiles_that_need_to_be_rasterized_have_memory_ && 490 !memory_usage_above_limit) 491 return; 492 493 rasterizer_->CheckForCompletedTasks(); 494 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 495 496 TileVector tiles_that_need_to_be_rasterized; 497 AssignGpuMemoryToTiles(&prioritized_tiles_, 498 &tiles_that_need_to_be_rasterized); 499 500 // |tiles_that_need_to_be_rasterized| will be empty when we reach a 501 // steady memory state. Keep scheduling tasks until we reach this state. 502 if (!tiles_that_need_to_be_rasterized.empty()) { 503 ScheduleTasks(tiles_that_need_to_be_rasterized); 504 return; 505 } 506 507 FreeResourcesForReleasedTiles(); 508 509 resource_pool_->ReduceResourceUsage(); 510 511 // We don't reserve memory for required-for-activation tiles during 512 // accelerated gestures, so we just postpone activation when we don't 513 // have these tiles, and activate after the accelerated gesture. 514 // Likewise if we don't allow any tiles (as is the case when we're 515 // invisible), if we have tiles that aren't ready, then we shouldn't 516 // activate as activation can cause checkerboards. 517 bool allow_rasterize_on_demand = 518 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY && 519 global_state_.memory_limit_policy != ALLOW_NOTHING; 520 521 // Use on-demand raster for any required-for-activation tiles that have not 522 // been been assigned memory after reaching a steady memory state. This 523 // ensures that we activate even when OOM. 524 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 525 Tile* tile = it->second; 526 ManagedTileState& mts = tile->managed_state(); 527 ManagedTileState::TileVersion& tile_version = 528 mts.tile_versions[mts.raster_mode]; 529 530 if (tile->required_for_activation() && !tile_version.IsReadyToDraw()) { 531 // If we can't raster on demand, give up early (and don't activate). 532 if (!allow_rasterize_on_demand) 533 return; 534 535 tile_version.set_rasterize_on_demand(); 536 client_->NotifyTileStateChanged(tile); 537 } 538 } 539 540 DCHECK(IsReadyToActivate()); 541 ready_to_activate_check_notifier_.Schedule(); 542 return; 543 } 544 545 if (task_set == REQUIRED_FOR_ACTIVATION) { 546 TRACE_EVENT2("cc", 547 "TileManager::DidFinishRunningTasks", 548 "task_set", 549 "REQUIRED_FOR_ACTIVATION", 550 "all_tiles_required_for_activation_have_memory", 551 all_tiles_required_for_activation_have_memory_); 552 // This is only a true indication that all tiles required for 553 // activation are initialized when no tiles are OOM. We need to 554 // wait for DidFinishRunningTasks() to be called, try to re-assign 555 // memory and in worst case use on-demand raster when tiles 556 // required for activation are OOM. 557 if (!all_tiles_required_for_activation_have_memory_) 558 return; 559 560 ready_to_activate_check_notifier_.Schedule(); 561 } 562 } 563 564 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) { 565 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins"); 566 567 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy; 568 const TreePriority tree_priority = global_state_.tree_priority; 569 570 // For each tree, bin into different categories of tiles. 571 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { 572 Tile* tile = it->second; 573 ManagedTileState& mts = tile->managed_state(); 574 575 const ManagedTileState::TileVersion& tile_version = 576 tile->GetTileVersionForDrawing(); 577 bool tile_is_ready_to_draw = tile_version.IsReadyToDraw(); 578 bool tile_is_active = tile_is_ready_to_draw || 579 mts.tile_versions[mts.raster_mode].raster_task_.get(); 580 581 // Get the active priority and bin. 582 TilePriority active_priority = tile->priority(ACTIVE_TREE); 583 ManagedTileBin active_bin = BinFromTilePriority(active_priority); 584 585 // Get the pending priority and bin. 586 TilePriority pending_priority = tile->priority(PENDING_TREE); 587 ManagedTileBin pending_bin = BinFromTilePriority(pending_priority); 588 589 bool pending_is_low_res = pending_priority.resolution == LOW_RESOLUTION; 590 bool pending_is_non_ideal = 591 pending_priority.resolution == NON_IDEAL_RESOLUTION; 592 bool active_is_non_ideal = 593 active_priority.resolution == NON_IDEAL_RESOLUTION; 594 595 // Adjust bin state based on if ready to draw. 596 active_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][active_bin]; 597 pending_bin = kBinReadyToDrawMap[tile_is_ready_to_draw][pending_bin]; 598 599 // Adjust bin state based on if active. 600 active_bin = kBinIsActiveMap[tile_is_active][active_bin]; 601 pending_bin = kBinIsActiveMap[tile_is_active][pending_bin]; 602 603 // We never want to paint new non-ideal tiles, as we always have 604 // a high-res tile covering that content (paint that instead). 605 if (!tile_is_ready_to_draw && active_is_non_ideal) 606 active_bin = NEVER_BIN; 607 if (!tile_is_ready_to_draw && pending_is_non_ideal) 608 pending_bin = NEVER_BIN; 609 610 ManagedTileBin tree_bin[NUM_TREES]; 611 tree_bin[ACTIVE_TREE] = kBinPolicyMap[memory_policy][active_bin]; 612 tree_bin[PENDING_TREE] = kBinPolicyMap[memory_policy][pending_bin]; 613 614 // Adjust pending bin state for low res tiles. This prevents pending tree 615 // low-res tiles from being initialized before high-res tiles. 616 if (pending_is_low_res) 617 tree_bin[PENDING_TREE] = std::max(tree_bin[PENDING_TREE], EVENTUALLY_BIN); 618 619 TilePriority tile_priority; 620 switch (tree_priority) { 621 case SAME_PRIORITY_FOR_BOTH_TREES: 622 mts.bin = std::min(tree_bin[ACTIVE_TREE], tree_bin[PENDING_TREE]); 623 tile_priority = tile->combined_priority(); 624 break; 625 case SMOOTHNESS_TAKES_PRIORITY: 626 mts.bin = tree_bin[ACTIVE_TREE]; 627 tile_priority = active_priority; 628 break; 629 case NEW_CONTENT_TAKES_PRIORITY: 630 mts.bin = tree_bin[PENDING_TREE]; 631 tile_priority = pending_priority; 632 break; 633 default: 634 NOTREACHED(); 635 } 636 637 // Bump up the priority if we determined it's NEVER_BIN on one tree, 638 // but is still required on the other tree. 639 bool is_in_never_bin_on_both_trees = tree_bin[ACTIVE_TREE] == NEVER_BIN && 640 tree_bin[PENDING_TREE] == NEVER_BIN; 641 642 if (mts.bin == NEVER_BIN && !is_in_never_bin_on_both_trees) 643 mts.bin = tile_is_active ? AT_LAST_AND_ACTIVE_BIN : AT_LAST_BIN; 644 645 mts.resolution = tile_priority.resolution; 646 mts.priority_bin = tile_priority.priority_bin; 647 mts.distance_to_visible = tile_priority.distance_to_visible; 648 mts.required_for_activation = tile_priority.required_for_activation; 649 650 mts.visible_and_ready_to_draw = 651 tree_bin[ACTIVE_TREE] == NOW_AND_READY_TO_DRAW_BIN; 652 653 // Tiles that are required for activation shouldn't be in NEVER_BIN unless 654 // smoothness takes priority or memory policy allows nothing to be 655 // initialized. 656 DCHECK(!mts.required_for_activation || mts.bin != NEVER_BIN || 657 tree_priority == SMOOTHNESS_TAKES_PRIORITY || 658 memory_policy == ALLOW_NOTHING); 659 660 // If the tile is in NEVER_BIN and it does not have an active task, then we 661 // can release the resources early. If it does have the task however, we 662 // should keep it in the prioritized tile set to ensure that AssignGpuMemory 663 // can visit it. 664 if (mts.bin == NEVER_BIN && 665 !mts.tile_versions[mts.raster_mode].raster_task_.get()) { 666 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); 667 continue; 668 } 669 670 // Insert the tile into a priority set. 671 tiles->InsertTile(tile, mts.bin); 672 } 673 } 674 675 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { 676 TRACE_EVENT0("cc", "TileManager::ManageTiles"); 677 678 // Update internal state. 679 if (state != global_state_) { 680 global_state_ = state; 681 prioritized_tiles_dirty_ = true; 682 } 683 684 // We need to call CheckForCompletedTasks() once in-between each call 685 // to ScheduleTasks() to prevent canceled tasks from being scheduled. 686 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { 687 rasterizer_->CheckForCompletedTasks(); 688 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 689 } 690 691 UpdatePrioritizedTileSetIfNeeded(); 692 693 TileVector tiles_that_need_to_be_rasterized; 694 AssignGpuMemoryToTiles(&prioritized_tiles_, 695 &tiles_that_need_to_be_rasterized); 696 697 // Finally, schedule rasterizer tasks. 698 ScheduleTasks(tiles_that_need_to_be_rasterized); 699 700 TRACE_EVENT_INSTANT1("cc", 701 "DidManage", 702 TRACE_EVENT_SCOPE_THREAD, 703 "state", 704 BasicStateAsValue()); 705 706 TRACE_COUNTER_ID1("cc", 707 "unused_memory_bytes", 708 this, 709 resource_pool_->total_memory_usage_bytes() - 710 resource_pool_->acquired_memory_usage_bytes()); 711 } 712 713 bool TileManager::UpdateVisibleTiles() { 714 TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles"); 715 716 rasterizer_->CheckForCompletedTasks(); 717 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 718 719 TRACE_EVENT_INSTANT1( 720 "cc", 721 "DidUpdateVisibleTiles", 722 TRACE_EVENT_SCOPE_THREAD, 723 "stats", 724 RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_)); 725 update_visible_tiles_stats_ = RasterTaskCompletionStats(); 726 727 bool did_initialize_visible_tile = did_initialize_visible_tile_; 728 did_initialize_visible_tile_ = false; 729 return did_initialize_visible_tile; 730 } 731 732 scoped_refptr<base::debug::ConvertableToTraceFormat> 733 TileManager::BasicStateAsValue() const { 734 scoped_refptr<base::debug::TracedValue> value = 735 new base::debug::TracedValue(); 736 BasicStateAsValueInto(value.get()); 737 return value; 738 } 739 740 void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const { 741 state->SetInteger("tile_count", tiles_.size()); 742 state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_); 743 state->BeginDictionary("global_state"); 744 global_state_.AsValueInto(state); 745 state->EndDictionary(); 746 } 747 748 void TileManager::AssignGpuMemoryToTiles( 749 PrioritizedTileSet* tiles, 750 TileVector* tiles_that_need_to_be_rasterized) { 751 TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); 752 753 // Maintain the list of released resources that can potentially be re-used 754 // or deleted. 755 // If this operation becomes expensive too, only do this after some 756 // resource(s) was returned. Note that in that case, one also need to 757 // invalidate when releasing some resource from the pool. 758 resource_pool_->CheckBusyResources(); 759 760 // Now give memory out to the tiles until we're out, and build 761 // the needs-to-be-rasterized queue. 762 all_tiles_that_need_to_be_rasterized_have_memory_ = true; 763 all_tiles_required_for_activation_have_memory_ = true; 764 765 // Cast to prevent overflow. 766 int64 soft_bytes_available = 767 static_cast<int64>(bytes_releasable_) + 768 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - 769 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); 770 int64 hard_bytes_available = 771 static_cast<int64>(bytes_releasable_) + 772 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) - 773 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); 774 int resources_available = resources_releasable_ + 775 global_state_.num_resources_limit - 776 resource_pool_->acquired_resource_count(); 777 size_t soft_bytes_allocatable = 778 std::max(static_cast<int64>(0), soft_bytes_available); 779 size_t hard_bytes_allocatable = 780 std::max(static_cast<int64>(0), hard_bytes_available); 781 size_t resources_allocatable = std::max(0, resources_available); 782 783 size_t bytes_that_exceeded_memory_budget = 0; 784 size_t soft_bytes_left = soft_bytes_allocatable; 785 size_t hard_bytes_left = hard_bytes_allocatable; 786 787 size_t resources_left = resources_allocatable; 788 bool oomed_soft = false; 789 bool oomed_hard = false; 790 bool have_hit_soft_memory = false; // Soft memory comes after hard. 791 792 unsigned schedule_priority = 1u; 793 for (PrioritizedTileSet::Iterator it(tiles, true); it; ++it) { 794 Tile* tile = *it; 795 ManagedTileState& mts = tile->managed_state(); 796 797 mts.scheduled_priority = schedule_priority++; 798 799 mts.raster_mode = tile->DetermineOverallRasterMode(); 800 801 ManagedTileState::TileVersion& tile_version = 802 mts.tile_versions[mts.raster_mode]; 803 804 // If this tile doesn't need a resource, then nothing to do. 805 if (!tile_version.requires_resource()) 806 continue; 807 808 // If the tile is not needed, free it up. 809 if (mts.bin == NEVER_BIN) { 810 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); 811 continue; 812 } 813 814 const bool tile_uses_hard_limit = mts.bin <= NOW_BIN; 815 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); 816 const size_t tile_bytes_left = 817 (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left; 818 819 // Hard-limit is reserved for tiles that would cause a calamity 820 // if they were to go away, so by definition they are the highest 821 // priority memory, and must be at the front of the list. 822 DCHECK(!(have_hit_soft_memory && tile_uses_hard_limit)); 823 have_hit_soft_memory |= !tile_uses_hard_limit; 824 825 size_t tile_bytes = 0; 826 size_t tile_resources = 0; 827 828 // It costs to maintain a resource. 829 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 830 if (mts.tile_versions[mode].resource_) { 831 tile_bytes += bytes_if_allocated; 832 tile_resources++; 833 } 834 } 835 836 // Allow lower priority tiles with initialized resources to keep 837 // their memory by only assigning memory to new raster tasks if 838 // they can be scheduled. 839 bool reached_scheduled_raster_tasks_limit = 840 tiles_that_need_to_be_rasterized->size() >= kScheduledRasterTasksLimit; 841 if (!reached_scheduled_raster_tasks_limit) { 842 // If we don't have the required version, and it's not in flight 843 // then we'll have to pay to create a new task. 844 if (!tile_version.resource_ && !tile_version.raster_task_.get()) { 845 tile_bytes += bytes_if_allocated; 846 tile_resources++; 847 } 848 } 849 850 // Tile is OOM. 851 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) { 852 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); 853 854 // This tile was already on screen and now its resources have been 855 // released. In order to prevent checkerboarding, set this tile as 856 // rasterize on demand immediately. 857 if (mts.visible_and_ready_to_draw) 858 tile_version.set_rasterize_on_demand(); 859 860 oomed_soft = true; 861 if (tile_uses_hard_limit) { 862 oomed_hard = true; 863 bytes_that_exceeded_memory_budget += tile_bytes; 864 } 865 } else { 866 resources_left -= tile_resources; 867 hard_bytes_left -= tile_bytes; 868 soft_bytes_left = 869 (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0; 870 if (tile_version.resource_) 871 continue; 872 } 873 874 DCHECK(!tile_version.resource_); 875 876 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| 877 // has reached it's limit or we've failed to assign gpu memory to this 878 // or any higher priority tile. Preventing tiles that fit into memory 879 // budget to be rasterized when higher priority tile is oom is 880 // important for two reasons: 881 // 1. Tile size should not impact raster priority. 882 // 2. Tiles with existing raster task could otherwise incorrectly 883 // be added as they are not affected by |bytes_allocatable|. 884 bool can_schedule_tile = 885 !oomed_soft && !reached_scheduled_raster_tasks_limit; 886 887 if (!can_schedule_tile) { 888 all_tiles_that_need_to_be_rasterized_have_memory_ = false; 889 if (tile->required_for_activation()) 890 all_tiles_required_for_activation_have_memory_ = false; 891 it.DisablePriorityOrdering(); 892 continue; 893 } 894 895 tiles_that_need_to_be_rasterized->push_back(tile); 896 } 897 898 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. 899 ever_exceeded_memory_budget_ |= oomed_hard; 900 if (ever_exceeded_memory_budget_) { 901 TRACE_COUNTER_ID2("cc", 902 "over_memory_budget", 903 this, 904 "budget", 905 global_state_.hard_memory_limit_in_bytes, 906 "over", 907 bytes_that_exceeded_memory_budget); 908 } 909 did_oom_on_last_assign_ = oomed_hard; 910 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", oomed_hard); 911 memory_stats_from_last_assign_.total_budget_in_bytes = 912 global_state_.hard_memory_limit_in_bytes; 913 memory_stats_from_last_assign_.bytes_allocated = 914 hard_bytes_allocatable - hard_bytes_left; 915 memory_stats_from_last_assign_.bytes_unreleasable = 916 resource_pool_->acquired_memory_usage_bytes() - bytes_releasable_; 917 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; 918 } 919 920 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { 921 ManagedTileState& mts = tile->managed_state(); 922 if (mts.tile_versions[mode].resource_) { 923 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); 924 925 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); 926 DCHECK_GE(resources_releasable_, 1u); 927 928 bytes_releasable_ -= BytesConsumedIfAllocated(tile); 929 --resources_releasable_; 930 } 931 } 932 933 void TileManager::FreeResourcesForTile(Tile* tile) { 934 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 935 FreeResourceForTile(tile, static_cast<RasterMode>(mode)); 936 } 937 } 938 939 void TileManager::FreeUnusedResourcesForTile(Tile* tile) { 940 DCHECK(tile->IsReadyToDraw()); 941 ManagedTileState& mts = tile->managed_state(); 942 RasterMode used_mode = LOW_QUALITY_RASTER_MODE; 943 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 944 if (mts.tile_versions[mode].IsReadyToDraw()) { 945 used_mode = static_cast<RasterMode>(mode); 946 break; 947 } 948 } 949 950 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { 951 if (mode != used_mode) 952 FreeResourceForTile(tile, static_cast<RasterMode>(mode)); 953 } 954 } 955 956 void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw( 957 Tile* tile) { 958 bool was_ready_to_draw = tile->IsReadyToDraw(); 959 FreeResourcesForTile(tile); 960 if (was_ready_to_draw) 961 client_->NotifyTileStateChanged(tile); 962 } 963 964 void TileManager::ScheduleTasks( 965 const TileVector& tiles_that_need_to_be_rasterized) { 966 TRACE_EVENT1("cc", 967 "TileManager::ScheduleTasks", 968 "count", 969 tiles_that_need_to_be_rasterized.size()); 970 971 DCHECK(did_check_for_completed_tasks_since_last_schedule_tasks_); 972 973 raster_queue_.Reset(); 974 975 // Build a new task queue containing all task currently needed. Tasks 976 // are added in order of priority, highest priority task first. 977 for (TileVector::const_iterator it = tiles_that_need_to_be_rasterized.begin(); 978 it != tiles_that_need_to_be_rasterized.end(); 979 ++it) { 980 Tile* tile = *it; 981 ManagedTileState& mts = tile->managed_state(); 982 ManagedTileState::TileVersion& tile_version = 983 mts.tile_versions[mts.raster_mode]; 984 985 DCHECK(tile_version.requires_resource()); 986 DCHECK(!tile_version.resource_); 987 988 if (!tile_version.raster_task_.get()) 989 tile_version.raster_task_ = CreateRasterTask(tile); 990 991 TaskSetCollection task_sets; 992 if (tile->required_for_activation()) 993 task_sets.set(REQUIRED_FOR_ACTIVATION); 994 task_sets.set(ALL); 995 raster_queue_.items.push_back( 996 RasterTaskQueue::Item(tile_version.raster_task_.get(), task_sets)); 997 } 998 999 // We must reduce the amount of unused resoruces before calling 1000 // ScheduleTasks to prevent usage from rising above limits. 1001 resource_pool_->ReduceResourceUsage(); 1002 1003 // Schedule running of |raster_tasks_|. This replaces any previously 1004 // scheduled tasks and effectively cancels all tasks not present 1005 // in |raster_tasks_|. 1006 rasterizer_->ScheduleTasks(&raster_queue_); 1007 1008 // It's now safe to clean up orphan tasks as raster worker pool is not 1009 // allowed to keep around unreferenced raster tasks after ScheduleTasks() has 1010 // been called. 1011 orphan_raster_tasks_.clear(); 1012 1013 did_check_for_completed_tasks_since_last_schedule_tasks_ = false; 1014 } 1015 1016 scoped_refptr<ImageDecodeTask> TileManager::CreateImageDecodeTask( 1017 Tile* tile, 1018 SkPixelRef* pixel_ref) { 1019 return make_scoped_refptr(new ImageDecodeTaskImpl( 1020 pixel_ref, 1021 tile->layer_id(), 1022 rendering_stats_instrumentation_, 1023 base::Bind(&TileManager::OnImageDecodeTaskCompleted, 1024 base::Unretained(this), 1025 tile->layer_id(), 1026 base::Unretained(pixel_ref)))); 1027 } 1028 1029 scoped_refptr<RasterTask> TileManager::CreateRasterTask(Tile* tile) { 1030 ManagedTileState& mts = tile->managed_state(); 1031 1032 scoped_ptr<ScopedResource> resource = 1033 resource_pool_->AcquireResource(tile->size()); 1034 const ScopedResource* const_resource = resource.get(); 1035 1036 // Create and queue all image decode tasks that this tile depends on. 1037 ImageDecodeTask::Vector decode_tasks; 1038 PixelRefTaskMap& existing_pixel_refs = image_decode_tasks_[tile->layer_id()]; 1039 for (PicturePileImpl::PixelRefIterator iter( 1040 tile->content_rect(), tile->contents_scale(), tile->picture_pile()); 1041 iter; 1042 ++iter) { 1043 SkPixelRef* pixel_ref = *iter; 1044 uint32_t id = pixel_ref->getGenerationID(); 1045 1046 // Append existing image decode task if available. 1047 PixelRefTaskMap::iterator decode_task_it = existing_pixel_refs.find(id); 1048 if (decode_task_it != existing_pixel_refs.end()) { 1049 decode_tasks.push_back(decode_task_it->second); 1050 continue; 1051 } 1052 1053 // Create and append new image decode task for this pixel ref. 1054 scoped_refptr<ImageDecodeTask> decode_task = 1055 CreateImageDecodeTask(tile, pixel_ref); 1056 decode_tasks.push_back(decode_task); 1057 existing_pixel_refs[id] = decode_task; 1058 } 1059 1060 return make_scoped_refptr( 1061 new RasterTaskImpl(const_resource, 1062 tile->picture_pile(), 1063 tile->content_rect(), 1064 tile->contents_scale(), 1065 mts.raster_mode, 1066 mts.resolution, 1067 tile->layer_id(), 1068 static_cast<const void*>(tile), 1069 tile->source_frame_number(), 1070 tile->use_picture_analysis(), 1071 rendering_stats_instrumentation_, 1072 base::Bind(&TileManager::OnRasterTaskCompleted, 1073 base::Unretained(this), 1074 tile->id(), 1075 base::Passed(&resource), 1076 mts.raster_mode), 1077 &decode_tasks)); 1078 } 1079 1080 void TileManager::OnImageDecodeTaskCompleted(int layer_id, 1081 SkPixelRef* pixel_ref, 1082 bool was_canceled) { 1083 // If the task was canceled, we need to clean it up 1084 // from |image_decode_tasks_|. 1085 if (!was_canceled) 1086 return; 1087 1088 LayerPixelRefTaskMap::iterator layer_it = image_decode_tasks_.find(layer_id); 1089 if (layer_it == image_decode_tasks_.end()) 1090 return; 1091 1092 PixelRefTaskMap& pixel_ref_tasks = layer_it->second; 1093 PixelRefTaskMap::iterator task_it = 1094 pixel_ref_tasks.find(pixel_ref->getGenerationID()); 1095 1096 if (task_it != pixel_ref_tasks.end()) 1097 pixel_ref_tasks.erase(task_it); 1098 } 1099 1100 void TileManager::OnRasterTaskCompleted( 1101 Tile::Id tile_id, 1102 scoped_ptr<ScopedResource> resource, 1103 RasterMode raster_mode, 1104 const PicturePileImpl::Analysis& analysis, 1105 bool was_canceled) { 1106 DCHECK(tiles_.find(tile_id) != tiles_.end()); 1107 1108 Tile* tile = tiles_[tile_id]; 1109 ManagedTileState& mts = tile->managed_state(); 1110 ManagedTileState::TileVersion& tile_version = mts.tile_versions[raster_mode]; 1111 DCHECK(tile_version.raster_task_.get()); 1112 orphan_raster_tasks_.push_back(tile_version.raster_task_); 1113 tile_version.raster_task_ = NULL; 1114 1115 if (was_canceled) { 1116 ++update_visible_tiles_stats_.canceled_count; 1117 resource_pool_->ReleaseResource(resource.Pass()); 1118 return; 1119 } 1120 1121 ++update_visible_tiles_stats_.completed_count; 1122 1123 if (analysis.is_solid_color) { 1124 tile_version.set_solid_color(analysis.solid_color); 1125 resource_pool_->ReleaseResource(resource.Pass()); 1126 } else { 1127 tile_version.set_use_resource(); 1128 tile_version.resource_ = resource.Pass(); 1129 1130 bytes_releasable_ += BytesConsumedIfAllocated(tile); 1131 ++resources_releasable_; 1132 } 1133 1134 FreeUnusedResourcesForTile(tile); 1135 if (tile->priority(ACTIVE_TREE).distance_to_visible == 0.f) 1136 did_initialize_visible_tile_ = true; 1137 1138 client_->NotifyTileStateChanged(tile); 1139 } 1140 1141 scoped_refptr<Tile> TileManager::CreateTile(PicturePileImpl* picture_pile, 1142 const gfx::Size& tile_size, 1143 const gfx::Rect& content_rect, 1144 float contents_scale, 1145 int layer_id, 1146 int source_frame_number, 1147 int flags) { 1148 scoped_refptr<Tile> tile = make_scoped_refptr(new Tile(this, 1149 picture_pile, 1150 tile_size, 1151 content_rect, 1152 contents_scale, 1153 layer_id, 1154 source_frame_number, 1155 flags)); 1156 DCHECK(tiles_.find(tile->id()) == tiles_.end()); 1157 1158 tiles_[tile->id()] = tile.get(); 1159 used_layer_counts_[tile->layer_id()]++; 1160 prioritized_tiles_dirty_ = true; 1161 return tile; 1162 } 1163 1164 void TileManager::SetRasterizerForTesting(Rasterizer* rasterizer) { 1165 rasterizer_ = rasterizer; 1166 rasterizer_->SetClient(this); 1167 } 1168 1169 bool TileManager::IsReadyToActivate() const { 1170 const std::vector<PictureLayerImpl*>& layers = client_->GetPictureLayers(); 1171 1172 for (std::vector<PictureLayerImpl*>::const_iterator it = layers.begin(); 1173 it != layers.end(); 1174 ++it) { 1175 if (!(*it)->AllTilesRequiredForActivationAreReadyToDraw()) 1176 return false; 1177 } 1178 1179 return true; 1180 } 1181 1182 void TileManager::CheckIfReadyToActivate() { 1183 TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); 1184 1185 rasterizer_->CheckForCompletedTasks(); 1186 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; 1187 1188 if (IsReadyToActivate()) 1189 client_->NotifyReadyToActivate(); 1190 } 1191 1192 } // namespace cc 1193