Chromium Code Reviews| Index: cc/resources/tile_manager.cc |
| diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc |
| index 56f495f05e370d93ad01b49032cac6d32b1915a8..f17830c41cfdd818cd259b296d31841ab7f631f1 100644 |
| --- a/cc/resources/tile_manager.cc |
| +++ b/cc/resources/tile_manager.cc |
| @@ -18,6 +18,7 @@ |
| #include "cc/debug/traced_value.h" |
| #include "cc/layers/picture_layer_impl.h" |
| #include "cc/resources/raster_buffer.h" |
| +#include "cc/resources/rasterizer.h" |
| #include "cc/resources/tile.h" |
| #include "cc/resources/tile_task_runner.h" |
| #include "ui/gfx/geometry/rect_conversions.h" |
| @@ -201,9 +202,10 @@ scoped_ptr<TileManager> TileManager::Create( |
| base::SequencedTaskRunner* task_runner, |
| ResourcePool* resource_pool, |
| TileTaskRunner* tile_task_runner, |
| + Rasterizer* rasterizer, |
| size_t scheduled_raster_task_limit) { |
| return make_scoped_ptr(new TileManager(client, task_runner, resource_pool, |
| - tile_task_runner, |
| + tile_task_runner, rasterizer, |
| scheduled_raster_task_limit)); |
| } |
| @@ -212,15 +214,24 @@ TileManager::TileManager( |
| const scoped_refptr<base::SequencedTaskRunner>& task_runner, |
| ResourcePool* resource_pool, |
| TileTaskRunner* tile_task_runner, |
| + Rasterizer* rasterizer, |
| size_t scheduled_raster_task_limit) |
| : client_(client), |
| task_runner_(task_runner), |
| resource_pool_(resource_pool), |
| tile_task_runner_(tile_task_runner), |
| + rasterizer_(rasterizer), |
| scheduled_raster_task_limit_(scheduled_raster_task_limit), |
| all_tiles_that_need_to_be_rasterized_are_scheduled_(true), |
| did_check_for_completed_tasks_since_last_schedule_tasks_(true), |
| did_oom_on_last_assign_(false), |
| + ready_to_activate_notifier_( |
| + task_runner_.get(), |
| + base::Bind(&TileManager::NotifyReadyToActivate, |
| + base::Unretained(this))), |
| + ready_to_draw_notifier_( |
| + task_runner_.get(), |
| + base::Bind(&TileManager::NotifyReadyToDraw, base::Unretained(this))), |
| ready_to_activate_check_notifier_( |
| task_runner_.get(), |
| base::Bind(&TileManager::CheckIfReadyToActivate, |
| @@ -317,8 +328,12 @@ void TileManager::DidFinishRunningTileTasks(TaskSet task_set) { |
| tile_task_runner_->CheckForCompletedTasks(); |
| did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| + client_->BuildRasterQueue(&raster_priority_queue_, |
| + global_state_.tree_priority); |
| TileVector tiles_that_need_to_be_rasterized; |
| - AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized); |
| + AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
| + scheduled_raster_task_limit_, false); |
| + raster_priority_queue_.Reset(); |
| // |tiles_that_need_to_be_rasterized| will be empty when we reach a |
| // steady memory state. Keep scheduling tasks until we reach this state. |
| @@ -392,38 +407,109 @@ void TileManager::PrepareTiles( |
| global_state_ = state; |
| - // We need to call CheckForCompletedTasks() once in-between each call |
| - // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| - if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| - tile_task_runner_->CheckForCompletedTasks(); |
| - did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| + PrepareTilesMode prepare_tiles_mode = rasterizer_->GetPrepareTilesMode(); |
| + |
| + if (prepare_tiles_mode != PrepareTilesMode::PREPARE_NONE) { |
| + // We need to call CheckForCompletedTasks() once in-between each call |
| + // to ScheduleTasks() to prevent canceled tasks from being scheduled. |
| + if (!did_check_for_completed_tasks_since_last_schedule_tasks_) { |
| + tile_task_runner_->CheckForCompletedTasks(); |
| + did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| + } |
| + |
| + FreeResourcesForReleasedTiles(); |
| + CleanUpReleasedTiles(); |
| + |
| + client_->BuildRasterQueue(&raster_priority_queue_, |
| + global_state_.tree_priority); |
| + TileVector tiles_that_need_to_be_rasterized; |
| + |
| + AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
| + scheduled_raster_task_limit_, false); |
| + |
| + raster_priority_queue_.Reset(); |
| + |
| + // Schedule tile tasks. |
| + ScheduleTasks(tiles_that_need_to_be_rasterized); |
| + |
| + did_notify_ready_to_activate_ = false; |
| + did_notify_ready_to_draw_ = false; |
| + } else { |
| + did_notify_ready_to_activate_ = false; |
| + did_notify_ready_to_draw_ = false; |
| + ready_to_activate_notifier_.Schedule(); |
|
vmpstr
2014/12/23 09:51:02
I'm not really a fan of these callbacks. Can we ju
hendrikw
2014/12/23 18:10:33
Nope, they must be scheduled. vmiura, can you jum
vmiura
2014/12/23 18:33:13
The client can end up recursing back into TM::Prep
|
| + ready_to_draw_notifier_.Schedule(); |
| } |
| + TRACE_EVENT_INSTANT1("cc", "DidPrepareTiles", TRACE_EVENT_SCOPE_THREAD, |
| + "state", BasicStateAsValue()); |
| + |
| + TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, |
| + resource_pool_->total_memory_usage_bytes() - |
| + resource_pool_->acquired_memory_usage_bytes()); |
| +} |
| + |
| +void TileManager::SynchronouslyRasterizeTiles( |
| + const GlobalStateThatImpactsTilePriority& state) { |
| + TRACE_EVENT0("cc", "TileManager::SynchronouslyRasterizeTiles"); |
| + |
| + DCHECK(rasterizer_->GetPrepareTilesMode() != |
| + PrepareTilesMode::RASTERIZE_PRIORITIZED_TILES); |
| + |
| + global_state_ = state; |
| + |
| FreeResourcesForReleasedTiles(); |
| CleanUpReleasedTiles(); |
| + client_->BuildRasterQueue(&raster_priority_queue_, |
|
vmpstr
2014/12/23 09:51:03
I think I've mentioned this on the original patch,
hendrikw
2014/12/23 18:10:33
I guess I'll talk with you about this when you get
|
| + global_state_.tree_priority); |
| TileVector tiles_that_need_to_be_rasterized; |
| - AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized); |
| + AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
| + std::numeric_limits<size_t>::max(), true); |
| - // Schedule tile tasks. |
| - ScheduleTasks(tiles_that_need_to_be_rasterized); |
| + // We must reduce the amount of unused resoruces before calling |
| + // RunTasks to prevent usage from rising above limits. |
| + resource_pool_->ReduceResourceUsage(); |
| - did_notify_ready_to_activate_ = false; |
| - did_notify_ready_to_draw_ = false; |
| + // Run and complete all raster task synchronously. |
| + rasterizer_->RasterizeTiles(tiles_that_need_to_be_rasterized, resource_pool_, |
| + this); |
| - TRACE_EVENT_INSTANT1("cc", "DidPrepare", TRACE_EVENT_SCOPE_THREAD, "state", |
| + // Use on-demand raster for any tiles that have not been been assigned |
| + // memory. This ensures that we draw even when OOM. |
| + while (!raster_priority_queue_.IsEmpty()) { |
| + Tile* tile = raster_priority_queue_.Top(); |
| + TileDrawInfo& draw_info = tile->draw_info(); |
| + |
| + if (tile->required_for_draw() && !draw_info.IsReadyToDraw()) { |
| + draw_info.set_rasterize_on_demand(); |
| + client_->NotifyTileStateChanged(tile); |
| + } |
| + raster_priority_queue_.Pop(); |
| + } |
| + raster_priority_queue_.Reset(); |
| + |
| + if (IsReadyToDraw()) |
| + client_->NotifyReadyToDraw(); |
| + |
| + TRACE_EVENT_INSTANT1("cc", "DidRasterize", TRACE_EVENT_SCOPE_THREAD, "state", |
| BasicStateAsValue()); |
| - TRACE_COUNTER_ID1("cc", |
| - "unused_memory_bytes", |
| - this, |
| + TRACE_COUNTER_ID1("cc", "unused_memory_bytes", this, |
| resource_pool_->total_memory_usage_bytes() - |
| resource_pool_->acquired_memory_usage_bytes()); |
| } |
| -void TileManager::UpdateVisibleTiles() { |
| +void TileManager::UpdateVisibleTiles( |
| + const GlobalStateThatImpactsTilePriority& state) { |
| TRACE_EVENT0("cc", "TileManager::UpdateVisibleTiles"); |
| + DCHECK(rasterizer_); |
| + PrepareTilesMode prepare_tiles_mode = rasterizer_->GetPrepareTilesMode(); |
| + |
| + if (prepare_tiles_mode != PrepareTilesMode::RASTERIZE_PRIORITIZED_TILES) |
| + SynchronouslyRasterizeTiles(state); |
| + |
| tile_task_runner_->CheckForCompletedTasks(); |
| did_check_for_completed_tasks_since_last_schedule_tasks_ = true; |
| @@ -520,7 +606,9 @@ bool TileManager::TilePriorityViolatesMemoryPolicy( |
| } |
| void TileManager::AssignGpuMemoryToTiles( |
| - TileVector* tiles_that_need_to_be_rasterized) { |
| + TileVector* tiles_that_need_to_be_rasterized, |
| + size_t scheduled_raster_task_limit, |
| + bool required_for_draw_only) { |
| TRACE_EVENT_BEGIN0("cc", "TileManager::AssignGpuMemoryToTiles"); |
| // Maintain the list of released resources that can potentially be re-used |
| @@ -544,24 +632,29 @@ void TileManager::AssignGpuMemoryToTiles( |
| resource_pool_->acquired_resource_count()); |
| eviction_priority_queue_is_up_to_date_ = false; |
| - client_->BuildRasterQueue(&raster_priority_queue_, |
| - global_state_.tree_priority); |
| while (!raster_priority_queue_.IsEmpty()) { |
| Tile* tile = raster_priority_queue_.Top(); |
| + |
| + if (required_for_draw_only) { |
| + if (!tile->required_for_draw()) { |
| + raster_priority_queue_.Pop(); |
|
vmpstr
2014/12/23 09:51:02
I think this needs some thought. I don't like the
vmiura
2014/12/23 18:33:13
Initially I think we might want to have fewer chan
hendrikw
2014/12/23 18:54:29
Done.
|
| + continue; |
| + } |
| + } |
| + |
| TilePriority priority = tile->combined_priority(); |
| if (TilePriorityViolatesMemoryPolicy(priority)) { |
| TRACE_EVENT_INSTANT0( |
| - "cc", |
| - "TileManager::AssignGpuMemory tile violates memory policy", |
| + "cc", "TileManager::AssignGpuMemory tile violates memory policy", |
| TRACE_EVENT_SCOPE_THREAD); |
| break; |
| } |
| // We won't be able to schedule this tile, so break out early. |
| if (tiles_that_need_to_be_rasterized->size() >= |
| - scheduled_raster_task_limit_) { |
| + scheduled_raster_task_limit) { |
| all_tiles_that_need_to_be_rasterized_are_scheduled_ = false; |
| break; |
| } |
| @@ -592,8 +685,7 @@ void TileManager::AssignGpuMemoryToTiles( |
| bool memory_usage_is_within_limit = |
| FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( |
| tile_memory_limit - memory_required_by_tile_to_be_scheduled, |
| - priority, |
| - &memory_usage); |
| + priority, &memory_usage); |
| // If we couldn't fit the tile into our current memory limit, then we're |
| // done. |
| @@ -624,10 +716,7 @@ void TileManager::AssignGpuMemoryToTiles( |
| memory_stats_from_last_assign_.had_enough_memory = |
| had_enough_memory_to_schedule_tiles_needed_now; |
| - raster_priority_queue_.Reset(); |
| - |
| - TRACE_EVENT_END2("cc", |
| - "TileManager::AssignGpuMemoryToTiles", |
| + TRACE_EVENT_END2("cc", "TileManager::AssignGpuMemoryToTiles", |
| "all_tiles_that_need_to_be_rasterized_are_scheduled", |
| all_tiles_that_need_to_be_rasterized_are_scheduled_, |
| "had_enough_memory_to_schedule_tiles_needed_now", |
| @@ -770,6 +859,13 @@ void TileManager::OnImageDecodeTaskCompleted(int layer_id, |
| pixel_ref_tasks.erase(task_it); |
| } |
| +void TileManager::CompleteRasterTask( |
|
vmpstr
2014/12/23 09:51:03
Why not just call OnRasterTaskCompleted with false
hendrikw
2014/12/23 18:10:33
Changing to a callback, so it doesn't matter.
|
| + Tile::Id tile_id, |
| + scoped_ptr<ScopedResource> resource, |
| + const RasterSource::SolidColorAnalysis& analysis) { |
| + OnRasterTaskCompleted(tile_id, resource.Pass(), analysis, false); |
| +} |
| + |
| void TileManager::OnRasterTaskCompleted( |
|
vmpstr
2014/12/23 09:51:02
Maybe a better split would be if OnRasterTaskCompl
hendrikw
2014/12/23 18:10:33
I'm not sure what InitializeTile is, how it relate
|
| Tile::Id tile_id, |
| scoped_ptr<ScopedResource> resource, |
| @@ -779,9 +875,10 @@ void TileManager::OnRasterTaskCompleted( |
| Tile* tile = tiles_[tile_id]; |
| TileDrawInfo& draw_info = tile->draw_info(); |
| - DCHECK(tile->raster_task_.get()); |
| - orphan_raster_tasks_.push_back(tile->raster_task_); |
| - tile->raster_task_ = NULL; |
| + if (tile->raster_task_.get()) { |
| + orphan_raster_tasks_.push_back(tile->raster_task_); |
| + tile->raster_task_ = nullptr; |
| + } |
| if (was_canceled) { |
| ++update_visible_tiles_stats_.canceled_count; |
| @@ -853,6 +950,22 @@ bool TileManager::IsReadyToDraw() const { |
| return true; |
| } |
| +void TileManager::NotifyReadyToActivate() { |
| + TRACE_EVENT0("cc", "TileManager::NotifyReadyToActivate"); |
| + if (did_notify_ready_to_activate_) |
| + return; |
| + client_->NotifyReadyToActivate(); |
| + did_notify_ready_to_activate_ = true; |
| +} |
| + |
| +void TileManager::NotifyReadyToDraw() { |
| + TRACE_EVENT0("cc", "TileManager::NotifyReadyToDraw"); |
| + if (did_notify_ready_to_draw_) |
|
vmpstr
2014/12/23 09:51:02
We check this twice now on the software path..
hendrikw
2014/12/23 18:10:33
I only see one (REQUIRED_FOR_DRAW), where's the se
|
| + return; |
| + client_->NotifyReadyToDraw(); |
| + did_notify_ready_to_draw_ = true; |
| +} |
| + |
| void TileManager::CheckIfReadyToActivate() { |
| TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); |
| @@ -864,8 +977,7 @@ void TileManager::CheckIfReadyToActivate() { |
| if (!IsReadyToActivate()) |
| return; |
| - client_->NotifyReadyToActivate(); |
| - did_notify_ready_to_activate_ = true; |
| + NotifyReadyToActivate(); |
| } |
| void TileManager::CheckIfReadyToDraw() { |
| @@ -879,8 +991,7 @@ void TileManager::CheckIfReadyToDraw() { |
| if (!IsReadyToDraw()) |
| return; |
| - client_->NotifyReadyToDraw(); |
| - did_notify_ready_to_draw_ = true; |
| + NotifyReadyToDraw(); |
| } |
| TileManager::MemoryUsage::MemoryUsage() : memory_bytes_(0), resource_count_(0) { |