Chromium Code Reviews| Index: cc/tile_manager.cc |
| diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc |
| index 83c0ab2b235d2f557631804d14967b174ae1e1bb..629d0e75e9acd1ff28f8b38655613a0910f574b3 100644 |
| --- a/cc/tile_manager.cc |
| +++ b/cc/tile_manager.cc |
| @@ -34,6 +34,15 @@ const int kMaxPendingUploadBytes = 20 * 1024 * 1024; |
| const int kMaxPendingUploadBytes = 100 * 1024 * 1024; |
| #endif |
| +// Limit the total number of cheap tile rasterizations we are allowed to perform |
| +// during a single frame as well as the time spent rasterizing. |
| +// TODO(skyostil): Determine these limits more dynamically. |
| +const int kMaxCheapRasterCount = 6; |
| +const int kMaxCheapRasterMilliseconds = 6; |
| + |
| +// Expected time for a cheap tile raster. Only used for tracing. |
| +const int kExpectedCheapRasterMilliseconds = 2; |
|
nduca
2013/02/06 08:34:57
I've been working off of 1. Why 2?
Sami
2013/02/06 15:25:14
Tom was telling me his heuristic gave 1 ms rasters
|
| + |
| // Determine bin based on three categories of tiles: things we need now, |
| // things we need soon, and eventually. |
| inline TileManagerBin BinFromTilePriority(const TilePriority& prio) { |
| @@ -116,7 +125,8 @@ TileManager::TileManager( |
| TileManagerClient* client, |
| ResourceProvider* resource_provider, |
| size_t num_raster_threads, |
| - bool record_rendering_stats) |
| + bool record_rendering_stats, |
| + bool use_cheapness_estimator) |
| : client_(client), |
| resource_pool_(ResourcePool::Create(resource_provider)), |
| raster_worker_pool_(RasterWorkerPool::Create(num_raster_threads, record_rendering_stats)), |
| @@ -124,7 +134,9 @@ TileManager::TileManager( |
| manage_tiles_call_count_(0), |
| bytes_pending_set_pixels_(0), |
| ever_exceeded_memory_budget_(false), |
| - record_rendering_stats_(record_rendering_stats) { |
| + record_rendering_stats_(record_rendering_stats), |
| + use_cheapness_estimator_(use_cheapness_estimator), |
| + cheap_raster_count_(0) { |
| for (int i = 0; i < NUM_STATES; ++i) { |
| for (int j = 0; j < NUM_TREES; ++j) { |
| for (int k = 0; k < NUM_BINS; ++k) |
| @@ -340,6 +352,11 @@ void TileManager::CheckForCompletedTileUploads() { |
| DispatchMoreTasks(); |
| } |
| +void TileManager::ResetCheapRasterBudget() { |
| + cheap_raster_count_ = 0; |
| + cheap_raster_time_ = base::TimeDelta(); |
| +} |
| + |
| void TileManager::GetMemoryStats( |
| size_t* memoryRequiredBytes, |
| size_t* memoryNiceToHaveBytes, |
| @@ -509,7 +526,7 @@ void TileManager::FreeResourcesForTile(Tile* tile) { |
| resource_pool_->ReleaseResource(managed_tile_state.resource.Pass()); |
| } |
| -bool TileManager::CanDispatchRasterTask(Tile* tile) { |
| +bool TileManager::CanDispatchRasterTask(Tile* tile) const { |
| if (raster_worker_pool_->IsBusy()) |
| return false; |
| size_t new_bytes_pending = bytes_pending_set_pixels_; |
| @@ -517,6 +534,39 @@ bool TileManager::CanDispatchRasterTask(Tile* tile) { |
| return new_bytes_pending <= kMaxPendingUploadBytes; |
| } |
| +bool TileManager::CanPerformCheapRaster(Tile* tile) const { |
| + if (!use_cheapness_estimator_) |
| + return false; |
| + if (global_state_.tree_priority == SMOOTHNESS_TAKES_PRIORITY) { |
|
nduca
2013/02/06 08:34:57
I'm not convinced of this part. Please remove and
Sami
2013/02/06 15:25:14
Okay, let's keep things simple.
|
| + TRACE_EVENT_INSTANT0( |
| + "cc", "TileManager::CanPerformCheapRaster smoothness"); |
| + return false; |
| + } |
| + // TODO(skyostil): Use synchronous uploads for inline rasters. |
|
nduca
2013/02/06 08:34:57
dont see why this todo is relevant here... sync up
Sami
2013/02/06 15:25:14
It's referring to the check against the total allo
|
| + size_t new_bytes_pending = bytes_pending_set_pixels_; |
| + new_bytes_pending += tile->bytes_consumed_if_allocated(); |
| + if (new_bytes_pending > kMaxPendingUploadBytes) |
| + return false; |
| + if (cheap_raster_count_ >= kMaxCheapRasterCount) { |
| + TRACE_EVENT_INSTANT0( |
| + "cc", "TileManager::CanPerformCheapRaster too many rasters"); |
| + return false; |
| + } |
| + base::TimeDelta maxCheapRasterTime = |
|
reveman
2013/02/05 20:59:13
nit: max_cheap_raster_time please
Sami
2013/02/06 15:25:14
Done (moved to lthi).
|
| + base::TimeDelta::FromMilliseconds(kMaxCheapRasterMilliseconds); |
| + if (cheap_raster_time_ >= maxCheapRasterTime) { |
|
reveman
2013/02/05 20:59:13
would we get better accuracy if we recorded a "che
Sami
2013/02/06 15:25:14
Good point, we could easily use more real time if
|
| + TRACE_EVENT_INSTANT0( |
| + "cc", "TileManager::CanPerformCheapRaster out of time"); |
| + return false; |
| + } |
| + if (!tile->picture_pile()->IsCheapInRect(tile->content_rect_, |
| + tile->contents_scale())) { |
| + TRACE_EVENT_INSTANT0("cc", "TileManager::CanPerformCheapRaster not cheap"); |
|
nduca
2013/02/06 08:34:57
please remove and integrate with what vlad did in
Sami
2013/02/06 15:25:14
Done.
|
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| void TileManager::DispatchMoreTasks() { |
| // Because tiles in the image decoding list have higher priorities, we |
| // need to process those tiles first before we start to handle the tiles |
| @@ -543,6 +593,20 @@ void TileManager::DispatchMoreTasks() { |
| ManagedTileState& managed_state = tile->managed_state(); |
| if (!managed_state.pending_pixel_refs.empty()) { |
| tiles_with_image_decoding_tasks_.push_back(tile); |
| + } else if (CanPerformCheapRaster(tile)) { |
| + cheap_raster_count_++; |
| + DCHECK(cheap_raster_count_ <= kMaxCheapRasterCount); |
| + base::TimeTicks begin_time = base::TimeTicks::Now(); |
|
reveman
2013/02/05 20:59:13
we recently made sure not to call base::TimeTicks:
Sami
2013/02/06 15:25:14
I'm not sure how else to keep track of time spent
|
| + PerformOneRaster(tile); |
| + base::TimeTicks end_time = base::TimeTicks::Now(); |
| + base::TimeDelta duration = end_time - begin_time; |
| + base::TimeDelta expectedCheapRasterTime = |
|
reveman
2013/02/05 20:59:13
nit: expected_cheap_raster_time
Sami
2013/02/06 15:25:14
Done (moved to lthi).
|
| + base::TimeDelta::FromMilliseconds(kExpectedCheapRasterMilliseconds); |
|
nduca
2013/02/06 08:34:57
is this duplicative? you've got the same boookeepi
Sami
2013/02/06 15:25:14
Yeah, no need for this now that Vlad's patch lande
|
| + if (duration > expectedCheapRasterTime) { |
| + TRACE_EVENT_INSTANT0( |
| + "cc", "TileManager::DispatchMoreTasks raster was not cheap"); |
| + } |
| + cheap_raster_time_ += duration; |
| } else { |
| if (!CanDispatchRasterTask(tile)) |
| return; |
| @@ -633,8 +697,8 @@ void TileManager::OnImageDecodeTaskCompleted( |
| DispatchMoreTasks(); |
| } |
| -void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
| - TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); |
| +scoped_ptr<ResourcePool::Resource> TileManager::PrepareTileForRaster( |
| + Tile* tile) { |
| ManagedTileState& managed_tile_state = tile->managed_state(); |
| DCHECK(managed_tile_state.can_use_gpu_memory); |
| scoped_ptr<ResourcePool::Resource> resource = |
| @@ -645,12 +709,17 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
| managed_tile_state.can_be_freed = false; |
| DidTileRasterStateChange(tile, RASTER_STATE); |
| + return resource.Pass(); |
| +} |
| +void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
| + TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask"); |
| + scoped_ptr<ResourcePool::Resource> resource = PrepareTileForRaster(tile); |
| ResourceProvider::ResourceId resource_id = resource->id(); |
| raster_worker_pool_->PostRasterTaskAndReply( |
| tile->picture_pile(), |
| - base::Bind(&TileManager::RunRasterTask, |
| + base::Bind(&TileManager::PerformRaster, |
| resource_pool_->resource_provider()->mapPixelBuffer( |
| resource_id), |
| tile->content_rect_, |
| @@ -662,11 +731,25 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
| manage_tiles_call_count_)); |
| } |
| -void TileManager::OnRasterTaskCompleted( |
| +void TileManager::PerformOneRaster(Tile* tile) { |
| + scoped_ptr<ResourcePool::Resource> resource = PrepareTileForRaster(tile); |
| + ResourceProvider::ResourceId resource_id = resource->id(); |
| + |
| + PerformRaster(resource_pool_->resource_provider()->mapPixelBuffer( |
| + resource_id), |
| + tile->content_rect_, |
| + tile->contents_scale(), |
| + tile->picture_pile(), |
| + &rendering_stats_); |
| + |
| + OnRasterCompleted(tile, resource.Pass(), manage_tiles_call_count_); |
| +} |
| + |
| +void TileManager::OnRasterCompleted( |
| scoped_refptr<Tile> tile, |
| scoped_ptr<ResourcePool::Resource> resource, |
| int manage_tiles_call_count_when_dispatched) { |
| - TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted"); |
| + TRACE_EVENT0("cc", "TileManager::OnRasterCompleted"); |
| // Release raster resources. |
| resource_pool_->resource_provider()->unmapPixelBuffer(resource->id()); |
| @@ -707,7 +790,14 @@ void TileManager::OnRasterTaskCompleted( |
| managed_tile_state.resource_is_being_initialized = false; |
| DidTileRasterStateChange(tile, IDLE_STATE); |
| } |
| +} |
| +void TileManager::OnRasterTaskCompleted( |
| + scoped_refptr<Tile> tile, |
| + scoped_ptr<ResourcePool::Resource> resource, |
| + int manage_tiles_call_count_when_dispatched) { |
| + OnRasterCompleted(tile, resource.Pass(), |
| + manage_tiles_call_count_when_dispatched); |
| DispatchMoreTasks(); |
| } |
| @@ -750,12 +840,12 @@ void TileManager::DidTileBinChange(Tile* tile, |
| } |
| // static |
| -void TileManager::RunRasterTask(uint8* buffer, |
| +void TileManager::PerformRaster(uint8* buffer, |
| const gfx::Rect& rect, |
| float contents_scale, |
| PicturePileImpl* picture_pile, |
| RenderingStats* stats) { |
| - TRACE_EVENT0("cc", "TileManager::RunRasterTask"); |
| + TRACE_EVENT0("cc", "TileManager::PerformRaster"); |
| DCHECK(picture_pile); |
| DCHECK(buffer); |
| SkBitmap bitmap; |