Chromium Code Reviews| 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 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 mts.visible_and_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : mts.bin; | 470 mts.visible_and_ready_to_draw ? NOW_AND_READY_TO_DRAW_BIN : mts.bin; |
| 471 | 471 |
| 472 // Insert the tile into a priority set. | 472 // Insert the tile into a priority set. |
| 473 tiles->InsertTile(tile, priority_bin); | 473 tiles->InsertTile(tile, priority_bin); |
| 474 } | 474 } |
| 475 } | 475 } |
| 476 | 476 |
| 477 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { | 477 void TileManager::ManageTiles(const GlobalStateThatImpactsTilePriority& state) { |
| 478 TRACE_EVENT0("cc", "TileManager::ManageTiles"); | 478 TRACE_EVENT0("cc", "TileManager::ManageTiles"); |
| 479 | 479 |
| 480 // Update internal state. | 480 // Update internal state. We use the soft-limit for the resource-pool |
| 481 // such that we will reduce to that limit after going over. | |
| 481 if (state != global_state_) { | 482 if (state != global_state_) { |
| 482 global_state_ = state; | 483 global_state_ = state; |
| 483 prioritized_tiles_dirty_ = true; | 484 prioritized_tiles_dirty_ = true; |
| 484 resource_pool_->SetResourceUsageLimits( | 485 resource_pool_->SetResourceUsageLimits( |
| 485 global_state_.memory_limit_in_bytes, | 486 global_state_.soft_memory_limit_in_bytes, |
| 486 global_state_.unused_memory_limit_in_bytes, | 487 global_state_.unused_memory_limit_in_bytes, |
| 487 global_state_.num_resources_limit); | 488 global_state_.num_resources_limit); |
| 488 } | 489 } |
| 489 | 490 |
| 490 // We need to call CheckForCompletedTasks() once in-between each call | 491 // We need to call CheckForCompletedTasks() once in-between each call |
| 491 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | 492 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| 492 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | 493 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| 493 raster_worker_pool_->CheckForCompletedTasks(); | 494 raster_worker_pool_->CheckForCompletedTasks(); |
| 494 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 495 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 495 } | 496 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 // resource(s) was returned. Note that in that case, one also need to | 612 // resource(s) was returned. Note that in that case, one also need to |
| 612 // invalidate when releasing some resource from the pool. | 613 // invalidate when releasing some resource from the pool. |
| 613 resource_pool_->CheckBusyResources(); | 614 resource_pool_->CheckBusyResources(); |
| 614 | 615 |
| 615 // Now give memory out to the tiles until we're out, and build | 616 // Now give memory out to the tiles until we're out, and build |
| 616 // the needs-to-be-rasterized queue. | 617 // the needs-to-be-rasterized queue. |
| 617 all_tiles_that_need_to_be_rasterized_have_memory_ = true; | 618 all_tiles_that_need_to_be_rasterized_have_memory_ = true; |
| 618 all_tiles_required_for_activation_have_memory_ = true; | 619 all_tiles_required_for_activation_have_memory_ = true; |
| 619 | 620 |
| 620 // Cast to prevent overflow. | 621 // Cast to prevent overflow. |
| 621 int64 bytes_available = | 622 int64 soft_bytes_available = |
|
vmpstr
2014/02/12 22:19:36
maybe visible_bytes_available and repaint_bytes_av
vmpstr
2014/02/12 22:20:20
s/repaint/prepaint/
epennerAtGoogle
2014/02/12 23:08:46
Arg! That's what I called it before! ;) I can cha
vmpstr
2014/02/12 23:21:04
Yeah, I see the problem. I guess soft/hard is OK,
| |
| 622 static_cast<int64>(bytes_releasable_) + | 623 static_cast<int64>(bytes_releasable_) + |
| 623 static_cast<int64>(global_state_.memory_limit_in_bytes) - | 624 static_cast<int64>(global_state_.soft_memory_limit_in_bytes) - |
| 625 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); | |
| 626 int64 hard_bytes_available = | |
| 627 static_cast<int64>(bytes_releasable_) + | |
| 628 static_cast<int64>(global_state_.hard_memory_limit_in_bytes) - | |
| 624 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); | 629 static_cast<int64>(resource_pool_->acquired_memory_usage_bytes()); |
| 625 int resources_available = resources_releasable_ + | 630 int resources_available = resources_releasable_ + |
| 626 global_state_.num_resources_limit - | 631 global_state_.num_resources_limit - |
| 627 resource_pool_->acquired_resource_count(); | 632 resource_pool_->acquired_resource_count(); |
| 628 | 633 size_t soft_bytes_allocatable = |
| 629 size_t bytes_allocatable = std::max(static_cast<int64>(0), bytes_available); | 634 std::max(static_cast<int64>(0), soft_bytes_available); |
| 635 size_t hard_bytes_allocatable = | |
| 636 std::max(static_cast<int64>(0), hard_bytes_available); | |
| 630 size_t resources_allocatable = std::max(0, resources_available); | 637 size_t resources_allocatable = std::max(0, resources_available); |
| 631 | 638 |
| 632 size_t bytes_that_exceeded_memory_budget = 0; | 639 size_t bytes_that_exceeded_memory_budget = 0; |
| 633 size_t bytes_left = bytes_allocatable; | 640 int64 soft_bytes_left = soft_bytes_allocatable; |
| 641 int64 hard_bytes_left = hard_bytes_allocatable; | |
| 642 | |
| 634 size_t resources_left = resources_allocatable; | 643 size_t resources_left = resources_allocatable; |
| 635 bool oomed = false; | 644 bool oomed_soft = false; |
| 645 bool oomed_hard = false; | |
| 636 | 646 |
| 637 // Memory we assign to raster tasks now will be deducted from our memory | 647 // Memory we assign to raster tasks now will be deducted from our memory |
| 638 // in future iterations if priorities change. By assigning at most half | 648 // in future iterations if priorities change. By assigning at most half |
| 639 // the raster limit, we will always have another 50% left even if priorities | 649 // the raster limit, we will always have another 50% left even if priorities |
| 640 // change completely (assuming we check for completed/cancelled rasters | 650 // change completely (assuming we check for completed/cancelled rasters |
| 641 // between each call to this function). | 651 // between each call to this function). |
| 642 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; | 652 size_t max_raster_bytes = max_raster_usage_bytes_ / 2; |
| 643 size_t raster_bytes = 0; | 653 size_t raster_bytes = 0; |
| 644 | 654 |
| 645 unsigned schedule_priority = 1u; | 655 unsigned schedule_priority = 1u; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 657 // If this tile doesn't need a resource, then nothing to do. | 667 // If this tile doesn't need a resource, then nothing to do. |
| 658 if (!tile_version.requires_resource()) | 668 if (!tile_version.requires_resource()) |
| 659 continue; | 669 continue; |
| 660 | 670 |
| 661 // If the tile is not needed, free it up. | 671 // If the tile is not needed, free it up. |
| 662 if (mts.bin == NEVER_BIN) { | 672 if (mts.bin == NEVER_BIN) { |
| 663 FreeResourcesForTile(tile); | 673 FreeResourcesForTile(tile); |
| 664 continue; | 674 continue; |
| 665 } | 675 } |
| 666 | 676 |
| 667 size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); | 677 const size_t bytes_if_allocated = BytesConsumedIfAllocated(tile); |
| 668 size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; | 678 const size_t raster_bytes_if_rastered = raster_bytes + bytes_if_allocated; |
| 679 const size_t tile_bytes_left = | |
| 680 (mts.bin == NOW_BIN) ? hard_bytes_left : soft_bytes_left; | |
|
vmpstr
2014/02/12 22:19:36
So in SMOOTHNESS_TAKES_PRIORITY, we prioritize the
epennerAtGoogle
2014/02/12 23:08:46
I had to deal with this sticky case before when we
vmpstr
2014/02/12 23:21:04
I guess the exception is NEW_CONTENT_TAKES_PRIORIT
| |
| 669 | 681 |
| 670 size_t tile_bytes = 0; | 682 size_t tile_bytes = 0; |
| 671 size_t tile_resources = 0; | 683 size_t tile_resources = 0; |
| 672 | 684 |
| 685 | |
|
reveman
2014/02/12 20:08:02
nit: no need for this line. I'm surprised the pres
epennerAtGoogle
2014/02/12 21:54:34
Sorry I didn't rerun git cl format. Done.
| |
| 673 // It costs to maintain a resource. | 686 // It costs to maintain a resource. |
| 674 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { | 687 for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| 675 if (mts.tile_versions[mode].resource_) { | 688 if (mts.tile_versions[mode].resource_) { |
| 676 tile_bytes += bytes_if_allocated; | 689 tile_bytes += bytes_if_allocated; |
| 677 tile_resources++; | 690 tile_resources++; |
| 678 } | 691 } |
| 679 } | 692 } |
| 680 | 693 |
| 681 // Allow lower priority tiles with initialized resources to keep | 694 // Allow lower priority tiles with initialized resources to keep |
| 682 // their memory by only assigning memory to new raster tasks if | 695 // their memory by only assigning memory to new raster tasks if |
| 683 // they can be scheduled. | 696 // they can be scheduled. |
| 684 if (raster_bytes_if_rastered <= max_raster_bytes) { | 697 if (raster_bytes_if_rastered <= max_raster_bytes) { |
| 685 // If we don't have the required version, and it's not in flight | 698 // If we don't have the required version, and it's not in flight |
| 686 // then we'll have to pay to create a new task. | 699 // then we'll have to pay to create a new task. |
| 687 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { | 700 if (!tile_version.resource_ && tile_version.raster_task_.is_null()) { |
| 688 tile_bytes += bytes_if_allocated; | 701 tile_bytes += bytes_if_allocated; |
| 689 tile_resources++; | 702 tile_resources++; |
| 690 } | 703 } |
| 691 } | 704 } |
| 692 | 705 |
| 693 // Tile is OOM. | 706 // Tile is OOM. |
| 694 if (tile_bytes > bytes_left || tile_resources > resources_left) { | 707 if (tile_bytes > tile_bytes_left || tile_resources > resources_left) { |
| 695 FreeResourcesForTile(tile); | 708 FreeResourcesForTile(tile); |
| 696 | 709 |
| 697 // This tile was already on screen and now its resources have been | 710 // This tile was already on screen and now its resources have been |
| 698 // released. In order to prevent checkerboarding, set this tile as | 711 // released. In order to prevent checkerboarding, set this tile as |
| 699 // rasterize on demand immediately. | 712 // rasterize on demand immediately. |
| 700 if (mts.visible_and_ready_to_draw) | 713 if (mts.visible_and_ready_to_draw) |
| 701 tile_version.set_rasterize_on_demand(); | 714 tile_version.set_rasterize_on_demand(); |
| 702 | 715 |
| 703 oomed = true; | 716 oomed_soft = true; |
| 704 bytes_that_exceeded_memory_budget += tile_bytes; | 717 if (mts.bin == NOW_BIN) { |
| 718 oomed_hard = true; | |
| 719 bytes_that_exceeded_memory_budget += tile_bytes; | |
| 720 } | |
| 705 } else { | 721 } else { |
| 706 bytes_left -= tile_bytes; | 722 hard_bytes_left -= tile_bytes; |
| 723 soft_bytes_left -= tile_bytes; | |
| 724 soft_bytes_left = std::max<int64>(0, soft_bytes_left); | |
|
reveman
2014/02/12 20:08:02
does it hurt to let this go negative? in that case
epennerAtGoogle
2014/02/12 21:54:34
Do you mean make it unsigned and add a if-statemen
reveman
2014/02/12 22:14:52
I was thinking you'd keep this signed and just let
| |
| 725 | |
| 707 resources_left -= tile_resources; | 726 resources_left -= tile_resources; |
| 708 | 727 |
| 709 if (tile_version.resource_) | 728 if (tile_version.resource_) |
| 710 continue; | 729 continue; |
| 711 } | 730 } |
| 712 | 731 |
| 713 DCHECK(!tile_version.resource_); | 732 DCHECK(!tile_version.resource_); |
| 714 | 733 |
| 715 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| | 734 // Tile shouldn't be rasterized if |tiles_that_need_to_be_rasterized| |
| 716 // has reached it's limit or we've failed to assign gpu memory to this | 735 // has reached it's limit or we've failed to assign gpu memory to this |
| 717 // or any higher priority tile. Preventing tiles that fit into memory | 736 // or any higher priority tile. Preventing tiles that fit into memory |
| 718 // budget to be rasterized when higher priority tile is oom is | 737 // budget to be rasterized when higher priority tile is oom is |
| 719 // important for two reasons: | 738 // important for two reasons: |
| 720 // 1. Tile size should not impact raster priority. | 739 // 1. Tile size should not impact raster priority. |
| 721 // 2. Tiles with existing raster task could otherwise incorrectly | 740 // 2. Tiles with existing raster task could otherwise incorrectly |
| 722 // be added as they are not affected by |bytes_allocatable|. | 741 // be added as they are not affected by |bytes_allocatable|. |
| 723 if (oomed || raster_bytes_if_rastered > max_raster_bytes) { | 742 if (oomed_soft || raster_bytes_if_rastered > max_raster_bytes) { |
| 724 all_tiles_that_need_to_be_rasterized_have_memory_ = false; | 743 all_tiles_that_need_to_be_rasterized_have_memory_ = false; |
| 725 if (tile->required_for_activation()) | 744 if (tile->required_for_activation()) |
| 726 all_tiles_required_for_activation_have_memory_ = false; | 745 all_tiles_required_for_activation_have_memory_ = false; |
| 727 it.DisablePriorityOrdering(); | 746 it.DisablePriorityOrdering(); |
| 728 continue; | 747 continue; |
| 729 } | 748 } |
| 730 | 749 |
| 731 raster_bytes = raster_bytes_if_rastered; | 750 raster_bytes = raster_bytes_if_rastered; |
| 732 tiles_that_need_to_be_rasterized->push_back(tile); | 751 tiles_that_need_to_be_rasterized->push_back(tile); |
| 733 } | 752 } |
| 734 | 753 |
| 735 ever_exceeded_memory_budget_ |= bytes_that_exceeded_memory_budget > 0; | 754 // OOM reporting uses hard-limit, soft-OOM is normal depending on limit. |
| 755 ever_exceeded_memory_budget_ |= oomed_hard; | |
| 736 if (ever_exceeded_memory_budget_) { | 756 if (ever_exceeded_memory_budget_) { |
| 737 TRACE_COUNTER_ID2("cc", | 757 TRACE_COUNTER_ID2("cc", |
| 738 "over_memory_budget", | 758 "over_memory_budget", |
| 739 this, | 759 this, |
| 740 "budget", | 760 "budget", |
| 741 global_state_.memory_limit_in_bytes, | 761 global_state_.hard_memory_limit_in_bytes, |
| 742 "over", | 762 "over", |
| 743 bytes_that_exceeded_memory_budget); | 763 bytes_that_exceeded_memory_budget); |
| 744 } | 764 } |
| 745 memory_stats_from_last_assign_.total_budget_in_bytes = | 765 memory_stats_from_last_assign_.total_budget_in_bytes = |
| 746 global_state_.memory_limit_in_bytes; | 766 global_state_.hard_memory_limit_in_bytes; |
| 747 memory_stats_from_last_assign_.bytes_allocated = | 767 memory_stats_from_last_assign_.bytes_allocated = |
| 748 bytes_allocatable - bytes_left; | 768 hard_bytes_allocatable - hard_bytes_left; |
| 749 memory_stats_from_last_assign_.bytes_unreleasable = | 769 memory_stats_from_last_assign_.bytes_unreleasable = |
| 750 bytes_allocatable - bytes_releasable_; | 770 hard_bytes_allocatable - bytes_releasable_; |
| 751 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; | 771 memory_stats_from_last_assign_.bytes_over = bytes_that_exceeded_memory_budget; |
| 752 } | 772 } |
| 753 | 773 |
| 754 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { | 774 void TileManager::FreeResourceForTile(Tile* tile, RasterMode mode) { |
| 755 ManagedTileState& mts = tile->managed_state(); | 775 ManagedTileState& mts = tile->managed_state(); |
| 756 if (mts.tile_versions[mode].resource_) { | 776 if (mts.tile_versions[mode].resource_) { |
| 757 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); | 777 resource_pool_->ReleaseResource(mts.tile_versions[mode].resource_.Pass()); |
| 758 | 778 |
| 759 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); | 779 DCHECK_GE(bytes_releasable_, BytesConsumedIfAllocated(tile)); |
| 760 DCHECK_GE(resources_releasable_, 1u); | 780 DCHECK_GE(resources_releasable_, 1u); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 975 flags)); | 995 flags)); |
| 976 DCHECK(tiles_.find(tile->id()) == tiles_.end()); | 996 DCHECK(tiles_.find(tile->id()) == tiles_.end()); |
| 977 | 997 |
| 978 tiles_[tile->id()] = tile; | 998 tiles_[tile->id()] = tile; |
| 979 used_layer_counts_[tile->layer_id()]++; | 999 used_layer_counts_[tile->layer_id()]++; |
| 980 prioritized_tiles_dirty_ = true; | 1000 prioritized_tiles_dirty_ = true; |
| 981 return tile; | 1001 return tile; |
| 982 } | 1002 } |
| 983 | 1003 |
| 984 } // namespace cc | 1004 } // namespace cc |
| OLD | NEW |