1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/command_buffer/common/skia_utils.h"
6
7 #include <inttypes.h>
8
9 #include "base/strings/stringprintf.h"
10 #include "base/trace_event/memory_dump_manager.h"
11 #include "base/trace_event/process_memory_dump.h"
12 #include "build/build_config.h"
13 #include "third_party/skia/include/core/SkTraceMemoryDump.h"
14 #include "third_party/skia/include/gpu/GrDirectContext.h"
15 #include "ui/gl/trace_util.h"
16
17 namespace gpu {
18 namespace raster {
19 namespace {
20
21 // Derives from SkTraceMemoryDump and implements graphics specific memory
22 // backing functionality.
23 class SkiaGpuTraceMemoryDump : public SkTraceMemoryDump {
24 public:
25 // This should never outlive the provided ProcessMemoryDump, as it should
26 // always be scoped to a single OnMemoryDump funciton call.
SkiaGpuTraceMemoryDump(base::trace_event::ProcessMemoryDump * pmd,base::Optional<uint64_t> share_group_tracing_guid)27 SkiaGpuTraceMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
28 base::Optional<uint64_t> share_group_tracing_guid)
29 : pmd_(pmd),
30 share_group_tracing_guid_(share_group_tracing_guid),
31 tracing_process_id_(base::trace_event::MemoryDumpManager::GetInstance()
32 ->GetTracingProcessId()) {}
33
34 ~SkiaGpuTraceMemoryDump() override = default;
35
36 // Overridden from SkTraceMemoryDump:
dumpNumericValue(const char * dump_name,const char * value_name,const char * units,uint64_t value)37 void dumpNumericValue(const char* dump_name,
38 const char* value_name,
39 const char* units,
40 uint64_t value) override {
41 auto* dump = GetOrCreateAllocatorDump(dump_name);
42 dump->AddScalar(value_name, units, value);
43 }
dumpStringValue(const char * dump_name,const char * value_name,const char * value)44 void dumpStringValue(const char* dump_name,
45 const char* value_name,
46 const char* value) override {
47 auto* dump = GetOrCreateAllocatorDump(dump_name);
48 dump->AddString(value_name, "", value);
49 }
50
setMemoryBacking(const char * dump_name,const char * backing_type,const char * backing_object_id)51 void setMemoryBacking(const char* dump_name,
52 const char* backing_type,
53 const char* backing_object_id) override {
54 // For uniformity, skia provides this value as a string. Convert back to a
55 // uint32_t.
56 uint32_t gl_id =
57 std::strtoul(backing_object_id, nullptr /* str_end */, 10 /* base */);
58
59 // Constants used by SkiaGpuTraceMemoryDump to identify different memory
60 // types.
61 const char* kGLTextureBackingType = "gl_texture";
62 const char* kGLBufferBackingType = "gl_buffer";
63 const char* kGLRenderbufferBackingType = "gl_renderbuffer";
64
65 // Populated in if statements below.
66 base::trace_event::MemoryAllocatorDumpGuid guid;
67
68 if (share_group_tracing_guid_) {
69 // If we have a |share_group_tracing_guid_|, we are in a render process
70 // and need to create client texture GUIDs for aliasing with the GPU
71 // process.
72 if (strcmp(backing_type, kGLTextureBackingType) == 0) {
73 guid = gl::GetGLTextureClientGUIDForTracing(*share_group_tracing_guid_,
74 gl_id);
75 } else if (strcmp(backing_type, kGLBufferBackingType) == 0) {
76 guid = gl::GetGLBufferGUIDForTracing(tracing_process_id_, gl_id);
77 } else if (strcmp(backing_type, kGLRenderbufferBackingType) == 0) {
78 guid = gl::GetGLRenderbufferGUIDForTracing(tracing_process_id_, gl_id);
79 }
80 } else {
81 // If we do not have a |share_group_tracing_guid_|, we are in the GPU
82 // process, being used for OOP-R. We need to create Raster dumps for
83 // aliasing with the transfer cache. Note that this is currently only
84 // needed for textures (not buffers or renderbuffers).
85 if (strcmp(backing_type, kGLTextureBackingType) == 0) {
86 guid = gl::GetGLTextureRasterGUIDForTracing(gl_id);
87 }
88 }
89
90 if (!guid.empty()) {
91 pmd_->CreateSharedGlobalAllocatorDump(guid);
92
93 auto* dump = GetOrCreateAllocatorDump(dump_name);
94
95 const int kImportance = 2;
96 pmd_->AddOwnershipEdge(dump->guid(), guid, kImportance);
97 }
98 }
99
setDiscardableMemoryBacking(const char * dump_name,const SkDiscardableMemory & discardable_memory_object)100 void setDiscardableMemoryBacking(
101 const char* dump_name,
102 const SkDiscardableMemory& discardable_memory_object) override {
103 // We don't use this class for dumping discardable memory.
104 NOTREACHED();
105 }
106
getRequestedDetails() const107 LevelOfDetail getRequestedDetails() const override {
108 // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
109 // (crbug.com/499731).
110 return kObjectsBreakdowns_LevelOfDetail;
111 }
112
shouldDumpWrappedObjects() const113 bool shouldDumpWrappedObjects() const override {
114 // Chrome already dumps objects it imports into Skia. Avoid duplicate dumps
115 // by asking Skia not to dump them.
116 return false;
117 }
118
119 private:
120 // Helper to create allocator dumps.
GetOrCreateAllocatorDump(const char * dump_name)121 base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
122 const char* dump_name) {
123 auto* dump = pmd_->GetAllocatorDump(dump_name);
124 if (!dump)
125 dump = pmd_->CreateAllocatorDump(dump_name);
126 return dump;
127 }
128
129 base::trace_event::ProcessMemoryDump* pmd_;
130 base::Optional<uint64_t> share_group_tracing_guid_;
131 uint64_t tracing_process_id_;
132
133 DISALLOW_COPY_AND_ASSIGN(SkiaGpuTraceMemoryDump);
134 };
135
136 } // namespace
137
DumpGrMemoryStatistics(const GrDirectContext * context,base::trace_event::ProcessMemoryDump * pmd,base::Optional<uint64_t> tracing_guid)138 void DumpGrMemoryStatistics(const GrDirectContext* context,
139 base::trace_event::ProcessMemoryDump* pmd,
140 base::Optional<uint64_t> tracing_guid) {
141 SkiaGpuTraceMemoryDump trace_memory_dump(pmd, tracing_guid);
142 context->dumpMemoryStatistics(&trace_memory_dump);
143 }
144
DumpBackgroundGrMemoryStatistics(const GrDirectContext * context,base::trace_event::ProcessMemoryDump * pmd)145 void DumpBackgroundGrMemoryStatistics(
146 const GrDirectContext* context,
147 base::trace_event::ProcessMemoryDump* pmd) {
148 using base::trace_event::MemoryAllocatorDump;
149
150 size_t skia_gr_cache_size;
151 context->getResourceCacheUsage(nullptr /* resourceCount */,
152 &skia_gr_cache_size);
153 std::string dump_name =
154 base::StringPrintf("skia/gpu_resources/context_0x%" PRIXPTR,
155 reinterpret_cast<uintptr_t>(context));
156 MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
157 dump->AddScalar(MemoryAllocatorDump::kNameSize,
158 MemoryAllocatorDump::kUnitsBytes, skia_gr_cache_size);
159 }
160
161 } // namespace raster
162 } // namespace gpu
163