summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/layer_tree_host_impl.cc25
-rw-r--r--cc/layer_tree_host_impl.h1
-rw-r--r--cc/tile_manager.cc82
-rw-r--r--cc/tile_manager.h11
-rw-r--r--cc/tile_priority.cc66
-rw-r--r--cc/tile_priority.h17
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