OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/viz/host/server_gpu_memory_buffer_manager.h" | 5 #include "components/viz/host/server_gpu_memory_buffer_manager.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/stringprintf.h" | |
8 #include "base/threading/sequenced_task_runner_handle.h" | 9 #include "base/threading/sequenced_task_runner_handle.h" |
10 #include "base/trace_event/memory_dump_manager.h" | |
11 #include "base/trace_event/process_memory_dump.h" | |
9 #include "gpu/ipc/client/gpu_memory_buffer_impl.h" | 12 #include "gpu/ipc/client/gpu_memory_buffer_impl.h" |
10 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h" | 13 #include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h" |
11 #include "gpu/ipc/common/gpu_memory_buffer_support.h" | 14 #include "gpu/ipc/common/gpu_memory_buffer_support.h" |
12 #include "services/ui/gpu/interfaces/gpu_service.mojom.h" | 15 #include "services/ui/gpu/interfaces/gpu_service.mojom.h" |
16 #include "ui/gfx/buffer_format_util.h" | |
17 #include "ui/gfx/gpu_memory_buffer_tracing.h" | |
18 | |
19 using base::trace_event::MemoryDumpManager; | |
reveman
2017/07/08 11:14:10
what's the justification for this? I think we pref
sadrul
2017/07/08 21:15:13
I have removed it.
Initially I was registering as
| |
13 | 20 |
14 namespace viz { | 21 namespace viz { |
15 | 22 |
23 ServerGpuMemoryBufferManager::BufferInfo::BufferInfo() = default; | |
24 ServerGpuMemoryBufferManager::BufferInfo::~BufferInfo() = default; | |
25 | |
16 ServerGpuMemoryBufferManager::ServerGpuMemoryBufferManager( | 26 ServerGpuMemoryBufferManager::ServerGpuMemoryBufferManager( |
17 ui::mojom::GpuService* gpu_service, | 27 ui::mojom::GpuService* gpu_service, |
18 int client_id) | 28 int client_id) |
19 : gpu_service_(gpu_service), | 29 : gpu_service_(gpu_service), |
20 client_id_(client_id), | 30 client_id_(client_id), |
21 native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), | 31 native_configurations_(gpu::GetNativeGpuMemoryBufferConfigurations()), |
22 task_runner_(base::SequencedTaskRunnerHandle::Get()), | 32 task_runner_(base::SequencedTaskRunnerHandle::Get()), |
23 weak_factory_(this) {} | 33 weak_factory_(this) {} |
24 | 34 |
25 ServerGpuMemoryBufferManager::~ServerGpuMemoryBufferManager() {} | 35 ServerGpuMemoryBufferManager::~ServerGpuMemoryBufferManager() {} |
26 | 36 |
27 void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer( | 37 void ServerGpuMemoryBufferManager::AllocateGpuMemoryBuffer( |
28 gfx::GpuMemoryBufferId id, | 38 gfx::GpuMemoryBufferId id, |
29 int client_id, | 39 int client_id, |
30 const gfx::Size& size, | 40 const gfx::Size& size, |
31 gfx::BufferFormat format, | 41 gfx::BufferFormat format, |
32 gfx::BufferUsage usage, | 42 gfx::BufferUsage usage, |
33 gpu::SurfaceHandle surface_handle, | 43 gpu::SurfaceHandle surface_handle, |
34 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback) { | 44 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback) { |
35 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 45 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
36 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) { | 46 if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER) { |
37 const bool is_native = native_configurations_.find(std::make_pair( | 47 const bool is_native = native_configurations_.find(std::make_pair( |
38 format, usage)) != native_configurations_.end(); | 48 format, usage)) != native_configurations_.end(); |
39 if (is_native) { | 49 if (is_native) { |
40 pending_buffers_.insert(client_id); | 50 pending_buffers_.insert(client_id); |
41 gpu_service_->CreateGpuMemoryBuffer( | 51 gpu_service_->CreateGpuMemoryBuffer( |
42 id, size, format, usage, client_id, surface_handle, | 52 id, size, format, usage, client_id, surface_handle, |
43 base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated, | 53 base::Bind(&ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated, |
44 weak_factory_.GetWeakPtr(), client_id, | 54 weak_factory_.GetWeakPtr(), client_id, |
55 gfx::BufferSizeForBufferFormat(size, format), | |
45 base::Passed(std::move(callback)))); | 56 base::Passed(std::move(callback)))); |
46 return; | 57 return; |
47 } | 58 } |
48 } | 59 } |
49 | 60 |
50 gfx::GpuMemoryBufferHandle buffer_handle; | 61 gfx::GpuMemoryBufferHandle buffer_handle; |
51 // The requests are coming in from untrusted clients. So verify that it is | 62 // The requests are coming in from untrusted clients. So verify that it is |
52 // possible to allocate shared memory buffer first. | 63 // possible to allocate shared memory buffer first. |
53 if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) && | 64 if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) && |
54 gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, | 65 gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, |
55 format)) { | 66 format)) { |
56 buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( | 67 buffer_handle = gpu::GpuMemoryBufferImplSharedMemory::CreateGpuMemoryBuffer( |
57 id, size, format); | 68 id, size, format); |
69 BufferInfo buffer_info; | |
70 DCHECK_EQ(gfx::SHARED_MEMORY_BUFFER, buffer_handle.type); | |
71 buffer_info.type = gfx::SHARED_MEMORY_BUFFER; | |
72 buffer_info.buffer_size_in_bytes = | |
73 gfx::BufferSizeForBufferFormat(size, format); | |
74 buffer_info.shared_memory_guid = buffer_handle.handle.GetGUID(); | |
75 allocated_buffers_[client_id].insert( | |
76 std::make_pair(buffer_handle.id, buffer_info)); | |
58 } | 77 } |
59 | 78 |
60 task_runner_->PostTask(FROM_HERE, | 79 task_runner_->PostTask(FROM_HERE, |
61 base::BindOnce(std::move(callback), buffer_handle)); | 80 base::BindOnce(std::move(callback), buffer_handle)); |
62 } | 81 } |
63 | 82 |
64 std::unique_ptr<gfx::GpuMemoryBuffer> | 83 std::unique_ptr<gfx::GpuMemoryBuffer> |
65 ServerGpuMemoryBufferManager::CreateGpuMemoryBuffer( | 84 ServerGpuMemoryBufferManager::CreateGpuMemoryBuffer( |
66 const gfx::Size& size, | 85 const gfx::Size& size, |
67 gfx::BufferFormat format, | 86 gfx::BufferFormat format, |
(...skipping 29 matching lines...) Expand all Loading... | |
97 weak_factory_.GetWeakPtr(), id, client_id_)); | 116 weak_factory_.GetWeakPtr(), id, client_id_)); |
98 } | 117 } |
99 | 118 |
100 void ServerGpuMemoryBufferManager::SetDestructionSyncToken( | 119 void ServerGpuMemoryBufferManager::SetDestructionSyncToken( |
101 gfx::GpuMemoryBuffer* buffer, | 120 gfx::GpuMemoryBuffer* buffer, |
102 const gpu::SyncToken& sync_token) { | 121 const gpu::SyncToken& sync_token) { |
103 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( | 122 static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( |
104 sync_token); | 123 sync_token); |
105 } | 124 } |
106 | 125 |
126 bool ServerGpuMemoryBufferManager::OnMemoryDump( | |
127 const base::trace_event::MemoryDumpArgs& args, | |
128 base::trace_event::ProcessMemoryDump* pmd) { | |
129 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | |
130 for (const auto& pair : allocated_buffers_) { | |
131 int client_id = pair.first; | |
132 for (const auto& buffer_pair : pair.second) { | |
133 gfx::GpuMemoryBufferId buffer_id = buffer_pair.first; | |
134 const BufferInfo& buffer_info = buffer_pair.second; | |
135 base::trace_event::MemoryAllocatorDump* dump = | |
136 pmd->CreateAllocatorDump(base::StringPrintf( | |
137 "gpumemorybuffer/client_%d/buffer_%d", client_id, buffer_id.id)); | |
138 if (!dump) | |
139 return false; | |
140 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | |
141 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
142 buffer_info.buffer_size_in_bytes); | |
143 | |
144 // Create the cross-process ownership edge. If the client creates a | |
145 // corresponding dump for the same buffer, this will avoid to | |
146 // double-count them in tracing. If, instead, no other process will emit a | |
147 // dump with the same guid, the segment will be accounted to the browser. | |
148 uint64_t client_tracing_process_id = ClientIdToTracingId(client_id); | |
149 | |
150 if (buffer_info.type == gfx::SHARED_MEMORY_BUFFER) { | |
151 auto shared_buffer_guid = gfx::GetSharedMemoryGUIDForTracing( | |
152 client_tracing_process_id, buffer_id); | |
153 pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_buffer_guid, | |
154 buffer_info.shared_memory_guid, | |
155 0 /* importance */); | |
156 } else { | |
157 auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing( | |
158 client_tracing_process_id, buffer_id); | |
159 pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); | |
160 pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid); | |
161 } | |
162 } | |
163 } | |
164 return true; | |
165 } | |
166 | |
107 void ServerGpuMemoryBufferManager::DestroyGpuMemoryBuffer( | 167 void ServerGpuMemoryBufferManager::DestroyGpuMemoryBuffer( |
108 gfx::GpuMemoryBufferId id, | 168 gfx::GpuMemoryBufferId id, |
109 int client_id, | 169 int client_id, |
110 const gpu::SyncToken& sync_token) { | 170 const gpu::SyncToken& sync_token) { |
111 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 171 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
112 if (native_buffers_[client_id].erase(id)) | 172 auto iter = allocated_buffers_[client_id].find(id); |
173 if (iter == allocated_buffers_[client_id].end()) | |
174 return; | |
175 DCHECK_NE(gfx::EMPTY_BUFFER, iter->second.type); | |
176 allocated_buffers_[client_id].erase(id); | |
177 if (iter->second.type != gfx::SHARED_MEMORY_BUFFER) | |
113 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, sync_token); | 178 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, sync_token); |
114 } | 179 } |
115 | 180 |
116 void ServerGpuMemoryBufferManager::DestroyAllGpuMemoryBufferForClient( | 181 void ServerGpuMemoryBufferManager::DestroyAllGpuMemoryBufferForClient( |
117 int client_id) { | 182 int client_id) { |
118 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 183 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
119 for (gfx::GpuMemoryBufferId id : native_buffers_[client_id]) | 184 for (auto pair : allocated_buffers_[client_id]) { |
120 gpu_service_->DestroyGpuMemoryBuffer(id, client_id, gpu::SyncToken()); | 185 DCHECK_NE(gfx::EMPTY_BUFFER, pair.second.type); |
121 native_buffers_.erase(client_id); | 186 if (pair.second.type != gfx::SHARED_MEMORY_BUFFER) { |
187 gpu_service_->DestroyGpuMemoryBuffer(pair.first, client_id, | |
188 gpu::SyncToken()); | |
189 } | |
190 } | |
191 allocated_buffers_.erase(client_id); | |
122 pending_buffers_.erase(client_id); | 192 pending_buffers_.erase(client_id); |
123 } | 193 } |
124 | 194 |
195 uint64_t ServerGpuMemoryBufferManager::ClientIdToTracingId( | |
196 int client_id) const { | |
197 if (client_id == client_id_) | |
198 return MemoryDumpManager::GetInstance()->GetTracingProcessId(); | |
199 // TODO(sad|ssid): Find a better way once crbug.com/661257 is resolved. | |
200 // The hash value is incremented so that the tracing id is never equal to | |
201 // MemoryDumpManager::kInvalidTracingProcessId. | |
202 return static_cast<uint64_t>(base::Hash( | |
203 reinterpret_cast<const char*>(&client_id), sizeof(client_id))) + | |
204 1; | |
205 } | |
206 | |
125 void ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated( | 207 void ServerGpuMemoryBufferManager::OnGpuMemoryBufferAllocated( |
126 int client_id, | 208 int client_id, |
209 size_t buffer_size_in_bytes, | |
127 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback, | 210 base::OnceCallback<void(const gfx::GpuMemoryBufferHandle&)> callback, |
128 const gfx::GpuMemoryBufferHandle& handle) { | 211 const gfx::GpuMemoryBufferHandle& handle) { |
129 DCHECK(task_runner_->RunsTasksInCurrentSequence()); | 212 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
130 if (pending_buffers_.find(client_id) == pending_buffers_.end()) { | 213 if (pending_buffers_.find(client_id) == pending_buffers_.end()) { |
131 // The client has been destroyed since the allocation request was made. | 214 // The client has been destroyed since the allocation request was made. |
132 if (!handle.is_null()) { | 215 if (!handle.is_null()) { |
133 gpu_service_->DestroyGpuMemoryBuffer(handle.id, client_id, | 216 gpu_service_->DestroyGpuMemoryBuffer(handle.id, client_id, |
134 gpu::SyncToken()); | 217 gpu::SyncToken()); |
135 } | 218 } |
136 std::move(callback).Run(gfx::GpuMemoryBufferHandle()); | 219 std::move(callback).Run(gfx::GpuMemoryBufferHandle()); |
137 return; | 220 return; |
138 } | 221 } |
139 if (!handle.is_null()) | 222 if (!handle.is_null()) { |
140 native_buffers_[client_id].insert(handle.id); | 223 BufferInfo buffer_info; |
224 buffer_info.type = handle.type; | |
225 buffer_info.buffer_size_in_bytes = buffer_size_in_bytes; | |
226 allocated_buffers_[client_id].insert( | |
227 std::make_pair(handle.id, buffer_info)); | |
228 } | |
141 std::move(callback).Run(handle); | 229 std::move(callback).Run(handle); |
142 } | 230 } |
143 | 231 |
144 } // namespace viz | 232 } // namespace viz |
OLD | NEW |