Index: cc/resources/tile_manager.cc |
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc |
index 309c2b3519d63e417843d01e72a9505d4bbbcee7..400a9e934241a2092960eae59f5966dffb08e4d6 100644 |
--- a/cc/resources/tile_manager.cc |
+++ b/cc/resources/tile_manager.cc |
@@ -203,9 +203,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)); |
} |
@@ -214,15 +215,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, |
@@ -319,8 +329,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. |
@@ -394,31 +408,100 @@ 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; |
+ enum Rasterizer::PrepareTilesMode prepare_tiles_mode = |
+ rasterizer_->PrepareTilesMode(); |
+ |
+ if (prepare_tiles_mode != GpuRasterizer::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(); |
+ 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::PrepareTilesBeforeDraw( |
+ const GlobalStateThatImpactsTilePriority& state) { |
+ DCHECK(rasterizer_); |
+ TRACE_EVENT0("cc", "TileManager::PrepareTilesBeforeDraw"); |
+ |
+ enum Rasterizer::PrepareTilesMode prepare_tiles_mode = |
+ rasterizer_->PrepareTilesMode(); |
+ |
+ if (prepare_tiles_mode == GpuRasterizer::RASTERIZE_PRIORITIZED_TILES) |
+ return; |
+ |
+ global_state_ = state; |
+ |
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); |
+ AssignGpuMemoryToTiles(&tiles_that_need_to_be_rasterized, |
+ std::numeric_limits<size_t>::max(), true); |
+ |
+ // We must reduce the amount of unused resoruces before calling |
+ // RunTasks to prevent usage from rising above limits. |
+ resource_pool_->ReduceResourceUsage(); |
+ |
+ // Run and complete all raster task synchronously. |
+ rasterizer_->RasterizeTiles(tiles_that_need_to_be_rasterized, resource_pool_, |
+ this); |
+ |
+ // 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(); |
+ ManagedTileState& mts = tile->managed_state(); |
- // Schedule tile tasks. |
- ScheduleTasks(tiles_that_need_to_be_rasterized); |
+ if (tile->required_for_draw() && !mts.draw_info.IsReadyToDraw()) { |
+ mts.draw_info.set_rasterize_on_demand(); |
+ client_->NotifyTileStateChanged(tile); |
+ } |
+ raster_priority_queue_.Pop(); |
+ } |
+ raster_priority_queue_.Reset(); |
- did_notify_ready_to_activate_ = false; |
- did_notify_ready_to_draw_ = false; |
+ if (IsReadyToDraw()) |
+ client_->NotifyReadyToDraw(); |
- TRACE_EVENT_INSTANT1("cc", "DidPrepare", TRACE_EVENT_SCOPE_THREAD, "state", |
+ 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()); |
} |
@@ -522,7 +605,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 |
@@ -546,24 +631,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(); |
+ 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; |
} |
@@ -596,8 +686,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. |
@@ -628,10 +717,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", |
@@ -783,6 +869,13 @@ void TileManager::OnImageDecodeTaskCompleted(int layer_id, |
pixel_ref_tasks.erase(task_it); |
} |
+void TileManager::CompleteRasterTask( |
+ Tile::Id tile_id, |
+ scoped_ptr<ScopedResource> resource, |
+ const RasterSource::SolidColorAnalysis& analysis) { |
+ OnRasterTaskCompleted(tile_id, resource.Pass(), analysis, false); |
+} |
+ |
void TileManager::OnRasterTaskCompleted( |
Tile::Id tile_id, |
scoped_ptr<ScopedResource> resource, |
@@ -792,9 +885,10 @@ void TileManager::OnRasterTaskCompleted( |
Tile* tile = tiles_[tile_id]; |
ManagedTileState& mts = tile->managed_state(); |
- DCHECK(mts.raster_task.get()); |
- orphan_raster_tasks_.push_back(mts.raster_task); |
- mts.raster_task = NULL; |
+ if (mts.raster_task.get()) { |
+ orphan_raster_tasks_.push_back(mts.raster_task); |
+ mts.raster_task = NULL; |
+ } |
if (was_canceled) { |
++update_visible_tiles_stats_.canceled_count; |
@@ -866,6 +960,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_) |
+ return; |
+ client_->NotifyReadyToDraw(); |
+ did_notify_ready_to_draw_ = true; |
+} |
+ |
void TileManager::CheckIfReadyToActivate() { |
TRACE_EVENT0("cc", "TileManager::CheckIfReadyToActivate"); |
@@ -877,8 +987,7 @@ void TileManager::CheckIfReadyToActivate() { |
if (!IsReadyToActivate()) |
return; |
- client_->NotifyReadyToActivate(); |
- did_notify_ready_to_activate_ = true; |
+ NotifyReadyToActivate(); |
} |
void TileManager::CheckIfReadyToDraw() { |
@@ -892,8 +1001,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) { |