Index: cc/resources/resource_provider.cc |
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc |
index 9f680669c089de2a3781732f5f4fca54987caf44..b1f782db7c8fc2b27dc2e0d6b1d4dfcfb1881fc7 100644 |
--- a/cc/resources/resource_provider.cc |
+++ b/cc/resources/resource_provider.cc |
@@ -13,6 +13,9 @@ |
#include "base/stl_util.h" |
#include "base/strings/string_split.h" |
#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/thread_task_runner_handle.h" |
+#include "base/trace_event/memory_dump_manager.h" |
#include "base/trace_event/trace_event.h" |
#include "cc/base/math_util.h" |
#include "cc/resources/platform_color.h" |
@@ -30,6 +33,7 @@ |
#include "ui/gfx/geometry/rect.h" |
#include "ui/gfx/geometry/vector2d.h" |
#include "ui/gfx/gpu_memory_buffer.h" |
+#include "ui/gl/trace_util.h" |
using gpu::gles2::GLES2Interface; |
@@ -404,6 +408,9 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create( |
} |
ResourceProvider::~ResourceProvider() { |
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
+ this); |
+ |
while (!children_.empty()) |
DestroyChildInternal(children_.begin(), FOR_SHUTDOWN); |
while (!resources_.empty()) |
@@ -1117,6 +1124,9 @@ ResourceProvider::ResourceProvider( |
void ResourceProvider::Initialize() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
+ this, base::ThreadTaskRunnerHandle::Get()); |
+ |
GLES2Interface* gl = ContextGL(); |
if (!gl) { |
default_resource_type_ = RESOURCE_TYPE_BITMAP; |
@@ -1958,4 +1968,59 @@ class GrContext* ResourceProvider::GrContext(bool worker_context) const { |
return context_provider ? context_provider->GrContext() : NULL; |
} |
+bool ResourceProvider::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ const uint64 tracing_process_id = |
+ base::trace_event::MemoryDumpManager::GetInstance()->tracing_process_id(); |
+ |
+ for (const auto& resource_entry : resources_) { |
+ const auto& resource = resource_entry.second; |
+ |
+ // Only log INTERNAL resources - other resources are owned by (and will be |
+ // logged by) another ResourceProvider. |
+ if (resource.origin != Resource::INTERNAL) |
+ continue; |
+ |
+ std::string dump_name = base::StringPrintf("cc/resource_memory/resource_%d", |
+ resource_entry.first); |
+ base::trace_event::MemoryAllocatorDump* dump = |
+ pmd->CreateAllocatorDump(dump_name); |
+ |
+ // Calculate the size of the current resource. |
+ // TODO(ericrk): Replace this with helper fn once crrev.com/1202843008 |
+ // goes in. |
+ unsigned bytes_per_pixel = BitsPerPixel(resource.format) / 8; |
+ uint32_t total_bytes = |
+ resource.size.height() * |
+ MathUtil::RoundUp(bytes_per_pixel * resource.size.width(), 4u); |
+ |
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
+ static_cast<uint64_t>(total_bytes)); |
+ |
+ // Resources which are shared across processes require a shared GUID to |
+ // prevent double counting the memory. We currently support shared GUIDs for |
+ // GpuMemoryBuffer, SharedBitmap, and GL backed resources. |
+ base::trace_event::MemoryAllocatorDumpGuid guid; |
+ if (resource.gpu_memory_buffer) { |
+ guid = gfx::GetGpuMemoryBufferGUIDForTracing( |
+ tracing_process_id, resource.gpu_memory_buffer->GetHandle().id); |
+ } else if (resource.shared_bitmap) { |
+ guid = GetSharedBitmapGUIDForTracing(resource.shared_bitmap->id()); |
+ } else if (resource.gl_id && resource.allocated) { |
+ guid = |
+ gfx::GetGLTextureGUIDForTracing(tracing_process_id, resource.gl_id); |
+ } |
+ |
+ if (!guid.empty()) { |
+ const int kImportance = 2; |
+ pmd->CreateSharedGlobalAllocatorDump(guid); |
+ pmd->AddOwnershipEdge(dump->guid(), guid, kImportance); |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace cc |