Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1448)

Unified Diff: cc/tile_manager.cc

Issue 12471007: Part 8 of cc/ directory shuffles: resources (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/tile_manager.h ('k') | cc/tile_priority.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/tile_manager.cc
diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc
deleted file mode 100644
index b7bd9dc5463dada49669e32b10ef54d1a6ae0c80..0000000000000000000000000000000000000000
--- a/cc/tile_manager.cc
+++ /dev/null
@@ -1,1114 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/tile_manager.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "cc/debug/devtools_instrumentation.h"
-#include "cc/platform_color.h"
-#include "cc/raster_worker_pool.h"
-#include "cc/resource_pool.h"
-#include "cc/tile.h"
-#include "third_party/skia/include/core/SkDevice.h"
-
-namespace cc {
-
-namespace {
-
-// If we raster too fast we become upload bound, and pending
-// uploads consume memory. For maximum upload throughput, we would
-// want to allow for upload_throughput * pipeline_time of pending
-// uploads, after which we are just wasting memory. Since we don't
-// know our upload throughput yet, this just caps our memory usage.
-#if defined(OS_ANDROID)
-// For reference, the Nexus10 can upload 1MB in about 2.5ms.
-// Assuming a three frame deep pipeline this implies ~20MB.
-const int kMaxPendingUploadBytes = 20 * 1024 * 1024;
-// TODO(epenner): We should remove this upload limit (crbug.com/176197)
-const int kMaxPendingUploads = 72;
-#else
-const int kMaxPendingUploadBytes = 100 * 1024 * 1024;
-const int kMaxPendingUploads = 1000;
-#endif
-
-#if defined(OS_ANDROID)
-const int kMaxNumPendingTasksPerThread = 8;
-#else
-const int kMaxNumPendingTasksPerThread = 40;
-#endif
-
-// Limit for time spent running cheap tasks during a single frame.
-// TODO(skyostil): Determine this limit more dynamically.
-const int kRunCheapTasksTimeMs = 6;
-
-// Determine bin based on three categories of tiles: things we need now,
-// things we need soon, and eventually.
-inline TileManagerBin BinFromTilePriority(const TilePriority& prio) {
- if (!prio.is_live)
- return NEVER_BIN;
-
- // The amount of time for which we want to have prepainting coverage.
- const float kPrepaintingWindowTimeSeconds = 1.0f;
- const float kBackflingGuardDistancePixels = 314.0f;
-
- // Explicitly limit how far ahead we will prepaint to limit memory usage.
- if (prio.distance_to_visible_in_pixels >
- TilePriority::kMaxDistanceInContentSpace)
- return NEVER_BIN;
-
- if (prio.time_to_visible_in_seconds == 0 ||
- prio.distance_to_visible_in_pixels < kBackflingGuardDistancePixels)
- return NOW_BIN;
-
- if (prio.resolution == NON_IDEAL_RESOLUTION)
- return EVENTUALLY_BIN;
-
- if (prio.time_to_visible_in_seconds < kPrepaintingWindowTimeSeconds)
- return SOON_BIN;
-
- return EVENTUALLY_BIN;
-}
-
-std::string ValueToString(scoped_ptr<base::Value> value)
-{
- std::string str;
- base::JSONWriter::Write(value.get(), &str);
- return str;
-}
-
-} // namespace
-
-scoped_ptr<base::Value> TileManagerBinAsValue(TileManagerBin bin) {
- switch (bin) {
- case NOW_BIN:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "NOW_BIN"));
- case SOON_BIN:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "SOON_BIN"));
- case EVENTUALLY_BIN:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "EVENTUALLY_BIN"));
- case NEVER_BIN:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "NEVER_BIN"));
- default:
- DCHECK(false) << "Unrecognized TileManagerBin value " << bin;
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "<unknown TileManagerBin value>"));
- }
-}
-
-scoped_ptr<base::Value> TileManagerBinPriorityAsValue(
- TileManagerBinPriority bin_priority) {
- switch (bin_priority) {
- case HIGH_PRIORITY_BIN:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "HIGH_PRIORITY_BIN"));
- case LOW_PRIORITY_BIN:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "LOW_PRIORITY_BIN"));
- default:
- DCHECK(false) << "Unrecognized TileManagerBinPriority value";
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "<unknown TileManagerBinPriority value>"));
- }
-}
-
-scoped_ptr<base::Value> TileRasterStateAsValue(
- TileRasterState raster_state) {
- switch (raster_state) {
- case IDLE_STATE:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "IDLE_STATE"));
- case WAITING_FOR_RASTER_STATE:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "WAITING_FOR_RASTER_STATE"));
- case RASTER_STATE:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "RASTER_STATE"));
- case UPLOAD_STATE:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "UPLOAD_STATE"));
- case FORCED_UPLOAD_COMPLETION_STATE:
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "FORCED_UPLOAD_COMPLETION_STATE"));
- default:
- DCHECK(false) << "Unrecognized TileRasterState value";
- return scoped_ptr<base::Value>(base::Value::CreateStringValue(
- "<unknown TileRasterState value>"));
- }
-}
-
-TileManager::TileManager(
- TileManagerClient* client,
- ResourceProvider* resource_provider,
- size_t num_raster_threads,
- 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)),
- manage_tiles_pending_(false),
- manage_tiles_call_count_(0),
- bytes_pending_upload_(0),
- has_performed_uploads_since_last_flush_(false),
- ever_exceeded_memory_budget_(false),
- record_rendering_stats_(false),
- use_cheapness_estimator_(use_cheapness_estimator),
- use_color_estimator_(use_color_estimator),
- did_schedule_cheap_tasks_(false),
- allow_cheap_tasks_(true),
- prediction_benchmarking_(prediction_benchmarking),
- pending_tasks_(0),
- max_pending_tasks_(kMaxNumPendingTasksPerThread * num_raster_threads) {
- for (int i = 0; i < NUM_STATES; ++i) {
- for (int j = 0; j < NUM_TREES; ++j) {
- for (int k = 0; k < NUM_BINS; ++k)
- raster_state_count_[i][j][k] = 0;
- }
- }
-}
-
-TileManager::~TileManager() {
- // Reset global state and manage. This should cause
- // our memory usage to drop to zero.
- global_state_ = GlobalStateThatImpactsTilePriority();
- AssignGpuMemoryToTiles();
- // This should finish all pending tasks and release any uninitialized
- // resources.
- raster_worker_pool_.reset();
- AbortPendingTileUploads();
- DCHECK_EQ(tiles_with_pending_upload_.size(), 0);
- DCHECK_EQ(all_tiles_.size(), 0);
- DCHECK_EQ(live_or_allocated_tiles_.size(), 0);
-}
-
-void TileManager::SetGlobalState(
- const GlobalStateThatImpactsTilePriority& global_state) {
- global_state_ = global_state;
- resource_pool_->SetMaxMemoryUsageBytes(global_state_.memory_limit_in_bytes);
- ScheduleManageTiles();
-}
-
-void TileManager::RegisterTile(Tile* tile) {
- all_tiles_.insert(tile);
-
- const ManagedTileState& mts = tile->managed_state();
- for (int i = 0; i < NUM_TREES; ++i)
- ++raster_state_count_[mts.raster_state][i][mts.tree_bin[i]];
-
- ScheduleManageTiles();
-}
-
-void TileManager::UnregisterTile(Tile* tile) {
- for (TileList::iterator it = tiles_with_image_decoding_tasks_.begin();
- it != tiles_with_image_decoding_tasks_.end(); it++) {
- if (*it == tile) {
- tiles_with_image_decoding_tasks_.erase(it);
- break;
- }
- }
- for (TileVector::iterator it = tiles_that_need_to_be_rasterized_.begin();
- it != tiles_that_need_to_be_rasterized_.end(); it++) {
- if (*it == tile) {
- tiles_that_need_to_be_rasterized_.erase(it);
- break;
- }
- }
- for (TileVector::iterator it = live_or_allocated_tiles_.begin();
- it != live_or_allocated_tiles_.end(); it++) {
- if (*it == tile) {
- live_or_allocated_tiles_.erase(it);
- break;
- }
- }
- TileSet::iterator it = all_tiles_.find(tile);
- DCHECK(it != all_tiles_.end());
- const ManagedTileState& mts = tile->managed_state();
- for (int i = 0; i < NUM_TREES; ++i)
- --raster_state_count_[mts.raster_state][i][mts.tree_bin[i]];
- FreeResourcesForTile(tile);
- all_tiles_.erase(it);
-}
-
-class BinComparator {
-public:
- bool operator() (const Tile* a, const Tile* b) const {
- const ManagedTileState& ams = a->managed_state();
- const ManagedTileState& bms = b->managed_state();
- if (ams.bin[HIGH_PRIORITY_BIN] != bms.bin[HIGH_PRIORITY_BIN])
- return ams.bin[HIGH_PRIORITY_BIN] < bms.bin[HIGH_PRIORITY_BIN];
-
- if (ams.bin[LOW_PRIORITY_BIN] != bms.bin[LOW_PRIORITY_BIN])
- return ams.bin[LOW_PRIORITY_BIN] < bms.bin[LOW_PRIORITY_BIN];
-
- if (ams.resolution != bms.resolution)
- return ams.resolution < bms.resolution;
-
- if (ams.time_to_needed_in_seconds != bms.time_to_needed_in_seconds)
- return ams.time_to_needed_in_seconds < bms.time_to_needed_in_seconds;
-
- if (ams.distance_to_visible_in_pixels != bms.distance_to_visible_in_pixels)
- return ams.distance_to_visible_in_pixels < bms.distance_to_visible_in_pixels;
-
- gfx::Rect a_rect = a->content_rect();
- gfx::Rect b_rect = b->content_rect();
- if (a_rect.y() != b_rect.y())
- return a_rect.y() < b_rect.y();
- return a_rect.x() < b_rect.x();
- }
-};
-
-void TileManager::SortTiles() {
- TRACE_EVENT0("cc", "TileManager::SortTiles");
- TRACE_COUNTER_ID1("cc", "LiveTileCount", this, live_or_allocated_tiles_.size());
-
- // Sort by bin, resolution and time until needed.
- std::sort(live_or_allocated_tiles_.begin(),
- live_or_allocated_tiles_.end(), BinComparator());
-}
-
-void TileManager::ManageTiles() {
- TRACE_EVENT0("cc", "TileManager::ManageTiles");
- manage_tiles_pending_ = false;
- ++manage_tiles_call_count_;
-
- const TreePriority tree_priority = global_state_.tree_priority;
- TRACE_COUNTER_ID1("cc", "TileCount", this, all_tiles_.size());
-
- // Memory limit policy works by mapping some bin states to the NEVER bin.
- TileManagerBin bin_map[NUM_BINS];
- if (global_state_.memory_limit_policy == ALLOW_NOTHING) {
- bin_map[NOW_BIN] = NEVER_BIN;
- bin_map[SOON_BIN] = NEVER_BIN;
- bin_map[EVENTUALLY_BIN] = NEVER_BIN;
- bin_map[NEVER_BIN] = NEVER_BIN;
- } else if (global_state_.memory_limit_policy == ALLOW_ABSOLUTE_MINIMUM) {
- bin_map[NOW_BIN] = NOW_BIN;
- bin_map[SOON_BIN] = NEVER_BIN;
- bin_map[EVENTUALLY_BIN] = NEVER_BIN;
- bin_map[NEVER_BIN] = NEVER_BIN;
- } else if (global_state_.memory_limit_policy == ALLOW_PREPAINT_ONLY) {
- bin_map[NOW_BIN] = NOW_BIN;
- bin_map[SOON_BIN] = SOON_BIN;
- bin_map[EVENTUALLY_BIN] = NEVER_BIN;
- bin_map[NEVER_BIN] = NEVER_BIN;
- } else {
- bin_map[NOW_BIN] = NOW_BIN;
- bin_map[SOON_BIN] = SOON_BIN;
- bin_map[EVENTUALLY_BIN] = EVENTUALLY_BIN;
- bin_map[NEVER_BIN] = NEVER_BIN;
- }
-
- live_or_allocated_tiles_.clear();
- // For each tree, bin into different categories of tiles.
- for (TileSet::iterator it = all_tiles_.begin();
- it != all_tiles_.end(); ++it) {
- Tile* tile = *it;
- ManagedTileState& mts = tile->managed_state();
-
- TilePriority prio[NUM_BIN_PRIORITIES];
- switch (tree_priority) {
- case SAME_PRIORITY_FOR_BOTH_TREES:
- prio[HIGH_PRIORITY_BIN] = prio[LOW_PRIORITY_BIN] =
- tile->combined_priority();
- break;
- case SMOOTHNESS_TAKES_PRIORITY:
- prio[HIGH_PRIORITY_BIN] = tile->priority(ACTIVE_TREE);
- prio[LOW_PRIORITY_BIN] = tile->priority(PENDING_TREE);
- break;
- case NEW_CONTENT_TAKES_PRIORITY:
- prio[HIGH_PRIORITY_BIN] = tile->priority(PENDING_TREE);
- prio[LOW_PRIORITY_BIN] = tile->priority(ACTIVE_TREE);
- break;
- }
-
- mts.resolution = prio[HIGH_PRIORITY_BIN].resolution;
- mts.time_to_needed_in_seconds =
- prio[HIGH_PRIORITY_BIN].time_to_visible_in_seconds;
- mts.distance_to_visible_in_pixels =
- prio[HIGH_PRIORITY_BIN].distance_to_visible_in_pixels;
- mts.bin[HIGH_PRIORITY_BIN] = BinFromTilePriority(prio[HIGH_PRIORITY_BIN]);
- mts.bin[LOW_PRIORITY_BIN] = BinFromTilePriority(prio[LOW_PRIORITY_BIN]);
- mts.gpu_memmgr_stats_bin = BinFromTilePriority(tile->combined_priority());
-
- DidTileTreeBinChange(tile,
- bin_map[BinFromTilePriority(tile->priority(ACTIVE_TREE))],
- ACTIVE_TREE);
- DidTileTreeBinChange(tile,
- bin_map[BinFromTilePriority(tile->priority(PENDING_TREE))],
- PENDING_TREE);
-
- for (int i = 0; i < NUM_BIN_PRIORITIES; ++i)
- mts.bin[i] = bin_map[mts.bin[i]];
-
- if (!mts.drawing_info.resource_ &&
- !mts.drawing_info.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());
-
- SortTiles();
-
- // Assign gpu memory and determine what tiles need to be rasterized.
- AssignGpuMemoryToTiles();
-
- TRACE_EVENT_INSTANT1("cc", "DidManage", "state",
- ValueToString(BasicStateAsValue()));
-
- // Finally, kick the rasterizer.
- DispatchMoreTasks();
-}
-
-void TileManager::CheckForCompletedTileUploads() {
- while (!tiles_with_pending_upload_.empty()) {
- Tile* tile = tiles_with_pending_upload_.front();
- ManagedTileState& managed_tile_state = tile->managed_state();
- DCHECK(managed_tile_state.drawing_info.resource_);
-
- // Set pixel tasks complete in the order they are posted.
- if (!resource_pool_->resource_provider()->DidSetPixelsComplete(
- managed_tile_state.drawing_info.resource_->id())) {
- break;
- }
-
- // It's now safe to release the pixel buffer.
- resource_pool_->resource_provider()->ReleasePixelBuffer(
- managed_tile_state.drawing_info.resource_->id());
-
- managed_tile_state.drawing_info.can_be_freed_ = true;
-
- bytes_pending_upload_ -= tile->bytes_consumed_if_allocated();
- DidTileRasterStateChange(tile, IDLE_STATE);
- DidFinishTileInitialization(tile);
-
- tiles_with_pending_upload_.pop();
- }
-
- DispatchMoreTasks();
-}
-
-void TileManager::AbortPendingTileUploads() {
- while (!tiles_with_pending_upload_.empty()) {
- Tile* tile = tiles_with_pending_upload_.front();
- ManagedTileState& managed_tile_state = tile->managed_state();
- DCHECK(managed_tile_state.drawing_info.resource_);
-
- resource_pool_->resource_provider()->AbortSetPixels(
- managed_tile_state.drawing_info.resource_->id());
- resource_pool_->resource_provider()->ReleasePixelBuffer(
- managed_tile_state.drawing_info.resource_->id());
-
- managed_tile_state.drawing_info.resource_is_being_initialized_ = false;
- managed_tile_state.drawing_info.can_be_freed_ = true;
- managed_tile_state.can_use_gpu_memory = false;
- FreeResourcesForTile(tile);
-
- bytes_pending_upload_ -= tile->bytes_consumed_if_allocated();
- DidTileRasterStateChange(tile, IDLE_STATE);
- tiles_with_pending_upload_.pop();
- }
-}
-
-void TileManager::DidCompleteFrame() {
- allow_cheap_tasks_ = true;
- did_schedule_cheap_tasks_ = false;
-}
-
-void TileManager::ForceTileUploadToComplete(Tile* tile) {
- ManagedTileState& managed_tile_state = tile->managed_state();
- if (managed_tile_state.raster_state == UPLOAD_STATE) {
- Resource* resource = tile->drawing_info().resource_.get();
- DCHECK(resource);
- resource_pool_->resource_provider()->
- ForceSetPixelsToComplete(resource->id());
- DidTileRasterStateChange(tile, FORCED_UPLOAD_COMPLETION_STATE);
- DidFinishTileInitialization(tile);
- }
-}
-
-void TileManager::GetMemoryStats(
- size_t* memoryRequiredBytes,
- size_t* memoryNiceToHaveBytes,
- size_t* memoryUsedBytes) const {
- *memoryRequiredBytes = 0;
- *memoryNiceToHaveBytes = 0;
- *memoryUsedBytes = 0;
- 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->drawing_info().requires_resource())
- continue;
-
- size_t tile_bytes = tile->bytes_consumed_if_allocated();
- if (mts.gpu_memmgr_stats_bin == NOW_BIN)
- *memoryRequiredBytes += tile_bytes;
- if (mts.gpu_memmgr_stats_bin != NEVER_BIN)
- *memoryNiceToHaveBytes += tile_bytes;
- if (mts.can_use_gpu_memory)
- *memoryUsedBytes += tile_bytes;
- }
-}
-
-scoped_ptr<base::Value> TileManager::BasicStateAsValue() const {
- scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
- state->SetInteger("tile_count", all_tiles_.size());
- state->Set("global_state", global_state_.AsValue().release());
- state->Set("memory_requirements", GetMemoryRequirementsAsValue().release());
- return state.PassAs<base::Value>();
-}
-scoped_ptr<base::Value> TileManager::AllTilesAsValue() const {
- scoped_ptr<base::ListValue> state(new base::ListValue());
- for (TileSet::const_iterator it = all_tiles_.begin();
- it != all_tiles_.end(); it++) {
- state->Append((*it)->AsValue().release());
- }
- return state.PassAs<base::Value>();
-}
-
-scoped_ptr<base::Value> TileManager::GetMemoryRequirementsAsValue() const {
- scoped_ptr<base::DictionaryValue> requirements(
- new base::DictionaryValue());
-
- size_t memoryRequiredBytes;
- size_t memoryNiceToHaveBytes;
- size_t memoryUsedBytes;
- GetMemoryStats(&memoryRequiredBytes,
- &memoryNiceToHaveBytes,
- &memoryUsedBytes);
- requirements->SetInteger("memory_required_bytes", memoryRequiredBytes);
- requirements->SetInteger("memory_nice_to_have_bytes", memoryNiceToHaveBytes);
- requirements->SetInteger("memory_used_bytes", memoryUsedBytes);
- return requirements.PassAs<base::Value>();
-}
-
-void TileManager::SetRecordRenderingStats(bool record_rendering_stats) {
- if (record_rendering_stats_ == record_rendering_stats)
- return;
-
- record_rendering_stats_ = record_rendering_stats;
- raster_worker_pool_->SetRecordRenderingStats(record_rendering_stats);
-}
-
-void TileManager::GetRenderingStats(RenderingStats* stats) {
- CHECK(record_rendering_stats_);
- raster_worker_pool_->GetRenderingStats(stats);
- stats->totalDeferredImageCacheHitCount =
- rendering_stats_.totalDeferredImageCacheHitCount;
- stats->totalImageGatheringCount = rendering_stats_.totalImageGatheringCount;
- stats->totalImageGatheringTime =
- rendering_stats_.totalImageGatheringTime;
-}
-
-bool TileManager::HasPendingWorkScheduled(WhichTree tree) const {
- // Always true when ManageTiles() call is pending.
- if (manage_tiles_pending_)
- return true;
-
- for (int i = 0; i < NUM_STATES; ++i) {
- switch (i) {
- case WAITING_FOR_RASTER_STATE:
- case RASTER_STATE:
- case UPLOAD_STATE:
- case FORCED_UPLOAD_COMPLETION_STATE:
- for (int j = 0; j < NEVER_BIN; ++j) {
- if (raster_state_count_[i][tree][j])
- return true;
- }
- break;
- case IDLE_STATE:
- break;
- default:
- NOTREACHED();
- }
- }
-
- return false;
-}
-
-void TileManager::DidFinishDispatchingWorkerPoolCompletionCallbacks() {
- // If a flush is needed, do it now before starting to dispatch more tasks.
- if (has_performed_uploads_since_last_flush_) {
- resource_pool_->resource_provider()->ShallowFlushIfSupported();
- has_performed_uploads_since_last_flush_ = false;
- }
-
- DispatchMoreTasks();
-}
-
-void TileManager::AssignGpuMemoryToTiles() {
- TRACE_EVENT0("cc", "TileManager::AssignGpuMemoryToTiles");
- size_t unreleasable_bytes = 0;
-
- // Now give memory out to the tiles until we're out, and build
- // the needs-to-be-rasterized queue.
- tiles_that_need_to_be_rasterized_.clear();
-
- // Reset the image decoding list so that we don't mess up with tile
- // priorities. Tiles will be added to the image decoding list again
- // when DispatchMoreTasks() is called.
- tiles_with_image_decoding_tasks_.clear();
-
- // By clearing the tiles_that_need_to_be_rasterized_ vector and
- // tiles_with_image_decoding_tasks_ list above we move all tiles
- // currently waiting for raster to idle state.
- // Call DidTileRasterStateChange() for each of these tiles to
- // have this state change take effect.
- // Some memory cannot be released. We figure out how much in this
- // loop as well.
- for (TileVector::iterator it = live_or_allocated_tiles_.begin();
- it != live_or_allocated_tiles_.end(); ++it) {
- Tile* tile = *it;
- ManagedTileState& mts = tile->managed_state();
- if (!tile->drawing_info().requires_resource())
- continue;
-
- if (!mts.drawing_info.can_be_freed_)
- unreleasable_bytes += tile->bytes_consumed_if_allocated();
- if (mts.raster_state == WAITING_FOR_RASTER_STATE)
- DidTileRasterStateChange(tile, IDLE_STATE);
- }
-
- size_t bytes_allocatable = global_state_.memory_limit_in_bytes - unreleasable_bytes;
- size_t bytes_that_exceeded_memory_budget_in_now_bin = 0;
- 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;
- ManagedTileState& mts = tile->managed_state();
- if (!tile->drawing_info().requires_resource())
- continue;
-
- size_t tile_bytes = tile->bytes_consumed_if_allocated();
- if (!mts.drawing_info.can_be_freed_)
- continue;
- if (mts.bin[HIGH_PRIORITY_BIN] == NEVER_BIN &&
- mts.bin[LOW_PRIORITY_BIN] == NEVER_BIN) {
- mts.can_use_gpu_memory = false;
- FreeResourcesForTile(tile);
- continue;
- }
- if (tile_bytes > bytes_left) {
- mts.can_use_gpu_memory = false;
- if (mts.bin[HIGH_PRIORITY_BIN] == NOW_BIN ||
- mts.bin[LOW_PRIORITY_BIN] == NOW_BIN)
- bytes_that_exceeded_memory_budget_in_now_bin += tile_bytes;
- FreeResourcesForTile(tile);
- continue;
- }
- bytes_left -= tile_bytes;
- mts.can_use_gpu_memory = true;
- if (!mts.drawing_info.resource_ &&
- !mts.drawing_info.resource_is_being_initialized_) {
- tiles_that_need_to_be_rasterized_.push_back(tile);
- DidTileRasterStateChange(tile, WAITING_FOR_RASTER_STATE);
- }
- }
-
- ever_exceeded_memory_budget_ |=
- bytes_that_exceeded_memory_budget_in_now_bin > 0;
- if (ever_exceeded_memory_budget_) {
- TRACE_COUNTER_ID2("cc", "over_memory_budget", this,
- "budget", global_state_.memory_limit_in_bytes,
- "over", bytes_that_exceeded_memory_budget_in_now_bin);
- }
- memory_stats_from_last_assign_.total_budget_in_bytes =
- global_state_.memory_limit_in_bytes;
- memory_stats_from_last_assign_.bytes_allocated =
- bytes_allocatable - bytes_left;
- memory_stats_from_last_assign_.bytes_unreleasable = unreleasable_bytes;
- memory_stats_from_last_assign_.bytes_over =
- bytes_that_exceeded_memory_budget_in_now_bin;
-
- // Reverse two tiles_that_need_* vectors such that pop_back gets
- // the highest priority tile.
- std::reverse(
- tiles_that_need_to_be_rasterized_.begin(),
- tiles_that_need_to_be_rasterized_.end());
-}
-
-void TileManager::FreeResourcesForTile(Tile* tile) {
- ManagedTileState& managed_tile_state = tile->managed_state();
- DCHECK(managed_tile_state.drawing_info.can_be_freed_);
- if (managed_tile_state.drawing_info.resource_)
- resource_pool_->ReleaseResource(
- managed_tile_state.drawing_info.resource_.Pass());
-}
-
-bool TileManager::CanDispatchRasterTask(Tile* tile) const {
- if (pending_tasks_ >= max_pending_tasks_)
- return false;
- size_t new_bytes_pending = bytes_pending_upload_;
- new_bytes_pending += tile->bytes_consumed_if_allocated();
- return new_bytes_pending <= kMaxPendingUploadBytes &&
- tiles_with_pending_upload_.size() < kMaxPendingUploads;
-}
-
-void TileManager::DispatchMoreTasks() {
- if (did_schedule_cheap_tasks_)
- allow_cheap_tasks_ = false;
-
- // 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. 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);
- if (managed_tile_state.pending_pixel_refs.empty()) {
- if (!CanDispatchRasterTask(*it))
- return;
- DispatchOneRasterTask(*it);
- tiles_with_image_decoding_tasks_.erase(it++);
- } else {
- ++it;
- }
- }
-
- // 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& mts = tile->managed_state();
-
- AnalyzeTile(tile);
- if (!tile->drawing_info().requires_resource()) {
- DidTileRasterStateChange(tile, IDLE_STATE);
- tiles_that_need_to_be_rasterized_.pop_back();
- continue;
- }
-
- DispatchImageDecodeTasksForTile(tile);
- if (!mts.pending_pixel_refs.empty()) {
- tiles_with_image_decoding_tasks_.push_back(tile);
- } else {
- if (!CanDispatchRasterTask(tile))
- return;
- DispatchOneRasterTask(tile);
- }
- tiles_that_need_to_be_rasterized_.pop_back();
- }
-}
-
-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);
- 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;
-
- if (managed_tile_state.picture_pile_analysis.is_solid_color) {
- tile->drawing_info().set_solid_color(
- managed_tile_state.picture_pile_analysis.solid_color);
- DidFinishTileInitialization(tile);
- } else if (managed_tile_state.picture_pile_analysis.is_transparent) {
- tile->drawing_info().set_transparent();
- DidFinishTileInitialization(tile);
- }
- }
-}
-
-void TileManager::GatherPixelRefsForTile(Tile* tile) {
- TRACE_EVENT0("cc", "TileManager::GatherPixelRefsForTile");
- 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_tile_state.pending_pixel_refs);
- managed_tile_state.need_to_gather_pixel_refs = false;
- if (record_rendering_stats_) {
- rendering_stats_.totalImageGatheringCount++;
- rendering_stats_.totalImageGatheringTime +=
- base::TimeTicks::HighResNow() - gather_begin_time;
- }
- }
-}
-
-void TileManager::DispatchImageDecodeTasksForTile(Tile* tile) {
- GatherPixelRefsForTile(tile);
- std::list<skia::LazyPixelRef*>& pending_pixel_refs =
- tile->managed_state().pending_pixel_refs;
- std::list<skia::LazyPixelRef*>::iterator it = pending_pixel_refs.begin();
- while (it != pending_pixel_refs.end()) {
- if (pending_decode_tasks_.end() != pending_decode_tasks_.find(
- (*it)->getGenerationID())) {
- ++it;
- continue;
- }
- // TODO(qinmin): passing correct image size to PrepareToDecode().
- if ((*it)->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
- rendering_stats_.totalDeferredImageCacheHitCount++;
- pending_pixel_refs.erase(it++);
- } else {
- if (pending_tasks_ >= max_pending_tasks_)
- return;
- DispatchOneImageDecodeTask(tile, *it);
- ++it;
- }
- }
-}
-
-void TileManager::DispatchOneImageDecodeTask(
- scoped_refptr<Tile> tile, skia::LazyPixelRef* pixel_ref) {
- TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodeTask");
- uint32_t pixel_ref_id = pixel_ref->getGenerationID();
- DCHECK(pending_decode_tasks_.end() ==
- pending_decode_tasks_.find(pixel_ref_id));
- pending_decode_tasks_[pixel_ref_id] = pixel_ref;
-
- raster_worker_pool_->PostTaskAndReply(
- base::Bind(&TileManager::RunImageDecodeTask, pixel_ref),
- base::Bind(&TileManager::OnImageDecodeTaskCompleted,
- base::Unretained(this),
- tile,
- pixel_ref_id));
- pending_tasks_++;
-}
-
-void TileManager::OnImageDecodeTaskCompleted(
- scoped_refptr<Tile> tile, uint32_t pixel_ref_id) {
- TRACE_EVENT0("cc", "TileManager::OnImageDecodeTaskCompleted");
- pending_decode_tasks_.erase(pixel_ref_id);
- pending_tasks_--;
-
- for (TileList::iterator it = tiles_with_image_decoding_tasks_.begin();
- it != tiles_with_image_decoding_tasks_.end(); ++it) {
- std::list<skia::LazyPixelRef*>& pixel_refs =
- (*it)->managed_state().pending_pixel_refs;
- for (std::list<skia::LazyPixelRef*>::iterator pixel_it =
- pixel_refs.begin(); pixel_it != pixel_refs.end(); ++pixel_it) {
- if (pixel_ref_id == (*pixel_it)->getGenerationID()) {
- pixel_refs.erase(pixel_it);
- break;
- }
- }
- }
-}
-
-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 =
- resource_pool_->AcquireResource(tile->tile_size_.size(), tile->format_);
- resource_pool_->resource_provider()->AcquirePixelBuffer(resource->id());
-
- managed_tile_state.drawing_info.resource_is_being_initialized_ = true;
- managed_tile_state.drawing_info.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();
- uint8* buffer =
- resource_pool_->resource_provider()->MapPixelBuffer(resource_id);
-
- ManagedTileState& managed_tile_state = tile->managed_state();
- // TODO(skyostil): Post all cheap tasks as cheap and instead use the time
- // limit to control their execution.
- bool is_cheap_task =
- allow_cheap_tasks_ &&
- global_state_.tree_priority != SMOOTHNESS_TAKES_PRIORITY &&
- managed_tile_state.picture_pile_analysis.is_cheap_to_raster;
- raster_worker_pool_->PostRasterTaskAndReply(
- tile->picture_pile(),
- is_cheap_task,
- base::Bind(&TileManager::RunRasterTask,
- buffer,
- tile->content_rect(),
- tile->contents_scale(),
- GetRasterTaskMetadata(*tile)),
- base::Bind(&TileManager::OnRasterTaskCompleted,
- base::Unretained(this),
- tile,
- base::Passed(&resource),
- manage_tiles_call_count_));
- if (is_cheap_task && !did_schedule_cheap_tasks_) {
- raster_worker_pool_->SetRunCheapTasksTimeLimit(
- base::TimeTicks::Now() +
- base::TimeDelta::FromMilliseconds(kRunCheapTasksTimeMs));
- did_schedule_cheap_tasks_ = true;
- }
- pending_tasks_++;
-}
-
-TileManager::RasterTaskMetadata TileManager::GetRasterTaskMetadata(
- const Tile& tile) const {
- RasterTaskMetadata metadata;
- const ManagedTileState& mts = tile.managed_state();
- 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;
- metadata.layer_id = tile.layer_id();
- return metadata;
-}
-
-void TileManager::OnRasterTaskCompleted(
- scoped_refptr<Tile> tile,
- scoped_ptr<ResourcePool::Resource> resource,
- int manage_tiles_call_count_when_dispatched) {
- TRACE_EVENT0("cc", "TileManager::OnRasterTaskCompleted");
-
- pending_tasks_--;
-
- // Release raster resources.
- resource_pool_->resource_provider()->UnmapPixelBuffer(resource->id());
-
- ManagedTileState& managed_tile_state = tile->managed_state();
- managed_tile_state.drawing_info.can_be_freed_ = true;
-
- // Tile can be freed after the completion of the raster task. Call
- // AssignGpuMemoryToTiles() to re-assign gpu memory to highest priority
- // tiles if ManageTiles() was called since task was dispatched. The result
- // of this could be that this tile is no longer allowed to use gpu
- // memory and in that case we need to abort initialization and free all
- // associated resources before calling DispatchMoreTasks().
- if (manage_tiles_call_count_when_dispatched != manage_tiles_call_count_)
- AssignGpuMemoryToTiles();
-
- // Finish resource initialization if |can_use_gpu_memory| is true.
- if (managed_tile_state.can_use_gpu_memory) {
- // The component order may be bgra if we're uploading bgra pixels to rgba
- // texture. Mark contents as swizzled if image component order is
- // different than texture format.
- managed_tile_state.drawing_info.contents_swizzled_ =
- !PlatformColor::SameComponentOrder(tile->format_);
-
- // Tile resources can't be freed until upload has completed.
- managed_tile_state.drawing_info.can_be_freed_ = false;
-
- resource_pool_->resource_provider()->BeginSetPixels(resource->id());
- has_performed_uploads_since_last_flush_ = true;
-
- managed_tile_state.drawing_info.resource_ = resource.Pass();
-
- bytes_pending_upload_ += tile->bytes_consumed_if_allocated();
- DidTileRasterStateChange(tile, UPLOAD_STATE);
- tiles_with_pending_upload_.push(tile);
- } else {
- resource_pool_->resource_provider()->ReleasePixelBuffer(resource->id());
- resource_pool_->ReleaseResource(resource.Pass());
- managed_tile_state.drawing_info.resource_is_being_initialized_ = false;
- DidTileRasterStateChange(tile, IDLE_STATE);
- }
-}
-
-void TileManager::DidFinishTileInitialization(Tile* tile) {
- ManagedTileState& managed_state = tile->managed_state();
- managed_state.drawing_info.resource_is_being_initialized_ = false;
- if (tile->priority(ACTIVE_TREE).distance_to_visible_in_pixels == 0)
- client_->DidInitializeVisibleTile();
-}
-
-void TileManager::DidTileRasterStateChange(Tile* tile, TileRasterState state) {
- ManagedTileState& mts = tile->managed_state();
- DCHECK_LT(state, NUM_STATES);
-
- for (int i = 0; i < NUM_TREES; ++i) {
- // Decrement count for current state.
- --raster_state_count_[mts.raster_state][i][mts.tree_bin[i]];
- DCHECK_GE(raster_state_count_[mts.raster_state][i][mts.tree_bin[i]], 0);
-
- // Increment count for new state.
- ++raster_state_count_[state][i][mts.tree_bin[i]];
- }
-
- mts.raster_state = state;
-}
-
-void TileManager::DidTileTreeBinChange(Tile* tile,
- TileManagerBin new_tree_bin,
- WhichTree tree) {
- ManagedTileState& mts = tile->managed_state();
-
- // Decrement count for current bin.
- --raster_state_count_[mts.raster_state][tree][mts.tree_bin[tree]];
- DCHECK_GE(raster_state_count_[mts.raster_state][tree][mts.tree_bin[tree]], 0);
-
- // Increment count for new bin.
- ++raster_state_count_[mts.raster_state][tree][new_tree_bin];
-
- mts.tree_bin[tree] = new_tree_bin;
-}
-
-// static
-void TileManager::RunRasterTask(uint8* buffer,
- const gfx::Rect& rect,
- float contents_scale,
- const RasterTaskMetadata& metadata,
- PicturePileImpl* picture_pile,
- RenderingStats* stats) {
- TRACE_EVENT2(
- "cc", "TileManager::RunRasterTask",
- "is_on_pending_tree",
- metadata.is_tile_in_pending_tree_now_bin,
- "is_low_res",
- metadata.tile_resolution == LOW_RESOLUTION);
- devtools_instrumentation::ScopedRasterTask raster_task(metadata.layer_id);
-
- DCHECK(picture_pile);
- DCHECK(buffer);
-
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height());
- bitmap.setPixels(buffer);
- SkDevice device(bitmap);
- SkCanvas canvas(&device);
-
- base::TimeTicks begin_time;
- if (stats)
- begin_time = base::TimeTicks::HighResNow();
-
- int64 total_pixels_rasterized = 0;
- picture_pile->Raster(&canvas, rect, contents_scale,
- &total_pixels_rasterized);
-
- if (stats) {
- stats->totalPixelsRasterized += total_pixels_rasterized;
-
- base::TimeTicks end_time = base::TimeTicks::HighResNow();
- base::TimeDelta duration = end_time - begin_time;
- stats->totalRasterizeTime += duration;
- if (metadata.is_tile_in_pending_tree_now_bin)
- stats->totalRasterizeTimeForNowBinsOnPendingTree += duration;
-
- UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.PictureRasterTimeMS",
- duration.InMilliseconds(),
- 0,
- 10,
- 10);
-
- 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);
-
- DCHECK_EQ(bitmap.rowBytes(),
- bitmap.width() * bitmap.bytesPerPixel());
-
- RecordSolidColorPredictorResults(
- reinterpret_cast<SkColor*>(bitmap.getPixels()),
- bitmap.getSize() / bitmap.bytesPerPixel(),
- analysis.is_solid_color,
- analysis.solid_color,
- analysis.is_transparent);
- }
- }
-}
-
-// static
-void TileManager::RecordCheapnessPredictorResults(bool is_predicted_cheap,
- bool is_actually_cheap) {
- if (is_predicted_cheap && !is_actually_cheap)
- UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorBadlyWrong", true);
- else if (!is_predicted_cheap && is_actually_cheap)
- UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorSafelyWrong", true);
-
- UMA_HISTOGRAM_BOOLEAN("Renderer4.CheapPredictorAccuracy",
- is_predicted_cheap == is_actually_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, 0u);
-
- bool is_actually_solid = true;
- bool is_transparent = true;
-
- SkColor actual_color = *actual_colors;
- for (unsigned 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");
- base::TimeTicks decode_begin_time;
- if (stats)
- decode_begin_time = base::TimeTicks::HighResNow();
- pixel_ref->Decode();
- if (stats) {
- stats->totalDeferredImageDecodeCount++;
- stats->totalDeferredImageDecodeTime +=
- base::TimeTicks::HighResNow() - decode_begin_time;
- }
-}
-
-} // namespace cc
« no previous file with comments | « cc/tile_manager.h ('k') | cc/tile_priority.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698