| 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 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 task_runner_.get(), | 233 task_runner_.get(), |
| 234 base::Bind(&TileManager::CheckIfReadyToActivate, | 234 base::Bind(&TileManager::CheckIfReadyToActivate, |
| 235 base::Unretained(this))), | 235 base::Unretained(this))), |
| 236 ready_to_draw_check_notifier_( | 236 ready_to_draw_check_notifier_( |
| 237 task_runner_.get(), | 237 task_runner_.get(), |
| 238 base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), | 238 base::Bind(&TileManager::CheckIfReadyToDraw, base::Unretained(this))), |
| 239 more_tiles_need_prepare_check_notifier_( | 239 more_tiles_need_prepare_check_notifier_( |
| 240 task_runner_.get(), | 240 task_runner_.get(), |
| 241 base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, | 241 base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, |
| 242 base::Unretained(this))), | 242 base::Unretained(this))), |
| 243 eviction_priority_queue_is_up_to_date_(false), | |
| 244 did_notify_ready_to_activate_(false), | 243 did_notify_ready_to_activate_(false), |
| 245 did_notify_ready_to_draw_(false) { | 244 did_notify_ready_to_draw_(false) { |
| 246 tile_task_runner_->SetClient(this); | 245 tile_task_runner_->SetClient(this); |
| 247 } | 246 } |
| 248 | 247 |
| 249 TileManager::~TileManager() { | 248 TileManager::~TileManager() { |
| 250 // Reset global state and manage. This should cause | 249 // Reset global state and manage. This should cause |
| 251 // our memory usage to drop to zero. | 250 // our memory usage to drop to zero. |
| 252 global_state_ = GlobalStateThatImpactsTilePriority(); | 251 global_state_ = GlobalStateThatImpactsTilePriority(); |
| 253 | 252 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 scheduled_raster_task_limit_, | 366 scheduled_raster_task_limit_, |
| 368 &tiles_that_need_to_be_rasterized); | 367 &tiles_that_need_to_be_rasterized); |
| 369 | 368 |
| 370 // Schedule tile tasks. | 369 // Schedule tile tasks. |
| 371 ScheduleTasks(tiles_that_need_to_be_rasterized); | 370 ScheduleTasks(tiles_that_need_to_be_rasterized); |
| 372 | 371 |
| 373 did_notify_ready_to_activate_ = false; | 372 did_notify_ready_to_activate_ = false; |
| 374 did_notify_ready_to_draw_ = false; | 373 did_notify_ready_to_draw_ = false; |
| 375 } else { | 374 } else { |
| 376 if (global_state_.hard_memory_limit_in_bytes == 0) { | 375 if (global_state_.hard_memory_limit_in_bytes == 0) { |
| 377 // TODO(vmpstr): Add a function to unconditionally create an eviction | |
| 378 // queue and guard the rest of the calls sites with this flag, instead of | |
| 379 // clearing here and building, which is a bit awkward. | |
| 380 eviction_priority_queue_is_up_to_date_ = false; | |
| 381 resource_pool_->CheckBusyResources(false); | 376 resource_pool_->CheckBusyResources(false); |
| 382 MemoryUsage memory_limit(0, 0); | 377 MemoryUsage memory_limit(0, 0); |
| 383 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), | 378 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), |
| 384 resource_pool_->acquired_resource_count()); | 379 resource_pool_->acquired_resource_count()); |
| 385 FreeTileResourcesUntilUsageIsWithinLimit(memory_limit, &memory_usage); | 380 FreeTileResourcesUntilUsageIsWithinLimit(nullptr, memory_limit, |
| 381 &memory_usage); |
| 386 } | 382 } |
| 387 | 383 |
| 388 did_notify_ready_to_activate_ = false; | 384 did_notify_ready_to_activate_ = false; |
| 389 did_notify_ready_to_draw_ = false; | 385 did_notify_ready_to_draw_ = false; |
| 390 ready_to_activate_notifier_.Schedule(); | 386 ready_to_activate_notifier_.Schedule(); |
| 391 ready_to_draw_notifier_.Schedule(); | 387 ready_to_draw_notifier_.Schedule(); |
| 392 } | 388 } |
| 393 | 389 |
| 394 TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, | 390 TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, |
| 395 "state", BasicStateAsValue()); | 391 "state", BasicStateAsValue()); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 } | 480 } |
| 485 | 481 |
| 486 void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const { | 482 void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const { |
| 487 state->SetInteger("tile_count", tiles_.size()); | 483 state->SetInteger("tile_count", tiles_.size()); |
| 488 state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_); | 484 state->SetBoolean("did_oom_on_last_assign", did_oom_on_last_assign_); |
| 489 state->BeginDictionary("global_state"); | 485 state->BeginDictionary("global_state"); |
| 490 global_state_.AsValueInto(state); | 486 global_state_.AsValueInto(state); |
| 491 state->EndDictionary(); | 487 state->EndDictionary(); |
| 492 } | 488 } |
| 493 | 489 |
| 494 void TileManager::RebuildEvictionQueueIfNeeded() { | 490 scoped_ptr<EvictionTilePriorityQueue> |
| 495 TRACE_EVENT1("cc", | 491 TileManager::FreeTileResourcesUntilUsageIsWithinLimit( |
| 496 "TileManager::RebuildEvictionQueueIfNeeded", | 492 scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue, |
| 497 "eviction_priority_queue_is_up_to_date", | |
| 498 eviction_priority_queue_is_up_to_date_); | |
| 499 if (eviction_priority_queue_is_up_to_date_) | |
| 500 return; | |
| 501 | |
| 502 eviction_priority_queue_.Reset(); | |
| 503 client_->BuildEvictionQueue(&eviction_priority_queue_, | |
| 504 global_state_.tree_priority); | |
| 505 eviction_priority_queue_is_up_to_date_ = true; | |
| 506 } | |
| 507 | |
| 508 bool TileManager::FreeTileResourcesUntilUsageIsWithinLimit( | |
| 509 const MemoryUsage& limit, | 493 const MemoryUsage& limit, |
| 510 MemoryUsage* usage) { | 494 MemoryUsage* usage) { |
| 511 while (usage->Exceeds(limit)) { | 495 while (usage->Exceeds(limit)) { |
| 512 RebuildEvictionQueueIfNeeded(); | 496 if (!eviction_priority_queue) { |
| 513 if (eviction_priority_queue_.IsEmpty()) | 497 eviction_priority_queue = |
| 514 return false; | 498 client_->BuildEvictionQueue(global_state_.tree_priority); |
| 499 } |
| 500 if (eviction_priority_queue->IsEmpty()) |
| 501 break; |
| 515 | 502 |
| 516 Tile* tile = eviction_priority_queue_.Top(); | 503 Tile* tile = eviction_priority_queue->Top(); |
| 517 *usage -= MemoryUsage::FromTile(tile); | 504 *usage -= MemoryUsage::FromTile(tile); |
| 518 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); | 505 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); |
| 519 eviction_priority_queue_.Pop(); | 506 eviction_priority_queue->Pop(); |
| 520 } | 507 } |
| 521 return true; | 508 return eviction_priority_queue; |
| 522 } | 509 } |
| 523 | 510 |
| 524 bool TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( | 511 scoped_ptr<EvictionTilePriorityQueue> |
| 512 TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( |
| 513 scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue, |
| 525 const MemoryUsage& limit, | 514 const MemoryUsage& limit, |
| 526 const TilePriority& other_priority, | 515 const TilePriority& other_priority, |
| 527 MemoryUsage* usage) { | 516 MemoryUsage* usage) { |
| 528 while (usage->Exceeds(limit)) { | 517 while (usage->Exceeds(limit)) { |
| 529 RebuildEvictionQueueIfNeeded(); | 518 if (!eviction_priority_queue) { |
| 530 if (eviction_priority_queue_.IsEmpty()) | 519 eviction_priority_queue = |
| 531 return false; | 520 client_->BuildEvictionQueue(global_state_.tree_priority); |
| 521 } |
| 522 if (eviction_priority_queue->IsEmpty()) |
| 523 break; |
| 532 | 524 |
| 533 Tile* tile = eviction_priority_queue_.Top(); | 525 Tile* tile = eviction_priority_queue->Top(); |
| 534 if (!other_priority.IsHigherPriorityThan(tile->combined_priority())) | 526 if (!other_priority.IsHigherPriorityThan(tile->combined_priority())) |
| 535 return false; | 527 break; |
| 536 | 528 |
| 537 *usage -= MemoryUsage::FromTile(tile); | 529 *usage -= MemoryUsage::FromTile(tile); |
| 538 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); | 530 FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); |
| 539 eviction_priority_queue_.Pop(); | 531 eviction_priority_queue->Pop(); |
| 540 } | 532 } |
| 541 return true; | 533 return eviction_priority_queue; |
| 542 } | 534 } |
| 543 | 535 |
| 544 bool TileManager::TilePriorityViolatesMemoryPolicy( | 536 bool TileManager::TilePriorityViolatesMemoryPolicy( |
| 545 const TilePriority& priority) { | 537 const TilePriority& priority) { |
| 546 switch (global_state_.memory_limit_policy) { | 538 switch (global_state_.memory_limit_policy) { |
| 547 case ALLOW_NOTHING: | 539 case ALLOW_NOTHING: |
| 548 return true; | 540 return true; |
| 549 case ALLOW_ABSOLUTE_MINIMUM: | 541 case ALLOW_ABSOLUTE_MINIMUM: |
| 550 return priority.priority_bin > TilePriority::NOW; | 542 return priority.priority_bin > TilePriority::NOW; |
| 551 case ALLOW_PREPAINT_ONLY: | 543 case ALLOW_PREPAINT_ONLY: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 576 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; | 568 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; |
| 577 bool had_enough_memory_to_schedule_tiles_needed_now = true; | 569 bool had_enough_memory_to_schedule_tiles_needed_now = true; |
| 578 | 570 |
| 579 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, | 571 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, |
| 580 global_state_.num_resources_limit); | 572 global_state_.num_resources_limit); |
| 581 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, | 573 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, |
| 582 global_state_.num_resources_limit); | 574 global_state_.num_resources_limit); |
| 583 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), | 575 MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), |
| 584 resource_pool_->acquired_resource_count()); | 576 resource_pool_->acquired_resource_count()); |
| 585 | 577 |
| 586 eviction_priority_queue_is_up_to_date_ = false; | 578 scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue; |
| 587 for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { | 579 for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { |
| 588 Tile* tile = raster_priority_queue->Top(); | 580 Tile* tile = raster_priority_queue->Top(); |
| 589 TilePriority priority = tile->combined_priority(); | 581 TilePriority priority = tile->combined_priority(); |
| 590 | 582 |
| 591 if (TilePriorityViolatesMemoryPolicy(priority)) { | 583 if (TilePriorityViolatesMemoryPolicy(priority)) { |
| 592 TRACE_EVENT_INSTANT0( | 584 TRACE_EVENT_INSTANT0( |
| 593 "cc", "TileManager::AssignGpuMemory tile violates memory policy", | 585 "cc", "TileManager::AssignGpuMemory tile violates memory policy", |
| 594 TRACE_EVENT_SCOPE_THREAD); | 586 TRACE_EVENT_SCOPE_THREAD); |
| 595 break; | 587 break; |
| 596 } | 588 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 618 } | 610 } |
| 619 | 611 |
| 620 bool tile_is_needed_now = priority.priority_bin == TilePriority::NOW; | 612 bool tile_is_needed_now = priority.priority_bin == TilePriority::NOW; |
| 621 | 613 |
| 622 // This is the memory limit that will be used by this tile. Depending on | 614 // This is the memory limit that will be used by this tile. Depending on |
| 623 // the tile priority, it will be one of hard_memory_limit or | 615 // the tile priority, it will be one of hard_memory_limit or |
| 624 // soft_memory_limit. | 616 // soft_memory_limit. |
| 625 MemoryUsage& tile_memory_limit = | 617 MemoryUsage& tile_memory_limit = |
| 626 tile_is_needed_now ? hard_memory_limit : soft_memory_limit; | 618 tile_is_needed_now ? hard_memory_limit : soft_memory_limit; |
| 627 | 619 |
| 620 const MemoryUsage& scheduled_tile_memory_limit = |
| 621 tile_memory_limit - memory_required_by_tile_to_be_scheduled; |
| 622 eviction_priority_queue = |
| 623 FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( |
| 624 eviction_priority_queue.Pass(), scheduled_tile_memory_limit, |
| 625 priority, &memory_usage); |
| 628 bool memory_usage_is_within_limit = | 626 bool memory_usage_is_within_limit = |
| 629 FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( | 627 !memory_usage.Exceeds(scheduled_tile_memory_limit); |
| 630 tile_memory_limit - memory_required_by_tile_to_be_scheduled, | |
| 631 priority, &memory_usage); | |
| 632 | 628 |
| 633 // If we couldn't fit the tile into our current memory limit, then we're | 629 // If we couldn't fit the tile into our current memory limit, then we're |
| 634 // done. | 630 // done. |
| 635 if (!memory_usage_is_within_limit) { | 631 if (!memory_usage_is_within_limit) { |
| 636 if (tile_is_needed_now) | 632 if (tile_is_needed_now) |
| 637 had_enough_memory_to_schedule_tiles_needed_now = false; | 633 had_enough_memory_to_schedule_tiles_needed_now = false; |
| 638 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; | 634 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; |
| 639 break; | 635 break; |
| 640 } | 636 } |
| 641 | 637 |
| 642 memory_usage += memory_required_by_tile_to_be_scheduled; | 638 memory_usage += memory_required_by_tile_to_be_scheduled; |
| 643 tiles_that_need_to_be_rasterized->push_back(tile); | 639 tiles_that_need_to_be_rasterized->push_back(tile); |
| 644 } | 640 } |
| 645 | 641 |
| 646 // Note that we should try and further reduce memory in case the above loop | 642 // Note that we should try and further reduce memory in case the above loop |
| 647 // didn't reduce memory. This ensures that we always release as many resources | 643 // didn't reduce memory. This ensures that we always release as many resources |
| 648 // as possible to stay within the memory limit. | 644 // as possible to stay within the memory limit. |
| 649 FreeTileResourcesUntilUsageIsWithinLimit(hard_memory_limit, &memory_usage); | 645 eviction_priority_queue = FreeTileResourcesUntilUsageIsWithinLimit( |
| 646 eviction_priority_queue.Pass(), hard_memory_limit, &memory_usage); |
| 650 | 647 |
| 651 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", | 648 UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", |
| 652 !had_enough_memory_to_schedule_tiles_needed_now); | 649 !had_enough_memory_to_schedule_tiles_needed_now); |
| 653 did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now; | 650 did_oom_on_last_assign_ = !had_enough_memory_to_schedule_tiles_needed_now; |
| 654 | 651 |
| 655 memory_stats_from_last_assign_.total_budget_in_bytes = | 652 memory_stats_from_last_assign_.total_budget_in_bytes = |
| 656 global_state_.hard_memory_limit_in_bytes; | 653 global_state_.hard_memory_limit_in_bytes; |
| 657 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); | 654 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); |
| 658 memory_stats_from_last_assign_.had_enough_memory = | 655 memory_stats_from_last_assign_.had_enough_memory = |
| 659 had_enough_memory_to_schedule_tiles_needed_now; | 656 had_enough_memory_to_schedule_tiles_needed_now; |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 result -= other; | 1040 result -= other; |
| 1044 return result; | 1041 return result; |
| 1045 } | 1042 } |
| 1046 | 1043 |
| 1047 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { | 1044 bool TileManager::MemoryUsage::Exceeds(const MemoryUsage& limit) const { |
| 1048 return memory_bytes_ > limit.memory_bytes_ || | 1045 return memory_bytes_ > limit.memory_bytes_ || |
| 1049 resource_count_ > limit.resource_count_; | 1046 resource_count_ > limit.resource_count_; |
| 1050 } | 1047 } |
| 1051 | 1048 |
| 1052 } // namespace cc | 1049 } // namespace cc |
| OLD | NEW |