diff options
-rw-r--r-- | cc/layer_tree_host_impl.cc | 25 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.h | 1 | ||||
-rw-r--r-- | cc/tile_manager.cc | 82 | ||||
-rw-r--r-- | cc/tile_manager.h | 11 | ||||
-rw-r--r-- | cc/tile_priority.cc | 66 | ||||
-rw-r--r-- | cc/tile_priority.h | 17 |
6 files changed, 193 insertions, 9 deletions
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc index 37ae8f4..42aa953 100644 --- a/cc/layer_tree_host_impl.cc +++ b/cc/layer_tree_host_impl.cc @@ -920,6 +920,7 @@ void LayerTreeHostImpl::createPendingTree() m_pendingTree = LayerTreeImpl::create(this); m_client->onCanDrawStateChanged(canDraw()); m_client->onHasPendingTreeStateChanged(pendingTree()); + TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree", m_pendingTree.get()); } void LayerTreeHostImpl::checkForCompletedTileUploads() @@ -929,6 +930,25 @@ void LayerTreeHostImpl::checkForCompletedTileUploads() m_tileManager->CheckForCompletedTileUploads(); } +scoped_ptr<base::Value> LayerTreeHostImpl::activationStateAsValue() const +{ + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); + state->SetBoolean("visible_resources_ready", pendingTree()->AreVisibleResourcesReady()); + state->Set("tile_manager", m_tileManager->AsValue().release()); + return state.PassAs<base::Value>(); +} + +namespace { + +std::string ValueToString(scoped_ptr<base::Value> value) +{ + std::string str; + base::JSONWriter::Write(value.get(), &str); + return str; +} + +} + void LayerTreeHostImpl::activatePendingTreeIfNeeded() { if (!pendingTree()) @@ -938,6 +958,10 @@ void LayerTreeHostImpl::activatePendingTreeIfNeeded() pendingTree()->UpdateDrawProperties(LayerTreeImpl::UPDATE_PENDING_TREE); + TRACE_EVENT_ASYNC_STEP1("cc", + "PendingTree", m_pendingTree.get(), "activate", + "state", ValueToString(activationStateAsValue())); + // It's always fine to activate to an empty tree. Otherwise, only // activate once all visible resources in pending tree are ready // or tile manager has no work scheduled for pending tree. @@ -952,6 +976,7 @@ void LayerTreeHostImpl::activatePendingTreeIfNeeded() void LayerTreeHostImpl::activatePendingTree() { CHECK(m_pendingTree); + TRACE_EVENT_ASYNC_END0("cc", "PendingTree", m_pendingTree.get()); m_activeTree->PushPersistedState(m_pendingTree.get()); m_activeTree->SetRootLayer(TreeSynchronizer::synchronizeTrees(m_pendingTree->RootLayer(), m_activeTree->DetachLayerTree(), m_activeTree.get())); diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h index 2e287c8..4414adb 100644 --- a/cc/layer_tree_host_impl.h +++ b/cc/layer_tree_host_impl.h @@ -172,6 +172,7 @@ public: const LayerTreeImpl* recycleTree() const { return m_recycleTree.get(); } void createPendingTree(); void checkForCompletedTileUploads(); + scoped_ptr<base::Value> activationStateAsValue() const; virtual void activatePendingTreeIfNeeded(); // Shortcuts to layers on the active tree. diff --git a/cc/tile_manager.cc b/cc/tile_manager.cc index 8bb05e2..f06c519 100644 --- a/cc/tile_manager.cc +++ b/cc/tile_manager.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/debug/trace_event.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "cc/platform_color.h" #include "cc/raster_worker_pool.h" @@ -67,8 +68,36 @@ TileManagerBin BinFromTilePriority(const TilePriority& prio) { 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"; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown TileManagerBin value>")); + } +} + ManagedTileState::ManagedTileState() : can_use_gpu_memory(false), can_be_freed(true), @@ -95,7 +124,8 @@ TileManager::TileManager( raster_worker_pool_(RasterWorkerPool::Create(num_raster_threads)), manage_tiles_pending_(false), manage_tiles_call_count_(0), - bytes_pending_set_pixels_(0) { + bytes_pending_set_pixels_(0), + ever_exceeded_memory_budget_(false) { for (int i = 0; i < NUM_STATES; ++i) { for (int j = 0; j < NUM_TREES; ++j) { for (int k = 0; k < NUM_BINS; ++k) @@ -214,7 +244,6 @@ void TileManager::ManageTiles() { ++manage_tiles_call_count_; const TreePriority tree_priority = global_state_.tree_priority; - TRACE_COUNTER_ID1("cc", "TreePriority", this, tree_priority); TRACE_COUNTER_ID1("cc", "TileCount", this, tiles_.size()); // For each tree, bin into different categories of tiles. @@ -291,6 +320,8 @@ void TileManager::ManageTiles() { // Assign gpu memory and determine what tiles need to be rasterized. AssignGpuMemoryToTiles(); + TRACE_EVENT_INSTANT1("cc", "DidManage", "state", ValueToString(AsValue())); + // Finally, kick the rasterizer. DispatchMoreTasks(); } @@ -327,13 +358,13 @@ void TileManager::CheckForCompletedTileUploads() { void TileManager::GetMemoryStats( size_t* memoryRequiredBytes, size_t* memoryNiceToHaveBytes, - size_t* memoryUsedBytes) { + size_t* memoryUsedBytes) const { *memoryRequiredBytes = 0; *memoryNiceToHaveBytes = 0; *memoryUsedBytes = 0; - for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { - Tile* tile = *it; - ManagedTileState& mts = tile->managed_state(); + for(size_t i = 0; i < tiles_.size(); i++) { + const Tile* tile = tiles_[i]; + const ManagedTileState& mts = tile->managed_state(); size_t tile_bytes = tile->bytes_consumed_if_allocated(); if (mts.gpu_memmgr_stats_bin == NOW_BIN) *memoryRequiredBytes += tile_bytes; @@ -344,6 +375,32 @@ void TileManager::GetMemoryStats( } } +scoped_ptr<base::Value> TileManager::AsValue() const { + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); + state->SetInteger("tile_count", 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::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::GetRenderingStats(RenderingStats* stats) { raster_worker_pool_->GetRenderingStats(stats); stats->totalDeferredImageCacheHitCount = @@ -411,6 +468,7 @@ void TileManager::AssignGpuMemoryToTiles() { } size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes; + size_t bytes_that_exceeded_memory_budget = 0; for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) { Tile* tile = *it; size_t tile_bytes = tile->bytes_consumed_if_allocated(); @@ -425,6 +483,7 @@ void TileManager::AssignGpuMemoryToTiles() { } if (tile_bytes > bytes_left) { managed_tile_state.can_use_gpu_memory = false; + bytes_that_exceeded_memory_budget += tile_bytes; FreeResourcesForTile(tile); continue; } @@ -437,6 +496,15 @@ void TileManager::AssignGpuMemoryToTiles() { } } + if (bytes_that_exceeded_memory_budget) + ever_exceeded_memory_budget_ = true; + + 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); + } + // Reverse two tiles_that_need_* vectors such that pop_back gets // the highest priority tile. std::reverse( @@ -454,7 +522,7 @@ void TileManager::FreeResourcesForTile(Tile* tile) { bool TileManager::CanDispatchRasterTask(Tile* tile) { if (raster_worker_pool_->IsBusy()) return false; - int new_bytes_pending = bytes_pending_set_pixels_; + size_t new_bytes_pending = bytes_pending_set_pixels_; new_bytes_pending += tile->bytes_consumed_if_allocated(); return new_bytes_pending <= kMaxPendingUploadBytes; } diff --git a/cc/tile_manager.h b/cc/tile_manager.h index 0c99439..6f51dea 100644 --- a/cc/tile_manager.h +++ b/cc/tile_manager.h @@ -39,7 +39,10 @@ enum TileManagerBin { EVENTUALLY_BIN = 2, // Nice to have, if we've got memory and time. NEVER_BIN = 3, // Dont bother. NUM_BINS = 4 + // Be sure to update TileManagerBinAsValue when adding new fields. }; +scoped_ptr<base::Value> TileManagerBinAsValue( + TileManagerBin bin); enum TileManagerBinPriority { HIGH_PRIORITY_BIN = 0, @@ -100,9 +103,11 @@ class CC_EXPORT TileManager { void ManageTiles(); void CheckForCompletedTileUploads(); + + scoped_ptr<base::Value> AsValue() const; void GetMemoryStats(size_t* memoryRequiredBytes, size_t* memoryNiceToHaveBytes, - size_t* memoryUsedBytes); + size_t* memoryUsedBytes) const; void GetRenderingStats(RenderingStats* stats); bool HasPendingWorkScheduled(WhichTree tree) const; @@ -137,6 +142,7 @@ class CC_EXPORT TileManager { void DidTileBinChange(Tile* tile, TileManagerBin bin, WhichTree tree); + scoped_ptr<Value> GetMemoryRequirementsAsValue() const; TileManagerClient* client_; scoped_ptr<ResourcePool> resource_pool_; @@ -160,7 +166,8 @@ class CC_EXPORT TileManager { typedef std::queue<scoped_refptr<Tile> > TileQueue; TileQueue tiles_with_pending_set_pixels_; - int bytes_pending_set_pixels_; + size_t bytes_pending_set_pixels_; + bool ever_exceeded_memory_budget_; RenderingStats rendering_stats_; diff --git a/cc/tile_priority.cc b/cc/tile_priority.cc index 1fde0bcd..5fcf4f2 100644 --- a/cc/tile_priority.cc +++ b/cc/tile_priority.cc @@ -4,6 +4,8 @@ #include "cc/tile_priority.h" +#include "base/values.h" + namespace { // TODO(qinmin): modify ui/range/Range.h to support template so that we @@ -53,6 +55,21 @@ namespace cc { const double TilePriority::kMaxTimeToVisibleInSeconds = 1000; +scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) { + switch (tree) { + case ACTIVE_TREE: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ACTIVE_TREE")); + case PENDING_TREE: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "PENDING_TREE")); + default: + DCHECK(false) << "Unrecognized WhichTree value"; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown WhichTree value>")); + } +} + int TilePriority::manhattanDistance(const gfx::RectF& a, const gfx::RectF& b) { gfx::RectF c = gfx::UnionRects(a, b); // Rects touching the edge of the screen should not be considered visible. @@ -101,4 +118,53 @@ double TilePriority::TimeForBoundsToIntersect(gfx::RectF previous_bounds, return range.IsEmpty() ? kMaxTimeToVisibleInSeconds : range.start_; } +scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( + TileMemoryLimitPolicy policy) { + switch (policy) { + case ALLOW_NOTHING: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_NOTHING")); + case ALLOW_ABSOLUTE_MINIMUM: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_ABSOLUTE_MINIMUM")); + case ALLOW_PREPAINT_ONLY: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_PREPAINT_ONLY")); + case ALLOW_ANYTHING: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "ALLOW_ANYTHING")); + default: + DCHECK(false) << "Unrecognized policy value"; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown>")); + } +} + +scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) { + switch (prio) { + case SAME_PRIORITY_FOR_BOTH_TREES: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "SAME_PRIORITY_FOR_BOTH_TREES")); + case SMOOTHNESS_TAKES_PRIORITY: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "SMOOTHNESS_TAKES_PRIORITY")); + case NEW_CONTENT_TAKES_PRIORITY: + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "NEW_CONTENT_TAKES_PRIORITY")); + default: + DCHECK(false) << "Unrecognized priority value"; + return scoped_ptr<base::Value>(base::Value::CreateStringValue( + "<unknown>")); + } +} + +scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const { + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); + state->Set("memory_limit_policy", TileMemoryLimitPolicyAsValue(memory_limit_policy).release()); + state->SetInteger("memory_limit_in_bytes", memory_limit_in_bytes); + state->Set("tree_priority", TreePriorityAsValue(tree_priority).release()); + return state.PassAs<base::Value>(); +} + + } // namespace cc diff --git a/cc/tile_priority.h b/cc/tile_priority.h index fb90060..b2fb5d2 100644 --- a/cc/tile_priority.h +++ b/cc/tile_priority.h @@ -8,10 +8,15 @@ #include <limits> #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "cc/picture_pile.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" +namespace base { +class Value; +} + namespace cc { enum WhichTree { @@ -20,7 +25,10 @@ enum WhichTree { ACTIVE_TREE = 0, PENDING_TREE = 1, NUM_TREES = 2 + // Be sure to update WhichTreeAsValue when adding new fields. }; +scoped_ptr<base::Value> WhichTreeAsValue( + WhichTree tree); enum TileResolution { LOW_RESOLUTION = 0 , @@ -91,13 +99,20 @@ enum TileMemoryLimitPolicy { // You're the only thing in town. Go crazy. ALLOW_ANYTHING, // Venti. + + // Be sure to update TreePriorityAsValue when adding new fields. }; +scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue( + TileMemoryLimitPolicy policy); enum TreePriority { SAME_PRIORITY_FOR_BOTH_TREES, SMOOTHNESS_TAKES_PRIORITY, NEW_CONTENT_TAKES_PRIORITY + + // Be sure to update TreePriorityAsValue when adding new fields. }; +scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio); class GlobalStateThatImpactsTilePriority { public: @@ -112,6 +127,8 @@ class GlobalStateThatImpactsTilePriority { size_t memory_limit_in_bytes; TreePriority tree_priority; + + scoped_ptr<base::Value> AsValue() const; }; } // namespace cc |