| 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/tiles/tile_manager.h" | 5 #include "cc/tiles/tile_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) { | 293 RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) { |
| 294 std::unique_ptr<base::trace_event::TracedValue> state( | 294 std::unique_ptr<base::trace_event::TracedValue> state( |
| 295 new base::trace_event::TracedValue()); | 295 new base::trace_event::TracedValue()); |
| 296 state->SetInteger("completed_count", | 296 state->SetInteger("completed_count", |
| 297 base::saturated_cast<int>(stats.completed_count)); | 297 base::saturated_cast<int>(stats.completed_count)); |
| 298 state->SetInteger("canceled_count", | 298 state->SetInteger("canceled_count", |
| 299 base::saturated_cast<int>(stats.canceled_count)); | 299 base::saturated_cast<int>(stats.canceled_count)); |
| 300 return std::move(state); | 300 return std::move(state); |
| 301 } | 301 } |
| 302 | 302 |
| 303 // static |
| 304 std::unique_ptr<TileManager> TileManager::Create( |
| 305 TileManagerClient* client, |
| 306 base::SequencedTaskRunner* task_runner, |
| 307 size_t scheduled_raster_task_limit, |
| 308 bool use_partial_raster) { |
| 309 // TODO(vmpstr): |task_runner| is a raw pointer that is implicitly converted |
| 310 // into a scoped_refptr. Figure out whether to plumb a ref pointer or whether |
| 311 // tile manager can have a non-owning pointer and fix. |
| 312 return base::WrapUnique(new TileManager( |
| 313 client, task_runner, scheduled_raster_task_limit, use_partial_raster)); |
| 314 } |
| 315 |
| 303 TileManager::TileManager(TileManagerClient* client, | 316 TileManager::TileManager(TileManagerClient* client, |
| 304 scoped_refptr<base::SequencedTaskRunner> task_runner, | 317 scoped_refptr<base::SequencedTaskRunner> task_runner, |
| 305 size_t scheduled_raster_task_limit, | 318 size_t scheduled_raster_task_limit, |
| 306 bool use_partial_raster) | 319 bool use_partial_raster) |
| 307 : client_(client), | 320 : client_(client), |
| 308 task_runner_(std::move(task_runner)), | 321 task_runner_(std::move(task_runner)), |
| 309 resource_pool_(nullptr), | 322 resource_pool_(nullptr), |
| 310 tile_task_manager_(nullptr), | 323 tile_task_manager_(nullptr), |
| 311 scheduled_raster_task_limit_(scheduled_raster_task_limit), | 324 scheduled_raster_task_limit_(scheduled_raster_task_limit), |
| 312 use_partial_raster_(use_partial_raster), | 325 use_partial_raster_(use_partial_raster), |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 // We need to call CheckForCompletedTasks() once in-between each call | 470 // We need to call CheckForCompletedTasks() once in-between each call |
| 458 // to ScheduleTasks() to prevent canceled tasks from being scheduled. | 471 // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| 459 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { | 472 if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| 460 tile_task_manager_->CheckForCompletedTasks(); | 473 tile_task_manager_->CheckForCompletedTasks(); |
| 461 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 474 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 462 } | 475 } |
| 463 | 476 |
| 464 FreeResourcesForReleasedTiles(); | 477 FreeResourcesForReleasedTiles(); |
| 465 CleanUpReleasedTiles(); | 478 CleanUpReleasedTiles(); |
| 466 | 479 |
| 467 std::vector<PrioritizedTile> tiles_that_need_to_be_rasterized = | 480 PrioritizedTileVector tiles_that_need_to_be_rasterized; |
| 468 AssignGpuMemoryToTiles(); | 481 std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue( |
| 482 client_->BuildRasterQueue(global_state_.tree_priority, |
| 483 RasterTilePriorityQueue::Type::ALL)); |
| 484 AssignGpuMemoryToTiles(raster_priority_queue.get(), |
| 485 scheduled_raster_task_limit_, |
| 486 &tiles_that_need_to_be_rasterized); |
| 469 | 487 |
| 470 // Inform the client that will likely require a draw if the highest priority | 488 // Inform the client that will likely require a draw if the highest priority |
| 471 // tile that will be rasterized is required for draw. | 489 // tile that will be rasterized is required for draw. |
| 472 client_->SetIsLikelyToRequireADraw( | 490 client_->SetIsLikelyToRequireADraw( |
| 473 !tiles_that_need_to_be_rasterized.empty() && | 491 !tiles_that_need_to_be_rasterized.empty() && |
| 474 tiles_that_need_to_be_rasterized.front().tile()->required_for_draw()); | 492 tiles_that_need_to_be_rasterized.front().tile()->required_for_draw()); |
| 475 | 493 |
| 476 // Schedule tile tasks. | 494 // Schedule tile tasks. |
| 477 ScheduleTasks(tiles_that_need_to_be_rasterized); | 495 ScheduleTasks(tiles_that_need_to_be_rasterized); |
| 478 | 496 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 case ALLOW_PREPAINT_ONLY: | 590 case ALLOW_PREPAINT_ONLY: |
| 573 return priority.priority_bin > TilePriority::SOON; | 591 return priority.priority_bin > TilePriority::SOON; |
| 574 case ALLOW_ANYTHING: | 592 case ALLOW_ANYTHING: |
| 575 return priority.distance_to_visible == | 593 return priority.distance_to_visible == |
| 576 std::numeric_limits<float>::infinity(); | 594 std::numeric_limits<float>::infinity(); |
| 577 } | 595 } |
| 578 NOTREACHED(); | 596 NOTREACHED(); |
| 579 return true; | 597 return true; |
| 580 } | 598 } |
| 581 | 599 |
| 582 std::vector<PrioritizedTile> TileManager::AssignGpuMemoryToTiles() { | 600 void TileManager::AssignGpuMemoryToTiles( |
| 601 RasterTilePriorityQueue* raster_priority_queue, |
| 602 size_t scheduled_raster_task_limit, |
| 603 PrioritizedTileVector* tiles_that_need_to_be_rasterized) { |
| 583 TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles"); | 604 TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles"); |
| 584 | 605 |
| 585 DCHECK(resource_pool_); | 606 DCHECK(resource_pool_); |
| 586 DCHECK(tile_task_manager_); | 607 DCHECK(tile_task_manager_); |
| 587 | 608 |
| 588 // Maintain the list of released resources that can potentially be re-used | 609 // Maintain the list of released resources that can potentially be re-used |
| 589 // or deleted. If this operation becomes expensive too, only do this after | 610 // or deleted. If this operation becomes expensive too, only do this after |
| 590 // some resource(s) was returned. Note that in that case, one also need to | 611 // some resource(s) was returned. Note that in that case, one also need to |
| 591 // invalidate when releasing some resource from the pool. | 612 // invalidate when releasing some resource from the pool. |
| 592 resource_pool_->CheckBusyResources(); | 613 resource_pool_->CheckBusyResources(); |
| 593 | 614 |
| 594 // Now give memory out to the tiles until we're out, and build | 615 // Now give memory out to the tiles until we're out, and build |
| 595 // the needs-to-be-rasterized queue. | 616 // the needs-to-be-rasterized queue. |
| 596 unsigned schedule_priority = 1u; | 617 unsigned schedule_priority = 1u; |
| 597 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; | 618 all_tiles_that_need_to_be_rasterized_are_scheduled_ = true; |
| 598 bool had_enough_memory_to_schedule_tiles_needed_now = true; | 619 bool had_enough_memory_to_schedule_tiles_needed_now = true; |
| 599 | 620 |
| 600 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, | 621 MemoryUsage hard_memory_limit(global_state_.hard_memory_limit_in_bytes, |
| 601 global_state_.num_resources_limit); | 622 global_state_.num_resources_limit); |
| 602 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, | 623 MemoryUsage soft_memory_limit(global_state_.soft_memory_limit_in_bytes, |
| 603 global_state_.num_resources_limit); | 624 global_state_.num_resources_limit); |
| 604 MemoryUsage memory_usage(resource_pool_->memory_usage_bytes(), | 625 MemoryUsage memory_usage(resource_pool_->memory_usage_bytes(), |
| 605 resource_pool_->resource_count()); | 626 resource_pool_->resource_count()); |
| 606 | 627 |
| 607 std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue( | |
| 608 client_->BuildRasterQueue(global_state_.tree_priority, | |
| 609 RasterTilePriorityQueue::Type::ALL)); | |
| 610 std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue; | 628 std::unique_ptr<EvictionTilePriorityQueue> eviction_priority_queue; |
| 611 std::vector<PrioritizedTile> tiles_that_need_to_be_rasterized; | |
| 612 for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { | 629 for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { |
| 613 const PrioritizedTile& prioritized_tile = raster_priority_queue->Top(); | 630 const PrioritizedTile& prioritized_tile = raster_priority_queue->Top(); |
| 614 Tile* tile = prioritized_tile.tile(); | 631 Tile* tile = prioritized_tile.tile(); |
| 615 TilePriority priority = prioritized_tile.priority(); | 632 TilePriority priority = prioritized_tile.priority(); |
| 616 | 633 |
| 617 if (TilePriorityViolatesMemoryPolicy(priority)) { | 634 if (TilePriorityViolatesMemoryPolicy(priority)) { |
| 618 TRACE_EVENT_INSTANT0( | 635 TRACE_EVENT_INSTANT0( |
| 619 "cc", "TileManager::AssignGpuMemory tile violates memory policy", | 636 "cc", "TileManager::AssignGpuMemory tile violates memory policy", |
| 620 TRACE_EVENT_SCOPE_THREAD); | 637 TRACE_EVENT_SCOPE_THREAD); |
| 621 break; | 638 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 635 tile->draw_info().set_solid_color(color); | 652 tile->draw_info().set_solid_color(color); |
| 636 tile->draw_info().set_was_ever_ready_to_draw(); | 653 tile->draw_info().set_was_ever_ready_to_draw(); |
| 637 if (!tile_is_needed_now) | 654 if (!tile_is_needed_now) |
| 638 tile->draw_info().set_was_a_prepaint_tile(); | 655 tile->draw_info().set_was_a_prepaint_tile(); |
| 639 client_->NotifyTileStateChanged(tile); | 656 client_->NotifyTileStateChanged(tile); |
| 640 continue; | 657 continue; |
| 641 } | 658 } |
| 642 } | 659 } |
| 643 | 660 |
| 644 // We won't be able to schedule this tile, so break out early. | 661 // We won't be able to schedule this tile, so break out early. |
| 645 if (tiles_that_need_to_be_rasterized.size() >= | 662 if (tiles_that_need_to_be_rasterized->size() >= |
| 646 scheduled_raster_task_limit_) { | 663 scheduled_raster_task_limit) { |
| 647 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; | 664 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; |
| 648 break; | 665 break; |
| 649 } | 666 } |
| 650 | 667 |
| 651 tile->scheduled_priority_ = schedule_priority++; | 668 tile->scheduled_priority_ = schedule_priority++; |
| 652 | 669 |
| 653 DCHECK(tile->draw_info().mode() == TileDrawInfo::OOM_MODE || | 670 DCHECK(tile->draw_info().mode() == TileDrawInfo::OOM_MODE || |
| 654 !tile->draw_info().IsReadyToDraw()); | 671 !tile->draw_info().IsReadyToDraw()); |
| 655 | 672 |
| 656 // If the tile already has a raster_task, then the memory used by it is | 673 // If the tile already has a raster_task, then the memory used by it is |
| (...skipping 23 matching lines...) Expand all Loading... |
| 680 // If we couldn't fit the tile into our current memory limit, then we're | 697 // If we couldn't fit the tile into our current memory limit, then we're |
| 681 // done. | 698 // done. |
| 682 if (!memory_usage_is_within_limit) { | 699 if (!memory_usage_is_within_limit) { |
| 683 if (tile_is_needed_now) | 700 if (tile_is_needed_now) |
| 684 had_enough_memory_to_schedule_tiles_needed_now = false; | 701 had_enough_memory_to_schedule_tiles_needed_now = false; |
| 685 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; | 702 all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; |
| 686 break; | 703 break; |
| 687 } | 704 } |
| 688 | 705 |
| 689 memory_usage += memory_required_by_tile_to_be_scheduled; | 706 memory_usage += memory_required_by_tile_to_be_scheduled; |
| 690 tiles_that_need_to_be_rasterized.push_back(prioritized_tile); | 707 tiles_that_need_to_be_rasterized->push_back(prioritized_tile); |
| 691 | 708 |
| 692 // Since we scheduled the tile, set whether it was a prepaint or not | 709 // Since we scheduled the tile, set whether it was a prepaint or not |
| 693 // assuming that the tile will successfully finish running. We don't have | 710 // assuming that the tile will successfully finish running. We don't have |
| 694 // priority information at the time the tile completes, so it should be done | 711 // priority information at the time the tile completes, so it should be done |
| 695 // here. | 712 // here. |
| 696 if (!tile_is_needed_now) | 713 if (!tile_is_needed_now) |
| 697 tile->draw_info().set_was_a_prepaint_tile(); | 714 tile->draw_info().set_was_a_prepaint_tile(); |
| 698 } | 715 } |
| 699 | 716 |
| 700 // Note that we should try and further reduce memory in case the above loop | 717 // Note that we should try and further reduce memory in case the above loop |
| (...skipping 11 matching lines...) Expand all Loading... |
| 712 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); | 729 memory_stats_from_last_assign_.total_bytes_used = memory_usage.memory_bytes(); |
| 713 DCHECK_GE(memory_stats_from_last_assign_.total_bytes_used, 0); | 730 DCHECK_GE(memory_stats_from_last_assign_.total_bytes_used, 0); |
| 714 memory_stats_from_last_assign_.had_enough_memory = | 731 memory_stats_from_last_assign_.had_enough_memory = |
| 715 had_enough_memory_to_schedule_tiles_needed_now; | 732 had_enough_memory_to_schedule_tiles_needed_now; |
| 716 | 733 |
| 717 TRACE_EVENT_END2("cc", "TileManager::AssignGpuMemoryToTiles", | 734 TRACE_EVENT_END2("cc", "TileManager::AssignGpuMemoryToTiles", |
| 718 "all_tiles_that_need_to_be_rasterized_are_scheduled", | 735 "all_tiles_that_need_to_be_rasterized_are_scheduled", |
| 719 all_tiles_that_need_to_be_rasterized_are_scheduled_, | 736 all_tiles_that_need_to_be_rasterized_are_scheduled_, |
| 720 "had_enough_memory_to_schedule_tiles_needed_now", | 737 "had_enough_memory_to_schedule_tiles_needed_now", |
| 721 had_enough_memory_to_schedule_tiles_needed_now); | 738 had_enough_memory_to_schedule_tiles_needed_now); |
| 722 return tiles_that_need_to_be_rasterized; | |
| 723 } | 739 } |
| 724 | 740 |
| 725 void TileManager::FreeResourcesForTile(Tile* tile) { | 741 void TileManager::FreeResourcesForTile(Tile* tile) { |
| 726 TileDrawInfo& draw_info = tile->draw_info(); | 742 TileDrawInfo& draw_info = tile->draw_info(); |
| 727 if (draw_info.resource_) { | 743 if (draw_info.resource_) { |
| 728 resource_pool_->ReleaseResource(draw_info.resource_, tile->id()); | 744 resource_pool_->ReleaseResource(draw_info.resource_, tile->id()); |
| 729 draw_info.resource_ = nullptr; | 745 draw_info.resource_ = nullptr; |
| 730 } | 746 } |
| 731 } | 747 } |
| 732 | 748 |
| 733 void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw( | 749 void TileManager::FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw( |
| 734 Tile* tile) { | 750 Tile* tile) { |
| 735 bool was_ready_to_draw = tile->draw_info().IsReadyToDraw(); | 751 bool was_ready_to_draw = tile->draw_info().IsReadyToDraw(); |
| 736 FreeResourcesForTile(tile); | 752 FreeResourcesForTile(tile); |
| 737 if (was_ready_to_draw) | 753 if (was_ready_to_draw) |
| 738 client_->NotifyTileStateChanged(tile); | 754 client_->NotifyTileStateChanged(tile); |
| 739 } | 755 } |
| 740 | 756 |
| 741 void TileManager::ScheduleTasks( | 757 void TileManager::ScheduleTasks( |
| 742 const std::vector<PrioritizedTile>& tiles_that_need_to_be_rasterized) { | 758 const PrioritizedTileVector& tiles_that_need_to_be_rasterized) { |
| 743 TRACE_EVENT1("cc", "TileManager::ScheduleTasks", "count", | 759 TRACE_EVENT1("cc", "TileManager::ScheduleTasks", "count", |
| 744 tiles_that_need_to_be_rasterized.size()); | 760 tiles_that_need_to_be_rasterized.size()); |
| 745 | 761 |
| 746 DCHECK(did_check_for_completed_tasks_since_last_schedule_tasks_); | 762 DCHECK(did_check_for_completed_tasks_since_last_schedule_tasks_); |
| 747 | 763 |
| 748 if (!has_scheduled_tile_tasks_) { | 764 if (!has_scheduled_tile_tasks_) { |
| 749 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); | 765 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); |
| 750 } | 766 } |
| 751 | 767 |
| 752 // Cancel existing OnTaskSetFinished callbacks. | 768 // Cancel existing OnTaskSetFinished callbacks. |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 } | 1074 } |
| 1059 } | 1075 } |
| 1060 } | 1076 } |
| 1061 | 1077 |
| 1062 void TileManager::CheckIfMoreTilesNeedToBePrepared() { | 1078 void TileManager::CheckIfMoreTilesNeedToBePrepared() { |
| 1063 tile_task_manager_->CheckForCompletedTasks(); | 1079 tile_task_manager_->CheckForCompletedTasks(); |
| 1064 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; | 1080 did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| 1065 | 1081 |
| 1066 // When OOM, keep re-assigning memory until we reach a steady state | 1082 // When OOM, keep re-assigning memory until we reach a steady state |
| 1067 // where top-priority tiles are initialized. | 1083 // where top-priority tiles are initialized. |
| 1068 std::vector<PrioritizedTile> tiles_that_need_to_be_rasterized = | 1084 PrioritizedTileVector tiles_that_need_to_be_rasterized; |
| 1069 AssignGpuMemoryToTiles(); | 1085 std::unique_ptr<RasterTilePriorityQueue> raster_priority_queue( |
| 1086 client_->BuildRasterQueue(global_state_.tree_priority, |
| 1087 RasterTilePriorityQueue::Type::ALL)); |
| 1088 AssignGpuMemoryToTiles(raster_priority_queue.get(), |
| 1089 scheduled_raster_task_limit_, |
| 1090 &tiles_that_need_to_be_rasterized); |
| 1070 | 1091 |
| 1071 // Inform the client that will likely require a draw if the highest priority | 1092 // Inform the client that will likely require a draw if the highest priority |
| 1072 // tile that will be rasterized is required for draw. | 1093 // tile that will be rasterized is required for draw. |
| 1073 client_->SetIsLikelyToRequireADraw( | 1094 client_->SetIsLikelyToRequireADraw( |
| 1074 !tiles_that_need_to_be_rasterized.empty() && | 1095 !tiles_that_need_to_be_rasterized.empty() && |
| 1075 tiles_that_need_to_be_rasterized.front().tile()->required_for_draw()); | 1096 tiles_that_need_to_be_rasterized.front().tile()->required_for_draw()); |
| 1076 | 1097 |
| 1077 // |tiles_that_need_to_be_rasterized| will be empty when we reach a | 1098 // |tiles_that_need_to_be_rasterized| will be empty when we reach a |
| 1078 // steady memory state. Keep scheduling tasks until we reach this state. | 1099 // steady memory state. Keep scheduling tasks until we reach this state. |
| 1079 if (!tiles_that_need_to_be_rasterized.empty()) { | 1100 if (!tiles_that_need_to_be_rasterized.empty()) { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 void TileManager::Signals::reset() { | 1264 void TileManager::Signals::reset() { |
| 1244 ready_to_activate = false; | 1265 ready_to_activate = false; |
| 1245 did_notify_ready_to_activate = false; | 1266 did_notify_ready_to_activate = false; |
| 1246 ready_to_draw = false; | 1267 ready_to_draw = false; |
| 1247 did_notify_ready_to_draw = false; | 1268 did_notify_ready_to_draw = false; |
| 1248 all_tile_tasks_completed = false; | 1269 all_tile_tasks_completed = false; |
| 1249 did_notify_all_tile_tasks_completed = false; | 1270 did_notify_all_tile_tasks_completed = false; |
| 1250 } | 1271 } |
| 1251 | 1272 |
| 1252 } // namespace cc | 1273 } // namespace cc |
| OLD | NEW |