Chromium Code Reviews| Index: cc/resources/tile_manager.cc |
| diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc |
| index 8edacf6896dbeeefb13022df1f679404577f09f4..ff16f301d6e5923c0fbb472f436bfb94f39dec6a 100644 |
| --- a/cc/resources/tile_manager.cc |
| +++ b/cc/resources/tile_manager.cc |
| @@ -16,6 +16,7 @@ |
| #include "cc/resources/image_raster_worker_pool.h" |
| #include "cc/resources/pixel_buffer_raster_worker_pool.h" |
| #include "cc/resources/tile.h" |
| +#include "skia/ext/paint_simplifier.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "ui/gfx/rect_conversions.h" |
| @@ -23,6 +24,18 @@ namespace cc { |
| namespace { |
| +class DisableLCDTextFilter : public SkDrawFilter { |
| + public: |
| + // SkDrawFilter interface. |
| + virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE { |
| + if (type != SkDrawFilter::kText_Type) |
| + return true; |
| + |
| + paint->setLCDRenderText(false); |
| + return true; |
| + } |
| +}; |
| + |
| // Determine bin based on three categories of tiles: things we need now, |
| // things we need soon, and eventually. |
| inline TileManagerBin BinFromTilePriority(const TilePriority& prio) { |
| @@ -306,15 +319,23 @@ void TileManager::CheckForCompletedTileUploads() { |
| it != tiles_that_need_to_be_initialized_for_activation_.end(); |
| ++it) { |
| Tile* tile = *it; |
| - if (!tile->managed_state().raster_task.is_null() && |
| - !tile->tile_version().forced_upload_) { |
| - if (!raster_worker_pool_->ForceUploadToComplete( |
| - tile->managed_state().raster_task)) |
| - continue; |
| + ManagedTileState& mts = tile->managed_state(); |
| - // Setting |forced_upload_| to true makes this tile ready to draw. |
| - tile->tile_version().forced_upload_ = true; |
| - initialized_tiles.insert(tile); |
| + for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| + ManagedTileState::TileVersion& pending_version = |
| + mts.tile_versions[mode]; |
| + if (!pending_version.raster_task_.is_null() && |
| + !pending_version.forced_upload_) { |
| + if (!raster_worker_pool_->ForceUploadToComplete( |
| + pending_version.raster_task_)) { |
| + continue; |
| + } |
| + // Setting |forced_upload_| to true makes this tile version |
| + // ready to draw. |
| + pending_version.forced_upload_ = true; |
| + initialized_tiles.insert(tile); |
| + break; |
| + } |
| } |
| } |
| @@ -323,7 +344,7 @@ void TileManager::CheckForCompletedTileUploads() { |
| ++it) { |
| Tile* tile = *it; |
| DidFinishTileInitialization(tile); |
| - DCHECK(tile->tile_version().IsReadyToDraw()); |
| + DCHECK(tile->IsReadyToDraw(NULL)); |
| } |
| } |
| @@ -338,10 +359,13 @@ void TileManager::GetMemoryStats( |
| it != tiles_.end(); |
| ++it) { |
| const Tile* tile = *it; |
| - if (!tile->tile_version().requires_resource()) |
| + const ManagedTileState& mts = tile->managed_state(); |
| + |
| + TileRasterMode mode; |
| + if (tile->IsReadyToDraw(&mode) && |
| + !mts.tile_versions[mode].requires_resource()) |
| continue; |
| - const ManagedTileState& mts = tile->managed_state(); |
| size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
| if (mts.gpu_memmgr_stats_bin == NOW_BIN) |
| *memory_required_bytes += tile_bytes; |
| @@ -393,6 +417,22 @@ void TileManager::AddRequiredTileForActivation(Tile* tile) { |
| tiles_that_need_to_be_initialized_for_activation_.insert(tile); |
| } |
| +TileRasterMode TileManager::DetermineRasterMode(const Tile* tile) const { |
| + DCHECK(tile); |
| + DCHECK(tile->picture_pile()); |
| + |
| + TileRasterMode raster_mode; |
| + |
| + if (tile->managed_state().resolution == LOW_RESOLUTION) |
| + raster_mode = LOW_QUALITY_RASTER_MODE; |
| + else if (!tile->picture_pile()->can_use_lcd_text()) |
| + raster_mode = HIGH_QUALITY_NO_LCD_RASTER_MODE; |
| + else |
| + raster_mode = HIGH_QUALITY_RASTER_MODE; |
| + |
| + return raster_mode; |
| +} |
| + |
| void TileManager::AssignGpuMemoryToTiles() { |
| TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles"); |
| @@ -406,8 +446,11 @@ void TileManager::AssignGpuMemoryToTiles() { |
| it != tiles_.end(); |
| ++it) { |
| const Tile* tile = *it; |
| - if (tile->tile_version().resource_) |
| - bytes_releasable += tile->bytes_consumed_if_allocated(); |
| + const ManagedTileState& mts = tile->managed_state(); |
| + for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| + if (mts.tile_versions[mode].resource_) |
| + bytes_releasable += tile->bytes_consumed_if_allocated(); |
| + } |
| } |
| // Cast to prevent overflow. |
| @@ -429,7 +472,13 @@ void TileManager::AssignGpuMemoryToTiles() { |
| ++it) { |
| Tile* tile = *it; |
| ManagedTileState& mts = tile->managed_state(); |
| - ManagedTileState::TileVersion& tile_version = tile->tile_version(); |
| + |
| + // Pick the better version out of the one we already set, |
| + // and the one that is required. |
| + mts.raster_mode = std::min(mts.raster_mode, DetermineRasterMode(tile)); |
| + |
| + ManagedTileState::TileVersion& tile_version = |
| + mts.tile_versions[mts.raster_mode]; |
| // If this tile doesn't need a resource, then nothing to do. |
| if (!tile_version.requires_resource()) |
| @@ -444,18 +493,19 @@ void TileManager::AssignGpuMemoryToTiles() { |
| size_t tile_bytes = 0; |
| // It costs to maintain a resource. |
| - if (tile_version.resource_) |
| - tile_bytes += tile->bytes_consumed_if_allocated(); |
| + for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| + if (mts.tile_versions[mode].resource_) |
| + tile_bytes += tile->bytes_consumed_if_allocated(); |
| + } |
| - // It will cost to allocate a resource. |
| - // Note that this is separate from the above condition, |
| - // so that it's clear why we're adding memory. |
| - if (!tile_version.resource_ && mts.raster_task.is_null()) |
| + // If we don't have the required version, and it's not in flight |
| + // then we'll have to pay to create a new task. |
| + if (!tile_version.resource_ && tile_version.raster_task_.is_null()) |
| tile_bytes += tile->bytes_consumed_if_allocated(); |
| // Tile is OOM. |
| if (tile_bytes > bytes_left) { |
| - tile->tile_version().set_rasterize_on_demand(); |
| + mts.tile_versions[mts.raster_mode].set_rasterize_on_demand(); |
| if (mts.tree_bin[PENDING_TREE] == NOW_BIN) { |
| tiles_requiring_memory_but_oomed.push_back(tile); |
| bytes_oom_in_now_bin_on_pending_tree += tile_bytes; |
| @@ -480,8 +530,10 @@ void TileManager::AssignGpuMemoryToTiles() { |
| if (!tile_version.resource_) |
| tiles_that_need_to_be_rasterized_.push_back(tile); |
| - if (!tile_version.resource_ && tile->required_for_activation()) |
| + if (!tile->IsReadyToDraw(NULL) && |
| + tile->required_for_activation()) { |
| AddRequiredTileForActivation(tile); |
| + } |
| } |
| // In OOM situation, we iterate tiles_, remove the memory for active tree |
| @@ -491,33 +543,44 @@ void TileManager::AssignGpuMemoryToTiles() { |
| for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { |
| Tile* tile = *it; |
| ManagedTileState& mts = tile->managed_state(); |
| - ManagedTileState::TileVersion& tile_version = tile->tile_version(); |
| - if (tile_version.resource_ && |
| - mts.tree_bin[PENDING_TREE] == NEVER_BIN && |
| + if (mts.tree_bin[PENDING_TREE] == NEVER_BIN && |
| mts.tree_bin[ACTIVE_TREE] != NOW_BIN) { |
| - DCHECK(!tile->required_for_activation()); |
| - FreeResourcesForTile(tile); |
| - tile_version.set_rasterize_on_demand(); |
| - bytes_freed += tile->bytes_consumed_if_allocated(); |
| - TileVector::iterator it = std::find( |
| - tiles_that_need_to_be_rasterized_.begin(), |
| - tiles_that_need_to_be_rasterized_.end(), |
| - tile); |
| - if (it != tiles_that_need_to_be_rasterized_.end()) |
| - tiles_that_need_to_be_rasterized_.erase(it); |
| - if (bytes_oom_in_now_bin_on_pending_tree <= bytes_freed) |
| - break; |
| + size_t bytes_that_can_be_freed = 0; |
| + for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| + ManagedTileState::TileVersion& tile_version = |
| + mts.tile_versions[mode]; |
| + if (tile_version.resource_) { |
| + DCHECK(!tile->required_for_activation()); |
| + bytes_that_can_be_freed += tile->bytes_consumed_if_allocated(); |
| + } |
| + } |
| + |
| + if (bytes_that_can_be_freed > 0) { |
| + FreeResourcesForTile(tile); |
| + bytes_freed += bytes_that_can_be_freed; |
| + mts.tile_versions[mts.raster_mode].set_rasterize_on_demand(); |
| + TileVector::iterator it = std::find( |
| + tiles_that_need_to_be_rasterized_.begin(), |
| + tiles_that_need_to_be_rasterized_.end(), |
| + tile); |
| + if (it != tiles_that_need_to_be_rasterized_.end()) |
| + tiles_that_need_to_be_rasterized_.erase(it); |
| + } |
| } |
| + |
| + if (bytes_oom_in_now_bin_on_pending_tree <= bytes_freed) |
| + break; |
| } |
| for (TileVector::iterator it = tiles_requiring_memory_but_oomed.begin(); |
| it != tiles_requiring_memory_but_oomed.end() && bytes_freed > 0; |
| ++it) { |
| Tile* tile = *it; |
| + ManagedTileState& mts = tile->managed_state(); |
| size_t bytes_needed = tile->bytes_consumed_if_allocated(); |
| if (bytes_needed > bytes_freed) |
| continue; |
| - tile->tile_version().set_use_resource(); |
| + mts.tile_versions[mts.raster_mode].set_use_resource(); |
| bytes_freed -= bytes_needed; |
| tiles_that_need_to_be_rasterized_.push_back(tile); |
| if (tile->required_for_activation()) |
| @@ -542,10 +605,26 @@ void TileManager::AssignGpuMemoryToTiles() { |
| bytes_that_exceeded_memory_budget_in_now_bin; |
| } |
| -void TileManager::FreeResourcesForTile(Tile* tile) { |
| - if (tile->tile_version().resource_) { |
| +void TileManager::FreeResourceForTile(Tile* tile, TileRasterMode mode) { |
| + ManagedTileState& mts = tile->managed_state(); |
| + if (mts.tile_versions[mode].resource_) { |
| resource_pool_->ReleaseResource( |
| - tile->tile_version().resource_.Pass()); |
| + mts.tile_versions[mode].resource_.Pass()); |
| + } |
| +} |
| + |
| +void TileManager::FreeResourcesForTile(Tile* tile) { |
| + for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| + FreeResourceForTile(tile, static_cast<TileRasterMode>(mode)); |
| + } |
| +} |
| + |
| +void TileManager::FreeUnusedResourcesForTile(Tile* tile) { |
| + TileRasterMode used_mode; |
| + bool version_is_used = tile->IsReadyToDraw(&used_mode); |
| + for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) { |
| + if (!version_is_used || mode != used_mode) |
| + FreeResourceForTile(tile, static_cast<TileRasterMode>(mode)); |
| } |
| } |
| @@ -560,16 +639,16 @@ void TileManager::ScheduleTasks() { |
| ++it) { |
| Tile* tile = *it; |
| ManagedTileState& mts = tile->managed_state(); |
| + ManagedTileState::TileVersion& tile_version = |
| + mts.tile_versions[mts.raster_mode]; |
| - DCHECK(tile->tile_version().requires_resource()); |
| - DCHECK(!tile->tile_version().resource_); |
| + DCHECK(tile_version.requires_resource()); |
| + DCHECK(!tile_version.resource_); |
| - // Create raster task for this tile if necessary. |
| - if (mts.raster_task.is_null()) |
| - mts.raster_task = CreateRasterTask(tile); |
| + if (tile_version.raster_task_.is_null()) |
| + tile_version.raster_task_ = CreateRasterTask(tile); |
| - // Finally append raster task. |
| - tasks.Append(mts.raster_task); |
| + tasks.Append(tile_version.raster_task_); |
| } |
| // Schedule running of |tasks|. This replaces any previously |
| @@ -611,19 +690,22 @@ TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( |
| metadata.layer_id = tile.layer_id(); |
| metadata.tile_id = &tile; |
| metadata.source_frame_number = tile.source_frame_number(); |
| + metadata.raster_mode = mts.raster_mode; |
| return metadata; |
| } |
| RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) { |
| TRACE_EVENT0("cc", "TileManager::CreateRasterTask"); |
| + ManagedTileState& mts = tile->managed_state(); |
| + |
| scoped_ptr<ResourcePool::Resource> resource = |
| resource_pool_->AcquireResource( |
| tile->tile_size_.size(), |
| - tile->tile_version().resource_format_); |
| + mts.tile_versions[mts.raster_mode].resource_format_); |
| const Resource* const_resource = resource.get(); |
| - tile->tile_version().resource_id_ = resource->id(); |
| + mts.tile_versions[mts.raster_mode].resource_id_ = resource->id(); |
| PicturePileImpl::Analysis* analysis = new PicturePileImpl::Analysis; |
| @@ -656,6 +738,7 @@ RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) { |
| pending_decode_tasks_[id] = decode_task; |
| } |
| + RasterTaskMetadata metadata = GetRasterTaskMetadata(*tile); |
| return RasterWorkerPool::RasterTask( |
| tile->picture_pile(), |
| const_resource, |
| @@ -665,19 +748,20 @@ RasterWorkerPool::RasterTask TileManager::CreateRasterTask(Tile* tile) { |
| tile->content_rect(), |
| tile->contents_scale(), |
| use_color_estimator_, |
| - GetRasterTaskMetadata(*tile), |
| + metadata, |
| rendering_stats_instrumentation_), |
| base::Bind(&TileManager::RunRasterTask, |
| analysis, |
| tile->content_rect(), |
| tile->contents_scale(), |
| - GetRasterTaskMetadata(*tile), |
| + metadata, |
| rendering_stats_instrumentation_)), |
| base::Bind(&TileManager::OnRasterTaskCompleted, |
| base::Unretained(this), |
| make_scoped_refptr(tile), |
| base::Passed(&resource), |
| - base::Owned(analysis)), |
| + base::Owned(analysis), |
| + metadata.raster_mode), |
| &decode_tasks); |
| } |
| @@ -685,13 +769,17 @@ void TileManager::OnRasterTaskCompleted( |
| scoped_refptr<Tile> tile, |
| scoped_ptr<ResourcePool::Resource> resource, |
| PicturePileImpl::Analysis* analysis, |
| + TileRasterMode raster_mode, |
| bool was_canceled) { |
| TRACE_EVENT1("cc", "TileManager::OnRasterTaskCompleted", |
| "was_canceled", was_canceled); |
| ManagedTileState& mts = tile->managed_state(); |
| - DCHECK(!mts.raster_task.is_null()); |
| - mts.raster_task.Reset(); |
| + ManagedTileState::TileVersion& tile_version = |
| + mts.tile_versions[raster_mode]; |
| + DCHECK(!mts.tile_versions[raster_mode].raster_task_.is_null()); |
|
reveman
2013/06/06 15:40:13
nit: DCHECK(!tile_version.raster_task_.is_null())
|
| + tile_version.raster_task_.Reset(); |
| + tile_version.forced_upload_ = false; |
|
reveman
2013/06/06 15:40:13
I prefer if we land this fix separately. I created
|
| if (was_canceled) { |
| resource_pool_->ReleaseResource(resource.Pass()); |
| @@ -702,12 +790,14 @@ void TileManager::OnRasterTaskCompleted( |
| mts.picture_pile_analyzed = true; |
| if (analysis->is_solid_color) { |
| - tile->tile_version().set_solid_color(analysis->solid_color); |
| + tile_version.set_solid_color(analysis->solid_color); |
| resource_pool_->ReleaseResource(resource.Pass()); |
| } else { |
| - tile->tile_version().resource_ = resource.Pass(); |
| + tile_version.resource_ = resource.Pass(); |
| } |
| + FreeUnusedResourcesForTile(tile.get()); |
| + |
| DidFinishTileInitialization(tile.get()); |
| } |
| @@ -791,6 +881,7 @@ scoped_ptr<base::Value> TileManager::RasterTaskMetadata::AsValue() const { |
| is_tile_in_pending_tree_now_bin); |
| res->Set("resolution", TileResolutionAsValue(tile_resolution).release()); |
| res->SetInteger("source_frame_number", source_frame_number); |
| + res->SetInteger("raster_mode", raster_mode); |
| return res.PassAs<base::Value>(); |
| } |
| @@ -818,6 +909,23 @@ bool TileManager::RunRasterTask( |
| SkCanvas canvas(device); |
| + skia::RefPtr<SkDrawFilter> draw_filter; |
| + switch (metadata.raster_mode) { |
| + case LOW_QUALITY_RASTER_MODE: |
| + draw_filter = skia::AdoptRef(new skia::PaintSimplifier); |
| + break; |
| + case HIGH_QUALITY_NO_LCD_RASTER_MODE: |
| + draw_filter = skia::AdoptRef(new DisableLCDTextFilter); |
| + break; |
| + case HIGH_QUALITY_RASTER_MODE: |
| + break; |
| + case NUM_RASTER_MODES: |
| + default: |
| + NOTREACHED(); |
| + } |
| + |
| + canvas.setDrawFilter(draw_filter.get()); |
| + |
| if (stats_instrumentation->record_rendering_stats()) { |
| PicturePileImpl::RasterStats raster_stats; |
| picture_pile->RasterToBitmap(&canvas, rect, contents_scale, &raster_stats); |