| 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 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 } | 454 } |
| 455 } | 455 } |
| 456 | 456 |
| 457 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { | 457 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { |
| 458 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 458 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
| 459 | 459 |
| 460 // Update internal state. | 460 // Update internal state. |
| 461 if (state != global_state_) { | 461 if (state != global_state_) { |
| 462 global_state_ = state; | 462 global_state_ = state; |
| 463 prioritized_tiles_dirty_ = true; | 463 prioritized_tiles_dirty_ = true; |
| 464 // Soft limit is used for resource pool such that |
| 465 // memory returns to soft limit after going over. |
| 464 resource_pool_->SetResourceUsageLimits( | 466 resource_pool_->SetResourceUsageLimits( |
| 465 global_state_.memory_limit_in_bytes, | 467 global_state_.soft_memory_limit_in_bytes, |
| 466 global_state_.unused_memory_limit_in_bytes, | 468 global_state_.unused_memory_limit_in_bytes, |
| 467 global_state_.num_resources_limit); | 469 global_state_.num_resources_limit); |
| 468 } | 470 } |
| 469 | 471 |
| 470 // We need to call CheckForCompletedTasks() once in-between each call | 472 // We need to call CheckForCompletedTasks() once in-between each call |
| 471 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | 473 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| 472 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | 474 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| 473 raster_worker_pool_->CheckForCompletedTasks(); | 475 raster_worker_pool_->CheckForCompletedTasks(); |
| 474 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 476 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 475 } | 477 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 // resource(s) was returned. Note that in that case, one also need to | 593 // resource(s) was returned. Note that in that case, one also need to |
| 592 // invalidate when releasing some resource from the pool. | 594 // invalidate when releasing some resource from the pool. |
| 593 resource_pool_->CheckBusyResources(); | 595 resource_pool_->CheckBusyResources(); |
| 594 | 596 |
| 595 // Now give memory out to the tiles until we're out, and build | 597 // Now give memory out to the tiles until we're out, and build |
| 596 // the needs-to-be-rasterized queue. | 598 // the needs-to-be-rasterized queue. |
| 597 all_tiles_that_need_to_be_rasterized_have_memory_ = true; | 599 all_tiles_that_need_to_be_rasterized_have_memory_ = true; |
| 598 all_tiles_required_for_activation_have_memory_ = true; | 600 all_tiles_required_for_activation_have_memory_ = true; |
| 599 | 601 |
| 600 // Cast to prevent overflow. | 602 // Cast to prevent overflow. |
| 601 int64 bytes_available = | 603 int64 soft_bytes_available = |
| 602 static_cast<int64>(bytes_releasable_) + | 604 static_cast<int64>(bytes_releasable_) + |
| 603 static_cast<int64>(global_state_.memory_limit_in_bytes) - | 605 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - |
| 606 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
| 607 int64 hard_bytes_available = |
| 608 static_cast<int64>(bytes_releasable_) + |
| 609 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) - |
| 604 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); | 610 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
| 605 int resources_available = resources_releasable_ + | 611 int resources_available = resources_releasable_ + |
| 606 global_state_.num_resources_limit - | 612 global_state_.num_resources_limit - |
| 607 resource_pool_->acquired_resource_count(); | 613 resource_pool_->acquired_resource_count(); |
| 608 | 614 size_t soft_bytes_allocatable = |
| 609 size_t bytes_allocatable = std::max(static_cast<int64>(0), bytes_available); | 615 std::max(static_cast<int64>(0), soft_bytes_available); |
| 616 size_t hard_bytes_allocatable = |
| 617 std::max(static_cast<int64>(0), hard_bytes_available); |
| 610 size_t resources_allocatable = std::max(0, resources_available); | 618 size_t resources_allocatable = std::max(0, resources_available); |
| 611 | 619 |
| 612 size_t bytes_that_exceeded_memory_budget = 0; | 620 size_t bytes_that_exceeded_memory_budget = 0; |
| 613 size_t bytes_left = bytes_allocatable; | 621 size_t soft_bytes_left = soft_bytes_allocatable; |
| 622 size_t hard_bytes_left = hard_bytes_allocatable; |
| 623 |
| 614 size_t resources_left = resources_allocatable; | 624 size_t resources_left = resources_allocatable; |
| 615 bool oomed = false; | 625 bool oomed_soft = false; |
| 626 bool oomed_hard = false; |
| 616 | 627 |
| 617 // Memory we assign to raster tasks now will be deducted from our memory | 628 // Memory we assign to raster tasks now will be deducted from our memory |
| 618 // in future iterations if priorities change. By assigning at most half | 629 // in future iterations if priorities change. By assigning at most half |
| 619 // the raster limit, we will always have another 50% left even if priorities | 630 // the raster limit, we will always have another 50% left even if priorities |
| 620 // change completely (assuming we check for completed/cancelled rasters | 631 // change completely (assuming we check for completed/cancelled rasters |
| 621 // between each call to this function). | 632 // between each call to this function). |
| 622 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; | 633 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; |
| 623 size_t raster_bytes = 0; | 634 size_t raster_bytes = 0; |
| 624 | 635 |
| 625 unsigned schedule_priority = 1u; | 636 unsigned schedule_priority = 1u; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 637 // If this tile doesn't need a resource, then nothing to do. | 648 // If this tile doesn't need a resource, then nothing to do. |
| 638 if (!tile_version.requires_resource()) | 649 if (!tile_version.requires_resource()) |
| 639 continue; | 650 continue; |
| 640 | 651 |
| 641 // If the tile is not needed, free it up. | 652 // If the tile is not needed, free it up. |
| 642 if (mts.bin == NEVER_BIN) { | 653 if (mts.bin == NEVER_BIN) { |
| 643 FreeResourcesForTile(tile); | 654 FreeResourcesForTile(tile); |
| 644 continue; | 655 continue; |
| 645 } | 656 } |
| 646 | 657 |
| 647 size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); | 658 const bool tile_uses_hard_limit = mts.bin <= NOW_BIN; |
| 648 size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; | 659 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); |
| 660 const size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; |
| 661 const size_t tile_bytes_left = |
| 662 (tile_uses_hard_limit) ? hard_bytes_left : soft_bytes_left; |
| 649 | 663 |
| 650 size_t tile_bytes = 0; | 664 size_t tile_bytes = 0; |
| 651 size_t tile_resources = 0; | 665 size_t tile_resources = 0; |
| 652 | 666 |
| 653 // It costs to maintain a resource. | 667 // It costs to maintain a resource. |
| 654 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { | 668 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| 655 if (mts.tile_versions[mode].resource_) { | 669 if (mts.tile_versions[mode].resource_) { |
| 656 tile_bytes += bytes_if_allocated; | 670 tile_bytes += bytes_if_allocated; |
| 657 tile_resources++; | 671 tile_resources++; |
| 658 } | 672 } |
| 659 } | 673 } |
| 660 | 674 |
| 661 // Allow lower priority tiles with initialized resources to keep | 675 // Allow lower priority tiles with initialized resources to keep |
| 662 // their memory by only assigning memory to new raster tasks if | 676 // their memory by only assigning memory to new raster tasks if |
| 663 // they can be scheduled. | 677 // they can be scheduled. |
| 664 if (raster_bytes_if_rastered <= max_raster_bytes) { | 678 if (raster_bytes_if_rastered <= max_raster_bytes) { |
| 665 // If we don't have the required version, and it's not in flight | 679 // If we don't have the required version, and it's not in flight |
| 666 // then we'll have to pay to create a new task. | 680 // then we'll have to pay to create a new task. |
| 667 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { | 681 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { |
| 668 tile_bytes += bytes_if_allocated; | 682 tile_bytes += bytes_if_allocated; |
| 669 tile_resources++; | 683 tile_resources++; |
| 670 } | 684 } |
| 671 } | 685 } |
| 672 | 686 |
| 673 // Tile is OOM. | 687 // Tile is OOM. |
| 674 if (tile_bytes > bytes_left || tile_resources > resources_left) { | 688 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) { |
| 675 FreeResourcesForTile(tile); | 689 FreeResourcesForTile(tile); |
| 676 | 690 |
| 677 // This tile was already on screen and now its resources have been | 691 // This tile was already on screen and now its resources have been |
| 678 // released. In order to prevent checkerboarding, set this tile as | 692 // released. In order to prevent checkerboarding, set this tile as |
| 679 // rasterize on demand immediately. | 693 // rasterize on demand immediately. |
| 680 if (mts.visible_and_ready_to_draw && use_rasterize_on_demand_) | 694 if (mts.visible_and_ready_to_draw && use_rasterize_on_demand_) |
| 681 tile_version.set_rasterize_on_demand(); | 695 tile_version.set_rasterize_on_demand(); |
| 682 | 696 |
| 683 oomed = true; | 697 oomed_soft = true; |
| 684 bytes_that_exceeded_memory_budget += tile_bytes; | 698 if (tile_uses_hard_limit) { |
| 699 oomed_hard = true; |
| 700 bytes_that_exceeded_memory_budget += tile_bytes; |
| 701 } |
| 685 } else { | 702 } else { |
| 686 bytes_left -= tile_bytes; | |
| 687 resources_left -= tile_resources; | 703 resources_left -= tile_resources; |
| 688 | 704 hard_bytes_left -= tile_bytes; |
| 705 soft_bytes_left = |
| 706 (soft_bytes_left > tile_bytes) ? soft_bytes_left - tile_bytes : 0; |
| 689 if (tile_version.resource_) | 707 if (tile_version.resource_) |
| 690 continue; | 708 continue; |
| 691 } | 709 } |
| 692 | 710 |
| 693 DCHECK(!tile_version.resource_); | 711 DCHECK(!tile_version.resource_); |
| 694 | 712 |
| 695 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| | 713 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| |
| 696 // has reached it's limit or we've failed to assign gpu memory to this | 714 // has reached it's limit or we've failed to assign gpu memory to this |
| 697 // or any higher priority tile. Preventing tiles that fit into memory | 715 // or any higher priority tile. Preventing tiles that fit into memory |
| 698 // budget to be rasterized when higher priority tile is oom is | 716 // budget to be rasterized when higher priority tile is oom is |
| 699 // important for two reasons: | 717 // important for two reasons: |
| 700 // 1. Tile size should not impact raster priority. | 718 // 1. Tile size should not impact raster priority. |
| 701 // 2. Tiles with existing raster task could otherwise incorrectly | 719 // 2. Tiles with existing raster task could otherwise incorrectly |
| 702 // be added as they are not affected by |bytes_allocatable|. | 720 // be added as they are not affected by |bytes_allocatable|. |
| 703 if (oomed || raster_bytes_if_rastered > max_raster_bytes) { | 721 if (oomed_soft || raster_bytes_if_rastered > max_raster_bytes) { |
| 704 all_tiles_that_need_to_be_rasterized_have_memory_ = false; | 722 all_tiles_that_need_to_be_rasterized_have_memory_ = false; |
| 705 if (tile->required_for_activation()) | 723 if (tile->required_for_activation()) |
| 706 all_tiles_required_for_activation_have_memory_ = false; | 724 all_tiles_required_for_activation_have_memory_ = false; |
| 707 it.DisablePriorityOrdering(); | 725 it.DisablePriorityOrdering(); |
| 708 continue; | 726 continue; |
| 709 } | 727 } |
| 710 | 728 |
| 711 raster_bytes = raster_bytes_if_rastered; | 729 raster_bytes = raster_bytes_if_rastered; |
| 712 tiles_that_need_to_be_rasterized->push_back(tile); | 730 tiles_that_need_to_be_rasterized->push_back(tile); |
| 713 } | 731 } |
| 714 | 732 |
| 715 ever_exceeded_memory_budget_ |= bytes_that_exceeded_memory_budget > 0; | 733 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. |
| 734 ever_exceeded_memory_budget_ |= oomed_hard; |
| 716 if (ever_exceeded_memory_budget_) { | 735 if (ever_exceeded_memory_budget_) { |
| 717 TRACE_COUNTER_ID2("cc", | 736 TRACE_COUNTER_ID2("cc", |
| 718 "over_memory_budget", | 737 "over_memory_budget", |
| 719 this, | 738 this, |
| 720 "budget", | 739 "budget", |
| 721 global_state_.memory_limit_in_bytes, | 740 global_state_.hard_memory_limit_in_bytes, |
| 722 "over", | 741 "over", |
| 723 bytes_that_exceeded_memory_budget); | 742 bytes_that_exceeded_memory_budget); |
| 724 } | 743 } |
| 725 memory_stats_from_last_assign_.total_budget_in_bytes = | 744 memory_stats_from_last_assign_.total_budget_in_bytes = |
| 726 global_state_.memory_limit_in_bytes; | 745 global_state_.hard_memory_limit_in_bytes; |
| 727 memory_stats_from_last_assign_.bytes_allocated = | 746 memory_stats_from_last_assign_.bytes_allocated = |
| 728 bytes_allocatable - bytes_left; | 747 hard_bytes_allocatable - hard_bytes_left; |
| 729 memory_stats_from_last_assign_.bytes_unreleasable = | 748 memory_stats_from_last_assign_.bytes_unreleasable = |
| 730 bytes_allocatable - bytes_releasable_; | 749 hard_bytes_allocatable - bytes_releasable_; |
| 731 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; | 750 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; |
| 732 } | 751 } |
| 733 | 752 |
| 734 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { | 753 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { |
| 735 ManagedTileState& mts = tile->managed_state(); | 754 ManagedTileState& mts = tile->managed_state(); |
| 736 if (mts.tile_versions[mode].resource_) { | 755 if (mts.tile_versions[mode].resource_) { |
| 737 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); | 756 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); |
| 738 | 757 |
| 739 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); | 758 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); |
| 740 DCHECK_GE(resources_releasable_, 1u); | 759 DCHECK_GE(resources_releasable_, 1u); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 flags)); | 976 flags)); |
| 958 DCHECK(tiles_.find(tile->id()) == tiles_.end()); | 977 DCHECK(tiles_.find(tile->id()) == tiles_.end()); |
| 959 | 978 |
| 960 tiles_[tile->id()] = tile; | 979 tiles_[tile->id()] = tile; |
| 961 used_layer_counts_[tile->layer_id()]++; | 980 used_layer_counts_[tile->layer_id()]++; |
| 962 prioritized_tiles_dirty_ = true; | 981 prioritized_tiles_dirty_ = true; |
| 963 return tile; | 982 return tile; |
| 964 } | 983 } |
| 965 | 984 |
| 966 } // namespace cc | 985 } // namespace cc |
| OLD | NEW |