OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/resources/tile_manager.h" | 5 #include "cc/resources/tile_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/debug/trace_event_argument.h" | 12 #include "base/debug/trace_event_argument.h" |
| 13 #include "base/debug/trace_event_synthetic_delay.h" |
13 #include "base/json/json_writer.h" | 14 #include "base/json/json_writer.h" |
| 15 #include "base/lazy_instance.h" |
14 #include "base/logging.h" | 16 #include "base/logging.h" |
15 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
16 #include "cc/debug/devtools_instrumentation.h" | 18 #include "cc/debug/devtools_instrumentation.h" |
17 #include "cc/debug/frame_viewer_instrumentation.h" | 19 #include "cc/debug/frame_viewer_instrumentation.h" |
18 #include "cc/debug/traced_value.h" | 20 #include "cc/debug/traced_value.h" |
19 #include "cc/layers/picture_layer_impl.h" | 21 #include "cc/layers/picture_layer_impl.h" |
20 #include "cc/resources/rasterizer.h" | 22 #include "cc/resources/rasterizer.h" |
21 #include "cc/resources/tile.h" | 23 #include "cc/resources/tile.h" |
22 #include "skia/ext/paint_simplifier.h" | 24 #include "skia/ext/paint_simplifier.h" |
23 #include "third_party/skia/include/core/SkBitmap.h" | 25 #include "third_party/skia/include/core/SkBitmap.h" |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 all_tiles_required_for_activation_have_memory_(true), | 377 all_tiles_required_for_activation_have_memory_(true), |
376 bytes_releasable_(0), | 378 bytes_releasable_(0), |
377 resources_releasable_(0), | 379 resources_releasable_(0), |
378 ever_exceeded_memory_budget_(false), | 380 ever_exceeded_memory_budget_(false), |
379 rendering_stats_instrumentation_(rendering_stats_instrumentation), | 381 rendering_stats_instrumentation_(rendering_stats_instrumentation), |
380 did_initialize_visible_tile_(false), | 382 did_initialize_visible_tile_(false), |
381 did_check_for_completed_tasks_since_last_schedule_tasks_(true), | 383 did_check_for_completed_tasks_since_last_schedule_tasks_(true), |
382 ready_to_activate_check_notifier_( | 384 ready_to_activate_check_notifier_( |
383 task_runner_.get(), | 385 task_runner_.get(), |
384 base::Bind(&TileManager::CheckIfReadyToActivate, | 386 base::Bind(&TileManager::CheckIfReadyToActivate, |
385 base::Unretained(this))) { | 387 base::Unretained(this))), |
| 388 raster_required_for_activation_synthetic_delay_( |
| 389 base::debug::TraceEventSyntheticDelay::Lookup( |
| 390 "cc.RasterRequiredForActivation")) { |
386 rasterizer_->SetClient(this); | 391 rasterizer_->SetClient(this); |
387 } | 392 } |
388 | 393 |
389 TileManager::~TileManager() { | 394 TileManager::~TileManager() { |
390 // Reset global state and manage. This should cause | 395 // Reset global state and manage. This should cause |
391 // our memory usage to drop to zero. | 396 // our memory usage to drop to zero. |
392 global_state_ = GlobalStateThatImpactsTilePriority(); | 397 global_state_ = GlobalStateThatImpactsTilePriority(); |
393 | 398 |
394 RasterTaskQueue empty; | 399 RasterTaskQueue empty; |
395 rasterizer_->ScheduleTasks(&empty); | 400 rasterizer_->ScheduleTasks(&empty); |
(...skipping 17 matching lines...) Expand all Loading... |
413 DCHECK(TilePriority() == tile->combined_priority()); | 418 DCHECK(TilePriority() == tile->combined_priority()); |
414 | 419 |
415 prioritized_tiles_dirty_ = true; | 420 prioritized_tiles_dirty_ = true; |
416 released_tiles_.push_back(tile); | 421 released_tiles_.push_back(tile); |
417 } | 422 } |
418 | 423 |
419 void TileManager::DidChangeTilePriority(Tile* tile) { | 424 void TileManager::DidChangeTilePriority(Tile* tile) { |
420 prioritized_tiles_dirty_ = true; | 425 prioritized_tiles_dirty_ = true; |
421 } | 426 } |
422 | 427 |
423 bool TileManager::ShouldForceTasksRequiredForActivationToComplete() const { | 428 TaskSetCollection TileManager::TasksThatShouldBeForcedToComplete() const { |
424 return global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; | 429 TaskSetCollection tasks_that_should_be_forced_to_complete; |
| 430 if (global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY) |
| 431 tasks_that_should_be_forced_to_complete[REQUIRED_FOR_ACTIVATION] = true; |
| 432 return tasks_that_should_be_forced_to_complete; |
425 } | 433 } |
426 | 434 |
427 void TileManager::FreeResourcesForReleasedTiles() { | 435 void TileManager::FreeResourcesForReleasedTiles() { |
428 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); | 436 for (std::vector<Tile*>::iterator it = released_tiles_.begin(); |
429 it != released_tiles_.end(); | 437 it != released_tiles_.end(); |
430 ++it) { | 438 ++it) { |
431 Tile* tile = *it; | 439 Tile* tile = *it; |
432 FreeResourcesForTile(tile); | 440 FreeResourcesForTile(tile); |
433 } | 441 } |
434 } | 442 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 | 478 |
471 prioritized_tiles_.Clear(); | 479 prioritized_tiles_.Clear(); |
472 | 480 |
473 FreeResourcesForReleasedTiles(); | 481 FreeResourcesForReleasedTiles(); |
474 CleanUpReleasedTiles(); | 482 CleanUpReleasedTiles(); |
475 | 483 |
476 GetTilesWithAssignedBins(&prioritized_tiles_); | 484 GetTilesWithAssignedBins(&prioritized_tiles_); |
477 prioritized_tiles_dirty_ = false; | 485 prioritized_tiles_dirty_ = false; |
478 } | 486 } |
479 | 487 |
480 void TileManager::DidFinishRunningTasks() { | 488 void TileManager::DidFinishRunningTasks(TaskSet task_set) { |
481 TRACE_EVENT0("cc", "TileManager::DidFinishRunningTasks"); | 489 TRACE_EVENT1( |
| 490 "cc", "TileManager::DidFinishRunningTasks", "task_set", task_set); |
482 | 491 |
483 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > | 492 if (task_set == ALL) { |
484 global_state_.soft_memory_limit_in_bytes; | 493 bool memory_usage_above_limit = resource_pool_->total_memory_usage_bytes() > |
| 494 global_state_.soft_memory_limit_in_bytes; |
485 | 495 |
486 // When OOM, keep re-assigning memory until we reach a steady state | 496 // When OOM, keep re-assigning memory until we reach a steady state |
487 // where top-priority tiles are initialized. | 497 // where top-priority tiles are initialized. |
488 if (all_tiles_that_need_to_be_rasterized_have_memory_ && | 498 if (all_tiles_that_need_to_be_rasterized_have_memory_ && |
489 !memory_usage_above_limit) | 499 !memory_usage_above_limit) |
490 return; | 500 return; |
491 | 501 |
492 rasterizer_->CheckForCompletedTasks(); | 502 rasterizer_->CheckForCompletedTasks(); |
493 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 503 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
494 | 504 |
495 TileVector tiles_that_need_to_be_rasterized; | 505 TileVector tiles_that_need_to_be_rasterized; |
496 AssignGpuMemoryToTiles(&prioritized_tiles_, | 506 AssignGpuMemoryToTiles(&prioritized_tiles_, |
497 &tiles_that_need_to_be_rasterized); | 507 &tiles_that_need_to_be_rasterized); |
498 | 508 |
499 // |tiles_that_need_to_be_rasterized| will be empty when we reach a | 509 // |tiles_that_need_to_be_rasterized| will be empty when we reach a |
500 // steady memory state. Keep scheduling tasks until we reach this state. | 510 // steady memory state. Keep scheduling tasks until we reach this state. |
501 if (!tiles_that_need_to_be_rasterized.empty()) { | 511 if (!tiles_that_need_to_be_rasterized.empty()) { |
502 ScheduleTasks(tiles_that_need_to_be_rasterized); | 512 ScheduleTasks(tiles_that_need_to_be_rasterized); |
503 return; | 513 return; |
| 514 } |
| 515 |
| 516 FreeResourcesForReleasedTiles(); |
| 517 |
| 518 resource_pool_->ReduceResourceUsage(); |
| 519 |
| 520 // We don't reserve memory for required-for-activation tiles during |
| 521 // accelerated gestures, so we just postpone activation when we don't |
| 522 // have these tiles, and activate after the accelerated gesture. |
| 523 bool allow_rasterize_on_demand = |
| 524 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; |
| 525 |
| 526 // Use on-demand raster for any required-for-activation tiles that have not |
| 527 // been been assigned memory after reaching a steady memory state. This |
| 528 // ensures that we activate even when OOM. |
| 529 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| 530 Tile* tile = it->second; |
| 531 ManagedTileState& mts = tile->managed_state(); |
| 532 ManagedTileState::TileVersion& tile_version = |
| 533 mts.tile_versions[mts.raster_mode]; |
| 534 |
| 535 if (tile->required_for_activation() && !tile_version.IsReadyToDraw()) { |
| 536 // If we can't raster on demand, give up early (and don't activate). |
| 537 if (!allow_rasterize_on_demand) |
| 538 return; |
| 539 |
| 540 tile_version.set_rasterize_on_demand(); |
| 541 client_->NotifyTileStateChanged(tile); |
| 542 } |
| 543 } |
| 544 |
| 545 DCHECK(IsReadyToActivate()); |
| 546 ready_to_activate_check_notifier_.Schedule(); |
| 547 } else if (task_set == REQUIRED_FOR_ACTIVATION) { |
| 548 // This is only a true indication that all tiles required for |
| 549 // activation are initialized when no tiles are OOM. We need to |
| 550 // wait for DidFinishRunningTasks() to be called, try to re-assign |
| 551 // memory and in worst case use on-demand raster when tiles |
| 552 // required for activation are OOM. |
| 553 if (!all_tiles_required_for_activation_have_memory_) |
| 554 return; |
| 555 |
| 556 ready_to_activate_check_notifier_.Schedule(); |
504 } | 557 } |
505 | |
506 FreeResourcesForReleasedTiles(); | |
507 | |
508 resource_pool_->ReduceResourceUsage(); | |
509 | |
510 // We don't reserve memory for required-for-activation tiles during | |
511 // accelerated gestures, so we just postpone activation when we don't | |
512 // have these tiles, and activate after the accelerated gesture. | |
513 bool allow_rasterize_on_demand = | |
514 global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY; | |
515 | |
516 // Use on-demand raster for any required-for-activation tiles that have not | |
517 // been been assigned memory after reaching a steady memory state. This | |
518 // ensures that we activate even when OOM. | |
519 for (TileMap::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | |
520 Tile* tile = it->second; | |
521 ManagedTileState& mts = tile->managed_state(); | |
522 ManagedTileState::TileVersion& tile_version = | |
523 mts.tile_versions[mts.raster_mode]; | |
524 | |
525 if (tile->required_for_activation() && !tile_version.IsReadyToDraw()) { | |
526 // If we can't raster on demand, give up early (and don't activate). | |
527 if (!allow_rasterize_on_demand) | |
528 return; | |
529 | |
530 tile_version.set_rasterize_on_demand(); | |
531 client_->NotifyTileStateChanged(tile); | |
532 } | |
533 } | |
534 | |
535 DCHECK(IsReadyToActivate()); | |
536 ready_to_activate_check_notifier_.Schedule(); | |
537 } | 558 } |
538 | 559 |
539 void TileManager::DidFinishRunningTasksRequiredForActivation() { | 560 base::debug::TraceEventSyntheticDelay* TileManager::SyntheticDelayForTasks( |
540 // This is only a true indication that all tiles required for | 561 TaskSet task_set) const { |
541 // activation are initialized when no tiles are OOM. We need to | 562 if (task_set == REQUIRED_FOR_ACTIVATION) |
542 // wait for DidFinishRunningTasks() to be called, try to re-assign | 563 return raster_required_for_activation_synthetic_delay_; |
543 // memory and in worst case use on-demand raster when tiles | 564 else |
544 // required for activation are OOM. | 565 return NULL; |
545 if (!all_tiles_required_for_activation_have_memory_) | |
546 return; | |
547 | |
548 ready_to_activate_check_notifier_.Schedule(); | |
549 } | 566 } |
550 | 567 |
551 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) { | 568 void TileManager::GetTilesWithAssignedBins(PrioritizedTileSet* tiles) { |
552 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins"); | 569 TRACE_EVENT0("cc", "TileManager::GetTilesWithAssignedBins"); |
553 | 570 |
554 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy; | 571 const TileMemoryLimitPolicy memory_policy = global_state_.memory_limit_policy; |
555 const TreePriority tree_priority = global_state_.tree_priority; | 572 const TreePriority tree_priority = global_state_.tree_priority; |
556 | 573 |
557 // For each tree, bin into different categories of tiles. | 574 // For each tree, bin into different categories of tiles. |
558 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { | 575 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
966 ManagedTileState& mts = tile->managed_state(); | 983 ManagedTileState& mts = tile->managed_state(); |
967 ManagedTileState::TileVersion& tile_version = | 984 ManagedTileState::TileVersion& tile_version = |
968 mts.tile_versions[mts.raster_mode]; | 985 mts.tile_versions[mts.raster_mode]; |
969 | 986 |
970 DCHECK(tile_version.requires_resource()); | 987 DCHECK(tile_version.requires_resource()); |
971 DCHECK(!tile_version.resource_); | 988 DCHECK(!tile_version.resource_); |
972 | 989 |
973 if (!tile_version.raster_task_.get()) | 990 if (!tile_version.raster_task_.get()) |
974 tile_version.raster_task_ = CreateRasterTask(tile); | 991 tile_version.raster_task_ = CreateRasterTask(tile); |
975 | 992 |
976 raster_queue_.items.push_back(RasterTaskQueue::Item( | 993 TaskSetCollection task_sets; |
977 tile_version.raster_task_.get(), tile->required_for_activation())); | 994 if (tile->required_for_activation()) |
978 raster_queue_.required_for_activation_count += | 995 task_sets.set(REQUIRED_FOR_ACTIVATION); |
979 tile->required_for_activation(); | 996 task_sets.set(ALL); |
| 997 raster_queue_.items.push_back( |
| 998 RasterTaskQueue::Item(tile_version.raster_task_.get(), task_sets)); |
980 } | 999 } |
981 | 1000 |
982 // We must reduce the amount of unused resoruces before calling | 1001 // We must reduce the amount of unused resoruces before calling |
983 // ScheduleTasks to prevent usage from rising above limits. | 1002 // ScheduleTasks to prevent usage from rising above limits. |
984 resource_pool_->ReduceResourceUsage(); | 1003 resource_pool_->ReduceResourceUsage(); |
985 | 1004 |
986 // Schedule running of |raster_tasks_|. This replaces any previously | 1005 // Schedule running of |raster_tasks_|. This replaces any previously |
987 // scheduled tasks and effectively cancels all tasks not present | 1006 // scheduled tasks and effectively cancels all tasks not present |
988 // in |raster_tasks_|. | 1007 // in |raster_tasks_|. |
989 rasterizer_->ScheduleTasks(&raster_queue_); | 1008 rasterizer_->ScheduleTasks(&raster_queue_); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); | 1187 TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); |
1169 | 1188 |
1170 rasterizer_->CheckForCompletedTasks(); | 1189 rasterizer_->CheckForCompletedTasks(); |
1171 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 1190 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
1172 | 1191 |
1173 if (IsReadyToActivate()) | 1192 if (IsReadyToActivate()) |
1174 client_->NotifyReadyToActivate(); | 1193 client_->NotifyReadyToActivate(); |
1175 } | 1194 } |
1176 | 1195 |
1177 } // namespace cc | 1196 } // namespace cc |
OLD | NEW |