Index: cc/tile_manager.cc |
diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc |
index 054b5e55fbd19b16633e9ccac9cdc3a5fae16ea4..2c43d514daa66885adf536da0c170eb91bdfeba4 100644 |
--- a/cc/tile_manager.cc |
+++ b/cc/tile_manager.cc |
@@ -145,7 +145,8 @@ ManagedTileState::ManagedTileState() |
raster_state(IDLE_STATE), |
resolution(NON_IDEAL_RESOLUTION), |
time_to_needed_in_seconds(std::numeric_limits<float>::infinity()), |
- distance_to_visible_in_pixels(std::numeric_limits<float>::infinity()) { |
+ distance_to_visible_in_pixels(std::numeric_limits<float>::infinity()), |
+ picture_pile_analyzed(false) { |
for (int i = 0; i < NUM_TREES; ++i) { |
tree_bin[i] = NEVER_BIN; |
bin[i] = NEVER_BIN; |
@@ -170,6 +171,10 @@ scoped_ptr<base::Value> ManagedTileState::AsValue() const { |
state->Set("resolution", TileResolutionAsValue(resolution).release()); |
state->Set("time_to_needed_in_seconds", MathUtil::asValueSafely(time_to_needed_in_seconds).release()); |
state->Set("distance_to_visible_in_pixels", MathUtil::asValueSafely(distance_to_visible_in_pixels).release()); |
+ state->SetBoolean("is_picture_pile_analyzed", picture_pile_analyzed); |
+ state->SetBoolean("is_cheap_to_raster", picture_pile_analysis.is_cheap_to_raster); |
+ state->SetBoolean("is_transparent", picture_pile_analysis.is_transparent); |
+ state->SetBoolean("is_solid_color", picture_pile_analysis.is_solid_color); |
return state.PassAs<base::Value>(); |
} |
@@ -177,7 +182,9 @@ TileManager::TileManager( |
TileManagerClient* client, |
ResourceProvider* resource_provider, |
size_t num_raster_threads, |
- bool use_cheapness_estimator) |
+ bool use_cheapness_estimator, |
+ bool use_color_estimator, |
+ bool prediction_benchmarking) |
: client_(client), |
resource_pool_(ResourcePool::Create(resource_provider)), |
raster_worker_pool_(RasterWorkerPool::Create(this, num_raster_threads)), |
@@ -188,8 +195,10 @@ TileManager::TileManager( |
ever_exceeded_memory_budget_(false), |
record_rendering_stats_(false), |
use_cheapness_estimator_(use_cheapness_estimator), |
+ use_color_estimator_(use_color_estimator), |
allow_cheap_tasks_(true), |
- did_schedule_cheap_tasks_(false) { |
+ did_schedule_cheap_tasks_(false), |
+ prediction_benchmarking_(prediction_benchmarking) { |
for (int i = 0; i < NUM_STATES; ++i) { |
for (int j = 0; j < NUM_TREES; ++j) { |
for (int k = 0; k < NUM_BINS; ++k) |
@@ -371,12 +380,13 @@ void TileManager::ManageTiles() { |
for (int i = 0; i < NUM_BIN_PRIORITIES; ++i) |
mts.bin[i] = bin_map[mts.bin[i]]; |
- if (tile->priority(ACTIVE_TREE).is_live || |
- tile->priority(PENDING_TREE).is_live || |
- tile->managed_state().resource || |
- tile->managed_state().resource_is_being_initialized) { |
- live_or_allocated_tiles_.push_back(tile); |
- } |
+ if (!tile->managed_state().resource && |
+ !tile->managed_state().resource_is_being_initialized && |
+ !tile->priority(ACTIVE_TREE).is_live && |
+ !tile->priority(PENDING_TREE).is_live) |
+ continue; |
+ |
+ live_or_allocated_tiles_.push_back(tile); |
} |
TRACE_COUNTER_ID1("cc", "LiveOrAllocatedTileCount", this, |
live_or_allocated_tiles_.size()); |
@@ -459,6 +469,9 @@ void TileManager::GetMemoryStats( |
for (size_t i = 0; i < live_or_allocated_tiles_.size(); i++) { |
const Tile* tile = live_or_allocated_tiles_[i]; |
const ManagedTileState& mts = tile->managed_state(); |
+ if (tile->is_transparent() || tile->is_solid_color()) |
+ continue; |
+ |
size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
if (mts.gpu_memmgr_stats_bin == NOW_BIN) |
*memoryRequiredBytes += tile_bytes; |
@@ -579,9 +592,13 @@ void TileManager::AssignGpuMemoryToTiles() { |
for (TileVector::iterator it = live_or_allocated_tiles_.begin(); |
it != live_or_allocated_tiles_.end(); ++it) { |
Tile* tile = *it; |
- if (!tile->managed_state().can_be_freed) |
+ if (tile->is_solid_color() || tile->is_transparent()) |
+ continue; |
+ |
+ ManagedTileState& managed_tile_state = tile->managed_state(); |
+ if (!managed_tile_state.can_be_freed) |
unreleasable_bytes += tile->bytes_consumed_if_allocated(); |
- if (tile->managed_state().raster_state == WAITING_FOR_RASTER_STATE) |
+ if (managed_tile_state.raster_state == WAITING_FOR_RASTER_STATE) |
DidTileRasterStateChange(tile, IDLE_STATE); |
} |
@@ -590,8 +607,11 @@ void TileManager::AssignGpuMemoryToTiles() { |
size_t bytes_left = bytes_allocatable; |
for (TileVector::iterator it = live_or_allocated_tiles_.begin(); it != live_or_allocated_tiles_.end(); ++it) { |
Tile* tile = *it; |
- size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
+ if (tile->is_solid_color() || tile->is_transparent()) |
+ continue; |
+ |
ManagedTileState& managed_tile_state = tile->managed_state(); |
+ size_t tile_bytes = tile->bytes_consumed_if_allocated(); |
if (!managed_tile_state.can_be_freed) |
continue; |
if (managed_tile_state.bin[HIGH_PRIORITY_BIN] == NEVER_BIN && |
@@ -661,12 +681,13 @@ 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 |
- // in the need_to_be_rasterized queue. |
+ // in the need_to_be_rasterized queue. Note that solid/transparent tiles |
+ // will not be put into the decoding list. |
for(TileList::iterator it = tiles_with_image_decoding_tasks_.begin(); |
it != tiles_with_image_decoding_tasks_.end(); ) { |
+ ManagedTileState& managed_tile_state = (*it)->managed_state(); |
DispatchImageDecodeTasksForTile(*it); |
- ManagedTileState& managed_state = (*it)->managed_state(); |
- if (managed_state.pending_pixel_refs.empty()) { |
+ if (managed_tile_state.pending_pixel_refs.empty()) { |
if (!CanDispatchRasterTask(*it)) |
return; |
DispatchOneRasterTask(*it); |
@@ -676,13 +697,23 @@ void TileManager::DispatchMoreTasks() { |
} |
} |
- // Process all tiles in the need_to_be_rasterized queue. If a tile has |
- // image decoding tasks, put it to the back of the image decoding list. |
+ // Process all tiles in the need_to_be_rasterized queue. If a tile is |
+ // solid/transparent, then we are done (we don't need to rasterize |
+ // the tile). If a tile has image decoding tasks, put it to the back |
+ // of the image decoding list. |
while (!tiles_that_need_to_be_rasterized_.empty()) { |
Tile* tile = tiles_that_need_to_be_rasterized_.back(); |
+ ManagedTileState& managed_tile_state = tile->managed_state(); |
+ |
+ AnalyzeTile(tile); |
+ if (tile->is_solid_color() || tile->is_transparent()) { |
Sami
2013/03/06 11:14:49
If we're doing prediction benchmarking, then we'd
|
+ DidTileRasterStateChange(tile, IDLE_STATE); |
+ tiles_that_need_to_be_rasterized_.pop_back(); |
+ continue; |
+ } |
+ |
DispatchImageDecodeTasksForTile(tile); |
- ManagedTileState& managed_state = tile->managed_state(); |
- if (!managed_state.pending_pixel_refs.empty()) { |
+ if (!managed_tile_state.pending_pixel_refs.empty()) { |
tiles_with_image_decoding_tasks_.push_back(tile); |
} else { |
if (!CanDispatchRasterTask(tile)) |
@@ -693,18 +724,35 @@ void TileManager::DispatchMoreTasks() { |
} |
} |
+void TileManager::AnalyzeTile(Tile* tile) { |
+ ManagedTileState& managed_tile_state = tile->managed_state(); |
+ if ((use_cheapness_estimator_ || use_color_estimator_) && |
+ !managed_tile_state.picture_pile_analyzed) { |
+ tile->picture_pile()->AnalyzeInRect(tile->content_rect(), |
+ tile->contents_scale(), |
+ &managed_tile_state.picture_pile_analysis); |
Sami
2013/03/06 11:14:49
Nit: line too long.
|
+ managed_tile_state.picture_pile_analysis.is_cheap_to_raster &= |
+ use_cheapness_estimator_; |
+ managed_tile_state.picture_pile_analysis.is_solid_color &= |
+ use_color_estimator_; |
+ managed_tile_state.picture_pile_analysis.is_transparent &= |
+ use_color_estimator_; |
+ managed_tile_state.picture_pile_analyzed = true; |
+ } |
+} |
+ |
void TileManager::GatherPixelRefsForTile(Tile* tile) { |
TRACE_EVENT0("cc", "TileManager::GatherPixelRefsForTile"); |
- ManagedTileState& managed_state = tile->managed_state(); |
- if (managed_state.need_to_gather_pixel_refs) { |
+ ManagedTileState& managed_tile_state = tile->managed_state(); |
+ if (managed_tile_state.need_to_gather_pixel_refs) { |
base::TimeTicks gather_begin_time; |
if (record_rendering_stats_) |
gather_begin_time = base::TimeTicks::HighResNow(); |
tile->picture_pile()->GatherPixelRefs( |
tile->content_rect_, |
tile->contents_scale_, |
- managed_state.pending_pixel_refs); |
- managed_state.need_to_gather_pixel_refs = false; |
+ managed_tile_state.pending_pixel_refs); |
+ managed_tile_state.need_to_gather_pixel_refs = false; |
if (record_rendering_stats_) { |
rendering_stats_.totalImageGatheringCount++; |
rendering_stats_.totalImageGatheringTime += |
@@ -794,12 +842,12 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
uint8* buffer = |
resource_pool_->resource_provider()->mapPixelBuffer(resource_id); |
- bool is_cheap = use_cheapness_estimator_ && allow_cheap_tasks_ && |
- tile->picture_pile()->IsCheapInRect(tile->content_rect_, |
- tile->contents_scale()); |
+ ManagedTileState& managed_tile_state = tile->managed_state(); |
+ bool is_cheap_to_raster = |
+ managed_tile_state.picture_pile_analysis.is_cheap_to_raster; |
raster_worker_pool_->PostRasterTaskAndReply( |
tile->picture_pile(), |
- is_cheap, |
+ allow_cheap_tasks_ && is_cheap_to_raster, |
base::Bind(&TileManager::RunRasterTask, |
buffer, |
tile->content_rect(), |
@@ -810,14 +858,14 @@ void TileManager::DispatchOneRasterTask(scoped_refptr<Tile> tile) { |
tile, |
base::Passed(&resource), |
manage_tiles_call_count_)); |
- did_schedule_cheap_tasks_ |= is_cheap; |
+ did_schedule_cheap_tasks_ |= (allow_cheap_tasks_ && is_cheap_to_raster); |
} |
TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata( |
const Tile& tile) const { |
RasterTaskMetadata metadata; |
const ManagedTileState& mts = tile.managed_state(); |
- metadata.use_cheapness_estimator = use_cheapness_estimator_; |
+ metadata.prediction_benchmarking = prediction_benchmarking_; |
metadata.is_tile_in_pending_tree_now_bin = |
mts.tree_bin[PENDING_TREE] == NOW_BIN; |
metadata.tile_resolution = mts.resolution; |
@@ -958,11 +1006,19 @@ void TileManager::RunRasterTask(uint8* buffer, |
10, |
10); |
- if (metadata.use_cheapness_estimator) { |
- bool is_predicted_cheap = |
- picture_pile->IsCheapInRect(rect, contents_scale); |
+ if (metadata.prediction_benchmarking) { |
+ PicturePileImpl::Analysis analysis; |
+ picture_pile->AnalyzeInRect(rect, contents_scale, &analysis); |
+ bool is_predicted_cheap = analysis.is_cheap_to_raster; |
bool is_actually_cheap = duration.InMillisecondsF() <= 1.0f; |
RecordCheapnessPredictorResults(is_predicted_cheap, is_actually_cheap); |
+ |
+ RecordSolidColorPredictorResults( |
+ reinterpret_cast<SkColor*>(bitmap.getPixels()), |
+ bitmap.getSize() / bitmap.bytesPerPixel(), |
+ analysis.is_solid_color, |
+ analysis.solid_color, |
+ analysis.is_transparent); |
} |
} |
} |
@@ -980,6 +1036,58 @@ void TileManager::RecordCheapnessPredictorResults(bool is_predicted_cheap, |
} |
// static |
+void TileManager::RecordSolidColorPredictorResults( |
+ const SkColor* actual_colors, |
+ size_t color_count, |
+ bool is_predicted_solid, |
+ SkColor predicted_color, |
+ bool is_predicted_transparent) { |
+ DCHECK_GT(color_count, 0); |
+ |
+ bool is_actually_solid = true; |
+ bool is_transparent = true; |
+ |
+ SkColor actual_color = *actual_colors; |
+ for (int i = 0; i < color_count; ++i) { |
+ SkColor current_color = actual_colors[i]; |
+ if (current_color != actual_color || |
+ SkColorGetA(current_color) != 255) |
+ is_actually_solid = false; |
+ |
+ if (SkColorGetA(current_color) != 0) |
+ is_transparent = false; |
+ |
+ if(!is_actually_solid && !is_transparent) |
+ break; |
+ } |
+ |
+ if (is_predicted_solid && !is_actually_solid) |
+ UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.WrongActualNotSolid", true); |
+ else if (is_predicted_solid && |
+ is_actually_solid && |
+ predicted_color != actual_color) |
+ UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.WrongColor", true); |
+ else if (!is_predicted_solid && is_actually_solid) |
+ UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.WrongActualSolid", true); |
+ |
+ bool correct_guess = (is_predicted_solid && is_actually_solid && |
+ predicted_color == actual_color) || |
+ (!is_predicted_solid && !is_actually_solid); |
+ UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.Accuracy", correct_guess); |
+ |
+ if (correct_guess) |
+ UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsCorrectSolid", |
+ is_predicted_solid); |
+ |
+ if (is_predicted_transparent) |
+ UMA_HISTOGRAM_BOOLEAN( |
+ "Renderer4.ColorPredictor.PredictedTransparentIsActually", |
+ is_transparent); |
+ UMA_HISTOGRAM_BOOLEAN("Renderer4.ColorPredictor.IsActuallyTransparent", |
+ is_transparent); |
+} |
+ |
+// static |
void TileManager::RunImageDecodeTask(skia::LazyPixelRef* pixel_ref, |
RenderingStats* stats) { |
TRACE_EVENT0("cc", "TileManager::RunImageDecodeTask"); |